FPGA / ARM / DSP Wishbone SoC
< Using GNUARM >
Lab2 : Wishbone1
ARM SoC / FPGA Wishbone Bus 整合實驗2
▋Introduction
Lab.2 在FPGA部分是基於Wishbone0建立之Wishbone SoC Bus System Wishbone1。Wishbone1除了原有的Wishbone Framework, ARM Master與GPIO Slave外,增加了2個Masters:C6x DSP Wishbone Master與HSPI Host Link SPI wishbone Master及一個雜項功能的wbreg Slave. 這架構使得ARM9, C6x DSP, 及Host Link SPI這3個Masters可以基於Wishbone共用資源及交換資料, 完成分別或共同之工作。有關C6x DSP的實驗將在下一個章節進行;Host Link SPI則是提供Wishbone及C6x DPS連結PC IDS交換資料或除錯用。
此實驗以FPGA之設計為主, ARM執行之程式與前一章節相同,控制GPIO Slave驅動之LED。
▋Design Summery
Verilog電路架構描述主要是在Wishbone Bus Framework增加C6x DSP, 及Host Link SPI這3個Masters以及一個雜項功能的wbreg Slave。
HSPI,Host Link SPI,使用者可以透過PC端IDS,透過master wbshpi,在Wishbone上發出讀或寫之transcations,可將PC端資料download to/upload from Wishbone內之任何位址,包括暫存器read/write等,作為除錯等功能,下個章節有更多相關介紹。
wbreg slave主要包含一些Wishbone Master或Slave所需的控制暫存器,及一些雜項暫存器,例如GPIO,下一章節將直接使用此一GPIO,取代wbios之功能。wbreg slave另外還包含一塊RAM及一些對應暫存器,做為處理器或masters間之mail box,以達成處理器或masters間交換訊息資料或同步之用。即是藉由此wbreg slave,使得PC IDS可以download/upload DSP之記憶體,或燒錄DSP模組之Flash記憶體。
Wishbone1還包含wbc6x此一master,因此,Wishbone1主要是作為一個ARM與DSP share memory的最簡單架構,可參考布落格內有相關的DSP實驗。
▋Hierarchy
▋ARM9 C Programs : gatest03
gatest03.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <serial.h>
#define xMin 0
#define xMac 479
#define xMax 480
#define yMin 0
#define yMac 271
#define yMax 272
#define cbRow (xMax*1)
#define xLMin xMin
#define xLMax xMax
#define xLMid ((xLMax+xLMin)/2)
#define yLMin (yMin + 8*8)
#define yLMax yMax
#define yLMid ((yLMax+yLMin)/2)
#define cbLine (480/8)
#define swap(a,b) if (1) { int t; t = (a); (a) = (b); (b) = t; } else
unsigned char tfont[(0x80-0x20)*8] = {
/* 20 ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 21 '!' */ 0x04, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
/* 22 '"' */ 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 23 '#' */ 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x00, 0x00, 0x00,
/* 24 '$' */ 0x0E, 0x14, 0x0E, 0x05, 0x0E, 0x00, 0x00, 0x00,
/* 25 '%' */ 0x19, 0x1A, 0x04, 0x0B, 0x13, 0x00, 0x00, 0x00,
/* 26 '&' */ 0x0C, 0x0A, 0x0C, 0x12, 0x0D, 0x00, 0x00, 0x00,
/* 27 ''' */ 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 28 '(' */ 0x04, 0x08, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
/* 29 ')' */ 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00,
/* 2A '*' */ 0x15, 0x0E, 0x04, 0x0E, 0x15, 0x00, 0x00, 0x00,
/* 2B '+' */ 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x00, 0x00,
/* 2C ',' */ 0x00, 0x00, 0x00, 0x06, 0x02, 0x04, 0x00, 0x00,
/* 2D '-' */ 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 2E '.' */ 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00,
/* 2F '/' */ 0x01, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00, 0x00,
/* 30 '0' */ 0x0E, 0x11, 0x15, 0x11, 0x0E, 0x00, 0x00, 0x00,
/* 31 '1' */ 0x04, 0x0C, 0x04, 0x04, 0x0E, 0x00, 0x00, 0x00,
/* 32 '2' */ 0x0E, 0x01, 0x0E, 0x10, 0x1F, 0x00, 0x00, 0x00,
/* 33 '3' */ 0x0E, 0x01, 0x0E, 0x01, 0x0E, 0x00, 0x00, 0x00,
/* 34 '4' */ 0x12, 0x12, 0x1F, 0x02, 0x02, 0x00, 0x00, 0x00,
/* 35 '5' */ 0x1E, 0x10, 0x1E, 0x01, 0x1E, 0x00, 0x00, 0x00,
/* 36 '6' */ 0x0E, 0x10, 0x1E, 0x11, 0x0E, 0x00, 0x00, 0x00,
/* 37 '7' */ 0x1F, 0x02, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00,
/* 38 '8' */ 0x0E, 0x11, 0x0E, 0x11, 0x0E, 0x00, 0x00, 0x00,
/* 39 '9' */ 0x0E, 0x11, 0x0F, 0x01, 0x0E, 0x00, 0x00, 0x00,
/* 3A ':' */ 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x00,
/* 3B ';' */ 0x00, 0x06, 0x06, 0x00, 0x06, 0x0C, 0x00, 0x00,
/* 3C '<' */ 0x02, 0x04, 0x08, 0x04, 0x02, 0x00, 0x00, 0x00,
/* 3D '=' */ 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00,
/* 3E '>' */ 0x08, 0x04, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00,
/* 3F '?' */ 0x0E, 0x01, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
/* 40 '@' */ 0x0E, 0x17, 0x17, 0x10, 0x0E, 0x00, 0x00, 0x00,
/* 41 'A' */ 0x0E, 0x11, 0x1F, 0x11, 0x11, 0x00, 0x00, 0x00,
/* 42 'B' */ 0x1E, 0x11, 0x1E, 0x11, 0x1E, 0x00, 0x00, 0x00,
/* 43 'C' */ 0x0E, 0x10, 0x10, 0x10, 0x0E, 0x00, 0x00, 0x00,
/* 44 'D' */ 0x1E, 0x11, 0x11, 0x11, 0x1E, 0x00, 0x00, 0x00,
/* 45 'E' */ 0x1F, 0x10, 0x1C, 0x10, 0x1F, 0x00, 0x00, 0x00,
/* 46 'F' */ 0x1F, 0x10, 0x1E, 0x10, 0x10, 0x00, 0x00, 0x00,
/* 47 'G' */ 0x0E, 0x10, 0x13, 0x11, 0x0E, 0x00, 0x00, 0x00,
/* 48 'H' */ 0x11, 0x11, 0x1F, 0x11, 0x11, 0x00, 0x00, 0x00,
/* 49 'I' */ 0x0E, 0x04, 0x04, 0x04, 0x0E, 0x00, 0x00, 0x00,
/* 4A 'J' */ 0x01, 0x01, 0x01, 0x11, 0x0E, 0x00, 0x00, 0x00,
/* 4B 'K' */ 0x11, 0x12, 0x1C, 0x12, 0x11, 0x00, 0x00, 0x00,
/* 4C 'L' */ 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00,
/* 4D 'M' */ 0x11, 0x1B, 0x15, 0x11, 0x11, 0x00, 0x00, 0x00,
/* 4E 'N' */ 0x11, 0x19, 0x15, 0x13, 0x11, 0x00, 0x00, 0x00,
/* 4F 'O' */ 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00, 0x00,
/* 50 'P' */ 0x1E, 0x11, 0x1E, 0x10, 0x10, 0x00, 0x00, 0x00,
/* 51 'Q' */ 0x0E, 0x11, 0x11, 0x13, 0x0F, 0x00, 0x00, 0x00,
/* 52 'R' */ 0x1E, 0x11, 0x1E, 0x12, 0x11, 0x00, 0x00, 0x00,
/* 53 'S' */ 0x0E, 0x10, 0x0E, 0x01, 0x0E, 0x00, 0x00, 0x00,
/* 54 'T' */ 0x1F, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00,
/* 55 'U' */ 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00, 0x00,
/* 56 'V' */ 0x11, 0x11, 0x0A, 0x0A, 0x04, 0x00, 0x00, 0x00,
/* 57 'W' */ 0x11, 0x11, 0x15, 0x15, 0x0A, 0x00, 0x00, 0x00,
/* 58 'X' */ 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x00, 0x00, 0x00,
/* 59 'Y' */ 0x11, 0x0A, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00,
/* 5A 'Z' */ 0x1F, 0x02, 0x04, 0x08, 0x1F, 0x00, 0x00, 0x00,
/* 5B '[' */ 0x0E, 0x08, 0x08, 0x08, 0x0E, 0x00, 0x00, 0x00,
/* 5C '\' */ 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00,
/* 5D ']' */ 0x0E, 0x02, 0x02, 0x02, 0x0E, 0x00, 0x00, 0x00,
/* 5E '^' */ 0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 5F '_' */ 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
/* 60 '`' */ 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 61 'a' */ 0x00, 0x0C, 0x02, 0x1E, 0x0E, 0x00, 0x00, 0x00,
/* 62 'b' */ 0x10, 0x1C, 0x12, 0x12, 0x1C, 0x00, 0x00, 0x00,
/* 63 'c' */ 0x00, 0x0E, 0x10, 0x10, 0x0E, 0x00, 0x00, 0x00,
/* 64 'd' */ 0x02, 0x0E, 0x12, 0x12, 0x0E, 0x00, 0x00, 0x00,
/* 65 'e' */ 0x00, 0x0C, 0x1E, 0x10, 0x0C, 0x00, 0x00, 0x00,
/* 66 'f' */ 0x04, 0x08, 0x1C, 0x08, 0x08, 0x00, 0x00, 0x00,
/* 67 'g' */ 0x00, 0x0C, 0x12, 0x12, 0x0E, 0x02, 0x0C, 0x00,
/* 68 'h' */ 0x10, 0x1C, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00,
/* 69 'i' */ 0x00, 0x0C, 0x04, 0x04, 0x0E, 0x00, 0x00, 0x00,
/* 6A 'j' */ 0x00, 0x06, 0x02, 0x02, 0x02, 0x12, 0x0C, 0x00,
/* 6B 'k' */ 0x10, 0x12, 0x1C, 0x1C, 0x12, 0x00, 0x00, 0x00,
/* 6C 'l' */ 0x0C, 0x04, 0x04, 0x04, 0x0E, 0x00, 0x00, 0x00,
/* 6D 'm' */ 0x00, 0x1A, 0x15, 0x11, 0x11, 0x00, 0x00, 0x00,
/* 6E 'n' */ 0x00, 0x1C, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00,
/* 6F 'o' */ 0x00, 0x0C, 0x12, 0x12, 0x0C, 0x00, 0x00, 0x00,
/* 70 'p' */ 0x00, 0x1C, 0x12, 0x12, 0x1C, 0x10, 0x10, 0x00,
/* 71 'q' */ 0x00, 0x0E, 0x12, 0x12, 0x0E, 0x02, 0x02, 0x00,
/* 72 'r' */ 0x00, 0x1C, 0x12, 0x10, 0x10, 0x00, 0x00, 0x00,
/* 73 's' */ 0x00, 0x0E, 0x18, 0x06, 0x1C, 0x00, 0x00, 0x00,
/* 74 't' */ 0x04, 0x0E, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00,
/* 75 'u' */ 0x00, 0x12, 0x12, 0x12, 0x0E, 0x00, 0x00, 0x00,
/* 76 'v' */ 0x00, 0x12, 0x12, 0x14, 0x08, 0x00, 0x00, 0x00,
/* 77 'w' */ 0x00, 0x11, 0x11, 0x15, 0x0A, 0x00, 0x00, 0x00,
/* 78 'x' */ 0x00, 0x12, 0x0C, 0x0C, 0x12, 0x00, 0x00, 0x00,
/* 79 'y' */ 0x00, 0x12, 0x12, 0x12, 0x0E, 0x02, 0x0C, 0x00,
/* 7A 'z' */ 0x00, 0x1E, 0x04, 0x08, 0x1E, 0x00, 0x00, 0x00,
/* 7B '{' */ 0x04, 0x08, 0x1C, 0x08, 0x04, 0x00, 0x00, 0x00,
/* 7C '|' */ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00,
/* 7D '}' */ 0x04, 0x02, 0x07, 0x02, 0x04, 0x00, 0x00, 0x00,
/* 7E '~' */ 0x08, 0x15, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 7F *** */ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00
};
char *msg[]= {
"ARM9 ARM920T WITH 16K I/D CACHE",
"ZEPPELINX ZEPPELINX ZEPPELINX",
"XILINX FPGA ALTERA FPGA",
0
};
int abs(int n)
{
return (n >= 0) ? n : -n;
}
unsigned char* row(int r)
{
return (unsigned char*)((unsigned int)r*cbRow+0x10000000);
}
void clear(unsigned char cc)
{
volatile unsigned char *p,*pEnd;
pEnd = row(yMax);
for (p = row(yMin); p < pEnd; p++)
{
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop"); *p = cc; }
}
inline void plotxyc(int x,int y,unsigned int c)
{
unsigned int wc;
//x=x&0x1ff; y=y&0xff;
//x=0x10000000+(x<<2)+(y<<10);
x=0x10000000+x+(y*cbRow);
//c=c&0xff;
//wc=c|(c<<8)|(c<<16)|(c<<24);
*((volatile unsigned char *)x)=c;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
void putch(unsigned int x,unsigned int y, unsigned char c, unsigned char co)
{
unsigned int i,j;
unsigned char *pp=tfont+((c-0x20)<<3);
for(i=0; i<7;i++)
{
unsigned char bb=*pp; pp++;
for(j=0;j<=7;j++)
{
if(bb&0x80) plotxyc(x+j,y+i,co);
//plot(y+i,x+j,co);
else plotxyc(x+j,y+i,0);
bb<<=1;
}
}
}
void putstr(int x, int y, char* s,unsigned char cc)
{
int i=0;
unsigned char ch;
while((i<cbLine))
{ (ch=s[i++]);
if (ch==0) break;
putch(x,y,ch,cc);
x+=8; }
}
void lineY1(volatile unsigned char* p, unsigned m, int e, int x,
int dy, int _2dx, int _2dy,unsigned char cc)
{
p += (unsigned)x;// << 2;
*p = cc;
while (dy--) {
if (e > 0) {
p++;//=4;
e -= _2dy;
}
e += _2dx;
p += cbRow;
*p = cc;
}
}
void lineY2(volatile unsigned char* p, unsigned m, int e, int x,
int dy, int _2dx, int _2dy,unsigned char cc)
{
p += (unsigned)x << 2;
*p = cc;
while (dy--) {
if (e > 0) {
p--;//=4;
e -= _2dy;
}
e += _2dx;
p += cbRow;
*p = cc;
}
}
void lineX(volatile unsigned char* p, unsigned m, int e, int x,
int dx, int d, int _2dx, int _2dy,unsigned char cc)
{
int dbRow = (d > 0) ? cbRow : -cbRow;
p += (unsigned)x;// << 2;
*p = cc;
while (dx--) {
if (e > 0) {
p += dbRow;
e -= _2dx;
}
e += _2dy;
p++;//=4;
*p = cc;
}
}
void line(int x, int y, int x2, int y2,unsigned char cc)
{
int dx, dy, d;
int e;
dx = x2 - x;
dy = y2 - y;
if (abs(dx) >= abs(dy)) {
int _2dx, _2dy;
if (x > x2) {
swap(x, x2);
swap(y, y2);
dx = x2 - x;
dy = y2 - y;
}
if (dy >= 0) {
d = 1;
}
else {
d = -1;
dy = -dy;
}
_2dx = dx + dx;
_2dy = dy + dy;
e = _2dy - dx;
lineX(row(y), 0, e, x, dx, d, _2dx, _2dy, cc);
}
else {
int _2dx, _2dy;
if (y > y2) {
swap(x, x2);
swap(y, y2);
dx = x2 - x;
dy = y2 - y;
}
if (dx >= 0)
d = 1;
else {
d = -1;
dx = -dx;
}
_2dx = dx + dx;
_2dy = dy + dy;
e = _2dx - dy;
if (d == 1)
lineY1(row(y), 0, e, x, dy, _2dx, _2dy, cc);
else
lineY2(row(y), 0, e, x, dy, _2dx, _2dy, cc);
}
}
void drawrect(int x0,int y0,int x1,int y1, int x2, int y2,
int x3,int y3,unsigned char cc)
{
line(x0,y0,x1,y1,cc);
line(x1,y1,x2,y2,cc);
line(x2,y2,x3,y3,cc);
line(x3,y3,x0,y0,cc);
}
void initvga()
{
*((volatile unsigned int*)0x11f00020)=0x103;
*((volatile unsigned int*)0x11f00024)=0x10000000;
}
int main()
{
int pw,i,j,k,y,x;
int i0,i1,i2,i3,i4,i5,i6,i7;
volatile int *mptr;
unsigned int ss;
char sstr[128],ch;
void (*prst)(void)=0;
k=0;
serial_puts("graphics test !!! \n");
initvga();
ch=0x20;
do
{
ch=serial_getc();
clear(ch-0x20);
} while(ch!='q');
y = 0; x=0;
ch=0;
i0=0; i1=0; i2=0; i3=0; i4=0; i5=0; i6=0; i7=0;
do
{
clear(0x00);
for(k=0;k<2000;k++)
{
drawrect(i0,0,xMac,i1,xMac-i2,yMac,0,yMac-i3,j);
drawrect(i4,0,xMac,i5,xMac-i6,yMac,0,yMac-i7,0);
j=(j+1)&0xff;
i0=(i0+3); if(i0>xMac) i0=xMac-i0;
i1=(i1+5); if(i1>yMac) i1=yMac-i1;
i2=(i2+7); if(i2>xMac) i2=xMac-i2;
i3=(i3+11); if(i3>yMac) i3=yMac-i3;
i4=(i4+13); if(i4>xMac) i4=xMac-i4;
i5=(i5+17); if(i5>yMac) i5=yMac-i5;
i6=(i6+19); if(i6>xMac) i6=xMac-i6;
i7=(i7+23); if(i7>yMac) i7=yMac-i7;
}
sprintf(sstr,"i0=%x i1=%x i2=%x i3=%x i4=%x i5=%x i6=%x i7=%x\n",
i0,i1,i2,i3,i4,i5,i6,i7);
serial_puts(sstr);
clear(0x00);
for(k=0;k<200;k++)
{
putstr(0,y, msg[0],0xff+k); y+=8; x+=4;
putstr(0,y, msg[1],0x3f+k); y+=8; x+=4;
putstr(0,y, msg[2],0xaa+k); y+=8; x+=4;
y&=0xff; x&=0xff;
}
if(serial_tstc()) ch=serial_getc();
} while(ch!='q');
(*prst)(); // reset
}
▋serial.c / serial.h / crt.s 【code內容和gatest00共用】
gatest03.ld
ENTRY(_start)
MEMORY
{
flash : ORIGIN = 0, LENGTH = 256K
ram : ORIGIN = 0x40000000, LENGTH = 4K
sdram : ORIGIN = 0x30000000, LENGTH = 32*1024K
}
_stack_end = 0x30100000;
SECTIONS
{
. = 0x30000000;
.text :
{
*(.init)
*(.text)
*(.rodata)
*(.rodata.str1.4)
*(.glue_7)
*(.glue_7t)
_text_end = .;
} >sdram
.data :
{
_data = .;
*(.data)
_data_end = .;
} >sdram
.bss : /* collect all uninitialized .bss sections that go into RAM */
{
_bss_start = .;
*(.bss)
} >sdram
. = ALIGN(4);
_bss_end = . ;
}
PROVIDE( end = . );
Makefile
GNUARM = c:/sdk4arm/gat/garm/bin/
NAME = gatest03
CC = $(GNUARM)arm-elf-gcc
LD = $(GNUARM)arm-elf-ld -v
AR = $(GNUARM)arm-elf-ar
AS = $(GNUARM)arm-elf-as
CP = $(GNUARM)arm-elf-objcopy
OD = $(GNUARM)arm-elf-objdump
CFLAGS = -I . -I c:/sdk4arm/gat/garm/arm-elf/
include -c -fno-common -O0 -g
AFLAGS = -ahls -mapcs-32
LFLAGS = -Map $(NAME).map -T$(NAME).ld
CPFLAGS = --output-target=binary
ODFLAGS = -x --syms -D
LF1 = c:/sdk4arm/gat/garm/arm-elf/lib/libc.a
LF2 = c:/sdk4arm/gat/garm/lib/gcc/arm-elf/4.1.1/libgcc.a
all: $(NAME).bin
clean:
-rm *.lst *.o *.out *.bin *.map *.lst
$(NAME).bin: $(NAME).out
@ echo "...copying"
$(CP) $(CPFLAGS) $< $@
$(OD) $(ODFLAGS) $< > $(NAME).lst
$(NAME).out: crt.o serial.o $(NAME).o
@ echo "..linking"
$(LD) $(LFLAGS) -o $@ $^ $(LF1) $(LF2)
%.o: %.s
@ echo ".assembling"
$(AS) $(AFLAGS) -o $@ $< > $*.lst
%.o: %.c
@ echo ".compiling"
$(CC) $(CFLAGS) -o $@ $<
▋Setup
& Verification
