代码还没有写好,先放在这里,下午有空继续写写。
module test_ip_pack ;
reg rst = 0 ,clk = 0 ;
always #5 clk = ~clk ;
initial begin
$dumpfile("test_ip_pack.vd");
$dumpvars;
rst = 1;
@(posedge clk) ;
@(posedge clk) ;
rst = 0;
@(posedge clk) ;
end
wire ip_data_ack ;reg [7:0] c ;always @ (posedge clk)if (rst) c<=0; else if (ip_data_ack)c <= 1 + c;
ip_pack ip_pack (
.clk(clk),
.rst(rst),
.ip_TTL(64),
.ip_type('h12) ,
.ip_id(16'h1234),
.ip_src({8'd192,8'd168,8'd2,8'd2}),
.ip_dst({8'd192,8'd168,8'd2,8'd3}) ,
.ip_pack_valid ( 1'b1 ),
.ip_pack_len ('d8),
.ip_data_ack(ip_data_ack),
.ip_data(c) ,
.ip_tx_valid (),
.ip_tx_busy (1'b0 ) , // 平时必须保持busy是0
.ip_tx_data()
);
endmodule
/**/
module ip_pack (
input clk,rst,
input [7:0] ip_TTL,
input [7:0] ip_type ,
input [15:0] ip_id,
input [31:0]ip_src,ip_dst ,
input ip_pack_valid ,
input [15:0] ip_pack_len ,
// output ip_pack_ready ,
// input ip_data_valid ,
output reg ip_data_ack,
input [7:0] ip_data ,
output reg ip_tx_valid ,
// input ip_tx_ready , // 必须保持ready
input ip_tx_busy , // 平时必须保持busy是0
output reg [7:0] ip_tx_data
);
localparam ip_version = 4'h4 ; //ipv4
localparam header_len = 4'h5 ; //header length
wire [15:0] checksum ;
ip_chksum_gen ip_chksum_gen (
.clk(clk ) ,
.rst(rst ) ,
.valid( 1'b1) ,
.ready ( ) ,
.in0({ip_version, header_len,8'b0} ) ,//0
.in1( ip_pack_len) , //1
.in2(ip_id ) ,//2
.in3( 'h4000 ) , //3
.in4( {ip_TTL,ip_type} ) , //4
.in5( 0 ) ,//5
.in6(ip_src[31:16] ) ,//6
.in7(ip_src[15:0] ) ,//7
.in8(ip_dst[31:16] ) ,//8
.in9(ip_dst[15:0] ) ,//9
.checksum(checksum)
);
reg [7:0] wr_st ;
reg [11:0] cr_cntr ;always @ (posedge clk )case (wr_st) 200: cr_cntr <=cr_cntr+1 ;default cr_cntr<=1;endcase
reg [11:0] ip_pack_lenr ;always @ (posedge clk )case (wr_st) 100: ip_pack_lenr <=ip_pack_len[11:0] ; endcase
always @ (posedge clk) if (rst) wr_st<=0; else case (wr_st)
0: if (ip_pack_valid & ~ip_tx_busy ) wr_st<=100; // IDLE
100,101,102,103,104,105,106,107,108,109,
110,111,112,113,114,115,116,117,118: wr_st<=wr_st+1 ;
119:wr_st <= 200;
200:if ( cr_cntr == ip_pack_lenr )wr_st<=300;
default wr_st<=0;
endcase
reg [11:0] rd_addr ;
always @ (posedge clk) if (rst) wr_st<=0; else case (wr_st)
100:begin ip_tx_valid <=1;ip_tx_data<= {ip_version, header_len} ;end
101:begin ip_tx_valid <=1;ip_tx_data<= 0 ;end
102:begin ip_tx_valid <=1;ip_tx_data<= ip_pack_len[15:8] ;end
103:begin ip_tx_valid <=1;ip_tx_data<= ip_pack_len[7:0] ;end
104:begin ip_tx_valid <=1;ip_tx_data<= ip_id[15:8] ;end
105:begin ip_tx_valid <=1;ip_tx_data<= ip_id[7:0] ;end
106:begin ip_tx_valid <=1;ip_tx_data<= 'h40 ;end
107:begin ip_tx_valid <=1;ip_tx_data<= 0 ;end
108:begin ip_tx_valid <=1;ip_tx_data<= ip_TTL ;end
109:begin ip_tx_valid <=1;ip_tx_data<= ip_type; end
110:begin ip_tx_valid <=1;ip_tx_data<= checksum[15:8] ;end
111:begin ip_tx_valid <=1;ip_tx_data<= checksum[7:0] ;end
112:begin ip_tx_valid <=1;ip_tx_data<= ip_src[31:24];end
113:begin ip_tx_valid <=1;ip_tx_data<= ip_src[23:16] ;end
114:begin ip_tx_valid <=1;ip_tx_data<= ip_src[15:8] ;end
115:begin ip_tx_valid <=1;ip_tx_data<= ip_src[7:0] ;end
116:begin ip_tx_valid <=1;ip_tx_data<= ip_dst[31:24] ;end
117:begin ip_tx_valid <=1;ip_tx_data<= ip_dst[23:16] ;end
118:begin ip_tx_valid <=1;ip_tx_data<= ip_dst[15:8] ;end
119:begin ip_tx_valid <=1;ip_tx_data<= ip_dst[7:0] ;end
200:begin ip_tx_valid <=1;ip_tx_data<= ip_data[7:0] ;end
default begin ip_tx_valid <=0;ip_tx_data<= 0 ;end
endcase
always @ (posedge clk) ip_data_ack <= ( wr_st == 200 && cr_cntr != ip_pack_lenr ) || ( wr_st == 119 ) ;
endmodule
module ip_chksum_gen(
input clk,rst,
input valid,
output ready ,
input [15:0] in0,in1,in2,in3,in4,
input [15:0] in5,in6,in7,in8,in9,
output reg [15:0] checksum
);
//checksum function
function [31:0] checksum_adder
(
input [31:0] dataina,
input [31:0] datainb
);
begin
checksum_adder = dataina + datainb;
end
endfunction
function [31:0] checksum_out
(
input [31:0] dataina
);
begin
checksum_out = dataina[15:0]+dataina[31:16];
end
endfunction
//checksum generation
reg [16:0] checksum_tmp0 ;
reg [16:0] checksum_tmp1 ;
reg [16:0] checksum_tmp2 ;
reg [16:0] checksum_tmp3 ;
reg [16:0] checksum_tmp4 ;
reg [17:0] checksum_tmp5 ;
reg [17:0] checksum_tmp6 ;
reg [18:0] checksum_tmp7 ;
reg [19:0] checksum_tmp8 ;
reg [19:0] check_out ;
reg [19:0] checkout_buf ;
reg [4:0]valid_r ;always @ (posedge clk) valid_r <={valid_r[3:0],valid} ;
assign ready = valid_r[4];
always@(posedge clk)begin
checksum_tmp0 <= checksum_adder(in0,in1);
checksum_tmp1 <= checksum_adder(in2,in3) ;
checksum_tmp2 <= checksum_adder(in4,in5) ;
checksum_tmp3 <= checksum_adder(in5,in7) ;
checksum_tmp4 <= checksum_adder(in8,in9) ;// stage 1
checksum_tmp5 <= checksum_adder(checksum_tmp0, checksum_tmp1) ;
checksum_tmp6 <= checksum_adder(checksum_tmp2, checksum_tmp3) ;
checksum_tmp7 <= checksum_adder(checksum_tmp5, checksum_tmp6) ;
checksum_tmp8 <= checksum_adder(checksum_tmp4, checksum_tmp7) ; // stage2
check_out <= checksum_out(checksum_tmp8) ; //stage3
checkout_buf <= checksum_out(check_out) ; // stage4
checksum <= ~ checkout_buf[15:0] ; // stage5
end
endmodule
看仿真波形
上图表示妥妥的读取了8个字节的ip_data.
另外输出也没有问题。
可以看到输出了20字节的IP头,以及8字节的内容(8自己内容不满足实际以太网最小的数据包要求,这里只是实验仿真用,好数个数)。但是时序确保已经正常了。这里没有校验check_sum是否正确,可在后续的统调中进行。