Verilog/VHDL - 如何避免在单个always块中重置数据寄存器?

mks*_*uth 5 asynchronous verilog vhdl synchronous reset

我想避免重置不需要重置的数据寄存器.例如,当通过流水线级流数据时,如果每个级都有一个有效位,则不需要重置数据寄存器.(我相信这可以简化数据寄存器的路由和时序.)

这可以通过使用单独的always块(或vhdl中的进程)轻松完成,但我发现这很冗长,并且执行以下操作是有问题的,因为数据寄存器基本上是由重置启用的.

always @(posedge clk)
if (rst)
  out_valid <= 0;
  // NOTE: out_data is not reset
else begin
  out_valid <= in_valid;
  if (in_valid)
    out_data <= in_data + 1;
end
Run Code Online (Sandbox Code Playgroud)

相反,我一直把reset子句放在always块的末尾,并利用"last assignment wins"规则.

always @(posedge clk)
begin
  out_valid <= in_valid;
  if (in_valid)
    out_data <= in_data + 1;

  if (rst)
    out_valid <= 0
end
Run Code Online (Sandbox Code Playgroud)

我没有看到很多人使用这种风格.我有什么缺点或问题吗?有没有更好的方法呢?

额外问题:如果重置是异步的,该怎么办?如:

always @(posedge clk, posedge rst)
begin
  out_valid <= in_valid;
  if (in_valid)
    out_data <= in_data + 1;

  if (rst)
    out_valid <= 0
end
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我认为合成器将复位信号连接到数据寄存器,这违背了目的.是否有一种优雅的方法可以将数据寄存器与复位信号去耦,而无需使用单独的always块?

Chi*_*ggs 7

同步复位

我一直在使用" 最后的任务获胜 "来重置超过5年.我个人觉得它更容易阅读,它可以节省不必要地将整个过程缩进一级.在我使用的FPGA综合工具(ISE,Quartus,Synplify)中,我从未见过使用这种编码风格的任何问题.

异步复位

要回答有关异步复位的红利问题 - 这有点棘手.考虑以下:

typedef struct packed {
    logic               a;
    logic               b;
} state_t;

state_t                 state;

always_ff @(posedge clk or negedge areset_n) begin
    if (~areset_n) begin
        state.a         <= 1'b0;
    end else begin
        state.a         <= data_a;
        state.b         <= data_b;
    end
end
Run Code Online (Sandbox Code Playgroud)

我们有点问题.我们不希望state.b重置,但它state.a是重置的结构的一部分.作为优秀的工程师,我们使用always_ff流程但这实际上意味着我们无法将代码拆分为单独的流程.此外,它将变得非常混乱和容易出错,跟踪哪些成员被分配在大型州结构的哪个过程中.

上面的代码实际上综合了以下内容:

门控输入的示例

我们可以看到areset_n信号充当state.b寄存器的使能.通常这不是我们想要的,并且由于大多数FPGA本身不支持这种架构,因此合成工具被迫插入额外的逻辑来模拟使能:

在此输入图像描述

这种额外的逻辑减少了时序余量并耗尽了宝贵的资源.谢天谢地,有一个解决方法:

always_ff @(posedge clk or negedge areset_n) begin
    if (~areset_n) begin
        state.a         <= 1'b0;
        state.b         <= 1'bx;
    end else begin
        state.a         <= data_a;
        state.b         <= data_b;
    end
end
Run Code Online (Sandbox Code Playgroud)

请注意,我们已经分配xstate.b复位期间.我们可以看到,Quartus现在合成了我们想要的电路:

在此输入图像描述

奖金咆哮

顺便说一句,我不是被"标准练习"限制的忠实粉丝,因为工具可能获得的可能性是错误的."传统智慧"往往是不正确或过时的.

要冒险并将工具推向极限.如果您遇到工具中的错误或限制,则提出供应商的错误并调整您的样式以进行补偿.当然,有时你会花时间研究一个奇怪的错误,这个错误原来是工具链的错误,但无论如何你都应该看看工具的输出.花费的时间将远远超过一些新语言功能所提供的改进的抽象和重用水平.

如果我们中的更多人努力获得支持或参与改进语言的新功能,那么供应商将无法通过已经过时5年的工具来消磨我们所有人!RTL开发中的保守主义水平阻碍了创新 - 我们喜欢抱怨工具,但我们没有足够的参与来使它们变得更好.