RTL8211EG实现千兆网回环
这是我做的比较久的一个练习,主要困难在于前期看了协议看了别人的写法但是不知道实际的波形是怎么用的,所以这里给了我一个教训,以后学习别人的代码,一定要试着做仿真,把别人的仿真完后再回头变自己写代码自己做仿真,只要自己的仿真也做得和别人的一致整个设计就应该没什么问题了,我这里说的写代码指的是按照自己的理解写自己风格的代码。
废话先不多少上个结果先
RTL视图
整个模块很简单,就是接收+fifo+发送+crc,感觉这样很清爽,哪个模块有问题也能迅速定位到问题出在了哪里。
思路
具体的原理随便网上找下都有,我把具体模块信号打出来
发送模块
module udp_send(
input clk ,
input rst_n ,
input udp_start ,
input [15:0] tx_data_length ,
//fifo
input [10:0] fifo_rdusedw ,
input [7:0] fifo_rd_data ,
output reg fifo_rdreq ,
//crc
input [31:0] crc ,
output reg crc_init ,
output reg crc_en ,
//gmii
output reg gmii_tx_en ,
output reg [7:0] gmii_tx_data
);
接收模块
module udp_receive(
input clk ,
input rst_n ,
input [7:0] gmii_rx_data ,
input gmii_rx_dv ,
output wire[7:0] fifo_wr_data ,
output wire fifo_wrreq ,
output reg one_pkt_done ,
output reg [15:0] rx_data_length
顶层模块
module udp_loop(
input gmii_rx_clk ,
input rst_n ,
input [7:0] gmii_rx_data ,
input gmii_rx_dv ,
output wire [7:0] gmii_tx_data ,
output gmii_tx_clk ,
output wire gmii_tx_en
);
//======================================================================\
//************** Define Parameter and Internal Signals *****************
//======================================================================/
wire fifo_wrreq ;
wire [ 7: 0] fifo_wr_data ;
wire fifo_rdreq ;
wire [ 7: 0] fifo_rd_data ;
wire [10: 0] fifo_rdusedw ;
wire crc_init ;
wire crc_en ;
wire [31: 0] crc ;
wire one_pkt_done ;
wire [15:0] data_length ;
//======================================================================\
//**************************** Main Code *******************************
//======================================================================/
assign gmii_tx_clk = gmii_rx_clk;
udp_receive udp_receive_inst(
.clk (gmii_rx_clk ),
.rst_n (rst_n ),
.gmii_rx_data (gmii_rx_data ),
.gmii_rx_dv (gmii_rx_dv ),
.fifo_wr_data (fifo_wr_data ),
.fifo_wrreq (fifo_wrreq ),
.rx_data_length (data_length ),
.one_pkt_done (one_pkt_done )
);
udp_send udp_send_inst(
.clk (gmii_tx_clk ),
.rst_n (rst_n ),
.udp_start (one_pkt_done ),
.tx_data_length (data_length ),
//fifo
.fifo_rdusedw (fifo_rdusedw ),
.fifo_rd_data (fifo_rd_data ),
.fifo_rdreq (fifo_rdreq ),
//crc
.crc (crc ),
.crc_init (crc_init ),
.crc_en (crc_en ),
//gmii
.gmii_tx_en (gmii_tx_en ),
.gmii_tx_data (gmii_tx_data )
);
crc crc_inst(
.clk (gmii_tx_clk ),
.rst_n (rst_n ),
.din (gmii_tx_data ),
.crc_en (crc_en ),
.crc_init (crc_init ),
.crc (crc )
);
fifo fifo_inst(
.data (fifo_wr_data ),
.wrclk (gmii_tx_clk ),
.wrreq (fifo_wrreq ),
.q (fifo_rd_data ),
.rdclk (gmii_tx_clk ),
.rdreq (fifo_rdreq ),
.rdusedw (fifo_rdusedw ),
.wrusedw ( )
);
endmodule
仿真
我把仿真图也贴出来,方便大家写出来后对比)
仿真代码
`timescale 1 ns/ 1 ns
module udp_loop_vlg_tst();
reg gmii_rx_clk;
reg [7:0] gmii_rx_data;
reg gmii_rx_dv;
reg rst_n;
// wires
wire gmii_tx_clk;
wire [7:0] gmii_tx_data;
wire gmii_tx_en;
// assign statements (if any)
udp_loop i1 (
// port map - connection between master ports and signals/registers
.gmii_rx_clk(gmii_rx_clk),
.gmii_rx_data(gmii_rx_data),
.gmii_rx_dv(gmii_rx_dv),
.gmii_tx_clk(gmii_tx_clk),
.gmii_tx_data(gmii_tx_data),
.gmii_tx_en(gmii_tx_en),
.rst_n(rst_n)
);
always #4 gmii_rx_clk = ~gmii_rx_clk;
initial begin
gmii_rx_clk <= 1'b1;
rst_n <= 1'b1;
gmii_rx_dv <= 1'b0;
gmii_rx_data<= 8'h00;
#200
rst_n <= 1'b0;
#40
rst_n <= 1'b1;
#11000002
gmii_rx_dv <= 1'b1;
gmii_rx_data<= 8'h55;//preamble
#8
gmii_rx_data<= 8'h55;
#8
gmii_rx_data<= 8'h55;
#8
gmii_rx_data<= 8'h55;
#8
gmii_rx_data<= 8'h55;
#8
gmii_rx_data<= 8'h55;
#8
gmii_rx_data<= 8'h55;
#8
gmii_rx_data<= 8'hd5;//SFD
#8
gmii_rx_data<= 8'h00;//dest_mac_addr 48'h00_0a_35_01_fe_c0
#8
gmii_rx_data<= 8'h0a;
#8
gmii_rx_data<= 8'h35;
#8
gmii_rx_data<= 8'h01;
#8
gmii_rx_data<= 8'hfe;
#8
gmii_rx_data<= 8'hc0;
#8
gmii_rx_data<= 8'hb0;//src_mac_addr 48'hf8_32_e4_8d_88_8e
#8
gmii_rx_data<= 8'h7b;
#8
gmii_rx_data<= 8'h25;
#8
gmii_rx_data<= 8'h28;
#8
gmii_rx_data<= 8'hb2;
#8
gmii_rx_data<= 8'hf3;
#8
gmii_rx_data<= 8'h08;//eth_type 16'h0800
#8
gmii_rx_data<= 8'h00;
#8
gmii_rx_data<= 8'h45;//hardware_type 16'h0001;
#8
gmii_rx_data<= 8'h00;
#8
gmii_rx_data<= 8'h00;//UPT 16'h0800
#8
gmii_rx_data<= 8'h2e;
#8
gmii_rx_data<= 8'h00;//mac_addr_length 8'h6
#8
gmii_rx_data<= 8'h00;//ip_addr_length 8'h4
#8
gmii_rx_data<= 8'h00;//op_code 16'h0002
#8
gmii_rx_data<= 8'h00;
#8
gmii_rx_data<= 8'h40;//src_mac_addr 48'hf8_32_e4_8d_88_8e
#8
gmii_rx_data<= 8'h11;
#8
gmii_rx_data<= 8'hf9;
#8
gmii_rx_data<= 8'h69;
#8
gmii_rx_data<= 8'hc0;
#8
gmii_rx_data<= 8'ha8;
#8
gmii_rx_data<= 8'h00;//src_ip_addr 32'hc0_a8_00_03
#8
gmii_rx_data<= 8'h03;
#8
gmii_rx_data<= 8'hc0;
#8
gmii_rx_data<= 8'ha8;
#8
gmii_rx_data<= 8'h00;//dest_mac_addr 48'h00_0a_35_01_fe_c0
#8
gmii_rx_data<= 8'h02;
#8
gmii_rx_data<= 8'h17;
#8
gmii_rx_data<= 8'h70;
#8
gmii_rx_data<= 8'h13;
#8
gmii_rx_data<= 8'h88;
#8
gmii_rx_data<= 8'h00;
#8
gmii_rx_data<= 8'h1a;
#8
gmii_rx_data<= 8'h00;
#8
gmii_rx_data<= 8'h00;
#8
gmii_rx_data<= 8'ha1;//fill_in_data 18个8'haa
#8
gmii_rx_data<= 8'ha2;
#8
gmii_rx_data<= 8'ha3;
#8
gmii_rx_data<= 8'ha4;
#8
gmii_rx_data<= 8'ha5;
#8
gmii_rx_data<= 8'ha6;
#8
gmii_rx_data<= 8'ha7;
#8
gmii_rx_data<= 8'haa;
#8
gmii_rx_data<= 8'ha8;
#8
gmii_rx_data<= 8'ha9;
#8
gmii_rx_data<= 8'haa;
#8
gmii_rx_data<= 8'hab;
#8
gmii_rx_data<= 8'hac;
#8
gmii_rx_data<= 8'had;
#8
gmii_rx_data<= 8'hae;
#8
gmii_rx_data<= 8'haf;
#8
gmii_rx_data<= 8'hb0;
#8
gmii_rx_data<= 8'hb1;
#8
gmii_rx_data<= 8'h97;//crc
#8
gmii_rx_data<= 8'h00;//crc
#8
gmii_rx_data<= 8'h00;//crc
#8
gmii_rx_data<= 8'h00;//crc
#8
gmii_rx_dv <= 1'b0;
#100
$STOP;
end
endmodule
最后需要代码可以联系本人,主页上面有联系方式,有偿