您正确地确定了代码中的主要问题是没有正确处理寄存器和组合逻辑。只要你有一个寄存器(寄存器,而不是
reg
类型,它们不一样,对于那些刚接触Verilog的人来说,这很容易混淆),您需要以特定的方式定义它,以便合成和模拟工具能够处理它。最安全的做法是在组合逻辑和顺序存储(即实际寄存器)之间创建一个干净的分离。你开始这样做
Aint_reg
,
Bint_reg
,
out_reg
等但您需要对其值来自组合块的所有注册值执行此操作。因此,所有这些想法一起产生了这样的代码结构(不完全是您的代码,而是类似的东西):
input [31:0] A, B;
output reg [31:0] out;
reg [31:0] regA, regB;
reg [3:0] state, nextState;
always @(posedge clk or negedge rst) begin
if (~rst) begin
regA <= '0;
regB <= '0;
state <= IDLE;
end
else begin
regA <= nextA;
regB <= nextB;
state <= nextState;
end
end
always @(*) begin
// Default; I always do this here to ensure there are no cases in which I dont assign a combinational value for this block
// it always helps me keep track of which variables are assigned in which block
nextA = regA;
nextB = regB;
nextState = state;
out = '0;
case (state)
// In here is your case body, where you can reassign nextA, nextB, nextState and out
// where the assignments are only dependent on A, B, regA, regB and state (ie, the values NOT assigned in this block)
endcase
end
记住这一点,你只需要
Aint\u注册
,
Bint\U注册
等;所以你不需要分配
A_reg
,
Breg
,等等。还请注意,如果这意味着输出的计时将被延迟,那么如果需要立即从组合块中推出值,则始终可以绕过寄存器。据我所知,您可能在重置期间遇到加载问题,只要重置,这是可以理解的(
nrst
)断言(即0),则不会加载任何内容。这就是重置的整个点,将系统保持在已知状态,直到其提升。所以直到
nrst公司
已取消评估,您的模块不应执行任何操作。其他几点:
-
正确格式化代码非常重要,确保代码始终干净,因为它有助于发现错误。我重新格式化了它,似乎缺少一个
begin..end
在
IDLE
状态
-
总是
开始终止
你的区块,它将避免这么多的错误
-
注意事物的大小,我看到您将变量声明为32位
reg [31:0]
但是只使用
31'd
这是31位。使用
'0
语法为零填充任何大小。
-
将寄存器设置为
'x
这并不理想,您应该让寄存器保持其状态(正如您对寄存器值和下一个寄存器值所做的那样)。
希望这能为你澄清一些事情。