10G UDP协议栈 (8)仲裁模块

一、仲裁模块在协议栈的作用

(1)在UDP层会有两种数据,一种为UDP数据,另外一种为ICMP数据,所以再将数据由UDP层传输到IP层的过程中需要对两种数据进行仲裁。

(2)在IP层会有两种数据,一种为IP数据包,另外一种为ARP数据包,所以再将数据由IP层数据传递到MAC层的过程中需要对两种数据进行仲裁。

二、模块功能

        首先对各通道输入进来的数据进行缓存,之后对于各个通道的数据进行轮询读取,防止一直再读一个通道数据造成另外一个通道数据的丢失。

所以模块需要一个轮询控制信号,去控制通道的读写。

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_channel_select <= 'd0;
    else 
        if(r_cnt == w_len + 1 && !w_user_fifo_empty1 && !r_arbiter_sig )//当C1通道有数据并且上一次读的是C0的时候,下一次要去读C1
            r_channel_select <= 1'b1;
        else if(r_cnt == w_len + 1 && !w_user_fifo_empty0 && r_arbiter_sig)
            r_channel_select <= 1'b0;
        else if(!w_user_fifo_empty1 && !r_arbiter_lock)//刚开始的时候,选择先有数据的通道
            r_channel_select <= 1'b1;
        else if(!w_user_fifo_empty0 && !r_arbiter_lock)
            r_channel_select <= 1'b0;        
        else
            r_channel_select <= r_channel_select;
end

另外,当去读其中一个通道的数据时,需要加入一个锁信号,锁住当前的通道,直到当前通道的一包数据读取结束。

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_arbiter_lock <= 1'b0;
    else 
        if(r_cnt == w_len + 1)
            r_arbiter_lock <= 1'b0;
        else if(!w_user_fifo_empty0 && !r_arbiter_lock && !r_channel_select && m_axis_o0_ready)
            r_arbiter_lock <= 1'b1;
        else if(!w_user_fifo_empty1 && !r_arbiter_lock && r_channel_select && m_axis_o0_ready) 
            r_arbiter_lock <= 1'b1;
        else
            r_arbiter_lock <= r_arbiter_lock;
end

同时还需要一个通道选择信号,去根据轮询控制信号选取读取的通道。

//通道选择
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_arbiter_sig <= 'd0;
    else 
        if(!w_user_fifo_empty0 && !r_arbiter_lock && !r_channel_select && m_axis_o0_ready)
            r_arbiter_sig <= 'd0;
        else if(!w_user_fifo_empty1 && !r_arbiter_lock && r_channel_select && m_axis_o0_ready)
            r_arbiter_sig <= 1'b1;
        else
            r_arbiter_sig <= r_arbiter_sig;     
end

总的代码如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/18 21:37:56
// Design Name: 
// Module Name: Aribter_2To1
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// IP:16'dlen,48'dsource_mac,16'dtype
// UDP ICMP://1'bMF,16'dlen,1'bsplit,8'dtype,13'doffset,16'dID
//
module Aribter_2To1 #(
    parameter       P_DATA_TYPE   = 1             //等于1的时候代表仲裁IP数据,等于0的时候代表仲裁UDP数据
)
(
    input           i_clk               ,
    input           i_rst               ,

    input  [63:0]   s_axis_c0_data      ,
    input  [79:0]   s_axis_c0_user      ,
    input  [7 :0]   s_axis_c0_keep      ,
    input           s_axis_c0_last      ,
    input           s_axis_c0_valid     ,
    output          s_axis_c0_ready     ,

    input  [63:0]   s_axis_c1_data      ,
    input  [79:0]   s_axis_c1_user      ,
    input  [7 :0]   s_axis_c1_keep      ,
    input           s_axis_c1_last      ,
    input           s_axis_c1_valid     ,
    output          s_axis_c1_ready     ,

    output [63:0]   m_axis_o0_data      ,
    output [79:0]   m_axis_o0_user      ,
    output [7 :0]   m_axis_o0_keep      ,
    output          m_axis_o0_last      ,
    output          m_axis_o0_valid     ,
    input           m_axis_o0_ready  
);

reg [63:0]          rm_axis_o0_data       ;
reg [79:0]          rm_axis_o0_user       ;
reg [7 :0]          rm_axis_o0_keep       ;
reg                 rm_axis_o0_last       ;
reg                 rm_axis_o0_valid      ;

reg                 r_data_fifo_rden0     ;
reg                 r_data_fifo_rden1     ;
reg                 r_keep_fifo_rden0     ;
reg                 r_keep_fifo_rden1     ;
reg                 r_user_fifo_rden0     ;
reg                 r_user_fifo_rden1     ;

reg                 r_arbiter_sig         ;
reg                 r_arbiter_lock        ;
reg [15:0]          r_cnt                 ;
reg                 r_channel_select      ;//保证两个通道是轮询读的

wire [63:0]         w_fifo_data_out0      ;
wire [7 :0]         w_fifo_keep_out0      ;
wire [79:0]         w_fifo_user_out0      ;
wire [63:0]         w_fifo_data_out1      ;
wire [7 :0]         w_fifo_keep_out1      ;
wire [79:0]         w_fifo_user_out1      ;

wire                w_user_fifo_empty0    ;
wire                w_user_fifo_empty1    ;
wire [15:0]         w_len                 ;    

assign m_axis_o0_data  =  rm_axis_o0_data ;
assign m_axis_o0_user  =  rm_axis_o0_user ;
assign m_axis_o0_keep  =  rm_axis_o0_keep ;
assign m_axis_o0_last  =  rm_axis_o0_last ;
assign m_axis_o0_valid =  rm_axis_o0_valid;


assign w_len = P_DATA_TYPE ?
               r_arbiter_sig ? w_fifo_user_out1[79:64] : w_fifo_user_out0[79:64] :
               r_arbiter_sig ? w_fifo_user_out1[53:38] : w_fifo_user_out1[53:38] ;


/***C0通道数据缓存****/
//数据
FIFO_DATA_64X256 u0_FIFO_DATA_64X256 (
  .clk          (i_clk              ),
  .srst         (i_rst              ),
  .din          (s_axis_c0_data     ),
  .wr_en        (s_axis_c0_valid    ),
  .rd_en        (r_data_fifo_rden0  ),
  .dout         (w_fifo_data_out0   ),
  .full         (),
  .empty        () 
);
//keep信号
FIFO_KEEP_8X32 u0_FIFO_KEEP_8X32 (
  .clk          (i_clk              ),
  .srst         (i_rst              ),
  .din          (s_axis_c0_keep     ),
  .wr_en        (s_axis_c0_last     ),
  .rd_en        (r_keep_fifo_rden0  ),
  .dout         (w_fifo_keep_out0   ),
  .full         (),
  .empty        () 
);
//user信号
FIFO_USER_INFO_80X128 u0_FIFO_USER_INFO_80X128 (
  .clk          (i_clk              ),
  .srst         (i_rst              ),
  .din          (s_axis_c0_user     ),
  .wr_en        (s_axis_c0_last     ),
  .rd_en        (r_user_fifo_rden0  ),
  .dout         (w_fifo_user_out0   ),
  .full         (),
  .empty        (w_user_fifo_empty0 ) 
);

/***C1通道数据缓存****/
//数据
FIFO_DATA_64X256 u1_FIFO_DATA_64X256 (
  .clk          (i_clk              ),
  .srst         (i_rst              ),
  .din          (s_axis_c1_data     ),
  .wr_en        (s_axis_c1_valid    ),
  .rd_en        (r_data_fifo_rden1  ),
  .dout         (w_fifo_data_out1   ),
  .full         (),
  .empty        () 
);
//keep信号
FIFO_KEEP_8X32 u1_FIFO_KEEP_8X32 (
  .clk          (i_clk              ),
  .srst         (i_rst              ),
  .din          (s_axis_c1_keep     ),
  .wr_en        (s_axis_c1_last     ),
  .rd_en        (r_keep_fifo_rden1  ),
  .dout         (w_fifo_keep_out1   ),
  .full         (),
  .empty        () 
);
//user信号
FIFO_USER_INFO_80X128 u1_FIFO_USER_INFO_80X128 (
  .clk          (i_clk              ),
  .srst         (i_rst              ),
  .din          (s_axis_c1_user     ),
  .wr_en        (s_axis_c1_last     ),
  .rd_en        (r_user_fifo_rden1  ),
  .dout         (w_fifo_user_out1   ),
  .full         (),
  .empty        (w_user_fifo_empty1 ) 
);

//
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_cnt <= 'd0;
    else
        if(r_cnt == w_len + 2)
            r_cnt <= 'd0;
        else if(r_arbiter_lock)
            r_cnt <= r_cnt + 1;
        else
            r_cnt <= r_cnt ;
end
//通道选择
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_arbiter_sig <= 'd0;
    else 
        if(!w_user_fifo_empty0 && !r_arbiter_lock && !r_channel_select && m_axis_o0_ready)
            r_arbiter_sig <= 'd0;
        else if(!w_user_fifo_empty1 && !r_arbiter_lock && r_channel_select && m_axis_o0_ready)
            r_arbiter_sig <= 1'b1;
        else
            r_arbiter_sig <= r_arbiter_sig;     
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_arbiter_lock <= 1'b0;
    else 
        if(r_cnt == w_len + 1)
            r_arbiter_lock <= 1'b0;
        else if(!w_user_fifo_empty0 && !r_arbiter_lock && !r_channel_select && m_axis_o0_ready)
            r_arbiter_lock <= 1'b1;
        else if(!w_user_fifo_empty1 && !r_arbiter_lock && r_channel_select && m_axis_o0_ready) 
            r_arbiter_lock <= 1'b1;
        else
            r_arbiter_lock <= r_arbiter_lock;
end
//轮询信号控制
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_channel_select <= 'd0;
    else 
        if(r_cnt == w_len + 1 && !w_user_fifo_empty1 && !r_arbiter_sig )//当C1通道有数据并且上一次读的是C0的时候,下一次要去读C1
            r_channel_select <= 1'b1;
        else if(r_cnt == w_len + 1 && !w_user_fifo_empty0 && r_arbiter_sig)
            r_channel_select <= 1'b0;
        else if(!w_user_fifo_empty1 && !r_arbiter_lock)//刚开始的时候,选择先有数据的通道
            r_channel_select <= 1'b1;
        else if(!w_user_fifo_empty0 && !r_arbiter_lock)
            r_channel_select <= 1'b0;        
        else
            r_channel_select <= r_channel_select;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_data_fifo_rden0 <= 'd0;
    else 
        if(r_cnt == w_len && r_data_fifo_rden0)
           r_data_fifo_rden0 <= 1'b0; 
        else if(r_user_fifo_rden0 )
           r_data_fifo_rden0 <= 1'b1; 
        else 
           r_data_fifo_rden0 <= r_data_fifo_rden0;  
end
//TODO:KEEP、USER信号的读
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_user_fifo_rden0 <= 'd0;
    else 
        if(!w_user_fifo_empty0 && !r_arbiter_lock && !r_channel_select && m_axis_o0_ready)
            r_user_fifo_rden0 <= 'd1;
        else if(r_user_fifo_rden0 )
            r_user_fifo_rden0 <= 1'b0;
        else
            r_user_fifo_rden0 <= 'd0;
end
//KEEP信号的读
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_keep_fifo_rden0 <= 'd0;
    else 
        if(r_cnt == w_len - 2)
            r_keep_fifo_rden0 <= 'd1;
        else if(r_keep_fifo_rden0)
            r_keep_fifo_rden0 <= 1'b0;
        else
            r_keep_fifo_rden0 <= 'd0;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_data_fifo_rden1 <= 'd0;
    else 
        if(r_cnt == w_len && r_data_fifo_rden1)
           r_data_fifo_rden1 <= 1'b0; 
        else if(r_user_fifo_rden1)
           r_data_fifo_rden1 <= 1'b1; 
        else 
           r_data_fifo_rden1 <= r_data_fifo_rden1;  
end
//TODO:KEEP、USER信号的读
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_user_fifo_rden1 <= 'd0;
    else 
        if(!w_user_fifo_empty1 && !r_arbiter_lock && r_channel_select && m_axis_o0_ready)
            r_user_fifo_rden1 <= 'd1;
        else if(r_user_fifo_rden1)
            r_user_fifo_rden1 <= 1'b0;
        else
            r_user_fifo_rden1 <= 'd0;
end
//KEEP信号的读
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_keep_fifo_rden1 <= 'd0;
    else 
        if(r_cnt == w_len - 2)
            r_keep_fifo_rden1 <= 'd1;
        else if(r_keep_fifo_rden1)
            r_keep_fifo_rden1 <= 1'b0;
        else
            r_keep_fifo_rden1 <= 'd0;
end

//输出控制
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_o0_data <= 'd0;
    else
        if(r_arbiter_lock && !r_arbiter_sig )
            rm_axis_o0_data <= w_fifo_data_out0;
        else if(r_arbiter_lock && r_arbiter_sig)
            rm_axis_o0_data <= w_fifo_data_out1;
        else
            rm_axis_o0_data <= rm_axis_o0_data;
end
//USER信号控制
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_o0_user <= 'd0;
    else
        if(r_arbiter_lock && !r_arbiter_sig)
            rm_axis_o0_user <= w_fifo_user_out0;
        else if(r_arbiter_lock && r_arbiter_sig)
            rm_axis_o0_user <= w_fifo_user_out1;
        else
            rm_axis_o0_user <= rm_axis_o0_user;
end
//Keep信号控制
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_o0_keep <= 'd0;
    else
        if(r_arbiter_lock && !r_arbiter_sig && r_cnt == w_len + 1)
            rm_axis_o0_keep <= w_fifo_keep_out0;
        else if(r_arbiter_lock && r_arbiter_sig && r_cnt == w_len + 1)
            rm_axis_o0_keep <= w_fifo_keep_out1;
        else
            rm_axis_o0_keep <= 8'hff;
end
//Last信号控制
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_o0_last <= 1'b0;
    else
        if(r_cnt == w_len + 1 && r_arbiter_lock)
            rm_axis_o0_last <= 1'b1; 
        else
            rm_axis_o0_last <= 1'b0;
end
//Valid信号
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_o0_valid <= 1'b0;
    else
        if(rm_axis_o0_last)
            rm_axis_o0_valid <= 1'b0;
        else if(r_arbiter_lock && r_cnt == 2)
            rm_axis_o0_valid <= 1'b1;
        else
            rm_axis_o0_valid <= rm_axis_o0_valid;
end

endmodule

三、模块仿真 

轮询信号去控制通道的选取

轮询读取各通道的数据,并将数据发送到输出端

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值