前言
仲裁器Arbiter是数字设计中非常常见的模块,应用也非常广泛。定义就是当有两个或两个以上的模块需要占用同一个资源的时候,我们需要由仲裁器arbiter来决定哪一个模块来占有这个资源。一般来说,提出占有资源的模块要产生一个请求(request),所有的请求送给仲裁器之后,仲裁器要返回一个许可(grant)。
固定优先级仲裁器(fixed priority)
固定优先级,每个模块的优先级是固定的,是提前分配好的,如果有两个模块同时产生request,那么优先级高的模块可以获得grant。假设有三个模块分别为CBA,用3bit 的request表示它们的请求,令越低的位优先级越高,即当request = 3'b011时,A优先级最高,所以grant=3'b001,将总线控制权交给模块A。
1.casex语句的固定优先仲裁
可以使用casex语句,来进行固定优先级仲裁,verilog代码如下:
1.1代码
module fixed_arbiter(
input rstn ,
input clk ,
input [2:0] request ,
output reg [2:0] grant
);
always @(posedge clk)begin
if(!rstn)begin
grant <= 3'b000;
end
else begin
casex(request)
3'b??1: grant <= 3'b001;
3'b?10: grant <= 3'b010;
3'b100: grant <= 3'b100;
default: grant <= 3'b000;
endcase
end
end
endmodule
casez语句和case语句的用法非常相似,其唯一的区别在于,状态z在casez语句中不会被视为正常的z状态,而是将表达式中,标记为z的那个(或那些)bit视为不在乎(dont care)。casex语句和casez语句的用法非常相似,其唯一的区别在于,casex可以同时将状态x和状态z均视为不在乎(dont care)。
正如上面的代码,当最低位为1时,不在乎前2bit是什么,只要最低位为1,那么就给grant赋值3'b001.
1.2testbench
module fixed_arbiter_tb();
reg clk, rstn;
wire [2:0] grant;
reg [2:0] request;
initial begin
forever #5 clk <= ~clk;
end
initial begin
clk <= 1'b0;
rstn <= 1'b0;
#15
rstn <= 1'b1;
request <= 3'b110;
#10
request <= #1 3'b011;
#10
request <= #1 3'b111;
#10
request <= #1 3'b010;
#50
$finish();
end
fixed_arbiter u_fixed_arbiter(
.clk (clk) ,
.rstn (rstn) ,
.request (request) ,
.grant (grant)
);
initial begin
$fsdbDumpfile("fixed_arbiter.fsdb");
$fsdbDumpvars(0);
end
endmodule
波形
2.利用补码特点,判断优先级。
一个数和它的补码相与,得到的结果是一个独热码,独热码为1的那一位是这个数最低的1。
例如a=4'b1011,a的补码为:~(a-1)=4'b0101。a和它的补码相与得到:4'b0001。
例如a=4'b1010,a的补码为:~(a-1)=4'b0110。a和它的补码相与得到:4'b0010。
利用这个特点,我们可以得到一个很简单的固定优先级仲裁器写法(使用按位运算符):
2.1代码
module fixed_arbiter(
input rstn ,
input clk ,
input [2:0] request ,
output reg [2:0] grant
);
always @(posedge clk)begin
if(!rstn)begin
grant <= 3'b000;
end
else begin
grant <= request & (~(request-1));
end
end
endmodule
其实就是利用了一个特性:一个数和它的补码相与,得到的结果是一个独热码,独热码为1的那一位是这个数最低的1。