62.以太网数据回环实验(5)

(1)UDP顶层模块代码:

module udp
(
    input   wire                gmii_txc        ,
    input   wire                gmii_rxc        ,
    input   wire                reset_n         ,
    input   wire                gmii_rx_dv      ,
    input   wire    [7:0]       gmii_rxd        ,
    input   wire                tx_start_en     ,
    input   wire    [31:0]      tx_data         ,
    input   wire    [15:0]      tx_byte_num     ,
      
    output  wire    [31:0]      rec_data        ,
    output  wire                rec_en          ,
    output  wire                rec_pkt_done    ,
    output  wire                rec_byte_num    ,
    output  wire    [7:0]       gmii_txd        ,
    output  wire                gmii_tx_en      ,
    output  wire                tx_done         ,
    output  wire                tx_req  
    
);

//开发板MAC地址(48位)
parameter BOARO_MAC     =   48'hff_ff_ff_ff_ff_ff   ;
//开发板IP地址(32位)
parameter BOARO_IP      =   {8'd0,8'd0,8'd0,8'd0}   ;
//目的MAC地址(48位)
parameter DES_MAC       =   48'hff_ff_ff_ff_ff_ff   ;
//目的IP地址(32位)
parameter DES_IP        =   {8'd0,8'd0,8'd0,8'd0}   ;

wire    [31:0]      crc_data    ;
wire    [31:0]      crc_next    ;
wire                crc_en      ;
wire                crc_clr     ;

defparam udp_rx_inst.BOARO_MAC = BOARO_MAC;
defparam udp_rx_inst.BOARO_IP  = BOARO_IP;
defparam udp_tx_inst.BOARO_MAC = BOARO_MAC;
defparam udp_tx_inst.BOARO_IP  = BOARO_IP;
defparam udp_tx_inst.DES_MAC   = DES_MAC;
defparam udp_tx_inst.DES_IP    = DES_IP;

udp_rx  udp_rx_inst(

    .gmii_rxc            (gmii_rxc       ),
    .reset_n             (reset_n        ),
    .gmii_rx_dv          (gmii_rx_dv     ),   
    .gmii_rxd            (gmii_rxd       ),   
    .rec_data            (rec_data       ),   
    .rec_en              (rec_en         ),   
    .rec_pkt_done        (rec_pkt_done   ),   
    .rec_byte_num        (rec_byte_num   )    

);

udp_tx  udp_tx_inst
(
    .gmii_txc    (gmii_txc          ),
    .reset_n     (reset_n           ),
    .tx_start_en (tx_start_en       ),       
    .tx_data     (tx_data           ),       
    .tx_byte_num (tx_byte_num       ),       
    .crc_data    (crc_data          ),       
    .crc_next    (crc_next[31:24]   ),       

    .gmii_txd    (gmii_txd          ),       
    .gmii_tx_en  (gmii_tx_en        ),       
    .tx_done     (tx_done           ),       
    .tx_req      (tx_req            ),       
    .crc_en      (crc_en            ),       
    .crc_clr     (crc_clr           )        
);

crc32_d8 crc32_d8_inst
(
    .gmii_txc      (gmii_txc        ),  
    .reset_n       (reset_n         ),  
    .data          (gmii_txd        ),  
    .crc_en        (crc_en          ),  
    .crc_clr       (crc_clr         ),  
    .crc_data      (crc_data        ),  
    .crc_next      (crc_next        )   
);

endmodule

(2)RTL视图:

(3)转换模块调用源语过程:

(4)gmii转rgmii代码:

module rgmii_tx
(
    input   wire            gmii_txc    ,
    input   wire    [7:0]   gmii_txd    ,
    input   wire            gmii_tx_en  ,

    output  wire            rgmii_txc   ,
    output  wire    [3:0]   rgmii_txd   ,
    output  wire            rgmii_tx_ctl
);

assign rgmii_txc = gmii_txc ;

ODDR #(
      .DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT(1'b0),    // Initial value of Q: 1'b0 or 1'b1
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
) 
ODDR_tx_inst (
      .Q    (rgmii_tx_ctl       ),   // 1-bit DDR output
      .C    (gmii_txc           ),   // 1-bit clock input
      .CE   (1'd1               ), // 1-bit clock enable input
      .D1   (gmii_tx_en         ), // 1-bit data input (positive edge)
      .D2   (gmii_tx_en         ), // 1-bit data input (negative edge)
      .R    (1'd0               ),   // 1-bit reset
      .S    (1'd0               )    // 1-bit set
);

genvar i;

generate for(i=0;i<4;i=i+1)

begin:  tx_data_bus

ODDR #(
      .DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT(1'b0),    // Initial value of Q: 1'b0 or 1'b1
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
) 
ODDR_tx_inst_ctl (
      .Q    (rgmii_txd[i]       ),   // 1-bit DDR output
      .C    (gmii_txc           ),   // 1-bit clock input
      .CE   (1'd1               ), // 1-bit clock enable input
      .D1   (gmii_txd[i]        ), // 1-bit data input (positive edge)
      .D2   (gmii_txd[4+i]      ), // 1-bit data input (negative edge)
      .R    (1'd0               ),   // 1-bit reset
      .S    (1'd0               )    // 1-bit set
);

end
endgenerate

endmodule

module rgmii_rx
(
    input   wire    [3:0]   rgmii_rxd       ,
    input   wire            rgmii_rxc       ,
    input   wire            rgmii_rx_ctl    ,
        
    output  wire            gmii_rxc        ,
    output  wire    [7:0]   gmii_rxd        ,
    output  wire            gmii_rx_ctl
);

wire    [1:0]   gmii_rx_ctl_t   ;

assign gmii_rx_ctl = gmii_rx_ctl_t[0] & gmii_rx_ctl_t[1]  ;

assign gmii_rxc  = rgmii_rxc    ;

IDDR #(
      .DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE", "SAME_EDGE" 
                                      //    or "SAME_EDGE_PIPELINED" 
      .INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
      .INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
) 
IDDR_rx_inst (
      .Q1       (gmii_rx_ctl_t[0]   ), // 1-bit output for positive edge of clock
      .Q2       (gmii_rx_ctl_t[1]   ), // 1-bit output for negative edge of clock
      .C        (gmii_rxc           ),   // 1-bit clock input
      .CE       (1'd1               ), // 1-bit clock enable input
      .D        (rgmii_rx_ctl       ),   // 1-bit DDR data input
      .R        (1'd0               ),   // 1-bit reset
      .S        (1'd0               )    // 1-bit set
);

genvar i;

generate for(i=0;i<4;i=i+1)

begin:  rx_data_bus
IDDR #(
      .DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE", "SAME_EDGE" 
                                      //    or "SAME_EDGE_PIPELINED" 
      .INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
      .INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
) 
IDDR_rx_inst_ctl (
      .Q1       (gmii_rxd[4+i]      ), // 1-bit output for positive edge of clock
      .Q2       (gmii_rxd[i]        ), // 1-bit output for negative edge of clock
      .C        (gmii_rxc           ),   // 1-bit clock input
      .CE       (1'd1               ), // 1-bit clock enable input
      .D        (rgmii_rxd[i]       ),   // 1-bit DDR data input
      .R        (1'd0               ),   // 1-bit reset
      .S        (1'd0               )    // 1-bit set
);
end
endgenerate

endmodule

module gmii_to_rgmii
(
    input   wire    [7:0]   gmii_txd    ,
    input   wire            gmii_tx_en  ,
    input   wire    [3:0]   rgmii_rxd   ,
    input   wire            rgmii_rx_ctl,
    input   wire            rgmii_rxc   ,
    
    output  wire            gmii_txc    ,
    output  wire            gmii_rxc    ,
    output  wire    [7:0]   gmii_rxd    ,
    output  wire            gmii_rx_ctl ,
    output  wire    [3:0]   rgmii_txd   ,
    output  wire            rgmii_tx_ctl,
    output  wire            rgmii_txc   
);

assign gmii_txc =  gmii_rxc;

rgmii_rx rgmii_rx_inst
(
    .rgmii_rxd       (rgmii_rxd     ),
    .rgmii_rxc       (rgmii_rxc     ),
    .rgmii_rx_ctl    (rgmii_rx_ctl  ),

    .gmii_rxc        (gmii_rxc      ),
    .gmii_rxd        (gmii_rxd      ),
    .gmii_rx_ctl     (gmii_rx_ctl   )
);

rgmii_tx rgmii_tx_inst
(
    .gmii_txc       (gmii_txc       ),
    .gmii_txd       (gmii_txd       ),
    .gmii_tx_en     (gmii_tx_en     ),
    
    .rgmii_txc      (rgmii_txc      ),
    .rgmii_txd      (rgmii_txd      ),
    .rgmii_tx_ctl   (rgmii_tx_ctl   )
);

endmodule

(5)顶层模块:

module eth_udp_loop
(
    input   wire                clk         ,
    input   wire                reset_n     ,
    input   wire                eth_rxc     ,
    input   wire    [3:0]       eth_rxd     ,
    input   wire                eth_rx_ctl  ,

    output  wire                eth_txc     ,
    output  wire    [3:0]       eth_txd     ,
    output  wire                eth_tx_ctl  ,
    output  wire                eth_reset_n    
);

wire                    clk_phase       ;
wire    [7:0]           gmii_txd        ; 
wire                    gmii_tx_en      ;
wire                    gmii_txc        ;
wire                    gmii_rxc        ;
wire    [7:0]           gmii_rxd        ;
wire                    gmii_rx_ctl     ;
wire                    rec_pkt_done    ;
wire    [31:0]          tx_data         ;
wire    [15:0]          rec_byte_num    ;
wire    [31:0]          rec_data        ;
wire                    rec_en          ;
wire                    tx_done         ;
wire                    tx_req          ;

assign eth_reset_n = 1'd1;

clk_phase clk_phase_inst
(
    .clkout (clk_phase  ),      // output clkout
    .reset  (~reset_n   ),      // input reset
    .locked (           ),      // output locked
    .clkin  (eth_rxc    )       // input clkin
);  

fifo fifo_inst (
    .clk        (gmii_rxc   ),      // input wire clk
    .srst       (~reset_n   ),      // input wire srst
    .din        (rec_data   ),      // input wire [31 : 0] din
    .wr_en      (rec_en     ),      // input wire wr_en
    .rd_en      (tx_req     ),      // input wire rd_en
    .dout       (tx_data    ),      // output wire [31 : 0] dout
    .full       (           ),      // output wire full
    .empty      (           )       // output wire empty
);
   
    
gmii_to_rgmii   gmii_to_rgmii_inst
(
    .gmii_txd    (gmii_txd      ),
    .gmii_tx_en  (gmii_tx_en    ),
    .rgmii_rxd   (eth_rxd       ),
    .rgmii_rx_ctl(eth_rx_ctl    ),
    .rgmii_rxc   (clk_phase     ),

    .gmii_txc    (gmii_txc      ),
    .gmii_rxc    (gmii_rxc      ),
    .gmii_rxd    (gmii_rxd      ),
    .gmii_rx_ctl (gmii_rx_ctl   ),
    .rgmii_txd   (eth_txd       ),
    .rgmii_tx_ctl(eth_tx_ctl    ),
    .rgmii_txc   (eth_txc       )
);      

defparam udp_inst.BOARO_MAC = 48'h12_34_56_78_9a_bc   ;
defparam udp_inst.BOARO_IP  = {8'd192,8'd168,8'd0,8'd234};
defparam udp_inst.DES_MAC   = 48'hff_ff_ff_ff_ff_ff;
defparam udp_inst.DES_IP    = {8'd192,8'd168,8'd0,8'd145};

udp udp_inst
(
    .gmii_txc        (gmii_txc      ),
    .gmii_rxc        (gmii_rxc      ),
    .reset_n         (reset_n       ),
    .gmii_rx_dv      (gmii_rx_ctl   ),
    .gmii_rxd        (gmii_rxd      ),
    .tx_start_en     (rec_pkt_done  ),
    .tx_data         (tx_data       ),
    .tx_byte_num     (rec_byte_num  ),

    .rec_data        (rec_data      ),
    .rec_en          (rec_en        ),
    .rec_pkt_done    (rec_pkt_done  ),
    .rec_byte_num    (rec_byte_num  ),
    .gmii_txd        (gmii_txd      ),
    .gmii_tx_en      (gmii_tx_en    ),
    .tx_done         (tx_done       ),
    .tx_req          (tx_req        )   
    
);         


endmodule

(6)仿真代码及波形:

`timescale 1ns / 1ps

module tb_eth_udp_loop;

reg             clk             ;   //50MHz
reg             eth_rxc         ;   //125MHz
reg             eth_rxc_x2      ;   //250MHz
reg             reset_n         ;
reg             start_flag      ;   //数据输入开始标志信号
reg             eth_rx_ctl      ;
reg     [11:0]  cnt_data        ;   //数据包字节计数器
reg     [655:0] data_mem        ;   //82 * 8 =656 

wire    [3:0]   eth_rxd         ;
wire            eth_reset_n     ;
wire    [3:0]   eth_txd         ;
wire            eth_tx_ctl      ;
wire            eth_txc         ;

initial clk = 1'd1;
always#10 clk = ~clk;

initial eth_rxc = 1'd1;
always#4 eth_rxc = ~eth_rxc;

initial eth_rxc_x2 = 1'd1;
always#2 eth_rxc_x2 = ~eth_rxc_x2;

initial begin
    reset_n <= 1'd0;
    start_flag <= 1'd0;
    #200;
    reset_n <= 1'd1;
    #100;
    start_flag <= 1'd1;
    #50;
    start_flag <= 1'd0;
    #6000;
    $stop;
end

//data_mem
always@(negedge eth_rxc_x2 or negedge reset_n)
    if(reset_n == 1'b0)
        data_mem    <=  'hFE_DC_BA_98_76_54_32_10_FE_DC_BA_98_76_54_32_10_FE_DC_BA_98_76_54_32_10_FE_DC_BA_98_76_54_32_10_00_00_28_00_D2_04_D2_04_EA_00_A8_C0_91_00_A8_C0_00_00_11_80_00_00_00_5F_3C_00_00_45_00_08_2D_DB_4A_5E_D5_E0_BC_9A_78_56_34_12_D5_55_55_55_55_55_55_55;
    else    if(eth_rx_ctl == 1'b1)
        data_mem    <=  data_mem >> 4;
    else
        data_mem    <=  data_mem;

always@(posedge eth_rxc_x2 or negedge reset_n)
    if(!reset_n)
        cnt_data <= 12'd0;
    else if(eth_rx_ctl)
        cnt_data <= cnt_data + 12'd1;
    else 
        cnt_data <= cnt_data;
        
always@(posedge eth_rxc_x2 or negedge reset_n)
    if(!reset_n)
        eth_rx_ctl <= 1'd0;
    else if(cnt_data == 12'd163)      //86个字母减去4个验证字节,x2 = 164 164-1=163
        eth_rx_ctl <= 1'd0;
    else if(start_flag)
        eth_rx_ctl <= 1'd1;
    else 
        eth_rx_ctl <= eth_rx_ctl;

assign  eth_rxd =  eth_rx_ctl ? data_mem[3:0]: 4'd0;

eth_udp_loop    eth_udp_loop_inst
(
    .clk         (clk       ),
    .reset_n     (reset_n   ),
    .eth_rxc     (eth_rxc   ),
    .eth_rxd     (eth_rxd   ),
    .eth_rx_ctl  (eth_rx_ctl),

    .eth_txc     (eth_txc),
    .eth_txd     (eth_txd   ),
    .eth_tx_ctl  (eth_tx_ctl),
    .eth_reset_n (eth_reset_n)   
);

endmodule

(7)实验现象:

相关推荐
乌恩大侠1 小时前
O-RAN Fronthual CU/Sync/Mgmt 平面和协议栈
5g·平面·fpga开发·架构
DS小龙哥15 小时前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
上理考研周导师1 天前
第二章 虚拟仪器及其构成原理
fpga开发
FPGA技术实战1 天前
《探索Zynq MPSoC》学习笔记(二)
fpga开发·mpsoc
bigbig猩猩2 天前
FPGA(现场可编程门阵列)的时序分析
fpga开发
Terasic友晶科技2 天前
第2篇 使用Intel FPGA Monitor Program创建基于ARM处理器的汇编或C语言工程<二>
fpga开发·汇编语言和c语言
码农阿豪2 天前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
江山如画,佳人北望2 天前
EDA技术简介
fpga开发
淘晶驰AK2 天前
电子设计竞赛准备经历分享
嵌入式硬件·fpga开发