赞
踩
前文链接:FPGA - 以太网UDP通信(一)
在以上文章中介绍了以太网简介,以太网UDP通信硬件结构,以及PHY芯片RGMII接口-GMII接口转换逻辑,以及数据链路层(MAC层)接受发送逻辑,IP层接受发送逻辑,UDP层接收发送逻辑,接下来完成以太网UDP通信的顶层设计。
在之前文章中已经介绍了UDP通信结构框图,如下:
在之前文章中,我们已经完成了物理层(RGMII接口-GMII接口转换逻辑),数据链路层(MAC层接受发送逻辑),网络层(IP层接受发送逻辑),传输层(UDP层接受发送逻辑)。接下来将各层连接起来完成以太网UDP通信的顶层设计。
首先,我们将mac_layer,ip_layer,udp_layer例化udp_protocol_stack:
- `timescale 1ns / 1ps
-
- module udp_protocol_stack #(
- parameter LOCAL_MAC_ADDR = 48'hffffff_ffffff ,
- parameter TARGET_MAC_ADDR = 48'hffffff_ffffff ,
- parameter LOCAL_IP_ADDR = 32'h0 ,
- parameter TARGET_IP_ADDR = 32'h0 ,
- parameter LOCAL_PORT = 16'h0 ,
- parameter TARGET_PORT = 16'h0
-
- )(
- input phy_tx_clk ,
- input phy_rx_clk ,
- input reset ,
-
- /* ------------GMII接口信号--------------------------*/
- input gmii_rx_data_vld ,
- input [7:0] gmii_rx_data ,
- output gmii_tx_data_vld ,
- output [7:0] gmii_tx_data ,
-
- /* ------------用户接送端信号--------------------------*/
- input app_rx_clk ,
- output app_rx_data_vld ,
- output app_rx_data_last ,
- output [7:0] app_rx_data ,
- output [15:0] app_rx_length ,
-
- /*--------------用户发送端信号--------------------------*/
- input app_tx_clk ,
- input app_tx_data_vld ,
- input app_tx_data_last ,
- input [7:0] app_tx_data ,
- input [15:0] app_tx_length ,
- output app_tx_ready
-
- );
-
-
- wire app_tx_req ;
-
- wire mac_rx_data_vld ;
- wire mac_rx_data_last ;
- wire [7:0] mac_rx_data ;
- wire [15:0] mac_rx_frame_type ;
- wire mac_tx_data_vld ;
- wire mac_tx_data_last ;
- wire [7:0] mac_tx_data ;
- wire [15:0] mac_tx_frame_type ;
- wire [15:0] mac_tx_length ;
-
- wire ip_rx_data_vld ;
- wire ip_rx_data_last ;
- wire [7:0] ip_rx_data ;
- wire ip_tx_data_vld ;
- wire ip_tx_data_last ;
- wire [15:0] ip_tx_length ;
- wire [7:0 ] ip_tx_data ;
-
- wire udp_rx_data_vld ;
- wire udp_rx_data_last ;
- wire [7:0] udp_rx_data ;
- wire [15:0] udp_rx_length ;
- wire udp_tx_data_vld ;
- wire udp_tx_data_last ;
- wire [7:0] udp_tx_data ;
- wire [15:0] udp_tx_length ;
-
- wire icmp_rx_data_vld ;
- wire icmp_rx_data_last ;
- wire [7:0] icmp_rx_data ;
- wire [15:0] icmp_rx_length ;
-
- wire arp_rx_data_vld ;
- wire arp_rx_data_last ;
- wire [7:0] arp_rx_data ;
-
- /*---------------------------------------------------*\
- 复位信号处理
- \*---------------------------------------------------*/
- reg [19:0] phy_rx_reset_timer;
- reg phy_rx_reset_d0;
- reg phy_rx_reset_d1;
- reg phy_rx_reset ;
-
- always @(posedge phy_rx_clk or posedge reset) begin
- if (reset)
- phy_rx_reset_timer <= 0;
- else if (phy_rx_reset_timer <= 20'h000ff)
- phy_rx_reset_timer <= phy_rx_reset_timer + 1;
- else
- phy_rx_reset_timer <= phy_rx_reset_timer;
- end
-
- always @(posedge phy_rx_clk or posedge reset) begin
- if (reset) begin
- phy_rx_reset_d0 <= 1'b1;
- phy_rx_reset_d1 <= 1'b1;
- phy_rx_reset <= 1'b1;
- end
- else begin
- phy_rx_reset_d0 <= phy_rx_reset_timer <= 20'h000ff;
- phy_rx_reset_d1 <= phy_rx_reset_d0;
- phy_rx_reset <= phy_rx_reset_d1;
- end
- end
-
- //---------------------------------------------------------------------------
- reg [19:0] phy_tx_reset_timer;
- reg phy_tx_reset_d0;
- reg phy_tx_reset_d1;
- reg phy_tx_reset ;
- always @(posedge phy_tx_clk or posedge reset) begin
- if (reset)
- phy_tx_reset_timer <= 0;
- else if (phy_tx_reset_timer <= 20'h000ff)
- phy_tx_reset_timer <= phy_tx_reset_timer + 1;
- else
- phy_tx_reset_timer <= phy_tx_reset_timer;
- end
-
- always @(posedge phy_tx_clk or posedge reset) begin
- if (reset) begin
- phy_tx_reset_d0 <= 1'b1;
- phy_tx_reset_d1 <= 1'b1;
- phy_tx_reset <= 1'b1;
- end
- else begin
- phy_tx_reset_d0 <= phy_tx_reset_timer <= 20'h000ff;
- phy_tx_reset_d1 <= phy_tx_reset_d0;
- phy_tx_reset <= phy_tx_reset_d1;
- end
- end
-
- //---------------------------------------------------------------------------
- reg [19:0] app_tx_reset_timer;
- reg app_tx_reset_d0;
- reg app_tx_reset_d1;
- reg app_tx_reset ;
-
- always @(posedge app_tx_clk or posedge reset) begin
- if (reset)
- app_tx_reset_timer <= 0;
- else if (app_tx_reset_timer <= 20'h000ff)
- app_tx_reset_timer <= app_tx_reset_timer + 1;
- else
- app_tx_reset_timer <= app_tx_reset_timer;
- end
-
- always @(posedge app_tx_clk or posedge reset) begin
- if (reset) begin
- app_tx_reset_d0 <= 1'b1;
- app_tx_reset_d1 <= 1'b1;
- app_tx_reset <= 1'b1;
- end
- else begin
- app_tx_reset_d0 <= app_tx_reset_timer <= 20'h000ff;
- app_tx_reset_d1 <= app_tx_reset_d0;
- app_tx_reset <= app_tx_reset_d1;
- end
- end
- //---------------------------------------------------------------------------
- reg [19:0] app_rx_reset_timer;
- reg app_rx_reset_d0;
- reg app_rx_reset_d1;
- reg app_rx_reset ;
- always @(posedge app_rx_clk or posedge reset) begin
- if (reset)
- app_rx_reset_timer <= 0;
- else if (app_rx_reset_timer <= 20'h000ff)
- app_rx_reset_timer <= app_rx_reset_timer + 1;
- else
- app_rx_reset_timer <= app_rx_reset_timer;
- end
-
- always @(posedge app_rx_clk or posedge reset) begin
- if (reset) begin
- app_rx_reset_d0 <= 1'b1;
- app_rx_reset_d1 <= 1'b1;
- app_rx_reset <= 1'b1;
- end
- else begin
- app_rx_reset_d0 <= app_rx_reset_timer <= 20'h000ff;
- app_rx_reset_d1 <= app_rx_reset_d0;
- app_rx_reset <= app_rx_reset_d1;
- end
- end
-
- /*---------------------------------------------------*\
- 模块例化
- \*---------------------------------------------------*/
- mac_layer #(
- .LOCAL_MAC_ADDR(LOCAL_MAC_ADDR),
- .TARGET_MAC_ADDR(TARGET_MAC_ADDR),
- .CRC_CHACK_EN(1)
- ) mac_layer (
- .app_tx_clk (app_tx_clk),
- .app_rx_clk (app_rx_clk),
- .phy_tx_clk (phy_tx_clk),
- .phy_rx_clk (phy_rx_clk),
-
- .app_tx_reset (app_tx_reset),
- .app_rx_reset (app_rx_reset),
- .phy_tx_reset (phy_tx_reset),
- .phy_rx_reset (phy_rx_reset),
-
- .gmii_rx_data_vld (gmii_rx_data_vld),
- .gmii_rx_data (gmii_rx_data),
- .gmii_tx_data_vld (gmii_tx_data_vld),
- .gmii_tx_data (gmii_tx_data),
-
- .mac_rx_data_vld (mac_rx_data_vld),
- .mac_rx_data_last (mac_rx_data_last),
- .mac_rx_data (mac_rx_data),
- .mac_rx_frame_type (mac_rx_frame_type),
-
- .mac_tx_data_vld (ip_tx_data_vld),
- .mac_tx_data_last (ip_tx_data_last),
- .mac_tx_data (ip_tx_data),
- .mac_tx_frame_type (16'h0800 ), //ip层
- .mac_tx_length (ip_tx_length)
- );
- mac_to_ip_arp mac_to_ip_arp
- (
- .clk (app_rx_clk),
- .reset (app_rx_reset),
- .mac_rx_data_vld (mac_rx_data_vld),
- .mac_rx_data_last (mac_rx_data_last),
- .mac_rx_data (mac_rx_data),
- .mac_rx_frame_type (mac_rx_frame_type),
- .ip_rx_data_vld (ip_rx_data_vld),
- .ip_rx_data_last (ip_rx_data_last),
- .ip_rx_data (ip_rx_data),
- .arp_rx_data_vld (arp_rx_data_vld),
- .arp_rx_data_last (arp_rx_data_last),
- .arp_rx_data (arp_rx_data)
- );
- ip_layer #(
- .LOCAL_IP_ADDR(LOCAL_IP_ADDR),
- .TARGET_IP_ADDR(TARGET_IP_ADDR)
- ) ip_layer (
- .app_tx_clk (app_tx_clk),
- .app_rx_clk (app_rx_clk),
- .app_rx_reset (app_rx_reset),
- .app_tx_reset (app_tx_reset),
- .ip_rx_data_vld (ip_rx_data_vld),
- .ip_rx_data_last (ip_rx_data_last),
- .ip_rx_data (ip_rx_data),
- .ip_tx_data_vld (ip_tx_data_vld),
- .ip_tx_data_last (ip_tx_data_last),
- .ip_tx_length (ip_tx_length),
- .ip_tx_data (ip_tx_data),
- .udp_rx_data_vld (udp_rx_data_vld),
- .udp_rx_data_last (udp_rx_data_last),
- .udp_rx_data (udp_rx_data),
- .udp_rx_length (udp_rx_length),
- .udp_tx_data_vld (udp_tx_data_vld),
- .udp_tx_data_last (udp_tx_data_last),
- .udp_tx_data (udp_tx_data),
- .udp_tx_length (udp_tx_length),
- .icmp_rx_data_vld (icmp_rx_data_vld),
- .icmp_rx_data_last (icmp_rx_data_last),
- .icmp_rx_data (icmp_rx_data),
- .icmp_rx_length (icmp_rx_length)
- );
- udp_layer #(
- .LOCAL_PORT(LOCAL_PORT),
- .TARGET_PORT(TARGET_PORT)
- ) udp_layer (
- .app_tx_clk (app_tx_clk),
- .app_rx_clk (app_rx_clk),
- .app_tx_reset (app_tx_reset),
- .app_rx_reset (app_rx_reset),
- .udp_rx_data_vld (udp_rx_data_vld),
- .udp_rx_data_last (udp_rx_data_last),
- .udp_rx_data (udp_rx_data),
- .udp_rx_length (udp_rx_length),
- .udp_tx_data_vld (udp_tx_data_vld),
- .udp_tx_data_last (udp_tx_data_last),
- .udp_tx_data (udp_tx_data),
- .udp_tx_length (udp_tx_length),
- .app_rx_data_vld (app_rx_data_vld),
- .app_rx_data_last (app_rx_data_last),
- .app_rx_data (app_rx_data),
- .app_rx_length (app_rx_length),
- .app_tx_data_vld (app_tx_data_vld),
- .app_tx_data_last (app_tx_data_last),
- .app_tx_data (app_tx_data),
- .app_tx_length (app_tx_length),
- .app_tx_req (app_tx_req),
- .app_tx_ready (app_tx_ready)
- );
- endmodule
在上述代码中为什么要对复位信号处理呢,因为输入的复位并不能保证在这四个时钟(app_tx_clk,app_rx_clk,phy_tx_clk,phy_rx_clk)下的。所以复位信号在分别在这4个时钟域下进行打拍,就可以分别得到这4个时钟域下复位信号。
根据udp_protocol_stack和rgmii_interface(FPGA - 以太网UDP通信(一)中)·将两部分例化封装顶层top:
- `timescale 1ns / 1ps
-
- module top(
- input wire clkin_50m ,
-
- input phy_rgmii_rx_clk_i ,
- input phy_rgmii_rx_ctl ,
- input [3:0] phy_rgmii_rx_data ,
-
- output phy_rgmii_tx_clk ,
- output phy_rgmii_tx_ctl ,
- output [3:0] phy_rgmii_tx_data ,
-
- output phy_reset
- );
-
- parameter LOCAL_MAC_ADDR = {8'd0,8'd1,8'd2,8'd3,8'd4,8'd5};
- parameter TARGET_MAC_ADDR = {8'd0,8'd1,8'd2,8'd3,8'd4,8'd5};
- parameter LOCAL_IP_ADDR = {8'd0,8'd1,8'd2,8'd3};
- parameter TARGET_IP_ADDR = {8'd0,8'd1,8'd2,8'd3};
- parameter LOCAL_PORT = 16'h8060;
- parameter TARGET_PORT = 16'h8060;
-
- wire reset;
- wire clkout_125m;
- wire clkout_200m;
- wire delay_refclk;
- wire phy_tx_clk;
- wire phy_rx_clk;
- wire app_rx_clk;
- wire app_tx_clk;
-
- wire gmii_rx_vld;
- wire gmii_rx_error;
- wire [7:0] gmii_rx_data;
- wire gmii_tx_vld;
- wire [7:0] gmii_tx_data;
-
- wire app_rx_data_vld;
- wire app_rx_data_last;
- wire [7:0] app_rx_data;
- wire [15:0] app_rx_length;
- wire app_tx_data_vld;
- wire app_tx_data_last;
- wire [7:0] app_tx_data;
- wire [15:0] app_tx_length;
- wire app_tx_ready;
-
- wire phy_rgmii_rx_clk;
- wire pll_locked;
- /*------------------------------------------*\
- clk and reset
- \*------------------------------------------*/
-
- clk_wiz_1 instance_name
- (
- // Clock out ports
- .clk_out1(phy_rgmii_rx_clk), // output clk_out1
- // Status and control signals
- .locked(pll_locked), // output locked
- // Clock in ports
- .clk_in1(phy_rgmii_rx_clk_i)); // input clk_in1
-
-
- assign delay_refclk = clkout_200m;
- assign phy_tx_clk = clkout_125m;
- assign app_rx_clk = clkout_200m;
- assign app_tx_clk = clkout_200m;
- assign phy_reset = ~reset;
-
- /*------------------------------------------*\
- 模块例化
- \*------------------------------------------*/
- clock_and_reset clock_and_reset (
- .clkin_50m (clkin_50m),
- .clkout_125m (clkout_125m),
- .clkout_200m (clkout_200m),
- .reset (reset)
- );
-
- rgmii_interface rgmii_interface(
- .reset (reset),
-
- .delay_refclk (delay_refclk),
-
- .phy_rgmii_rx_clk (phy_rgmii_rx_clk),
- .phy_rgmii_rx_ctl (phy_rgmii_rx_ctl),
- .phy_rgmii_rx_data (phy_rgmii_rx_data),
-
- .phy_rgmii_tx_clk (phy_rgmii_tx_clk),
- .phy_rgmii_tx_ctl (phy_rgmii_tx_ctl),
- .phy_rgmii_tx_data (phy_rgmii_tx_data),
-
- .gmii_rx_clk (phy_rx_clk), //rgmii_interface输出的gmii_rx_clk
- .gmii_rx_vld (gmii_rx_vld),
- .gmii_rx_error (gmii_rx_error),
- .gmii_rx_data (gmii_rx_data),
-
- .gmii_tx_clk (phy_tx_clk),
- .gmii_tx_vld (gmii_tx_vld),
- .gmii_tx_data (gmii_tx_data)
- );
-
- udp_protocol_stack #(
- .LOCAL_MAC_ADDR (LOCAL_MAC_ADDR),
- .TARGET_MAC_ADDR (TARGET_MAC_ADDR),
- .LOCAL_IP_ADDR (LOCAL_IP_ADDR),
- .TARGET_IP_ADDR (TARGET_IP_ADDR),
- .LOCAL_PORT (LOCAL_PORT),
- .TARGET_PORT (TARGET_PORT)
- ) udp_protocol_stack (
- .phy_tx_clk (phy_tx_clk),
- .phy_rx_clk (phy_rx_clk),
- .reset (reset),
-
- .gmii_rx_data_vld (gmii_rx_vld),
- .gmii_rx_data (gmii_rx_data),
- .gmii_tx_data_vld (gmii_tx_vld),
- .gmii_tx_data (gmii_tx_data),
-
- .app_rx_clk (app_rx_clk),
- .app_rx_data_vld (app_rx_data_vld),
- .app_rx_data_last (app_rx_data_last),
- .app_rx_data (app_rx_data),
- .app_rx_length (app_rx_length),
-
- .app_tx_clk (app_tx_clk),
- .app_tx_data_vld (app_tx_data_vld),
- .app_tx_data_last (app_tx_data_last),
- .app_tx_data (app_tx_data),
- .app_tx_length (app_tx_length),
- .app_tx_ready (app_tx_ready)
- );
-
- /*------------------------------------------*\
- 上板回环
- \*------------------------------------------*/
- c_shift_ram_0 top_delay_1 (
- .A(60), // input wire [5 : 0] A
- .D({app_rx_data_vld,app_rx_data_last,6'd0}), // input wire [7 : 0] D
- .CLK(clkout_200m), // input wire CLK
- .Q({app_tx_data_vld,app_tx_data_last,6'd0}) // output wire [7 : 0] Q
- );
- c_shift_ram_0 top_delay_2 (
- .A(60), // input wire [5 : 0] A
- .D(app_rx_data), // input wire [7 : 0] D
- .CLK(clkout_200m), // input wire CLK
- .Q(app_tx_data) // output wire [7 : 0] Q
- );
-
- c_shift_ram_1 top_delay_3 (
- .A(60), // input wire [5 : 0] A
- .D(app_rx_length), // input wire [15 : 0] D
- .CLK(clkout_200m), // input wire CLK
- .Q(app_tx_length) // output wire [15 : 0] Q
- );
-
-
- endmodule
注意(我在这里也调试了好久) :PHY芯片的时钟(phy_rgmii_rx_clk_i)是外部时钟,将外部时钟信号不加处理直接引入FPGA芯片使用,有时候会导致意想不到的BUG发生,而且这种BUG是不可重复的。
将外部时钟直接连接到FPGA芯片的普通I/O管脚,而非专用时钟输入管脚,将会导致下面问题:
1.由于该时钟信号是通过各种长短布线资源,甚至经过LUT连接才能到达其驱动的各个寄存器,因此该时钟信号从进入FPGA管脚,到传递到各个寄存器的时钟输入端,其时间是很难保持相同的,距离的远近直接决定了该时钟信号的传输延迟(时钟延迟)。而这个传输延迟的差值,可能达到几纳秒甚至十几纳秒。这个差值,将直接影响数据的建立和保持时间,造成时序无法收敛,从而导致设计失败。
2.使用非全局布线资源,时钟信号在布线的过程中更容易受到周围信号的干扰。导致时钟质量变差。什么意思呢?打个比方,一只小鸟和一只兔子共同穿越一个满是灰尘的工地。工地上到处都是灰尘。小鸟从空中飞过,不直接与灰尘接触,因此基本不会沾到灰尘,因为它有自己独立的路线和空间。而兔子因为不会飞,因此只能跑着从工地中穿过,那么,不可避免的,兔子的脚上会沾上灰尘。导致当兔子穿过这个工地的时候,早已由小白兔变成了小灰兔。时钟信号也是如此,全局时钟资源有专门的时钟路径,在自己的空间走线,不穿过或很少穿过各种高速翻转的逻辑区域,因此很少受到污染。而非全局时钟资源没有专门的时钟路径,只能使用通用布线资源,而这些布线不可避免的会穿过很多高速翻转的逻辑区域。从而受到这些逻辑的翻转噪声的污染。最终时钟信号变的很差。例如边沿上升和下降更慢,占空比发生变化,时钟抖动增大等。
所以,在这里我把PHY芯片的时钟(phy_rgmii_rx_clk_i)引入到PLL中,输入(phy_rgmii_rx_clk_i)125Mhz 输出(phy_rgmii_rx_clk)125Mhz,并将其相位设置为90,延时一下,使其更稳定,这样就保证了外部输入时钟的稳定性。
对以太网UDP通信设计进行仿真,仿真代码如下:
- `timescale 1ns / 1ps
- module tb_top();
-
- parameter LOCAL_MAC_ADDR = {8'd0,8'd1,8'd2,8'd3,8'd4,8'd5};
- parameter TARGET_MAC_ADDR = {8'd0,8'd1,8'd2,8'd3,8'd4,8'd5};
- parameter LOCAL_IP_ADDR = {8'd0,8'd1,8'd2,8'd3};
- parameter TARGET_IP_ADDR = {8'd0,8'd1,8'd2,8'd3};
- parameter LOCAL_PORT = 16'h8060;
- parameter TARGET_PORT = 16'h8060;
-
- reg phy_clk ;
- reg clk ;
- reg reset ;
-
- wire gmii_rx_data_vld ;
- wire [7:0] gmii_rx_data ;
- wire gmii_tx_data_vld ;
- wire [7:0] gmii_tx_data ;
-
- wire app_rx_data_vld ;
- wire app_rx_data_last ;
- wire [7 :0] app_rx_data ;
- wire [15:0] app_rx_length ;
-
- reg app_tx_data_vld ;
- reg app_tx_data_last ;
- reg [7 :0] app_tx_data ;
- reg [15:0] app_tx_length ;
- wire app_tx_ready ;
-
- initial begin
- phy_clk = 0;
- forever # (4)
- phy_clk = ~ phy_clk;
- end
-
- initial begin
- clk = 0;
- forever # (10) //20ns
- clk = ~ clk;
- end
-
- initial begin
- reset = 1;
- #2000
- reset = 0;
- end
- /*----------------------------------------------------*\
- 发起APP请求
- \*----------------------------------------------------*/
- initial begin
- #300000
- upd_rw_test(18);
-
- upd_rw_test(1024);
- #3000;
- $stop;
- end
-
-
- /*----------------------------------------------------*\
- 封装task任务
- \*----------------------------------------------------*/
- task upd_rw_test
- (
- input [15:0] length
- );begin
- #3000;
- wait(app_tx_ready);
- app_tx_data_vld <= 0;
- app_tx_data_last <= 0;
- app_tx_length <= length;
- #400;
-
- repeat(length)@(posedge clk)begin
- app_tx_data_vld <= 1;
- end
- app_tx_data_vld <= 1;
- app_tx_data_last <= 1;
- #20;
- app_tx_data_vld <= 0;
- app_tx_data_last <= 0;
- end
- endtask
-
-
- always @(posedge clk ) begin
- if (reset) begin
- app_tx_data <= 0;
- end
- else if (app_tx_data_vld) begin
- app_tx_data <= app_tx_data + 1;
- end
- end
-
-
- assign gmii_rx_data_vld = gmii_tx_data_vld ;
- assign gmii_rx_data = gmii_tx_data ;
-
- udp_protocol_stack #(
- .LOCAL_MAC_ADDR(LOCAL_MAC_ADDR),
- .TARGET_MAC_ADDR(TARGET_MAC_ADDR),
- .LOCAL_IP_ADDR(LOCAL_IP_ADDR),
- .TARGET_IP_ADDR(TARGET_IP_ADDR),
- .LOCAL_PORT(LOCAL_PORT),
- .TARGET_PORT(TARGET_PORT)
- ) udp_protocol_stack (
- .phy_tx_clk (phy_clk),
- .phy_rx_clk (phy_clk),
- .reset (reset),
-
- .gmii_rx_data_vld (gmii_rx_data_vld),
- .gmii_rx_data (gmii_rx_data),
- .gmii_tx_data_vld (gmii_tx_data_vld),
- .gmii_tx_data (gmii_tx_data),
-
- .app_rx_clk (clk),
- .app_rx_data_vld (app_rx_data_vld),
- .app_rx_data_last (app_rx_data_last),
- .app_rx_data (app_rx_data),
- .app_rx_length (app_rx_length),
-
- .app_tx_clk (clk),
- .app_tx_data_vld (app_tx_data_vld),
- .app_tx_data_last (app_tx_data_last),
- .app_tx_data (app_tx_data),
- .app_tx_length (app_tx_length),
- .app_tx_ready (app_tx_ready)
- );
-
- endmodule
udp_send:
ip_send:
mac_send:
mac_receive:
mac_to_ip_arp:
ip_receive:
udp_receive:
top:
修改源mac地址和ip地址,以及目标mac地址和ip地址。
- parameter LOCAL_MAC_ADDR = {8'h48,8'h2c,8'ha0,8'hdf,8'h00,8'hff};
- parameter TARGET_MAC_ADDR = {8'h88,8'ha4,8'hc2,8'hc8,8'h19,8'h11};
- parameter LOCAL_IP_ADDR = {8'd169,8'd254,8'd189,8'd137};
- parameter TARGET_IP_ADDR = {8'd169,8'd254,8'd189,8'd136};
- parameter LOCAL_PORT = 16'd1234;
- parameter TARGET_PORT = 16'd1234;
逻辑综合,布局布线,生成Bitstream:
打开网络调试助手:
打开后点击发送:
可以看到可以正常接收。
我们完成了以太网udp通信的发送与接受。同时,也已经了解了MAC协议首部,IP协议首部,UDP协议首部的具体内容,并完成了各层的接受与发送。
但是本次设计的以太网udp通信,只做了udp协议回环,不带arp和icmp的功能,是简化版本的 udp工程,开发板和PC通信,需要手动在电脑端添加板卡的ip地址和mac地址。
如下图,完整的以太网udp通信是包括arp和icmp功能:
但是,在我们的代码设计中,我们按每一层去编写设计代码,因此,想要完成完整的udp设计,只需要mac层后提添加ICMP功能,在ip层后添加ARP功能。添加这2个功能后要涉及一个很大的问题:仲裁,设计好仲裁后,就可以完成完整版本的udp工程。
至此,简化版的以太网udp通信的发送与接受设计完成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。