编辑:正如有人指出的那样,我最初只指出了如何设置输入信号,并举了两个特殊情况作为例子。让我试着解释一下它是如何工作的。你的问题是一个好的开始:
为什么 ~(double_req-base) ?
正如有人向您指出的那样,这是基于ripple borrow subtractor 的原理。当您从另一个数字中减去一个数字时,无论您使用哪种数字系统,您都从最低的顺序开始,并尝试从相同的顺序中减去两个数字。在二进制示例中,如下所示:
1011 = 11
0010 - = 2 -
────── ────
1001 = 9
如您所见,1 - 1 是有效的并产生0。但是,如果无法做到这一点,您可以借更高的订单号。 This image 显示了一个简单的例子,说明这在十进制系统中的样子。十进制系统中的示例可能是:
1001 = 01(10)1 = 9
0010 - = 00 1 0 - = 2 -
────── ───────── ───
0111 = 01 1 1 = 7
由于0 - 1不可能在第二个位置,我们从第四个位置取1,将第三个位置设置为1,并将第二个位置设置为10(所以,十进制系统中的2) .这与example in the decimal system I posted before 非常相似。
对仲裁器很重要:从base 的位置看,原始数字 (req) 的下一个 1 将设置为零。基本位置和0 之间的所有数字都将设置为1。将减法的结果取反后,从底部看,只有这个位置将是1。
但是,使用这种技术,比基数低的数字仍然可以是1。因此,我们将原始数字与您计算的数字 (double_req & ~(double_req-base)) 结合起来。这确保了可能的1s 在位置低于 比base 被消除。
最后,它被加倍的事实确保它不会用完可以借用的头寸。如果它需要从这些“第二个”加倍块中借用,析取 (double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH]) 确保它返回正确的索引。我在下面的示例中添加了一个示例。
原帖
您可以将base 解释为req 中的起始索引。这是代码将考虑仲裁的第一位。您应该将此值设置为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
这是正确的,因为我们将第二个位置设置为基数,而下一个有效位置是第三个。另一个示例,其中基数是在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