参考了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 Aribe_LoopPrior (
- input wire Aribe_Clk ,
- input wire Aribe_Rst_n ,
- //req
- input wire Req_0 ,
- input wire Req_1 ,
- input wire Req_2 ,
- input wire Req_3 ,
-
- output wire Req_True ,
- );
- localparam Process_0 = 5'b00001;
- localparam Process_1 = 5'b00010;
- localparam Process_2 = 5'b00100;
- localparam Process_3 = 5'b01000;
-
- reg [3:0] Concat_Req_0 ;
- reg [7:0] Concat_Req_1 ;
- reg [3:0] Concat_Req_Process ;
- reg [3:0] Concat_Req_Intv ;
- reg [3:0] Concat_Result ;
- reg [3:0] Aribe_Prior_Value ;
-
- reg [4:0] STATE ;
- reg [4:0] Last_STATE ;
- reg Process_Flag ;
- reg Process_Flag_0 ;
- reg Process_Flag_1 ;
- reg Process_Flag_2 ;
- reg Process_Flag_3 ;
- wire Process_First_Begin ;
-
- wire Process_Done ;
-
- assign Process_First_Begin = |Concat_Req_0 ;//有请求未处理则将其拉高
-
- //Process_Flag将在每一次Axi busy前拉高,使用Axi busy的下降沿(或者其他的结束标识来拉低)
- always @(posedge Aribe_Clk or negedge Aribe_Rst_n) begin
- if(Aribe_Rst_n == 'd0) begin
- Process_Flag <= 1'b0;
- end else if(Process_First_Begin == 1'b1 && Process_Flag == 1'b0) begin
- Process_Flag <= 1'b1;
- end else if(Process_Done == 1'b1) begin
- Process_Flag <= 1'b0;
- end
- end
- always @(posedge Aribe_Clk) begin
- {Process_Flag_0,Process_Flag_1,
- Process_Flag_2,Process_Flag_3} <= {Process_Flag,Process_Flag_0,
- Process_Flag_1,Process_Flag_2};
- end
- always @(posedge Aribe_Clk or negedge Aribe_Rst_n) begin
- if(Aribe_Rst_n == 'd0) begin
- Concat_Req_0 <= 'd0;
- Concat_Req_1 <= 'd0;
- end else if(Process_First_Begin == 1'b1 && Process_Flag == 1'b0)begin
- Concat_Req_0 <= {Req_0, Req_1, Req_2, Req_3};
- Concat_Req_1 <= {2{Req_0, Req_1, Req_2, Req_3}};
- end
- end
-
- //每次传输结束以后修改优先级
- always @(posedge Aribe_Clk or negedge Aribe_Rst_n) begin
- if(Aribe_Rst_n == 'd0) begin
- Aribe_Prior_Value <= 4'b0001;
- end else if(Process_Done == 1'b1) begin
- case (Last_STATE)
- Process_0: begin
- Aribe_Prior_Value <= 4'b0010;
- end
- Process_1: begin
- Aribe_Prior_Value <= 4'b0100;
- end
- Process_2: begin
- Aribe_Prior_Value <= 4'b1000;
- end
- Process_3: begin
- Aribe_Prior_Value <= 4'b0001;
- end
- default: begin
- Aribe_Prior_Value <= 4'b0001;
- end
- endcase
- end
- end
-
- always @(posedge Aribe_Clk or negedge Aribe_Rst_n) begin
- if(Aribe_Rst_n == 'd0) begin
- Concat_Req_Process <= 'd0;
- end else if(Process_Flag == 1'b1 && Process_Flag_0 == 1'b0) begin
- Concat_Req_Process <= Concat_Req_1 - Aribe_Prior_Value;
- end
- end
-
- always @(posedge Aribe_Clk or negedge Aribe_Rst_n) begin
- if(Aribe_Rst_n == 'd0) begin
- Concat_Req_Intv <= 'd0;
- end else if(Process_Flag_0 == 1'b1 && Process_Flag_1 == 1'b0) begin
- Concat_Req_Intv <= ~(Concat_Req_Process[3:0]);
- end
- end
-
- always @(posedge Aribe_Clk or negedge Aribe_Rst_n) begin
- if(Aribe_Rst_n == 'd0) begin
- Concat_Result <= 'd0;
- end else if(Process_Flag_1 == 1'b1 && Process_Flag_2 == 1'b0) begin
- Concat_Result <= Concat_Req_Intv & Concat_Req_0;
- end
- end
-
- always @(posedge Aribe_Clk or negedge Aribe_Rst_n) begin
- if(Aribe_Rst_n == 'd0) begin
- Req_True <= 'd0;
- end else if(Process_Flag_2 == 1'b1 && Process_Flag_3 == 1'b0)
- Req_True <= 1'b1;
- end
- always @(posedge Aribe_Clk or negedge Aribe_Rst_n) begin
- if(Aribe_Rst_n == 'd0) begin
- STATE <= 'd0;
- end else if(Process_Flag_2 == 1'b1 && Process_Flag_3 == 1'b0) begin
- case (Concat_Result)
- 4'b0001:begin
- STATE <= Process_0;
- end
- 4'b0010:begin
- STATE <= Process_1;
- end
- 4'b0100:begin
- STATE <= Process_2;
- end
- 4'b1000:begin
- STATE <= Process_3;
- end
- default: STATE <= Process_0;
- endcase
- end
- end
- always @(posedge Aribe_Clk or negedge Aribe_Rst_n) begin
- if(Aribe_Rst_n == 'd0) begin
- Last_STATE <= 'd0;
- end else if(Process_Flag_3 == 1'b1) begin
- Last_STATE <= STATE;
- end
- end
- endmodule