module udp_tx_pack_tb ;
reg rst = 0 ,clk = 0 ;
always #5 clk = ~clk ;
initial begin
$dumpfile("test_udp_tx_pack.vd");
$dumpvars;
rst = 1;
@(posedge clk) ;
@(posedge clk) ;
rst = 0;
@(posedge clk) ;
end
wire [31:0]src_ip ={8'd192,8'd168,8'd2,8'd4} ;
wire [31:0]dst_ip ={8'd192,8'd168,8'd2,8'd3} ;
wire [15:0] src_port = 16'd1234 ;
wire [15:0] dst_port = 16'hcdef ;
wire [15:0]test_len = 8;
reg [31:0] c;always @(posedge clk) if (rst) c<=0; else c<=c+1; // system counter for debug
udp_ip_pack udp_ip_pack (
.clk(clk),
.rst(rst),
.s_src_ip(src_ip),
.s_dst_ip(dst_ip),
.s_src_port(src_port),
.s_dst_port(dst_port),
.s_tx_len(test_len),
.s_tx_start(~s_tx_busy ),
.s_tx_busy (s_tx_busy),
.s_tx_dat(c[7:0]),
.s_ip_type( c[7:0] ) ,
.s_ip_id( c[15:0] ),
.m_ip_tx_valid() ,
.m_ip_tx_busy (1'b0) ,
.m_ip_tx_data ()
);
endmodule
module udp_ip_pack (
input clk,rst,
input [31:0] s_src_ip,s_dst_ip,
input [15:0] s_src_port,s_dst_port, s_tx_len,
input s_tx_start,
output s_tx_busy ,
input [7:0] s_tx_dat,
input [7:0] s_ip_type ,
input [15:0] s_ip_id,
output m_ip_tx_valid ,
input m_ip_tx_busy ,
output [7:0] m_ip_tx_data
);
wire [31:0] src_ip,dst_ip;
wire [7:0] udp_tx_dat ;
wire [15:0] udp_tx_len ;
udp_pack udp_pack (
.clk(clk),
.rst(rst ),
.s_src_ip(s_src_ip ),
.s_dst_ip( s_dst_ip),
.s_src_port( s_src_port),
.s_dst_port( s_dst_port),
.s_tx_len(s_tx_len ),
.s_tx_start(s_tx_start),
.s_tx_busy (s_tx_busy),
.s_tx_dat( s_tx_dat ),
.m_tx_len (udp_tx_len),
.m_pack_valid(udp_pack_valid),
.m_data_ready (ip_data_ack),
.m_tx_dat (udp_tx_dat),
.m_src_ip(src_ip),
.m_dst_ip(dst_ip)
);
ip_pack ip_pack (
.clk(clk),
.rst(rst),
.s_ip_TTL(8'd64),
.s_ip_type(s_ip_type) ,
.s_ip_id(s_ip_id),
.s_ip_src(src_ip),
.s_ip_dst(dst_ip) ,
.s_ip_pack_valid ( udp_pack_valid),
.s_ip_pack_len (udp_tx_len),
.s_ip_data_ack(ip_data_ack),
.s_ip_data( udp_tx_dat) ,
.m_ip_tx_valid ( m_ip_tx_valid),
.m_ip_tx_busy ( m_ip_tx_busy) ,
.m_ip_tx_data ( m_ip_tx_data )
);
endmodule
module udp_pack (
input clk,rst,
input [31:0] s_src_ip,s_dst_ip,
input [15:0] s_src_port,s_dst_port, s_tx_len,
input s_tx_start,
output reg s_tx_busy ,
input [7:0] s_tx_dat,
output reg [15:0] m_tx_len ,
output reg m_pack_valid,
input m_data_ready ,
output[7:0] m_tx_dat ,
output reg [31:0] m_src_ip,m_dst_ip
);
reg [11:0] wr_addr,wr_addr_end ,rd_addr_end;
reg [7:0] wr_data;
reg wr_req;
reg wr_en ;
reg [11:0] rd_addr ;
reg [15:0] st,st2 ;
reg [11:0] wr_cntr ;
reg [15:0] src_port_reg ,dst_port_reg , tx_len_reg ;
always @ (posedge clk) if (rst) {src_port_reg ,dst_port_reg }<=0;else if (st==100&s_tx_start) {src_port_reg ,dst_port_reg } <={ s_src_port,s_dst_port };
always @ (posedge clk) if (rst) wr_addr_end<=0; else if (st==100&s_tx_start) wr_addr_end <= s_tx_len + 6;
always @ ( posedge clk ) if (rst) rd_addr_end<=0; else if (st==100&s_tx_start) rd_addr_end <= s_tx_len + 7;
always @(posedge clk) if (st==100&s_tx_start){m_src_ip,m_dst_ip}<={s_src_ip,s_dst_ip};
always @ (posedge clk) if (rst)st<=0;else case (st)
0:st<=100;
100: if (s_tx_start)st<= 200;
200: if (wr_addr == wr_addr_end ) st <= 300 ;
300,301,302,303,304,305,306,307:st<=st+1;
308: st<=400;// tell st2 can now pick this data
400: st<=500;
500: if (rd_addr==10 && st2==400) st<=600;
600: st<=100; // ok , free now
default st<=0;
endcase
reg [15:0] chksum = 0 ;
always @(posedge clk) if (rst) chksum<=0; else case (st)
0,100: chksum <= 0;
200,300,301,302,303,304,305,306,307: chksum<=chksum+wr_data ;
endcase
always @(posedge clk) if (rst) s_tx_busy<=0;else case(st)200:s_tx_busy<=1;600:s_tx_busy<=0;endcase
always @(posedge clk)case (st)
100:begin wr_en<=1;wr_data<= s_tx_dat; wr_addr<= 8; end
200:begin wr_en<=1;wr_data<= s_tx_dat; wr_addr<=wr_addr+1; end
301:begin wr_en<=1;wr_data<= src_port_reg[7:0]; wr_addr<=0 ; end
300:begin wr_en<=1;wr_data<= src_port_reg[15:8]; wr_addr<=1 ; end
303:begin wr_en<=1;wr_data<= dst_port_reg[7:0]; wr_addr<=2 ; end
302:begin wr_en<=1;wr_data<= dst_port_reg[15:8]; wr_addr<=3 ; end
304:begin wr_en<=1;wr_data<= 8; wr_addr<=4 ; end
305:begin wr_en<=1;wr_data<= 0; wr_addr<=5 ; end
307:begin wr_en<=1;wr_data<= chksum[7:0]; wr_addr<=6 ; end
306:begin wr_en<=1;wr_data<= chksum[15:8]; wr_addr<=7 ; end
default begin wr_en<=0;wr_data<=0 ; wr_addr<= 0; end
endcase
always@(posedge clk) if (rst)st2<=0;else case (st2)
0:st2<=100;
100:if (st==400)st2<=200;
200:if (m_data_ready==1) st2<=400;
400:if (rd_addr == rd_addr_end) st2<=500 ;
500:st2<=600;
600:st2<=100;
default st2<=0;
endcase
always @ ( posedge clk ) if (rst) m_tx_len<=0; else if (st2==100) m_tx_len <= rd_addr_end + 1;
always @(posedge clk) if (rst)m_pack_valid<=0; else case (st2) 200:m_pack_valid<=1; 400:m_pack_valid<=0; endcase
always @ ( posedge clk ) case (st2)400: if (m_data_ready & (rd_addr != rd_addr_end)) rd_addr<=rd_addr+1;200: if(m_data_ready==1) rd_addr<=1;default rd_addr<=0;endcase
wire [7:0] rd_data ; assign m_tx_dat = rd_data;
ram2port #( .DWIDTH(8),.AWIDTH(12))ram2port_i(.clk(clk),.wr_en(wr_en),.wr_addr(wr_addr) ,
.rd_addr(rd_addr) ,.wr_data(wr_data),.rd_data(rd_data) );
endmodule
module ram2port
#(
parameter DWIDTH=32,
parameter AWIDTH=9
)
(
input clk,
input wr_en,
input [AWIDTH-1:0] wr_addr ,
input [AWIDTH-1:0] rd_addr ,
input [DWIDTH-1:0] wr_data,
output reg [DWIDTH-1:0] rd_data
);
reg [DWIDTH-1:0] ram [(1<<AWIDTH)-1:0];
integer i;
initial begin
for(i=0;i<(1<<AWIDTH);i=i+1)
ram[i] <= {DWIDTH{1'b0}};
rd_data <= 0;
end
always @ (posedge clk) if (wr_en) ram[wr_addr]<=wr_data;
always @ (posedge clk) rd_data <= ram[rd_addr] ;
endmodule
module ip_pack (
input clk,rst,
input [7:0] s_ip_TTL,
input [7:0] s_ip_type ,
input [15:0] s_ip_id,
input [31:0]s_ip_src,s_ip_dst ,
input s_ip_pack_valid ,
input [15:0] s_ip_pack_len ,
output reg s_ip_data_ack,
input [7:0] s_ip_data ,
output reg m_ip_tx_valid ,
input m_ip_tx_busy , // 平时必须保持busy是0
output reg [7:0] m_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( s_ip_pack_len) , //1
.in2(s_ip_id ) ,//2
.in3( 16'h4000 ) , //3
.in4( {s_ip_TTL,s_ip_type} ) , //4
.in5( 16'h0 ) ,//5
.in6(s_ip_src[31:16] ) ,//6
.in7(s_ip_src[15:0] ) ,//7
.in8(s_ip_dst[31:16] ) ,//8
.in9(s_ip_dst[15:0] ) ,//9
.checksum(checksum)
);
reg [7:0] wr_st ;
reg [15:0] cr_cntr ;always @ (posedge clk )case (wr_st) 200: cr_cntr <=cr_cntr+1 ;default cr_cntr<=1;endcase
reg [15:0] ip_pack_lenr ;always @ (posedge clk )case (wr_st) 100: ip_pack_lenr <=s_ip_pack_len[15:0] ; endcase
always @ (posedge clk) if (rst) wr_st<=0; else case (wr_st)
0: if (s_ip_pack_valid & ~m_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 m_ip_tx_valid <=1;m_ip_tx_data<= {ip_version, header_len} ;end
101:begin m_ip_tx_valid <=1;m_ip_tx_data<= 0 ;end
102:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_pack_len[15:8] ;end
103:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_pack_len[7:0] ;end
104:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_id[15:8] ;end
105:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_id[7:0] ;end
106:begin m_ip_tx_valid <=1;m_ip_tx_data<= 'h40 ;end
107:begin m_ip_tx_valid <=1;m_ip_tx_data<= 0 ;end
108:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_TTL ;end
109:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_type; end
110:begin m_ip_tx_valid <=1;m_ip_tx_data<= checksum[15:8] ;end
111:begin m_ip_tx_valid <=1;m_ip_tx_data<= checksum[7:0] ;end
112:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_src[31:24];end
113:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_src[23:16] ;end
114:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_src[15:8] ;end
115:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_src[7:0] ;end
116:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_dst[31:24] ;end
117:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_dst[23:16] ;end
118:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_dst[15:8] ;end
119:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_dst[7:0] ;end
200:begin m_ip_tx_valid <=1;m_ip_tx_data<= s_ip_data[7:0] ;end
default begin m_ip_tx_valid <=0;m_ip_tx_data<= 0 ;end
endcase
always @ (posedge clk) s_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
上述代码时序仿真通过,数据的真确定简单确认了,CHECKSUM等细节还要在整体统一调试时候进行验证分析。
?
?
下一步要
1,写好并验证mac+物理层组包,也是分两个两个模块mac.v和phy.v,分别写好之后串联在一起。
2,写一个选择模块,在mac输入之前,选择是ip层来的信号输入还是arp_reply以及icmp_reply回复。
3,有了上述发送部分,可以尝试在arp_cache.v里以及电脑里面加入对方ip和mac对应,尝试在FPGA上用UDP协议发给电脑数据包,并使用wireshark观察是否对,如果不成功进行调试。
4,成功后就要开始写接受的实现。就再分析。
下午要出去一趟,估计晚上才能回来,回来继续写。正确今天写好并仿真好mac和phy。明天抽时间进行实际包调试。
|