前言:
仲裁模块设计,解决当IP层同时收到UDP层和ICMP层数据以及MAC层同时收到ARP层和IP层数据时候的仲裁问题
一、模块设计
1、模块接口
设计代码为本人参考FPGA奇哥系列网课自行编写
端口A相较于端口B有更高的优先级
module Data_2to1_arbiter#(
parameter P_INTERVAL_LEN = 10
)(
input i_clk ,
input i_rst ,
input [7 :0] i_data_a ,
input i_valid_a ,
input i_last_a ,
input [15:0] i_len_a ,
input [15:0] i_type_a ,
input [7 :0] i_data_b ,
input i_valid_b ,
input i_last_b ,
input [15:0] i_len_b ,
input [15:0] i_type_b ,
output o_nxt_frame_stop ,
output [7 :0] o_data ,
output o_valid ,
output o_last ,
output [15:0] o_len ,
output [15:0] o_type
);
2、实现方式
通过FIFO实现仲裁过程:
ARP报文和ICMP报文具有更高的优先级,因为他们往往很久才会传输一次。
FIFO_8x256 FIFO_8x256_port_a (
.clk (i_clk ),
.din (ri_data_a ),
.wr_en (ri_valid_a ),
.rd_en (r_fifo_rden_a ),
.dout (w_fifo_douta ),
.full (w_fifo_fulla ),
.empty (w_fifo_emptya )
);
FIFO_32x16 FIFO_32x16_port_a (
.clk (i_clk ),
.din ({ri_type_a,ri_len_a} ),
.wr_en (w_valid_a_pos ),
.rd_en (w_fifo_rden_a_pos ),
.dout (w_fifo_douta_type_len ),
.full (),
.empty ()
);
FIFO_8x256 FIFO_8x256_port_b (
.clk (i_clk ),
.din (ri_data_b ),
.wr_en (ri_valid_b ),
.rd_en (r_fifo_rden_b ),
.dout (w_fifo_doutb ),
.full (w_fifo_fullb ),
.empty (w_fifo_emptyb )
);
FIFO_32x16 FIFO_32x16_port_b (
.clk (i_clk ),
.din ({ri_type_b,ri_len_b} ),
.wr_en (w_valid_b_pos ),
.rd_en (w_fifo_rden_b_pos ),
.dout (w_fifo_doutb_type_len ),
.full (),
.empty ()
);
一共有四个FIFO模块,分别用来存储端口A和端口B的数据和类型长度信息,输入的数据进入相应的FIFO当中,对应的类型和长度信息也存入FIFO,在if-else当中FIFO_a(存优先级高的报文,ICMP或ARP)的响应优先级更高,通过判断FIFO是否为空进行相应仲裁。
//每次发完数据仲裁信号归零,当仲裁信号为0时候才会响应下一次
always @(posedge i_clk or posedge i_rst)begin
if(i_rst)
r_arbiter <= 'd0;
else if(ro_last)
r_arbiter <= 'd0;
else if(!w_fifo_emptya && r_arbiter == 0 && r_interval_cnt == P_INTERVAL_LEN)
r_arbiter <= 'd1;
else if(!w_fifo_emptyb && r_arbiter == 0 && r_interval_cnt == P_INTERVAL_LEN)
r_arbiter <= 'd2;
else
r_arbiter <= r_arbiter;
end
总结:
完整代码参考GitHub:https://github.com/shun6-6/Tri_Eth_UDP_pro_stack