一、固定优先仲裁器
所谓固定优先仲裁器,即其优先级是固定的,当有多个请求到达时,按照优先级得到仲裁结果,并且优先级一直保持不变。如当有四个请求到达时,如果最高优先级为0号请求,则对0号请求响应,进一步说明,若请求状况为4'b0110,则响应1号请求,若为4'b1100则响应2号请求。
通过分析我们可知,若优先级是按照从右到左依次降低,即最低位的请求优先级最高,则我们只需要判断出请求中最低位的1即可,将仲裁结果中对应的位拉高,其余置0,利用之前介绍到的常用的数据处理方法(见下文),利用原码和补码相与实现。
数字电路中常用的几种数据处理方法-CSDN博客
Verilog实现如下:
module fixed_arbiter #(
parameter WIDTH = 4
)
(
input [WIDTH-1:0]request,
output [WIDTH-1:0]grant
);
assign grant = request & (~request + 'd1);
endmodule : fixed_arbiter
仿真结果如下:
二、RR轮询仲裁器
Round Robin就是考虑到公平性的一种仲裁算法,在固定优先级仲裁器的基础上进行设计。即在每次仲裁之后更新优先级,如最优先级mask初始为4'b1111,最低位优先级最高,则在输入请求为4'b1101的第一次仲裁后,输出仲裁结果为4'b0001,mask要变为4'b1110,优先级变为bit1的优先级最高,然后是bit2、bit3,即最低位请求已经被响应过了,接下来希望其他请求被响应,轮询着被仲裁。在请求还是4'b1101的情况下第二次的仲裁结果为4'b0100,这事因为bit1虽然优先级高于bit2但是没有请求,因此响应bit2的请求。当bit3的请求被响应后,优先级应变会1111,然后再次循环。一次完整的仲裁结果如下:
请求 | 优先级 | 仲裁结果 |
---|---|---|
1101 | 1111 | 0001 |
1101 | 1110 | 0100 |
1101 | 1000 | 1000 |
1101 | 1111 | 0001 |
1101 | 1110 | 0100 |
1101 | 1000 | 1000 |
结合上述的固定优先级仲裁,我们可以通过将请求和优先级相与的结果输入到固定优先级仲裁器得到RR轮询的结果。这样做的实质就是将已经响应过的bit位以及请求为0的bit位去除掉,然后为1的最低位满足在有请求的bit位中,其优先级最高。
那我们已经知道:
RR轮询仲裁器=优先级更新+固定优先级仲裁器
其中,固定优先级仲裁其的输入=请求&优先级。
接下来就是如何更新优先级,我们观察仲裁结果和优先级的变化情况,优先级就是将仲裁输出结果为1的高几位置为1,仲裁结果的本位及低位要变为0。如仲裁结果为0001,bit0为1,那bit3、bit2、bit1就要变为1,bit0变为0,优先级就要更新为1110;如仲裁结果为0010,那优先级就要更新为1100。当仲裁结果的最高位为1时,按照之前的算法此时变为4'b0000,不符合优先级变化要求,因此此时将其重置为1111。
那如何实现上述的变化呢,从要实现的效果来看,和之前文章提到的独热码的反码保留高位连续的1并将低位置0一致,仲裁结果为独热码,可参考下面文章:
数字电路中常用的几种数据处理方法-CSDN博客
因此优先级的更新为~grant&(~grant+1)
,并且当仲裁结果最高位为1时需要更新为4'b1111。
Verilog实现如下:
module RR#(
parameter WIDTH = 4
)
(
input clk,
input rst_n,
input [WIDTH-1:0] request,
output [WIDTH-1:0] grant_o
);
reg [WIDTH-1:0]mask;
wire [WIDTH-1:0]grant_0;
wire [WIDTH-1:0]grant_1;
wire [WIDTH-1:0]mask_req;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
mask <= ~0;
else
mask <= ~(grant_o[WIDTH-1:0]+grant_o[WIDTH-1:0] - 1'b1);
end
assign grant_o = (mask_req == 4'b0) ? grant_0 : grant_1;
assign mask_req = mask & request;
fixed_arbiter inst_fixed_arbiter_0
(
.request(request),
.grant(grant_0)
);
fixed_arbiter inst_fixed_arbiter_1
(
.request(mask_req),
.grant(grant_1)
);
endmodule : RR
在代码中我可以发现,我们没有采取在仲裁结果为1000时将优先级更新为1的情况,而是当mask为0时采用固定优先级更新,这时候和将mask重置为1的效果是一样的,当然也可以通过修改代码实现功能。
仿真结果如图所示: