一、摘要
通過在SOPC中定制軟核,在Quartus II中建立硬件工程,然后在NIOS II中建立3個工程,分別實現(xiàn)DM9000A測試、DM9000A自收發(fā)和基于DM9000A的UDP協(xié)議的例子。3個例子所使用的DM9000A的驅(qū)動是一樣的。
二、實驗平臺
軟件平臺:Quartus II 9.0 + Nios II 9.0
硬件平臺:DIY_DE2
三、實驗內(nèi)容1——>DM9000A測試
通過對DM9000A的初始化,測試DM9000A是否能夠正常的初始化,能否正常的運行。該內(nèi)容不需要使用網(wǎng)線。以下為實現(xiàn)步驟。
1、采用SOPC定制軟核
定制軟核的詳細(xì)步驟不再贅述,以上為定制的軟核。
cpu_0需要設(shè)置的地方:
Reset Vector:cfi_flash_0、
Exception Vector:sram_16bit_512k_0
第二個標(biāo)簽頁:Data Master處,Data Cache設(shè)置為None
之后分配地址,分配中斷號,生成即可。
2、硬件電路
采用原理圖的形式,創(chuàng)建頂層文件。
(1)添加生成的軟核;
(2)調(diào)用鎖相環(huán)IP核;
(3)連線、分配管腳;
(4)編譯、綜合,生成配置文件。
最后原理圖如下圖所示。
需要注意的問題:
(1)軟核程序在SDRAM里面運行,為了使軟核的速度提升,因此SDRAM的頻率和cpu的頻率都設(shè)置為100M。cpu時鐘clk_100和sdram操作時鐘clk_50都接PLL的c0,100M,無相位偏移;SDRAM的時鐘管腳SDRAM_CLK連接PLL的c1,100M,偏移-3ns。
(2)DM9000A的時鐘管腳接50M,直接連接晶振的輸入端即可。
(3)復(fù)位管腳接高電平VCC即可。
(4)CFI_FLASH的復(fù)位管腳FLASH_RESET接高電平VCC即可。
3、軟件方面
(1)打開NIOS II,新建工程,調(diào)用一個空的工程模板。
(2)添加DM9000A驅(qū)動:dm9000a.h和dm9000a.c,將上述兩個文件包括basic_io復(fù)制到上步建立的工程文件夾下。見附錄。
(3)添加一個新的.c文件,命名為main.c。將下列代碼復(fù)制到main.c內(nèi)。
main.c文件
- #include "basic_io.h"
- #include "DM9000A.C"
- int main()
- {
- unsigned int a;
- a=DM9000_init();
- DM9000_init(); // initialize DM9000 LAN chip //
- if(!a)
- {
- printf("Success");
- // TransmitPacket(unsigned char *data_ptr,unsigned int tx_len);
- // ReceivePacket (unsigned char *data_ptr,unsigned int *rx_len);
- }
- else
- printf("Failed");
-
- }
(4)編譯、下載、運行,之前要先將.sof的配置文件下載到FPGA內(nèi)。就可以看到RJ-45的黃色的燈和綠色的燈亮了起來。另外,在NIOS II的控制臺Console中也能看到輸出了 Success 。這時,說明DM9000A能正常運行,且初始化正常。
四、實驗內(nèi)容2——>實現(xiàn)DM9000A自收發(fā)
通過DM9000A將數(shù)據(jù)包發(fā)送出去,之后通過中斷接收。需要使用到網(wǎng)線A。
不需要改動硬件系統(tǒng),在上一步的基礎(chǔ)上,直接在NOIS II中新建工程,添加main.c文件。
main.c文件內(nèi)容如下:
- #include "basic_io.h"
- #include "DM9000A.C"
- #include "altera_avalon_pio_regs.h"
-
- unsigned int aaa,rx_len,i,packet_num;
- unsigned char RXT[68] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0x01,0x60,0x6E,0x11,0x02,0x0F,
- 0x08,0x00,0x11,0x22,0x33,0x44,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x00,0x00,0x00,0x20 };
-
-
- void ethernet_interrupts()
- {
- packet_num++;
- aaa=ReceivePacket (RXT,&rx_len);
- if(!aaa)
- {
- printf("\n\nReceive Packet Length = %d",rx_len);
- for(i=0;i<rx_len;i++)
- {
- if(i%8==0)
- printf("\n");
- printf("0x%2X,",RXT[i]);
- if(RXT[i] == 0x3f)
- IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0xff);
- }
- }
- }
-
- int main(void)
- {
- unsigned char TXT[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0x01,0x60,0x6E,0x11,0x02,0x0F,
- 0x08,0x00,0x11,0x22,0x33,0x44,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x55,0x66,0x77,0x88,0x99,0xAA,
- 0x00,0x00,0x00,0x20 };
- DM9000_init();
- alt_irq_register( DM9000A_IRQ, NULL, (void*)ethernet_interrupts );
- packet_num=0;
- while (1)
- {
- TransmitPacket(TXT,0x40);
- msleep(500);
- }
-
- return 0;
- }
- //
- //-------------------------------------------------------------------------
編譯、下載、運行。這時候?qū)⒕W(wǎng)線A插入DIY_DE2開發(fā)板的RJ-45,能夠看到黃色的燈閃爍,綠色的燈一直亮,另外,在NIOS II控制臺也能看到收到的數(shù)據(jù)。
五、簡單UDP協(xié)議的實現(xiàn)
DM9000A與PC的簡單通信,采用UDP協(xié)議,用B網(wǎng)線連接DIY_DE2與PC。FPGA內(nèi)部產(chǎn)生遞增數(shù)據(jù),夠一個數(shù)據(jù)包后,通過網(wǎng)絡(luò)將數(shù)據(jù)傳輸給PC,PC也可以通過網(wǎng)絡(luò)給FPGA發(fā)送數(shù)據(jù),F(xiàn)PGA則通過中斷接收數(shù)據(jù)。
同樣,直接在NOIS II中新建工程,添加main.c文件。
可以使用Wireshark軟件來捕捉數(shù)據(jù)包,并測試其傳輸速度。經(jīng)過測試:
cpu采用100MHz時,
(1)cpu/e:SRAM運行,速度3Mbps;
SDRAM運行,50MHz時,速度600Kbps;
SDRAM運行,100MHz時,速度1.0Mbps;
(2)cpu/f:SRAM運行,速度11Mbps。
main.c文件內(nèi)容如下:
- main.c文件
- #include <io.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include "system.h"
- #include "DM9000A.C"
- unsigned int aaa,rx_len,i,counter;
- unsigned char RXT[70];
-
- unsigned int IPsource_1,IPsource_2,IPsource_3,IPsource_4;
- unsigned int IPdestination_1,IPdestination_2,IPdestination_3,IPdestination_4;
- unsigned int IPchecksum1,IPchecksum2,IPchecksum3,IPchecksum4,IPchecksum5;
- unsigned int Mac_source1, Mac_source2, Mac_source3, Mac_source4, Mac_source5, Mac_source6;
- unsigned int Mac_dest1, Mac_dest2, Mac_dest3, Mac_dest4, Mac_dest5, Mac_dest6;
- unsigned int times, lenght_h, lenght_l;
- unsigned int flenght, IPlenght_h, IPlenght_l, data_lenght, IPlenght;
-
- /*
- // Next step try to recieve packets. (not available now).
- void ethernet_interrupts()
- {
- aaa=ReceivePacket (RXT,&rx_len);
- if(!aaa)
- {
- printf("\n\nReceive Packet Length = %d",rx_len);
- for(i=0;i<rx_len;i++)
- {
- if(i%8==0)
- printf("\n");
- printf("0x%2X,",RXT[i]);
- }
- }
- }
- */
- int main(void)
- {
- IPsource_1 = 0xC0; // Assign ie: 192.168.0.44 IP for the DE2
- IPsource_2 = 0xA8;
- IPsource_3 = 0x00;
- IPsource_4 = 0x2C;
- IPdestination_1 = 0xCA; // Insert your IP data here
- IPdestination_2 = 0x76;
- IPdestination_3 = 0xBB;
- IPdestination_4 = 0x57;
- Mac_dest1 = 0x00; // Insert your MAC address data here
- Mac_dest2 = 0x0F;
- Mac_dest3 = 0xEA;
- Mac_dest4 = 0xFD;
- Mac_dest5 = 0x9F;
- Mac_dest6 = 0x96;
- Mac_source1 = 0x01; // Assign an MAC address for DE2
- Mac_source2 = 0x60;
- Mac_source3 = 0x6E;
- Mac_source4 = 0x11;
- Mac_source5 = 0x02;
- Mac_source6 = 0x0F;
-
- data_lenght = 1468; // Maximun Data lenght 1468 bytes
-
- flenght = data_lenght + 0x2E; //Total packet lenght
- lenght_h = ((data_lenght+8) & 0xFF00)>>8; // Convert in H byte and L byte
- lenght_l = ((data_lenght+8) & 0x00FF);
-
- IPlenght = data_lenght + 8 + 20; // IP Lenght for IP header
- IPlenght_h = (IPlenght & 0xFF00)>>8; // Convert in H byte and L byte
- IPlenght_l = (IPlenght & 0x00FF);
-
- // Calculating the IP checksum
- IPchecksum1 = 0x0000C511 + (IPsource_1<<8)+IPsource_2+(IPsource_3<<8)+IPsource_4+
- (IPdestination_1<<8)+IPdestination_2+(IPdestination_3<<8)+(IPdestination_4)+
- (IPlenght_h<<8) + IPlenght_l;
- IPchecksum2 = ((IPchecksum1&0x0000FFFF)+(IPchecksum1>>16));
- IPchecksum3 = 0x0000FFFF - IPchecksum2;
- IPchecksum4 = (IPchecksum3 & 0xFF00)>>8;
- IPchecksum5 = (IPchecksum3 & 0x00FF);
-
- unsigned char SND[flenght]; // Payload buffer
-
- unsigned char TXT[] = { Mac_dest1, Mac_dest2, Mac_dest3, Mac_dest4 ,Mac_dest5, Mac_dest6,
- Mac_source1, Mac_source2, Mac_source3, Mac_source4, Mac_source5, Mac_source6,
- 0x08, 0x00, 0x45, 0x00, IPlenght_h, IPlenght_l,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0x11,
- IPchecksum4, IPchecksum5, IPsource_1, IPsource_2, IPsource_3, IPsource_4,
- IPdestination_1, IPdestination_2, IPdestination_3, IPdestination_4, 0x04, 0x00,
- 0x04, 0x00, lenght_h, lenght_l, 0x00, 0x00};
-
- for (i = 0; i < 42; i++) // Load the TXT[] in the SND (ethernet packet).
- SND[i] = TXT[i];
-
- for (i = 42; i < flenght-4; i++) // generating the data to send.
- SND[i] = i-42;
-
- SND[i++] = 0x35; // This checksum is not correct... but also the net recieve the packets correctly.
- SND[i++] = 0x15; // To do, calculate checksum.
- SND[i++] = 0xF0;
- SND[i++] = 0x13;
-
- DM9000_init(); // Initialize the DM9000A.
- // Next step try to recieve packets.(not available now).
- // alt_irq_register( DM9000A_IRQ, NULL, (void*)ethernet_interrupts );
-
- while (1)
- {
- TransmitPacket(SND,flenght); // Send repetitively 1468 bytes of data.
- // printf("0x%2X,",ior(NSR)); // For check if 10Mbps or 100Mbps active, 0x80 = 10Mbps, 0x40 = 100Mbps.
- // may happend an RX overflow buffer = 0x42
- // msleep(500);
- }
- return 0;
- }
-
//---------------------------------------------------------------
六、說明
UDP屬于無連接的通信,這里不必把IP設(shè)置成同一網(wǎng)段即可完成通信。
|