(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_busODDR #(.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
endgenerateendmodule
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
endgenerateendmodule
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 / 1psmodule 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 beginreset_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;elsedata_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=163eth_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)实验现象: