利用FIFO模拟UDP包文的发送

部分信号列表:

input          [15:0]    dest_port    ; //目的端口
input          [15:0]    sour_port    ; //源端口
input          [31:0]    dest_ip      ; //目的IP地址
input          [31:0]    sour_ip      ; //源IP地址
input          [15:0]    din          ; //输入的数据
input                    din_vld      ;
input                    din_sop      ;
input                    din_eop      ;
output   reg   [15:0]    dout         ;
output   reg             dout_vld     ;
output   reg             dout_sop     ;
output   reg             dout_eop     ;

长度:UDP报文的整个大小,最小为8个字节(仅为首部)。
在这里插入图片描述
输入的包文如下:
数据0 数据1 数据2 … 数据n-2 数据n-1
输出的包文如下:
UDP首部 数据0 数据1 … 数据n-2 数据n-1
UDP首部包括源端口、目的端口、长度和检验和。
首部的源端口和目的端口由输入信号sour_port和dest_port给出:
首部的长度包括UDP首部和UDP数据的长度,单位为字节。UDP首部长度固定为8字节,UDP数据长度来自于对输入包文的统计。
首部的检验和计算的是UDP伪首部、UDP首部和UDP数据的校验和。其计算方式为:
把伪首部添加到UDP上:
把所有位划分为16位(2字节)的字:
把所有16位的字相加,如果遇到进位,则将高于16字节的进位部分的值加到最低位上,举例,16’hBB5E+16’hFCED=17’h1B84B,则将1放到最低位,得到结果是16‘hB84C
将所有字相加得到的结果应该为一个16位的数,将该数取反则可以得到检验和checksum.
注意:UDP伪首部只用于计算检验和,是不用输出去的。

///
首先,需要使用计数器来区分包头和数据

//计数器计数写入的数据字节长度
always @(posedge clk or negedge rst_n)begin
   if(rst_n==0)begin
      cnt0 <= 0;
   end
   else if(add_cnt0)begin
      if(end_cnt0)begin
         cnt0 <= 0;
      end
      else begin
         cnt0 <= cnt0 + 1'b1;
      end
   end
end
assign    add_cnt0 = din_vld;
assign    end_cnt0 = add_cnt0 && cnt0 == din_eop;
//数据FIFO的写使能和写数据
assign    wr_en = din_vld ;
assign    wdata = {din_sop,din_eop,din};
//信息FIFO的写使能和写数据
assign    msg_wr_en = end_cnt0;
assign    msg_wdata = {cnt0 + 1,sum_tmp_b};

//数据的校验和计算
always @(*)begin
   if(din_sop && din_vld)
      sum_tmp_a = din;
   else if(din_vld)
      sum_tmp_a = sum + din;
   else
      sum_tmp_a = sum;
end

assign    sum_tmp_b = sum_tmp_a[16] + sum_tmp_a[15:0];

always @(posedge clk or negedge rst_n)begin
    if(rst_n==0)begin
       sum <= 0;
    end
    else begin
       sum <= sum_tmp_b;
    end
end

//UDP头部拼接
assign   data_head = {sour_port,dest_port,udp_len,udp_sum};
assign   pre_head  = {sour_ip,dest_ip,8'h0,8'hd17,udp_len,data_head};

assign   udp_len   = msg_q[31:16] + 8;
assign   udp_sum   = ~sum_3_0;

//计数器发UDP首部,一共8个字节
always @(posedge clk or negedge rst_n)begin
   if(rst_n==0)begin
      cnt <= 0;
   end
   else if(add_cnt)begin
      if(end_cnt)begin
         cnt <= 0;
      end
      else begin
         cnt <= cnt + 1'b1;
      end
   end
end
assign    add_cnt = flag == 0 && msg_empty == 0;
assign    end_cnt = add_cnt && cnt == 5 - 1;//因为计算校验和需要四个流水时钟,计算完后在第五个时钟被组装发送出去

assign    dout_eop_tmp = rd_en && q[16];

always @(posedge clk or negedge rst_n)begin
   if(rst_n==0)begin
      flag <= 0;
   end
   else if(end_cnt)begin
      flag <= 1;
   end
   else if(dout_eop_tmp)begin
      flag <= 0;
   end
end
//
//                     通过流水线计算出校验和                             //
//                     注意要在4拍内计算出来                              //
//
assign    sum_0_0_tmp = pre_head[159 -:16] + pre_head[143 -:16];
assign    sum_0_1_tmp = pre_head[127 -:16] + pre_head[111 -:16];
assign    sum_0_2_tmp = pre_head[95  -:16] + pre_head[79  -:16];
assign    sum_0_3_tmp = pre_head[63  -:16] + pre_head[47  -:16];
assign    sum_0_4_tmp = pre_head[31  -:16] + pre_head[15  -:16];
assign    sum_0_5_tmp = msg_q[15 :0];

always @(posedge clk or negedge rst_n)begin
   if(rst_n==0)begin
       sum_0_0 <= 0;
       sum_0_1 <= 0;
       sum_0_2 <= 0;
       sum_0_3 <= 0;
       sum_0_4 <= 0;
       sum_0_5 <= 0;
   end
   else if(add_cnt && cnt == 1-1)begin
       sum_0_0 <= sum_0_0_tmp[16] + sum_0_0_tmp[15:0];
       sum_0_1 <= sum_0_1_tmp[16] + sum_0_1_tmp[15:0];
       sum_0_2 <= sum_0_2_tmp[16] + sum_0_2_tmp[15:0]; 
       sum_0_3 <= sum_0_3_tmp[16] + sum_0_3_tmp[15:0];  
       sum_0_4 <= sum_0_4_tmp[16] + sum_0_4_tmp[15:0];
       sum_0_5 <= sum_0_5_tmp[16] + sum_0_5_tmp[15:0];    
   end
end

assign   sum_1_0_tmp = sum_0_0 + sum_0_1;
assign   sum_1_1_tmp = sum_0_2 + sum_0_3;
assign   sum_1_2_tmp = sum_0_4 + sum_0_5;

always @(posedge clk or negedge rst_n)begin
   if(rst_n)begin
      sum_1_0 <= 0;
      sum_1_1 <= 0;
      sum_1_2 <= 0;
   end
   else if(add_cnt && cnt == 2-1)begin
      sum_1_0 <= sum_1_0_tmp[16] + sum_1_0_tmp[15:0];
      sum_1_1 <= sum_1_1_tmp[16] + sum_1_1_tmp[15:0];
      sum_1_2 <= sum_1_2_tmp[16] + sum_1_2_tmp[15:0];      
   end
end

assign   sum_2_0_tmp = sum_1_0 + sum_1_1;
assign   sum_2_1_tmp = sum_1_2 ;
always @(posedge clk or negedge rst_n)begin
   if(rst_n==0)begin
      sum_2_0 <= 0;
      sum_2_1 <= 0;
   end
   else if(add_cnt && cnt == 3-1)begin
      sum_2_0 <= sum_2_0_tmp[16] + sum_2_0_tmp[15:0];
      sum_2_1 <= sum_2_1_tmp[16] + sum_2_1_tmp[15:0];
   end
end

assign  sum_3_0_tmp = sum_2_0 + sum_2_1;
always @(posedge clk or negedge rst_n)begin
   if(rst_n==0)begin
      sum_3_0 <= 0;
   end
   else if(add_cnt && cnt == 4-1)begin
      sum_3_0 <= sum_3_0_tmp[16] + sum_3_0_tmp[15:0];
   end
end

//数据FIFO的读使能
assign   rd_en = flag == 1 && msg_empty == 0;  //输出数据flag==1

//信息FIFO的读使能
assign   msg_rd_en = dout_eop_tmp;
assign   dout_eop_tmp = rd_en && q[16];

//dout
always @(posedge clk or negedge rst_n)begin
   if(rst_n==0)begin
      dout <= 0;
   end
   else if(add_cnt && cnt != 1-1)begin
      dout <= data_head[63 - 16*(cnt-1) -:16];
   end
   else 
      dout <= q[15:0];
end

//dout_sop
always @(posedge clk or negedge rst_n)begin
   if(rst_n===0)begin
      dout_sop <= 0;
   end
   else begin
      dout_sop <= add_cnt && cnt == 1-1;
   end
end

//dout_eop
always @(posedge clk or negedge rst_n)begin
   if(rst_n===0)begin
      dout_eop <= 0;
   end
   else begin
      dout_eop <= dout_eop_tmp;;
   end
end
//dout_vld
always @(posedge clk or negedge rst_n)begin
   if(rst_n===0)begin
      dout_vld <= 0;
   end
   else begin
      dout_vld <= rd_en || add_cnt;
   end
end


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值