一、仲裁模块在协议栈的作用
(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
三、模块仿真
轮询信号去控制通道的选取
轮询读取各通道的数据,并将数据发送到输出端