我正在学习Verilog,并尝试实现CD54HC40105 chip。使我绊倒的部分是冒泡的逻辑。
[基本上,这是一个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
块中实现的某种逻辑来完成。
我最初的直觉是,这将位于对always
寄存器的更改敏感的ctrl
块中。
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
时,它将无法执行任何操作。那我该怎么办?
谢谢,
我会使用一个generate循环。以下是一些入门知识(仅显示数据路径):
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关键字来显示意图。