我正在尝试在Verilog中的ARM CPU中实现寄存器文件。 我是verilog的新手,所以遇到了麻烦。
我想让寄存器文件将PC + 8的值保存在第15个寄存器中,并将寄存器号0的开头保存为0,以便寄存器文件在输入以下内容时能够将PC + 8作为输出:读寄存器之一是15,依此类推。
当前,我已经编写了这样的代码
reg[31:0] register[15:0];
initial
begin
register[15] = register15;//register15 is the input holding PC+8 as it's value
register[0] = 32'h00000000;
end
always @(posedge clk)
begin
outreg1 <= register[A1];// outreg1,2 are outputs (values of register A1, A2)
outreg2 <= register[A2];
end
但是,当“寄存器读取”发生时,我想使其全部以clk的姿势发生。但是,如果这样做,我是否必须将所有语句始终以@(posedge clk)的形式分配为阻塞分配'=',以使其依次进行并首先分配15和0?
我对阻止和取消阻止分配的了解还不是很清楚,因此我不确定是否可行。
答案 0 :(得分:2)
因此,这看起来像是尝试使用“ A1 ...”作为映射操纵器将输入值“ register0,... register15”重新映射到一组“ outreg1 ...”。
在这种情况下,您不能使用initial
块。初始块在模拟开始时仅运行一次,并且无法对输入更改做出反应。它们也不是可合成的。由于您说'registerN'也是输入,所以最好创建2个不同的always_blocks;
reg[31:0] register[15:0];
always @*
begin
register[15] = register15;//register15 is the input holding PC+8 as it's value
register[0] = 32'h00000000;
end
always @(posedge clk)
begin
outreg1 <= register[A1];// outreg1,2 are outputs (values of register A1, A2)
outreg2 <= register[A2];
end
阻塞分配和非阻塞分配之间的区别在于,对于非阻塞分配,在对设计中的所有此类块完成了姿势的所有评估之后,实际值将在以后分配给变量。这使得仿真在触发器和锁存器方面的表现更像硬件。例如,如果您有一个翻牌A
在相同的'posege clk'处给另一个翻牌B
喂食,则翻牌B
将捕获A
的输出,就像摆在翻牌之前一样。这就是硬件的行为方式。在这种情况下,使用阻塞分配会导致仿真结果无法预测,具体取决于模拟器的实现。
因此,经验法则是对表示锁存器和触发器的always
块的所有“输出”使用非阻塞分配。其他所有内容都必须被阻止。这意味着触发器/锁存器块可以在需要时对中间变量使用阻塞,但是最好避免。