(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)实验现象: