Блог

Реализация упрощенного протокола TCP с использованием NIOS II.

В данном проекте мы создадим систему на основе софт процессора Nios II, ядро Ethernet-интерфейса с поддержкой скоростей 10/100/1000, контроллер SGDMA, контроллер SDRAM и другие аппаратные компоненты для передачи и приема TCP пакетов. В дизайн добавлены два модуля фазовой автоподстройки частоты для генерации тактовых сигналов с различными частотами, чтобы тактировать трехскоростную систему Ethernet (которая реализует функцию MAC) для работы на скорости 10/100/1000 Мбит/с. После сборки аппаратной системы и загрузки схемы в ПЛИС, мы запустим прикладную программу, написанную на языке Си. На основе входных сигналов от платы наша программа устанавливает и закрывает TCP-соединение, передает и принимает кадры данных от порта Ethernet платы. Кадры Ethernet передаются на основе протокола Stop and Wait, а таймер процессора NIOS используется для повторной передачи кадров после таймаута.

На рисунке ниже, представлена схема получившейся SOPC:

pic1

Рассмотрим компоненты, составляющие нашу SOPC:

Компонент sys_clk (Clock Source) Входной буфер для сигнала частоты и сброса.

Параметры компонента sys_clk
СтраницаПараметрЗначениеЕдиницы
clock_source Clock frequency 100000000 Hz
clock_source Clock frequency is known Yes  
clock_source Reset synchronus edges None  

Компонент nios2_gen2_0 (Nios II Processor) основной процессор системы.  окне настроек выбрать NiosII/f, остальные настройки описаны в таблице.

Параметры компонента nios2
СтраницаПараметрЗначениеЕдиницы
Main Nios II Core Nios II/e  
Reset Vector Reset vector memory onchip_memory0_0.s1  
Reset Vector Reset vector offset 0x00000000  
Reset Vector Reset vector 0x01000000  
Exeption Vector Exeption vector memory onchip_memory0_0.s1  
Exeption Vector Exeption vector offset 0x00000020  
Exeption Vector Exeption vector 0x01000020  
Fast TLB Miss Exeption Vector Fast TLB Miss Exeption vector memory nios2_gen2_0.debug_mem_slave  
Fast TLB Miss Exeption Vector Fast TLB Miss Exeption vector offset 0x00000040  
Fast TLB Miss Exeption Vector Fast TLB Miss Exeption vector 0x00000000  

Компонент new_sdram_controller_0 (SDRAM Controller Intel FPGA IP) Контроллер SDRAM памяти. В данном случае в SDRAM будет размещаться память программ и буфера для приема/передачи TCP пакеты. Настройки контроллера приведены в таблице.

Параметры компонента new_sdram_controller_0
СтраницаПараметрЗначениеЕдиницы
Data Width Bits 8  
Architecture Chip select 1  
Architecture Banks 4  
Address Width Row 12  
Address Width Column 10  
Timing Cas latency cycles 2  
Timing Initialization refresh cycles 8  
Timing Issue one refresh command every 7.8125 uS
Timing Delay after powerup, before initialization 200.0 uS
Timing Duration of refresh command (t_rfc) 70.0 nS
Timing Duration of precharge command (t_rp) 20.0 nS
Timing ACTIVE to READ or WRITE delay (t_rcd) 20.0 nS
Timing Access time (t_ac) 5.5 nS
Timing Write recovery time (t_wr, no auto precharge) 14.0 nS

Компонент jtag_usart_0 (JTAG UART Intel FPGA IP) интерфейс отладчика системы. Компонент, предназначенный для передачи данных из Nios в IDE (аналог semihosting в ARM). Полезен для отладки. 

Параметры компонента jtag_usart_0
СтраницаПараметрЗначениеЕдиницы
Write FIFA (Data from Avalon to JTAG Buffer depth (bytes) 64 bytes
Write FIFA (Data from Avalon to JTAG IRQ threshold 8  
Write FIFA (Data from Avalon to JTAG Constuct using registers No  
Read FIFA (Data from JTAG to Avalon Buffer depth (bytes) 64 bytes
Read FIFA (Data from JTAG to Avalon IRQ threshold 8  
Read FIFA (Data from JTAG to Avalon Constuct using registers No  

Компонент tse (Triple-Speed Ethernet Intel FPGA IP) Контроллер трехскоростного драйвера MAC. Настройки контроллера приведены в таблице.

Параметры компонента tse
СтраницаПараметрЗначениеЕдиницы
Core Variations Core Variations 10/100/1000Mb Ethernet MAC  
10/100/1000Mb Ethernet MAC Interface RGMII  
10/100/1000Mb Ethernet MAC Use clock enable for MAC No  
10/100/1000Mb Ethernet MAC Use internal FIFO Yes  
10/100/1000Mb Ethernet MAC Number of ports 1 ;
Ethernet MAC Options Enable MAC 10/100 half duplex support Yes  
Ethernet MAC Options Enable local loopback on MII/GMII/RGMII No  
Ethernet MAC Options Enable supplemental MAC unicast addresses No  
Ethernet MAC Options Include statistics counters Yes  
Ethernet MAC Options Enable 64-bit statistics byte counters Yes  
Ethernet MAC Options Incluse multicast hashtable No  
Ethernet MAC Options Align packet headers to 32-bit boundary Yes  
Ethernet MAC Options Enable full-duplex flow control Yes  
Ethernet MAC Options Enable VLAN detection No  
Ethernet MAC Options Enable magic packet detection No  
MDIO Module Include MDIO module (MDC/MDIO) Yes  
MDIO Module Host clock divisor 40  
FIFO Options Width Width 32 bits
FIFO Options Depth Transmit 4096*32 bits
FIFO Options Depth Receive 4096*32 bits

Компонент sgdma_rx (Scatter-Gather DMA Controller Intel FPGA IP) Контроллер DMA для приема данных. Настройки контроллера приведены в таблице.

Параметры компонента sgdma_rx
СтраницаПараметрЗначениеЕдиницы
Transfer options Transfer mode Stream To Memory  
Data and error widths Data width 32  
Data and error widths Source error width 0  
Data and error widths Sink error width 6  
FIFO depth Data transfer FIFO depth 64  

Компонент sgdma_tx (Scatter-Gather DMA Controller Intel FPGA IP) Контроллер DMA для передачи данных. Настройки контроллера приведены в таблице.

Параметры компонента sgdma_tx
СтраницаПараметрЗначениеЕдиницы
Transfer options Transfer mode Memory To Stream  
Data and error widths Data width 32  
Data and error widths Source error width 1  
Data and error widths Sink error width 0  
FIFO depth Data transfer FIFO depth 64  

Компонент descriptor_memory (On-Chip Memory (RAM or ROM) Intel FPGA IP) Контроллер набортной памяти для хранения дескрипторов передаваемых данных. Настройки контроллера приведены в таблице.

Параметры компонента descriptor_memory
СтраницаПараметрЗначениеЕдиницы
Size Slave S1 Data width 8  
Size Total memory size 4096 bytes

В настройках компонентов led и switch нет ни чего интересного. это обычные компоненты ввода/вывода дискретных сигналов.

Компонент timer_0 (Interval Timer Intel FPGA IP) Таймер для создания интервалов времени. Настройки контроллера приведены в таблице.

Параметры компонента timer_0
СтраницаПараметрЗначениеЕдиницы
Timeout period Period 30  
Timeout period Units uS  
Timer counter size Counter Size 32  
Registers No Start/Stop controls bits No  
Registers Fixed period No  
Registers Readeable snapshot Yes  
Output signals System reset on timeout (Watchdog) No  
Output signals Timeout pulse (1 clock wide) No  

Верхний уровень системы:

Verilog Code:
  1. module simplified_tcp( // module and port declaration: fill the gaps
  2.  
  3. input CLOCK_50,
  4.  
  5. // KEY
  6. input [3:0]KEY,
  7. //input KEY , verify if needed.
  8.  
  9. //LED
  10. output [7:0] S1_LED,
  11.  
  12. // Ethernet : the signals used are:
  13. //the RGMII transmit clock,
  14. //the MDC reference,
  15. //the MDIO,
  16. //the hardware reset,
  17. //the RGMII receive clock,
  18. //the receive data,
  19. //the receive data valid,
  20. //the transmit data and
  21. //the transmit enable (check the manual)
  22. output ENET_GTX_CLK,
  23. input ENET_RX_CLK,
  24. output ENET_MDC,
  25. inout ENET_MDIO,
  26. //input ENET_TX_CLK,
  27. output [3:0]ENET_TX_DATA,
  28. output ENET_RST_N,
  29. input [3:0]ENET_RX_DATA,
  30. input ENET_RX_DV,
  31. output ENET_TX_EN,
  32. //sdram memory
  33. inout [7:0]dq,
  34. output [11:0]addr,
  35. output [1:0]ba,
  36. output cas_n,
  37. output dqm,
  38. output ras_n,
  39. output we_n,
  40. output clk_n
  41. );
  42.  
  43. wire sys_clk, clk_125, clk_25, clk_2p5;
  44. wire clk_sdram,clk1_125,clk1_25,clk1_2p5;
  45. wire rx_clk, tx_clk;
  46. wire core_reset_n;
  47. wire mdc, mdio_in, mdio_oen, mdio_out;
  48. wire eth_mode, ena_10;
  49. wire chpScpClk;
  50.  
  51. wire [3:0]ENET_RX_DATA_BUF;
  52.  
  53. assign rx_clk = ENET_RX_CLK;
  54.  
  55. // Assign MDIO and MDC signals
  56. assign mdio_in = ENET_MDIO;
  57. assign ENET_MDC = mdc;
  58. assign ENET_MDIO = mdio_oen ? 1'bz : mdio_out;
  59.  
  60. //Assign reset
  61. assign ENET_RST_N = core_reset_n;
  62.  
  63. //Assign SDRAM CLK
  64. assign clk_n = clk_sdram;
  65.  
  66. //BUF instances
  67. in_buf in_buf_inst (
  68. .datain ( ENET_RX_DATA ),
  69. .dataout ( ENET_RX_DATA_BUF )
  70. );
  71.  
  72. //PLL instances
  73.  
  74. my_pll pll_inst(
  75. .areset (1'b0),
  76. .inclk0 (CLOCK_50),
  77. .c0 (sys_clk),
  78. .c1 (clk_125),
  79. .c2 (clk_25),
  80. .c3 (clk_2p5),
  81. .locked (core_reset_n)
  82. );
  83.  
  84. pll_clock_PHY1 pll_inst1(
  85. .areset (1'b0),
  86. .inclk0 (CLOCK_50),
  87. .c0 (clk_sdram),
  88. .c1 (clk1_125),
  89. .c2 (clk1_25),
  90. .c3 (clk1_2p5)
  91. );
  92.  
  93.  
  94. // Transmission Clock in FPGA (TSE IP core)
  95. //assign tx_clk1 = 5;
  96. assign tx_clk = eth_mode ? clk_125 : ena_10 ? clk_2p5 : clk_25 ; // GbE Mode = 125MHz clock
  97. // ena_10? :
  98. // 10Mb Mode = 2.5MHz clock
  99. // ;
  100. // 100Mb Mode = 25 MHz clock
  101.  
  102. // Clock for transmission in PHY chip
  103. //assign gtx_clk1 = ;
  104. assign ENET_GTX_CLK= eth_mode ? clk1_125 : ena_10 ? clk1_2p5 : clk1_25; // GbE Mode = 125MHz clock
  105. // ena_10? :
  106. // 10Mb Mode = 2.5MHz clock
  107. // ;
  108. // 100Mb Mode = 25 MHz clock
  109.  
  110. // Nios II system instance
  111. nios_system system_inst (
  112. .clk_clk (sys_clk), // system clock (input)
  113. .led_export (S1_LED), // led (output)
  114. .new_sdram_controller_0_wire_addr (addr), // new_sdram_controller_0_wire.addr
  115. .new_sdram_controller_0_wire_ba (ba), // new_sdram_controller_0_wire.ba
  116. .new_sdram_controller_0_wire_cas_n (cas_n), // new_sdram_controller_0_wire.cas_n
  117. .new_sdram_controller_0_wire_cke (), // new_sdram_controller_0_wire.cke
  118. .new_sdram_controller_0_wire_cs_n (), // new_sdram_controller_0_wire.cs_n
  119. .new_sdram_controller_0_wire_dq (dq), // new_sdram_controller_0_wire.dq
  120. .new_sdram_controller_0_wire_dqm (dqm), // new_sdram_controller_0_wire.dqm
  121. .new_sdram_controller_0_wire_ras_n (ras_n), // new_sdram_controller_0_wire.ras_n
  122. .new_sdram_controller_0_wire_we_n (we_n), // new_sdram_controller_0_wire.we_n
  123. .reset_reset_n (core_reset_n), // system reset (input)
  124. .switch_export (KEY), // swicht button (input)
  125. .tse_mac_mdio_connection_mdc (mdc), // mdc (output)
  126. .tse_mac_mdio_connection_mdio_in (mdio_in), // mdio_in (input)
  127. .tse_mac_mdio_connection_mdio_out (mdio_out), // mdio_out (output)
  128. .tse_mac_mdio_connection_mdio_oen (mdio_oen), // mdio_oen (output)
  129. .tse_mac_rgmii_connection_rgmii_in (ENET_RX_DATA_BUF), // rgmii_in (rx data, input)
  130. .tse_mac_rgmii_connection_rgmii_out (ENET_TX_DATA), // gmii_out (tx data, output)
  131. .tse_mac_rgmii_connection_rx_control (ENET_RX_DV), // rx_control (receive data valid, input)
  132. .tse_mac_rgmii_connection_tx_control (ENET_TX_EN), // tx_control (tx enable, output)
  133. .tse_mac_status_connection_set_10 (), // tse_mac_status_connection.set_10
  134. .tse_mac_status_connection_set_1000 (), // set_1000
  135. .tse_mac_status_connection_eth_mode (eth_mode), // eth_mode (output)
  136. .tse_mac_status_connection_ena_10 (ena_10), // ena_10 (output)
  137. .tse_pcs_mac_rx_clock_connection_clk (rx_clk), // receive clock (input)
  138. .tse_pcs_mac_tx_clock_connection_clk (tx_clk) // transmit clock (input)
  139. );
  140. endmodule

Основными частями нашей системы являются:

  • nios_system- созданная нами SOPC. Содержит процессор NIOS, контроллер TSE, каналы DMA, контроллер SDRAM, таймер, устройства ввода/вывода.
  • in_buf- входной буфер для сигналов приемника RGMII.
  • my_pll- синтезатор часты с опорными сигналами для SOPC и режимов 10/100/1000 Мбит/С.
  • pll_clock- синтезатор часты с опорными сигналами для SDRAM памяти и сдвинутых по фазе частот для режимов 10/100/1000 Мбит/С.
  • assign tx_clk- схема выбора частоты для внутренней логики, в зависимости от режима 10/100/1000 Мбит/С.
  • assign ENET_GTX_CLK- схема выбора частоты для вннешней микросхемы PHY, в зависимости от режима 10/100/1000 Мбит/С.

Управляющая программа:

C++ Code:
  1. /*
  2.  * main.c
  3.  
  4.  *
  5.  * Created on: Dec 8, 2016
  6.  * Author: Darshan,Avinash,Aravind
  7.  */
  8. /*** NOTE : please interchange the MAC addresses and PORT numbers on the other board before running the C code in eclipse ***/
  9.  
  10. #include "system.h"
  11. #include
  12. #include
  13. #include
  14. #include //include the sgdma descriptor
  15. #include //include the sgdma registers
  16. #include //include the PIO registers
  17. #include "sys/alt_stdio.h"
  18. #include "sys/alt_irq.h"
  19. #include
  20. #include
  21. #include <sys/alt_cache.h>
  22. #include
  23. #include
  24. #include
  25.  
  26. /********* Initialize variables *****************/
  27. //uint8_t n = 0;
  28. uint8_t loss_count = 0;
  29. uint8_t loss_flag = 0;
  30. int pckt_rxed = 0;
  31. int succ_rxed = 0;
  32. uint8_t flag_syn = 0;
  33. uint8_t retr_count = 0;
  34. int in=0;
  35. uint8_t data_flag;
  36.  
  37. /********** Function Prototypes ******************/
  38. void statistics_counter();
  39. void rx_ethernet_isr (void *context);
  40. void create_pkt();
  41.  
  42. void add_phy_to_profile()
  43. {
  44.  
  45. /* supported PHY definition */
  46.  
  47. /* ------------------------------ */
  48. /* KSZ9031 */
  49. /* ------------------------------ */
  50. enum {
  51. KSZ9031_OUI = 0x10A1,
  52. KSZ9031_MODEL = 0x22,
  53. KSZ9031_REV = 0x02
  54. };
  55.  
  56. alt_tse_phy_profile KSZ9031 = {
  57. "KSZ9031", /* Micrel KSZ9031 */
  58. KSZ9031_OUI, /* OUI */
  59. KSZ9031_MODEL, /* Vender Model Number */
  60. KSZ9031_REV, /* Model Revision Number */
  61. 0x1F, /* Location of Status Register */
  62. 5, /* Location of Speed Status */
  63. 3, /* Location of Duplex Status */
  64. 0 /* Location of Link Status */
  65. /*&KSZ9031_phy_cfg,*/ /* function pointer to configure Micrel KSZ9031 */
  66. /*&KSZ9031_link_status_read*/ /* Function pointer to read from PHY specific status register */
  67. };
  68.  
  69. /* add supported PHY to profile */
  70. alt_tse_phy_add_profile(&KSZ9031);
  71. }
  72.  
  73. /*********** STRUCTS *******************************/
  74. struct tcp_conn {
  75. uint8_t link;
  76. unsigned char dest_mac[6];
  77. unsigned char source_mac[6];
  78. unsigned short source_port ;
  79. unsigned short dest_port;
  80. unsigned short ack_num;
  81. unsigned short seq_num;
  82. };
  83.  
  84. /*********** Create a receive frame ****************/
  85. unsigned char rx_frame[1518] = { 0 };
  86. unsigned char tx_frame[1518] = { 0 };
  87.  
  88. /************* Create sgdma transmit and receive devices **************/
  89.  
  90. alt_sgdma_dev * sgdma_tx_dev;
  91. alt_sgdma_dev * sgdma_rx_dev;
  92.  
  93. /************** Allocate descriptors in the descriptor_memory (onchip memory) *************/
  94. alt_sgdma_descriptor tx_descriptor __attribute__ (( section ( ".descriptor_memory" )));
  95. alt_sgdma_descriptor tx_descriptor_end __attribute__ (( section ( ".descriptor_memory" )));
  96.  
  97. alt_sgdma_descriptor rx_descriptor __attribute__ (( section ( ".descriptor_memory" )));
  98. alt_sgdma_descriptor rx_descriptor_end __attribute__ (( section ( ".descriptor_memory" )));
  99.  
  100. /************* Tcp connection structures *********************/
  101.  
  102. struct tcp_conn TCP[2];
  103.  
  104. /********************* Triple-sp **********************************************/
  105. volatile int *tse = (int *)TSE_BASE;
  106.  
  107. /******* MAIN BLOCK STARTS HERE ********************************/
  108.  
  109. int main(void){
  110. loss_flag=0;
  111. loss_count=0;
  112.  
  113. /**** Initializing timer status and control values *************/
  114. IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 0x0000);
  115. IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0x0000);
  116.  
  117. /****** copying TCP header values to structure ****************************/
  118. memmove(&TCP[0].dest_mac,"\x60\xe3\x27\x04\xd5\xe2",6);
  119. memmove(&TCP[0].source_mac,"\x60\xe3\x27\x04\xd5\xe3",6);
  120. memmove(&TCP[0].source_port, "\x00\x10", 2);
  121. memmove(&TCP[0].dest_port, "\x00\x20", 2);
  122. memmove(&TCP[0].seq_num, "\x00\x00", 2);
  123. memmove(&TCP[0].ack_num, "\x00\x00", 2);
  124. data_flag = 0;
  125.  
  126. /*********** Open the sgdma transmit device ********************/
  127. sgdma_tx_dev = alt_avalon_sgdma_open ("/dev/sgdma_tx");
  128. if (sgdma_tx_dev == NULL) {
  129. alt_printf ("Error: could not open scatter-gather dma transmit device\n");
  130. //return -1;
  131. } else alt_printf ("Opened scatter-gather dma transmit device\n");
  132.  
  133. /*********** Open the sgdma receive device *************************/
  134. sgdma_rx_dev = alt_avalon_sgdma_open ("/dev/sgdma_rx");
  135. if (sgdma_rx_dev == NULL) {
  136. alt_printf ("Error: could not open scatter-gather dma receive device\n");
  137. //return -1;
  138. } else alt_printf ("Opened scatter-gather dma receive device\n");
  139.  
  140. /**************** Set interrupts for the sgdma receive device , Create sgdma receive descriptor &
  141. Set up non-blocking transfer of sgdma receive descriptor **********/
  142. alt_avalon_sgdma_register_callback( sgdma_rx_dev, (alt_avalon_sgdma_callback) rx_ethernet_isr, 0x00000014, NULL );
  143. alt_avalon_sgdma_construct_stream_to_mem_desc( &rx_descriptor, &rx_descriptor_end, (alt_u32 *)rx_frame, 0, 0 );
  144. alt_avalon_sgdma_do_async_transfer( sgdma_rx_dev, &rx_descriptor );
  145.  
  146. add_phy_to_profile();
  147.  
  148. // Specify the addresses of the PHY devices to be accessed through MDIO interface
  149. *(tse + 0x0F) = 0x00;
  150.  
  151. // Read PHY registers by MDIO interface
  152. int regPhy[31];
  153. for(unsigned char i=0;i<32;i++)
  154. {
  155. regPhy[i]=*(tse + 0x80 + i);
  156. alt_printf("PHY %x : %x \n",i,regPhy[i]);
  157. }
  158.  
  159. int phyid1 = regPhy[2];
  160. int phyid2 = regPhy[3];
  161.  
  162. printf ("Phy found:id1 %x, id2 %x\n", phyid1, phyid2);
  163. /************ Disable read and write transfers and wait**************************/
  164. *(tse + 0x02 ) = *(tse + 0x02) | 0x00800220;
  165. while ( *(tse + 0x02 ) != ( *(tse + 0x02 ) | 0x00800220 )) alt_printf("n0");
  166.  
  167. /****************MAC FIFO Configuration*****************************************/
  168. *(tse + 0x09) = TSE_TRANSMIT_FIFO_DEPTH-16;
  169. *(tse + 0x0E) = 3;
  170. *(tse + 0x0D) = 8;
  171. *(tse + 0x07) =TSE_RECEIVE_FIFO_DEPTH-16;
  172. *(tse + 0x0C) = 8;
  173. *(tse + 0x0B) = 8;
  174. *(tse + 0x0A) = 0;
  175. *(tse + 0x08) = 0;
  176.  
  177. /***************** Initialize the MAC address************************************/
  178. *(tse + 0x03 ) = 0x0427E360; //mac_0
  179. *(tse + 0x04) = 0x0000E3D5; //mac_1
  180. /****************** MAC function configuration**********************************/
  181. *(tse + 0x05) = 1518 ;
  182. *(tse + 0x17) = 12;
  183. *(tse + 0x06 ) = 0xFFFF;
  184. *(tse + 0x02 ) = 0x00800220; //command config
  185.  
  186. /*************** Software reset the PHY chip and wait***************************/
  187. *(tse + 0x02 ) = 0x00802220;
  188. while ( *(tse + 0x02 ) != ( 0x00800220 ) ) alt_printf("n1");
  189.  
  190. /*** Enable read and write transfers, gigabit Ethernet operation and promiscuous mode*/
  191.  
  192. *(tse + 0x02 ) = *(tse + 0x02 ) | 0x0080023B;
  193. while ( *(tse + 0x02 ) != ( *(tse + 0x02) | 0x0080023B ) ) alt_printf("n2") ;
  194.  
  195.  
  196. uint8_t data = 0x00;
  197. uint8_t flag_a = 0;
  198. int delay = 0;
  199. int n; //variable to read timer status
  200.  
  201. //MMD register access example
  202. //Write MMD - Device Address 2h, Register 10h = 0001h to enable link-up detection to trigger PME for WOL.
  203. //1. Write Register Dh with 0002h // Set up register address for MMD – Device Address 2h.
  204. //2. Write Register Eh with 0010h // Select Register 10h of MMD – Device Address 2h.
  205. //3. Write Register Dh with 4002h // Select register data for MMD – Device Address 2h, Register 10h.
  206. //4. Write Register Eh with 0001h // Write value 0001h to MMD – Device Address 2h, Register 10h.
  207. *(tse + 0x80 + 0x0D)=0x0002;
  208. *(tse + 0x80 + 0x0E)=0x0008;
  209. *(tse + 0x80 + 0x0D)=0x4002;
  210. *(tse + 0x80 + 0x0E)=0x01EF;
  211. //Read MMD - Device Address 2h, Register 11h – 13h for the magic packet’s MAC address.
  212. //1. Write Register Dh with 0002h // Set up register address for MMD – Device Address 2h.
  213. //2. Write Register Eh with 0011h // Select Register 11h of MMD – Device Address 2h.
  214. //3. Write Register Dh with 8002h // Select register data for MMD – Device Address 2h, Register 11h.
  215. //4. Read Register Eh // Read data in MMD – Device Address 2h, Register 11h.
  216. //5. Read Register Eh // Read data in MMD – Device Address 2h, Register 12h.
  217. //6. Read Register Eh // Read data in MMD – Device Address 2h, Register 13h.
  218. *(tse + 0x80 + 0x0D)=0x0002;
  219. *(tse + 0x80 + 0x0E)=0x0008;
  220. *(tse + 0x80 + 0x0D)=0x8002;
  221. int txRxDelay=*(tse + 0x80 + 0x0E);
  222. alt_printf("Tx Rx delay %x \n",txRxDelay);
  223.  
  224. /********** Infinite Loop ******************************/
  225. while (1) {
  226. in = IORD_ALTERA_AVALON_PIO_DATA(SWITCH_BASE); //read the input from the switch
  227.  
  228. /**** Check if 3 way handshake already established *********************/
  229. if((TCP[0].link == 1) && (flag_syn == 0) && (in & 0x01)==1){
  230. flag_syn = 1;
  231. alt_printf("\nConnection already established, send data");
  232. }
  233.  
  234. if ((in & 0x01)== 1){// Syn if switch 1 is on
  235. //IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,0x01); //switch on or switch off the LED
  236. if(flag_syn == 0){
  237. flag_syn = 1; //setting flag bit to send only 1 syn packet when switch is ON
  238. flag_a = 1;
  239.  
  240. /******** Creating and Sending SYN packet******************************/
  241. /** SYN = 1 , SYN-ACK = 5 , ACK = 4 , FIN = 2 , FIN-ACK = 6
  242.   **** DATA = 8 , DATA ACK = 0X0C*****************************************/
  243. create_pkt();
  244. memmove(tx_frame+24, "\x01", 1);
  245. alt_printf(" timer started for SYN, status is : %x",IORD_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE));
  246.  
  247. /***** Transmitting the packet ***************************************/
  248. alt_printf("\nSYN TX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",
  249. tx_frame[2],tx_frame[3],tx_frame[4],tx_frame[5],tx_frame[6],tx_frame[7],tx_frame[8],
  250. tx_frame[9],tx_frame[10],tx_frame[11],tx_frame[12],tx_frame[13],tx_frame[14],tx_frame[15],
  251. tx_frame[16],tx_frame[17],tx_frame[18],tx_frame[19],tx_frame[20],tx_frame[21],tx_frame[22],
  252. tx_frame[23],tx_frame[24],tx_frame[25]);
  253. alt_dcache_flush_all();
  254. alt_avalon_sgdma_construct_mem_to_stream_desc(&tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 64, 0, 1, 1, 0);
  255. alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
  256. while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0);
  257.  
  258. /********** Starting Timer for SYN packet *************************************/
  259.  
  260. IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0x0002);
  261. IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE , 0xFFFF);
  262. IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE , 0xFFFF);
  263. IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 0x0007);
  264. /********** increment sequence number **************************************/
  265. TCP[0].seq_num++;
  266. }
  267. }
  268.  
  269. /****** Condition for sending FIN Packet when key 1 is OFF **********************************/
  270.  
  271. else if((flag_a == 1 )&& (in & 0x01) == 0){
  272. data_flag = 0;
  273. flag_syn = 0;
  274. flag_a=0;
  275. /******** Sending Fin packet ***************************************************/;
  276.  
  277. create_pkt();
  278. memcpy(tx_frame+24, "\x02", 1);
  279. alt_printf("\nFIN TX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",
  280. tx_frame[2],tx_frame[3],tx_frame[4],tx_frame[5],tx_frame[6],tx_frame[7],tx_frame[8],
  281. tx_frame[9],tx_frame[10],tx_frame[11],tx_frame[12],tx_frame[13],tx_frame[14],tx_frame[15],
  282. tx_frame[16],tx_frame[17],tx_frame[18],tx_frame[19],tx_frame[20],tx_frame[21],tx_frame[22],
  283. tx_frame[23],tx_frame[24],tx_frame[25]);
  284. alt_dcache_flush_all();
  285. alt_avalon_sgdma_construct_mem_to_stream_desc(&tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 64, 0, 1, 1, 0);
  286. alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
  287. while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0);
  288.  
  289. /************ Starting Timer for FIN Packet *******************************/
  290. IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0x0002);
  291. IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE , 0xAAAA);
  292. IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE , 0xFFFF);
  293. IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 0x0007);
  294. TCP[0].seq_num++;
  295. }
  296.  
  297. /********* condition to check DATA transmission if key 2 are ON *************/
  298. if((in & 0x02) == 0x00){
  299. delay++;
  300. /***** setting delay to display LED blinking *******************************/
  301. if(data_flag == 1 && delay == 1000000){
  302. delay = 0;
  303. data_flag = 0;
  304. create_pkt();
  305. data++;
  306. memcpy(tx_frame+24, "\x08",1);
  307. memcpy(tx_frame+25, &data, 1);
  308. alt_printf("\n DATA TX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
  309. tx_frame[2],tx_frame[3],tx_frame[4],tx_frame[5],tx_frame[6],tx_frame[7],tx_frame[8],
  310. tx_frame[9],tx_frame[10],tx_frame[11],tx_frame[12],tx_frame[13],tx_frame[14],tx_frame[15],
  311. tx_frame[16],tx_frame[17],tx_frame[18],tx_frame[19],tx_frame[20],tx_frame[21],tx_frame[22],
  312. tx_frame[23],tx_frame[24],tx_frame[25],tx_frame[26]);
  313. alt_dcache_flush_all();
  314. alt_avalon_sgdma_construct_mem_to_stream_desc(&tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 64, 0, 1, 1, 0);
  315. alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
  316. while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0);
  317.  
  318. /*** Starting Timer for DATA transmission ****************************************/
  319.  
  320. IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0x0002);
  321. IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE , 0xAAAA);
  322. IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE , 0x002F);
  323. IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 0x0007);
  324. TCP[0].seq_num++;
  325. }
  326. if (delay > 1000000){
  327. delay=0;
  328. }
  329. }
  330.  
  331. /******* Condition to check for re transmission *************************************/
  332. /*** Stop Retransmitting and exit if retransmit count reaches 50 (actual ethernet exits after count 16) ********************/
  333. n = IORD_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE);
  334. if(n == 3){
  335. retr_count++;
  336. if(retr_count>=50){
  337. retr_count = 0;
  338. alt_printf("\n retransmission limit exceeded, DISCONNECTED!!!");
  339. break;
  340. }
  341. /*** Stopping Timer if already running and starting timer for Data transmission ******************************************/
  342. IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 0x0008);
  343. IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0x0002);
  344.  
  345. //Transmit Function
  346. alt_printf("\n RE TX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",
  347. tx_frame[2],tx_frame[3],tx_frame[4],tx_frame[5],tx_frame[6],tx_frame[7],tx_frame[8],
  348. tx_frame[9],tx_frame[10],tx_frame[11],tx_frame[12],tx_frame[13],tx_frame[14],tx_frame[15],
  349. tx_frame[16],tx_frame[17],tx_frame[18],tx_frame[19],tx_frame[20],tx_frame[21],tx_frame[22],
  350. tx_frame[23],tx_frame[24],tx_frame[25]);
  351. alt_dcache_flush_all();
  352. alt_avalon_sgdma_construct_mem_to_stream_desc(&tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 64, 0, 1, 1, 0);
  353. alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
  354. while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0);
  355.  
  356. /************************ start timer******************************************/
  357. IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE , 0xAAAA);
  358. IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE , 0x02FF);
  359. IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 0x0007);
  360. alt_printf("\nRetx timer started for SYN, status:%d count:%d,",IORD_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE));
  361.  
  362. }
  363. }
  364. return 0;
  365. }
  366.  
  367. /****************************************************************************************
  368.  * Subroutine to read incoming Ethernet frames
  369. ****************************************************************************************/
  370. void rx_ethernet_isr (void *context)
  371. {
  372. retr_count = 0;
  373. pckt_rxed++;
  374. in = IORD_ALTERA_AVALON_PIO_DATA(SWITCH_BASE); //read the input from the switch
  375.  
  376. /***** If key 3 is ON drop receiving packets ***************************************/
  377.  
  378. if((in & 0x04) == 0x00){
  379. while (alt_avalon_sgdma_check_descriptor_status(&rx_descriptor) != 0);
  380. // Create new receive sgdma descriptor
  381. alt_avalon_sgdma_construct_stream_to_mem_desc( &rx_descriptor, &rx_descriptor_end, (alt_u32 *)rx_frame, 0, 0 );
  382. // Set up non-blocking transfer of sgdma receive descriptor
  383. alt_avalon_sgdma_do_async_transfer( sgdma_rx_dev, &rx_descriptor );
  384. return;
  385. }
  386. int sucessFrm;
  387. int crcErrorFrm;
  388. sucessFrm=*(tse+0x1B);
  389. crcErrorFrm=*(tse+0x1C);
  390. alt_printf("\nRX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
  391. rx_frame[2],rx_frame[3],rx_frame[4],rx_frame[5],rx_frame[6],rx_frame[7],rx_frame[8],
  392. rx_frame[9],rx_frame[10],rx_frame[11],rx_frame[12],rx_frame[13],rx_frame[14],rx_frame[15],
  393. rx_frame[16],rx_frame[17],rx_frame[18],rx_frame[19],rx_frame[20],rx_frame[21],rx_frame[22],
  394. rx_frame[23],rx_frame[24],rx_frame[25],rx_frame[26]);
  395. alt_printf("Number of successful frames:%x\n",sucessFrm);
  396. alt_printf("The number of receive frames with CRC error:%x\n",crcErrorFrm);
  397. alt_dcache_flush_all();
  398.  
  399. IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 0x0008);
  400. IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0x0000);
  401.  
  402. succ_rxed++; // successfully received frame incrementing upon reception
  403. /**** check if SYN frame is received *********************************************/
  404. if ( rx_frame [24] == 0x01) {
  405. TCP[0].link = 1;
  406.  
  407. /******* Sending SYN-ACK Frame ***************************************/
  408.  
  409. TCP[0].ack_num++;
  410. create_pkt();
  411. memmove(tx_frame+24,"\x05",1);//Setting syn-ack
  412.  
  413. //transmit_packet();
  414. alt_printf("\n SYN/ACK TX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",
  415. tx_frame[2],tx_frame[3],tx_frame[4],tx_frame[5],tx_frame[6],tx_frame[7],tx_frame[8],
  416. tx_frame[9],tx_frame[10],tx_frame[11],tx_frame[12],tx_frame[13],tx_frame[14],tx_frame[15],
  417. tx_frame[16],tx_frame[17],tx_frame[18],tx_frame[19],tx_frame[20],tx_frame[21],tx_frame[22],
  418. tx_frame[23],tx_frame[24],tx_frame[25]);
  419. alt_dcache_flush_all();
  420. alt_avalon_sgdma_construct_mem_to_stream_desc(&tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 64, 0, 1, 1, 0);
  421. alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
  422. while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0);
  423. TCP[0].seq_num++;
  424. }
  425.  
  426. /******************** Syn-Ack recieved *************************************************/
  427. else if((rx_frame[24]) == 0x05){
  428. TCP[0].link = 1;
  429.  
  430. /**************** Send ACknowledgement ************************************************/
  431. TCP[0].ack_num++;
  432. create_pkt();
  433. memmove(tx_frame+24,"\x04",1);//setting ack
  434.  
  435. //transmit_packet();
  436. alt_printf("\n Conn Est Ack TX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",
  437. tx_frame[2],tx_frame[3],tx_frame[4],tx_frame[5],tx_frame[6],tx_frame[7],tx_frame[8],
  438. tx_frame[9],tx_frame[10],tx_frame[11],tx_frame[12],tx_frame[13],tx_frame[14],tx_frame[15],
  439. tx_frame[16],tx_frame[17],tx_frame[18],tx_frame[19],tx_frame[20],tx_frame[21],tx_frame[22],
  440. tx_frame[23],tx_frame[24],tx_frame[25]);
  441. alt_dcache_flush_all();
  442. alt_avalon_sgdma_construct_mem_to_stream_desc(&tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 64, 0, 1, 1, 0);
  443. alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
  444. while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0);
  445.  
  446. data_flag = 1;
  447. TCP[0].seq_num++;
  448. }
  449.  
  450. /***************** FIN Recieved *************************************************/
  451. else if((rx_frame[24]) == 0x02){
  452. TCP[0].link = 0;
  453. data_flag = 0;
  454. /***************** Sending FIN-ACK **********************************************/
  455. TCP[0].ack_num++;
  456. create_pkt();
  457. memmove(tx_frame+24,"\x06",1);
  458.  
  459. //transmit_packet();
  460. alt_printf("\n FIN/ACK TX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",
  461. tx_frame[2],tx_frame[3],tx_frame[4],tx_frame[5],tx_frame[6],tx_frame[7],tx_frame[8],
  462. tx_frame[9],tx_frame[10],tx_frame[11],tx_frame[12],tx_frame[13],tx_frame[14],tx_frame[15],
  463. tx_frame[16],tx_frame[17],tx_frame[18],tx_frame[19],tx_frame[20],tx_frame[21],tx_frame[22],
  464. tx_frame[23],tx_frame[24],tx_frame[25]);
  465. alt_dcache_flush_all();
  466. alt_avalon_sgdma_construct_mem_to_stream_desc(&tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 64, 0, 1, 1, 0);
  467. alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
  468. while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0);
  469. TCP[0].seq_num++;
  470. }
  471.  
  472. /***************** Fin-Ack received **************************************************************/
  473.  
  474. else if(rx_frame[24] == 0x06){
  475. TCP[0].link = 0;
  476. //ack_send();
  477. TCP[0].ack_num++;
  478. create_pkt();
  479. memmove(tx_frame+24,"\x04",1);//setting ack
  480.  
  481. //transmit_packet();
  482. alt_printf("\n Conn Closed ACK TX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",
  483. tx_frame[2],tx_frame[3],tx_frame[4],tx_frame[5],tx_frame[6],tx_frame[7],tx_frame[8],
  484. tx_frame[9],tx_frame[10],tx_frame[11],tx_frame[12],tx_frame[13],tx_frame[14],tx_frame[15],
  485. tx_frame[16],tx_frame[17],tx_frame[18],tx_frame[19],tx_frame[20],tx_frame[21],tx_frame[22],
  486. tx_frame[23],tx_frame[24],tx_frame[25]);
  487. alt_dcache_flush_all();
  488. alt_avalon_sgdma_construct_mem_to_stream_desc(&tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 64, 0, 1, 1, 0);
  489. alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
  490. while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0);
  491. printf("\n Connection closed");
  492. printf("\n********************* Statistics - TCP **********************");
  493. printf("\nRxed Packets : %x",pckt_rxed);
  494. printf("\nSuccessfull Packets Rxed : %x",succ_rxed);
  495. printf("\nDropped Packets : %x",(pckt_rxed - succ_rxed));
  496. statistics_counter();
  497.  
  498. TCP[0].seq_num++;
  499. }
  500.  
  501. /***************** ACK Received *******************************************************/
  502. else if(rx_frame[24] == 0x04){
  503. //ack();
  504. if(TCP[0].link == 1){
  505. alt_printf("\n Connection establishment ack received");
  506. data_flag = 1;
  507. TCP[0].ack_num++;
  508. }
  509. else {
  510.  
  511. /***************** PRINT TCP STATISTICS ***********************************************/
  512. alt_printf("\n Connection closed");
  513. alt_printf("\n********************* Statistics - TCP **********************");
  514. alt_printf("\nRxed Packets : %x",pckt_rxed);
  515. alt_printf("\nSuccessfull Packets Rxed : %x",succ_rxed);
  516. alt_printf("\nDropped Packets : %x",(pckt_rxed - succ_rxed));
  517.  
  518. /********** Calling function for printing Ethernet statistics ***************************/
  519. statistics_counter();
  520. TCP[0].ack_num++;
  521. }
  522. }
  523.  
  524. /******************Data pkt received and sent to LED's**********/
  525. else if(rx_frame[24] == 0x08){
  526. TCP[0].ack_num++;
  527. IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,rx_frame[25]);
  528. create_pkt();
  529. memmove(tx_frame+24,"\x0C",1);
  530. alt_printf("\n DATA ACK TX_FRAME: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",
  531. tx_frame[2],tx_frame[3],tx_frame[4],tx_frame[5],tx_frame[6],tx_frame[7],tx_frame[8],
  532. tx_frame[9],tx_frame[10],tx_frame[11],tx_frame[12],tx_frame[13],tx_frame[14],tx_frame[15],
  533. tx_frame[16],tx_frame[17],tx_frame[18],tx_frame[19],tx_frame[20],tx_frame[21],tx_frame[22],
  534. tx_frame[23],tx_frame[24],tx_frame[25],tx_frame[26]);
  535. alt_dcache_flush_all();
  536. alt_avalon_sgdma_construct_mem_to_stream_desc(&tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, 64, 0, 1, 1, 0);
  537. alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
  538. while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0);
  539. TCP[0].seq_num++;
  540. }
  541. /********************* DATA ACKNOWLEDGEMENT RECEIVED***********************************/
  542. else if(rx_frame[24] == 0x0C){
  543. TCP[0].ack_num++;
  544. alt_printf("\n Data ACK received");
  545. data_flag = 1;
  546. }
  547.  
  548. // Wait until receive descriptor transfer is complete
  549. while (alt_avalon_sgdma_check_descriptor_status(&rx_descriptor) != 0);
  550. // Create new receive sgdma descriptor
  551. alt_avalon_sgdma_construct_stream_to_mem_desc( &rx_descriptor, &rx_descriptor_end, (alt_u32 *)rx_frame, 0, 0 );
  552. // Set up non-blocking transfer of sgdma receive descriptor
  553. alt_avalon_sgdma_do_async_transfer( sgdma_rx_dev, &rx_descriptor );
  554.  
  555.  
  556. }
  557.  
  558. /********* Function for Creating Packet before transmission ***********************/
  559. void create_pkt(){
  560. memset(tx_frame+26,0,37);
  561. memcpy(tx_frame+20, &TCP[0].seq_num, 2);
  562. memcpy(tx_frame+22, &TCP[0].ack_num, 2);
  563. memcpy(tx_frame+24, "\x00", 1);
  564. memmove(tx_frame, "\x00\x00",2);
  565. memmove(tx_frame+2, &TCP[0].dest_mac,6);
  566. memmove(tx_frame+8, &TCP[0].source_mac,6);
  567. memmove(tx_frame+14, "\x2E\x00", 2);
  568. memmove(tx_frame+16, &TCP[0].source_port, 2);
  569. memmove(tx_frame+18, &TCP[0].dest_port, 2);
  570. }
  571.  
  572. /******* Printing Ethernet Statistics *********************************************/
  573. void statistics_counter(){
  574. volatile int *tse = (int *)TSE_BASE;
  575. alt_printf("\n********************* Statistics - Ethernet **********************");
  576. alt_printf("\nnum frames successfully received: %x ", *(tse + 0x1B));
  577. alt_printf("\nnum error frames received: %x ", *(tse + 0x22));
  578. alt_printf("\nnum frames correctly received: %x ", *(tse + 0x1B) - *(tse + 0x22));
  579. alt_printf("\n******************************************************************");
  580. }
  581.  
  582.  

В программе происходит создание дескрипторов для передачи пакетов, инициализация MAC уровня, чтение и запись регистров с помощью интерфейса MDIO, настройка таймера и прерываний ну и собствено реализация отправки и приема пакетов.

Ну и по традиции видео работы, и исходники:

Проект: 1gb_nios_ii_tcp