【发布时间】:2017-07-15 06:22:47
【问题描述】:
我正在尝试制作一个 32x4(32 字,4 位)单端口 RAM 块。这是我的 Verilog 代码:
module RAM_array (input clk, wren, input [4:0] address,
input [3:0] data, output reg [3:0] q);
reg [3:0] mem [31:0]; // a 4 bit wide 32 word RAM block.
always @(posedge clk) begin
if (wren)
mem[address] <= data;
q <= mem[address];
end
endmodule
由于我在 DE-1-SoC 上使用 Altera 的 Cyclone V 芯片,我的代码基于他们的指南:http://quartushelp.altera.com/14.1/mergedProjects/hdl/vlog/vlog_pro_ram_inferred.htm
问题:每当我向块中的地址写入值时,我都必须等待一个额外的时钟周期才能将其写入。为什么会这样?
【问题讨论】:
-
你的意思是“等待一个额外的时钟周期让它被写入”还是你的意思是“等待一个额外的时钟周期让
q输出改变”?鉴于您编写代码的方式,输出q需要 2 个时钟周期才能更改。 -
您能否详细说明此处插入了额外的延迟周期是什么意思?如果您希望
q在下一个循环中反映新值,请尝试阻塞分配。至少 Verilog 不是我的强项,但如果合成器决定将逻辑映射到与代码本身具有不同语义的块,我会感到惊讶。 -
因为你在代码中使用了'non-blocking'赋值,所以q总是会得到mem[address]的旧值。所以,如果数据改变了,比如说'1'并且mem[address]之前是'0',verilog会将'1'分配给'mem'但是在它分配'0'给q之后。因此,您需要下一个时钟周期将值传播到“q”。
-
啊,我现在明白了。如果我希望 q 的值改变下一个时钟周期,那么使用阻塞分配是实现此目的的唯一方法吗?不是按顺序使用阻塞分配总是会阻塞糟糕的风格吗?或者这是否是指南的一个例外(我很确定必须有一种方法来改进我的设计,而不是使用阻塞语句......)
-
是的,在 flop 块的 输出 上使用阻塞是 bad。不过,您可以在内部温度上使用它。但是你现在问的是一个不同的问题。因此,您有一个问题:它应该如何在您的设计中发挥作用?
标签: verilog fpga intel-fpga