如何在组合 always 块中为输出分配默认值,以便即使使用不完整的 if-else 语句也不会推断出锁存器

mcl*_*fix 3 verilog

假设我想编写一个使用 4 个输入和 3 个输出的组合模块。为了模拟我的逻辑,我做这样的事情:

module ifelse (
      input wire a,
      input wire b,
      input wire c,
      input wire d,
      output reg y1,
      output reg y2,
      output reg y3
      );

     always @* begin

       if (a==1'b1 && b==1'b0) begin
         y1 = 1'b0;
         y3 = 1'b1;
         end
       else if (a==1'b0 && c==1'b1 && d==1'b0) begin
         y2 = 1'b1;
         y1 = 1'b1;
         end
       else if (a==1'b0 && c==1'b0) begin
         y3 = 1'b0;
         y2 = 1'b0;
       end
   end
endmodule
Run Code Online (Sandbox Code Playgroud)

好的,我知道这段代码会推断y1,y2和 的锁存器,y3避免这种情况的方法是始终为每个if-else块中的每个 LHS 分配一个值,如下所示:

module ifelse (
      input wire a,
      input wire b,
      input wire c,
      input wire d,
      output reg y1,
      output reg y2,
      output reg y3
      );

     always @* begin

       if (a==1'b1 && b==1'b0) begin
         y1 = 1'b0;
         y3 = 1'b1;
         y2 = 1'bx;
         end
       else if (a==1'b0 && c==1'b1 && d==1'b0) begin
         y2 = 1'b1;
         y1 = 1'b1;
         y3 = 1'bx;
         end
       else if (a==1'b0 && c==1'b0) begin
         y3 = 1'b0;
         y2 = 1'b0;
         y1 = 1'bx;
       end
       else begin
         y1 = 1'bx;
         y2 = 1'bx;
         y3 = 1'bx;
       end
   end
endmodule
Run Code Online (Sandbox Code Playgroud)

但是现在,想象一下有很多if-else块(我正在尝试描述教学微处理器的控制单元)并且有很多来自该模块的输出(数据路径中所有寄存器的控制线)微处理器)。必须为每个if-else块中的每个输出分配一个值肯定会导致代码不可读和不可维护,因为我包含在此的每个新输出always都必须包含在所有if-else块中。

然后,我的问题是:我是否必须明确地为我没有在特定 if-else 块中使用的所有输出分配一个值。对于未在组合always块中更新的信号,是否有类似“默认值”之类的东西,以便在评估之后always块后,所有未分配的输出都恢复为默认值或“无关”值?

到目前为止,我已经提出了这个解决方法,这似乎有效:

module ifelse(
    input wire a,
    input wire b,
    input wire c,
    input wire d,
    output reg y1,
    output reg y2,
    output reg y3
    );

   always @* begin
      // default values
      y1 = 1'bx;
      y2 = 1'bx;
      y3 = 1'bx;

      if (a==1'b1 && b==1'b0) begin
         y1 = 1'b0;
         y3 = 1'b1;
      end
      else if (a==1'b0 && c==1'b1 && d==1'b0) begin
         y2 = 1'b1;
         y1 = 1'b1;
      end
      else if (a==1'b0 && c==1'b0) begin
         y3 = 1'b0;
         y2 = 1'b0;
      end
   end
endmodule
Run Code Online (Sandbox Code Playgroud)

但我想要更优雅的东西,就像 Verilog 2001 处理组合的敏感度列表always一样,像这样:

module ifelse(
    input wire a,
    input wire b,
    input wire c,
    input wire d,
    output reg y1,
    output reg y2,
    output reg y3
    );

   always @* begin
      if (a==1'b1 && b==1'b0) begin
         y1 = 1'b0;
         y3 = 1'b1;
      end
      else if (a==1'b0 && c==1'b1 && d==1'b0) begin
         y2 = 1'b1;
         y1 = 1'b1;
      end
      else if (a==1'b0 && c==1'b0) begin
         y3 = 1'b0;
         y2 = 1'b0;
      end
      @* = x;  // unassigned outputs receive a default value of "dont care"
   end
endmodule
Run Code Online (Sandbox Code Playgroud)

所以如果我修改这个 always以添加仅在几个块中更新的新输出,我不必将它也包含在“默认”块中,就像我不必包含它一样在敏感列表中。

那么,Verilog 中是否存在这样的功能呢?实际上我的解决方法是这样做的,还是有更优雅的解决方案?

非常感谢 :)

小智 6

这样做的方法是在第一个语句之前,为启动块reg之后的每一个分配一个默认值。如果您打算合成信号,则不能分配给它……您希望获得什么样的硬件?请记住,信号上出现的 是未知值,而不是无关紧要的情况。beginif1'bxx

  • `x` 只能在 `if` 和 `case` 语句中用作“无关”。将“x”(未知)的值分配给 reg 或 wire 在语法上是正确的,但不可综合。 (2认同)