c0和c1表示输入的俩个数据通道,c0优先级高,P_ARBITER_LAYER 表示当前是在IP层进行仲裁还是MAC层,可复用于俩个模块。
module Abiter_module#(
parameter P_ARBITER_LAYER = 1
)(
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_out_data ,
output [79:0] m_axis_out_user ,
output [7 :0] m_axis_out_keep ,
output m_axis_out_last ,
output m_axis_out_valid ,
input m_axis_out_ready
);
MAC层负责接收来自IP层和ARP层的数据,IP层负责ICMP和UDP层数据,所以MAC层和IP层需要对上层协议的数据包进行仲裁,以决定先发送哪个上层数据。
于MAC层而言,ARP应当具有更高的优先级,于IP层而言,ICMP具有更高的优先级。
输入数据全部先进入FIFO,当任何一个通道的FIFO不为空时,即可开启仲裁锁,因为此时必然会有一个通道获得仲裁结果。
随后便可以根据当前获得仲裁的通道开启相应的FIFO进行数据输出。
//r_arbiter_flag = 0表示通道0响应仲裁,为1表示通道1响应仲裁
//通道0具有更高的相应优先级
always @(posedge i_clk or posedge i_rst)begin
if(i_rst)
r_arbiter_flag <= 'd0;
else if(!w_fifo_c0_user_empty && !r_arbiter_lock)
r_arbiter_flag <= 'd0;
else if(!w_fifo_c1_user_empty && !r_arbiter_lock)
r_arbiter_flag <= 'd1;
else
r_arbiter_flag <= r_arbiter_flag;
end
//r_arbiter_lock表示仲裁锁,得到一次仲裁结果后,
//只有当前仲裁的通道将一个数据包完整输出后才可以响应下一次仲裁
always @(posedge i_clk or posedge i_rst)begin
if(i_rst)
r_arbiter_lock <= 'd0;
else if(r_send_cnt == r_pkt_len && r_arbiter_lock && r_pkt_len != 0)
r_arbiter_lock <= 'd0;
else if(!r_arbiter_lock && !w_fifo_c0_user_empty)
r_arbiter_lock <= 'd1;
else if(!r_arbiter_lock && !w_fifo_c1_user_empty)
r_arbiter_lock <= 'd1;
else
r_arbiter_lock <= r_arbiter_lock;
end
输入三组通道0数据以及俩组通道1数据,其中第一组通道0数据和第一组通道1数据是同时产生的
fork
begin
repeat(10)@(posedge clk);
send_c0();
repeat(10)@(posedge clk);
send_c0();
repeat(10)@(posedge clk);
send_c0();
end
begin
repeat(10)@(posedge clk);
send_c1();
repeat(10)@(posedge clk);
send_c1();
end
join
仿真波形与验证思路符合。