参考了FPGA奇哥(下列视频中UP主)的讲解。
应该可以对多路读写DDR3进行操作,仅仲裁,不涉及DMA和Uibuf等。
2023年11月所写,暂未进行测试,日后补上。
第二天已完成测试,功能可行。
深入FPGA底层设计系列-循环优先级仲裁器算法:位屏蔽仲裁算法与Verilog代码编写_哔哩哔哩_bilibili
位屏蔽算法:
描述:对输入的多通道请求进行仲裁。
步骤:
(1)原码减去对应位数(优先级最高的位次)
(2)求得(1)中输出的反码
(3)通过(2)中输出与原码进行相与,留下优先级最高的请求。
举例:
【1】
四通道输入请求,ABCD。破解后为:4‘b1000,此时D通道优先级最高。
4'b1000-4’b1 =4'b0111 ~4'b0111 = 4'b1000
1000 & 1000 == 1000
仲裁完成,准许A通道请求。
【2】
四通道输入请求,ABCD。破解后为:4‘b1110,此时B通道优先级最高。
1110 - 0100 = 1010
~1010 = 0101
1110 & 0101 = 0100
仲裁完成,准许B通道请求。
Trick:
此外,为了仲裁A通道,需要对输入的请求进行拼接操作,实现向高位借位的过程。
每次完仲裁以后,都需要改变优先级最高的那一位的位次,完成循环。
自写代码参考:
module Fast_Aritbier_LoopPrior #(
parameter In_Channel_Num = 8
)(
input wire Aritbier_Clk ,
input wire Aritbier_Rst_n ,
input wire [In_Channel_Num-1:0] I_req ,
input wire I_Busy ,
output wire [In_Channel_Num-1:0] O_Aritbier_Req
);
//Aritbier Value
reg Aritbier_Value ;
//Aritbier Flag
wire Aritbier_Begin ;
reg Aritbier_Flag ;
reg [3:0] Aritbier_Flag_delay ;
//Busy
reg I_Busy_0;
reg I_Busy_1;
//req
reg [(In_Channel_Num<<1)-1:0] I_req_Double ;
reg [In_Channel_Num-1:0] r_O_Aritbier_Req;
assign Aritbier_Begin = |I_req;
assign O_Aritbier_Req = r_O_Aritbier_Req;
assign I_req_Double = {I_req,I_req};
always @(posedge Aritbier_Clk) begin
{I_Busy_0, I_Busy_1} <= {I_Busy,I_Busy_0};
end
//Aritbier_Flag
always @(posedge Aritbier_Clk or negedge Aritbier_Rst_n) begin
if(Aritbier_Rst_n == 'd0) begin
Aritbier_Flag <= 1'b0;
end else if(Aritbier_Begin == 1'b1 && Aritbier_Flag == 1'b0) begin
Aritbier_Flag <= 1'b1;
end else if(!I_Busy_0 && I_Busy_1) begin
Aritbier_Flag <= 1'b0;
end
end
always @(posedge Aritbier_Clk) begin
Aritbier_Flag_delay <= {Aritbier_Flag_delay[2:0],Aritbier_Flag};
end
always @(posedge Aritbier_Clk or negedge Aritbier_Rst_n) begin
if(Aritbier_Rst_n == 'd0) begin
Aritbier_Value <= {{(In_Channel_Num - 1){1'b0}},1'b1};
end else if((!I_Busy_0 && I_Busy_1) && Aritbier_Value[In_Channel_Num - 1] == 1'b1) begin
Aritbier_Value <= {{(In_Channel_Num - 1){1'b0}},1'b1};
end else if(!I_Busy_0 && I_Busy_1) begin
Aritbier_Value <= Aritbier_Value << 1;
end else begin
Aritbier_Value <= Aritbier_Value;
end
end
always @(posedge Aritbier_Clk or negedge Aritbier_Rst_n) begin
if(Aritbier_Rst_n == 'd0) begin
r_O_Aritbier_Req <= {(In_Channel_Num){1'b0}};
end else if(Aritbier_Flag == 1'b1 && Aritbier_Flag_delay[0] == 1'b0) begin
r_O_Aritbier_Req <= ((~(I_req_Double - {(In_Channel_Num){1'b0},Aritbier_Value}))&I_req);
end
end
endmodule