首页 > 解决方案 > 了解一个简单的循环仲裁器 verilog 代码

问题描述

看看下面的arbiter.v代码:

有人告诉我想想 rr_arbiter 是一个简化的波纹借用电路,可以环绕。

'base' 是一个热信号,指示应考虑授予的第一个请求。

嗯?你们知道如何生成“基本”输入信号吗?

注意减法。借位逻辑使其搜索以找到下一个设置位。

为什么 ~(double_req-base) ?

module arbiter (
    req, grant, base
);

parameter WIDTH = 16;

input [WIDTH-1:0] req;
output [WIDTH-1:0] grant;
input [WIDTH-1:0] base;

wire [2*WIDTH-1:0] double_req = {req,req};
wire [2*WIDTH-1:0] double_grant = double_req & ~(double_req-base);
assign grant = double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH];

endmodule

标签: verilogfpgaround-robin

解决方案


编辑:正如有人指出的那样,我最初只指出了如何设置输入信号,并举了两个特殊情况作为例子。让我试着解释一下它是如何工作的。你的问题是一个好的开始:

为什么 ~(double_req-base) ?

正如有人向您指出的那样,这是基于波纹借位减法器的原理。当您从另一个数字中减去一个数字时,无论您使用哪种数字系统,您都从最低的顺序开始,并尝试从相同的顺序中减去两个数字。在二进制示例中,这看起来像这样:

1011     =    11
0010 -   =     2 -
──────        ────
1001     =     9

如您所见,1 - 1is valid 并且 yield 0。但是,如果这不可能,您可以从更高的订单号借入。这张图片显示了一个简单的例子,说明它在十进制系统中的样子。十进制系统中的一个示例可能是:

1001     =     01(10)1     =    9
0010 -   =     00  1 0 -   =    2 - 
──────         ─────────        ───
0111     =     01  1 1     =    7

由于0 - 1在第二个位置是不可能的,我们从第四个位置取 1,将第三个位置1设置为并将第二个位置设置为10(因此,十进制系统中的 2)。这与我之前发布的十进制系统中的示例非常相似。

req对仲裁者很重要:从 的位置看,原始数字 ( ) 的下一个 1base将设置为零。基准位置和基准位置之间的所有数字0都将设置为1。将减法的结果取反后,只有这个位置是1从底部看到的。

1但是,使用这种技术仍然可以使用比基数更低的数字。因此,我们将原始数字与您计算的数字 ( double_req & ~(double_req-base)) 结合起来。这确保了低于位置的可能s1消除。base

最后,它加倍的事实确保它不会用完可以借用的头寸。如果它需要从这些“第二个”加倍块中借用,析取 ( double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH]) 确保它返回正确的索引。我在下面的示例中添加了一个示例。

原帖

您可以将其解释basereq. 这是代码将考虑仲裁的第一位。您应该将此值设置为last_arbitrated_position + 1

看看我在下面创建的 4 位(伪代码)示例。让我们取一些任意数字:

req  = 4'b1101 // Your vector from which one position should be arbitrated
base = 4'b0010 // The second position is the first position to consider

现在,从arbiter.v,以下内容:

double_req   = 1101 1101
double_grant = 1101 1101 & ~(1101 1011) = 1101 1101 & 0010 0100 = 0000 0100

在最后的步骤中,arbiter.v然后实际分配应该授予的位置:

grant = 0100 | 0000 = 0100

这是正确的,因为我们将第二个位置设置为基础,而下一个有效位置是第三个。另一个例子,其中 base 是一个在 中也有效的位置req,是:

req  = 4'b1111
base = 4'b0010
double_req   = 1111 1111
double_grant = 1111 1111 & ~(1111 1101) = 1111 1111 & 0000 0010 = 0000 0010
grant = 0010 | 0000

这又是正确的,因为在这种情况下,我们定义了可能被仲裁的第一个位置是第二个位置,并且这个位置确实有效。

您发布的代码示例还负责包装最重要的位。这意味着如果您设置了一个基数,但没有大于该基数的有效位置,它将环绕并从最低有效位开始仲裁。这种情况的一个例子是:

req  = 4'b0010
base = 4'b0100
double_req   = 0010 0010
double_grant = 0010 0010 & ~(1110 0001) = 0010 0010 & 0001 1110 = 0010 0000
grant = 0000 | 0010

推荐阅读