【问题标题】:Verilog Multistage Pipeline Buffer IssueVerilog 多级管道缓冲区问题
【发布时间】:2018-11-30 00:33:26
【问题描述】:

我正在为 Verilog HDL 中的 2 级管道处理器开展一个学校项目,但遇到了一个困扰我几天的问题。我将通过我的描述添加小代码 sn-ps 和我通过 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 的 cmets(我喜欢这个名字),我也能够将缓冲区的信号添加到我的模拟器中,但它显示的行为与输入信号完全相同。在下图中,您会注意到前 4 个时钟周期的行为正确,然后从缓冲区中出现随机值 0x00000000。然后在完全偏离轨道之前再多一个时钟周期是正确的。

【问题讨论】:

  • 为什么aluB 中的Buffer 是输入?
  • @Unn 实际上不是。那是一个错字。我仔细检查了我的代码,它确实是一个输出。感谢您指出这一点。
  • 在这种情况下,正常的调试过程是将alualuB 从您的Buffer 模块中放入波形显示中并跟踪出现问题的地方。为什么?因为即使我自己做,我也不相信“三重检查”。忽略一个案例太容易了。
  • @Oldfart 你是说在我得到这些相同信号的测试台文件中这样做吗?由于它们来自另一个模块,我如何将它们添加到输出中? ALUout 直接插入BufferaluA 端口,ALUoutM 插入BufferaluB 端口。既然是这样,我理解你的意思是我应该自己抓住两个端口?我该怎么做?
  • 大多数模拟器都有一个层次结构窗口,您可以像计算机上的文件系统一样展开它。选择一个模块,您的“信号”窗口将使用模块中的信号进行更新。选择信号并将其拖动到波形窗口。大多数模拟器需要重新启动以更新波形,除非您之前启用了一些“记录所有信号”选项。

标签: verilog


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-13
    • 2014-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多