数组需要始终@(my_array)块上的数组索引(在Verilog中实现寄存器冒泡)



我正在学习Verilog,并尝试实现CD54HC40105芯片。让我绊倒的部分是冒泡的逻辑。

基本上,这是一个FIFO芯片,通过通过内存冒泡单词来工作。每个单词一位用于跟踪该插槽中是否存在单词。

这是我需要实现的逻辑:在任何时候,如果某个插槽i中存在一个单词(这意味着ctrl[i] == 1(,并且下一个插槽中不存在单词(ctrl[i + 1] == 0(,则将插槽i中的单词与控制信号一起移动到下一个插槽i+1

它可能看起来像这样:

// Empty word next to B, it will shift right
+---+---+---+---+
| 1 | 1 | 0 | 0 |
+---+---+---+---+
| A | B |   |   |
+---+---+---+---+
// Empty word next to B and A, they will both shift right
+---+---+---+---+
| 1 | 0 | 1 | 0 |
+---+---+---+---+
| A |   | B |   |
+---+---+---+---+
// Empty word next to A, it will shift right
+---+---+---+---+
| 0 | 1 | 0 | 1 |
+---+---+---+---+
|   | A |   | B |
+---+---+---+---+
// No empty words
+---+---+---+---+
| 0 | 0 | 1 | 1 |
+---+---+---+---+
|   |   | A | B |
+---+---+---+---+

现在,该芯片没有时钟输入,也没有框图中的任何内部时钟。因此,这一切都是使用某种可以在某种always块中实现的逻辑来完成的。

我最初的直觉是,这将在一个对ctrl寄存器变化敏感的always块中。

reg[15:0] ctrl;
// ...
always @(ctrl) begin
for (i = 0; i < 15; i = i + 1) begin
if (ctrl[i] == 1 && ctrl[i + 1] == 0) begin
ctrl[i + 1] <= 1;
mem[i + 1] <= mem[i];
ctrl[i] <= 0;
end
end
end

但是我得到错误Array ctrl needs an array index here.我可以看到为什么会这样,但我仍然不知道否则我会怎么做。

理想情况下,我需要一些语法来执行此伪语法将执行的操作:

// for all i's
always @(posedge ctrl[i]) begin
// there are 16 slots, so we can never bubble the last index
if (i != 15 && ctrl[i + 1] == 0) begin
// ...
end
end

编辑

我意识到上述伪解决方案不起作用,因为当值移出时它不会做任何事情,从而导致ctrl[15]变得0。那我在这里做什么?

谢谢

我会使用生成循环。以下是帮助您入门的内容(仅显示数据路径(:

reg [0:16] ctrl;
reg [3:0] mem [0:16];
assign ctrl[0] = si_s;
assign mem[0] = d;
for (genvar i = 1; i <= 16; i++) begin : gen_loop
always @(*) begin
if (ctrl[i] && ctrl[i-1]) begin
mem[i] = mem[i-1];
end 
end
end
assign q = mem[16];

如果您可以使用SystemVerilog,则可能需要使用always_latch关键字来显示意图。