我正在为Verilog HDL中的2级管道处理器开发一个学校项目,但遇到了一个困扰我几天的问题。我将通过我的描述添加小代码段和通过ModelSim获得的信号图片。我只是从ALU中获取输出:
ALU #(BUS_WIDTH(BUS_WIDTH)) alu (
.A(Amux),
.B(Bmux),
.sel(ALUsel),
.Dout(ALUout)
);
然后,我以以下方式将其直接传递到同一文件中各阶段之间的缓冲区(为了便于阅读,其他信号和数据被缓冲了):
Buffer #(.BUS_WIDTH(BUS_WIDTH)) buff(
.clk(clk),
.reset(reset),
.aluA(ALUout),
.aluB(ALUoutM),
);
缓冲模块的内部如下所示(为了便于阅读,我再次删除了正在缓冲的所有其他内容:
module Buffer(
input clk,
input reset,
input [31:0] aluA,
output reg [31:0] aluB
);
always @(posedge clk)
begin
if (~reset)
begin
aluB <= 32'h00000000;
end else
begin
aluB <= aluA;
end
end
endmodule
这是在启动测试台并成功运行之前的几个周期后发生的。看图像,顶部信号是ALUout,第二个信号是ALUoutM。我希望得到的结果是使我的ALUoutM信号与上一个时钟周期的ALUout信号相匹配(我已经验证了完整的时钟周期是图像中信号变化之间的周期)。如前所述,在此周期之前的所有周期中都可以看到这种期望的结果。在第一个周期和第二个周期之间,结果并不理想,但随后又恢复了正确性。我已经三重检查并确认我的ALUoutM不受任何其他信号驱动。我主要是想弄清楚我是否在使用Verilog犯了一个我不知道的初学者错误。感谢您的任何帮助。
添加
根据Oldfart的评论(我喜欢这个名字),我也能够将缓冲区的信号添加到模拟器中,但是它显示的行为与输入信号完全相同。在下图中,您会注意到前4个时钟周期的行为正确,然后缓冲区中出现了一个随机值0x00000000。然后在完全脱离轨道之前再经过一个时钟周期是正确的。
答案 0 :(得分:0)
好的,感谢奥尔德法特(Oldfart)(仍然喜欢这个名字)给了我有关该问题的建议。在与教授和助教讨论完所有内容后,我更改了所有MUX,以在
上触发 always @ ( * )
信号。我以前将它们创建为
always @ (sel or input_a or input_b or ... or input_N)
并没有像预期的MUX那样立即传播我的数据。我相信这是因为所有输入都不会同时到达MUX,从而导致输出值可能会更改与更改的信号数量相同的次数(除非您很幸运地每个信号都同时到达)。在所有输入都传播到MUX之前,这可能多次给您错误的信号。简而言之,如果您按照我原来的方式进行操作,谁知道您最终将获得什么价值。
这与将我的输出“注册”到我的模块一起解决了我的问题。对于不确定我意思的人,当我声明输出时,我这样做
output reg [(width - 1):0] output_x
相对于
output [(width - 1):0] output_x
我不是100%地确定为什么这样做会有所帮助,但是当我回去执行此操作时,它使整个处理器给我的信号更好,达到了我的预期。我相信这是因为它导致所有输出“闩锁”。如果有人能详细说明为什么这样做会有帮助,我将不胜感激。