首页 > 解决方案 > Verilog 多级管道缓冲区问题

问题描述

我正在为 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。然后在完全偏离轨道之前再多一个时钟周期是正确的。

在此处输入图像描述

标签: verilog

解决方案


好的,感谢 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% 确定为什么这个有帮助,但是当我回去做这个时,它让整个处理器给了我更好的信号,就像我预期的那样。我相信这是因为它会导致所有输出“锁定”。如果有人能详细说明为什么这会有所帮助,我将不胜感激。


推荐阅读