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    [15:0]      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)实验现象:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值