调试错误 "procedural assignment to a non-register k is not permitted"
Debugging error "procedural assignment to a non-register k is not permitted"
我的 Verilog 代码如下所示。该模块实现了一个查找 table ROM,其地址寄存器在时钟脉冲时递增。其输出被解码为 32 位数字。我不明白为什么 k 需要是一个寄存器。事实上,我不希望 k 在地址寄存器更改后有时钟延迟。 addr
的解码是怎么规定的?
(请注意,这似乎与 SO 上类似命名的其他问题无关,因为我已经检查过了 - 我不想在输出上使用寄存器。我只想异步解码计数寄存器的输出。也许我对 <= 运算符感到困惑,我认为它总是会生成时钟寄存器,但也许我应该始终使用 <=.)
module k_rom (input clk, input reset, output [31:0] k);
// Constants defined by the SHA-2 standard.
reg [5:0] addr;
always @ (addr)
begin
case(addr)
6'h00: k = 32'h428a2f98;
6'h01: k = 32'h71374491;
6'h02: k = 32'hb5c0fbcf;
6'h03: k = 32'he9b5dba5;
6'h04: k = 32'h3956c25b;
6'h05: k = 32'h59f111f1;
6'h06: k = 32'h923f82a4;
6'h07: k = 32'hab1c5ed5;
6'h08: k = 32'hd807aa98;
6'h09: k = 32'h12835b01;
6'h0a: k = 32'h243185be;
// other constants not shown for brevity
6'h3c: k = 32'h90befffa;
6'h3d: k = 32'ha4506ceb;
6'h3e: k = 32'hbef9a3f7;
6'h3f: k = 32'hc67178f2;
endcase
end
always @ (posedge clk)
begin
if(reset)
addr <= 6'b0;
else
addr <= addr + 6'b1;
end
endmodule
程序块中赋值的LHS必须是reg
类型。过程赋值语句将值赋给 reg
、integer
、real
或 time
变量,不能 将值赋给 wire
.请注意,reg
可以根据某些触发事件保存或存储一些值,而 wire
不能存储任何值。
这里,k
是持有一些值,直到addr
信号改变。从今以后,它需要是 reg
类型。
默认情况下,output
信号的类型为 wire
。将 k
声明为 output reg [31:0] k
。
module k_rom (input clk, input reset, output reg [31:0] k);
阻塞赋值(=
)和非阻塞赋值(<=
)的使用在上面的代码中似乎是正确的。
对组合逻辑(always @(addr)
块)使用分块赋值(=
)。对顺序逻辑(always @(posedge clk)
块)使用非阻塞赋值(<=
)。
但您可能更喜欢使用 always @(*)
(或 always_comb
for SystemVerilog)而不是 always @(addr)
作为自动敏感度列表。
参考this PDF了解reg
和wire
的区别。
我的 Verilog 代码如下所示。该模块实现了一个查找 table ROM,其地址寄存器在时钟脉冲时递增。其输出被解码为 32 位数字。我不明白为什么 k 需要是一个寄存器。事实上,我不希望 k 在地址寄存器更改后有时钟延迟。 addr
的解码是怎么规定的?
(请注意,这似乎与 SO 上类似命名的其他问题无关,因为我已经检查过了 - 我不想在输出上使用寄存器。我只想异步解码计数寄存器的输出。也许我对 <= 运算符感到困惑,我认为它总是会生成时钟寄存器,但也许我应该始终使用 <=.)
module k_rom (input clk, input reset, output [31:0] k);
// Constants defined by the SHA-2 standard.
reg [5:0] addr;
always @ (addr)
begin
case(addr)
6'h00: k = 32'h428a2f98;
6'h01: k = 32'h71374491;
6'h02: k = 32'hb5c0fbcf;
6'h03: k = 32'he9b5dba5;
6'h04: k = 32'h3956c25b;
6'h05: k = 32'h59f111f1;
6'h06: k = 32'h923f82a4;
6'h07: k = 32'hab1c5ed5;
6'h08: k = 32'hd807aa98;
6'h09: k = 32'h12835b01;
6'h0a: k = 32'h243185be;
// other constants not shown for brevity
6'h3c: k = 32'h90befffa;
6'h3d: k = 32'ha4506ceb;
6'h3e: k = 32'hbef9a3f7;
6'h3f: k = 32'hc67178f2;
endcase
end
always @ (posedge clk)
begin
if(reset)
addr <= 6'b0;
else
addr <= addr + 6'b1;
end
endmodule
程序块中赋值的LHS必须是reg
类型。过程赋值语句将值赋给 reg
、integer
、real
或 time
变量,不能 将值赋给 wire
.请注意,reg
可以根据某些触发事件保存或存储一些值,而 wire
不能存储任何值。
这里,k
是持有一些值,直到addr
信号改变。从今以后,它需要是 reg
类型。
默认情况下,output
信号的类型为 wire
。将 k
声明为 output reg [31:0] k
。
module k_rom (input clk, input reset, output reg [31:0] k);
阻塞赋值(=
)和非阻塞赋值(<=
)的使用在上面的代码中似乎是正确的。
对组合逻辑(always @(addr)
块)使用分块赋值(=
)。对顺序逻辑(always @(posedge clk)
块)使用非阻塞赋值(<=
)。
但您可能更喜欢使用 always @(*)
(或 always_comb
for SystemVerilog)而不是 always @(addr)
作为自动敏感度列表。
参考this PDF了解reg
和wire
的区别。