UDP协议实现之IP发送实现

 

代码还没有写好,先放在这里,下午有空继续写写。


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是否正确,可在后续的统调中进行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值