我正在尝试在verilog中创建一个内存移位操作,并且想知道最好的方法。示例代码是:
reg [MSB:0] a [0:NO_OF_LOCATIONS];
// after some processing
for(i =0; i <= NO_OF_LOCATIONS; i= i+1)
a[i] = a[i+1]
如果我在Xilinx中使用ROM,它只能进行同步写操作,我需要在一个时钟周期内完成所有的移位。如果我确实使用了如上所述的记忆,我不确定在船上实施是否会导致亚稳态或不关心传播。
这也是最好的方法,而不是for循环?
答案 0 :(得分:0)
我假设这是时钟同步块的一部分,即如下所示(否则它没有多大意义,你写了“我需要在一个时钟周期内完成所有的移位”,这意味着这是同步设计的一部分):
reg [MSB:0] a [0:NO_OF_LOCATIONS];
always @(posedge clk)
if (...) begin
for(i =0; i < NO_OF_LOCATIONS; i= i+1)
a[i] <= a[i+1];
a[NO_OF_LOCATIONS] <= ...;
end
// also use a[] somewhere
assign a0 = a[0];
顺便说一下:a[]
中有NO_OF_LOCATIONS+1
个位置。我不确定这是否有意,但我就这样离开了。对于a[]
内存位置,[0:NO_OF_LOCATIONS-1]
的范围通常会写为NO_OF_LOCATIONS
。
请注意,我已将作业=
更改为<=
。当在一个时钟的always-block中分配一些东西并且你分配给它的东西被读取时总是阻塞之外的任何地方然后你必须分配非阻塞(即<=
)以避免模拟中的竞争条件导致模拟综合不匹配。
另请注意,我已将a[NO_OF_LOCATIONS]
的赋值考虑在内,因为它会从a[NO_OF_LOCATIONS+1]
得到它的值,这是超出范围的,因此总是为undef。如果没有这种改变,合成工具就可以正确地假设a[]
的所有元素都是常量undef,并且只是用常量'bx
替换该数组上的所有读数。
这是完美的代码。我不确定你为什么提高亚稳态,但只要...
表达式与clk
同步,这个电路就没有亚稳态。但它并没有真正模拟记忆。嗯,确实如此,但是有一个NO_OF_LOCATIONS
写入端口和NO_OF_LOCATIONS
读取端口(仅计算由for循环推断的读取端口)。即使你有这样的内存:使用它会非常低效,因为关于内存端口的昂贵之处是它能够解决任何内存位置,但是这个例子中的所有端口都有一个恒定的内存地址({{ 1}}在展开for循环后是常量)。因此,大量的读写端口将迫使综合工具将该存储器实现为一堆单独的寄存器。但是,如果您的目标架构具有专用的移位寄存器资源(例如许多fpgas),那么这可能会转换为移位寄存器。
对于i
的大值,您可以考虑使用游标在内存中实现fifo,而不是将整个内存的内容从一个元素移动到下一个元素。这只会从for循环中推断出一个写端口和没有读端口。例如:
NO_OF_LOCATIONS