verilog - 如何在Verilog中的组合模块中为输出分配“无关”值

标签 verilog

假设我们要描述一个满足以下真值表的组合电路:

a b | s0 s1 s2 s3
-----------------
0 0 |  1  d  d  d
0 1 |  0  1  d  d
1 0 |  0  0  1  d
1 1 |  0  0  0  1


(其中d代表“无关”值,也就是说,我们不在乎此输出的值是0还是1)

如果我们采用传统设计,则可以利用这些“无关”功能,并为它们分配最方便的值,这样生成的方程式(以及因此的电路)就是最简单的方程式。例如,我们可以将以前的真值表更改为此表:

a b | s0 s1 s2 s3
-----------------
0 0 |  1  1  1  1
0 1 |  0  1  0  1
1 0 |  0  0  1  1
1 1 |  0  0  0  1


最终方程将是(使用Verilog表示法):

s0 = ~a & ~b;
s1 = ~a;
s2 = ~b;
s3 = 1;


(请记住,当您必须在K地图中为输出选择值时,您将可以对尽可能多的单元格进行分组)

但是,如果我选择使用Verilog设计该怎么办?我不能做到这一点:

module encoder (
  input wire a,
  input wire b,
  output reg [3:0] s
  );

  always @* begin
    case ({a,b})
      2'b00  : s = 4'b1ddd;
      2'b01  : s = 4'b01dd;
      2'b10  : s = 4'b001d;
      2'b11  : s = 4'b0001;
      default: s = 4'bdddd; 
    endcase
  end
endmodule


我在How to assign default values to outputs in a combinational always block...处被告知,我也不能将x用作输出,而只能用作输入。如果我使用z,则由于需要三态缓冲器,因此在复杂性和所用资源方面,所得电路甚至会更糟。

因此,我不得不在设计时选择要输出的值(10),而这些值不必产生最优化的电路:

module encoder (
  input wire a,
  input wire b,
  output reg [3:0] s
  );

  always @* begin
    case ({a,b})
      2'b00  : s = 4'b1000;
      2'b01  : s = 4'b0100;
      2'b10  : s = 4'b0010;
      2'b11  : s = 4'b0001;
      default: s = 4'b0000; 
    endcase
  end
endmodule


得出这些方程式(暂时忽略default子句):

s0 = ~a & ~b;
s1 = ~a & b;
s2 = a & ~b;
s3 = a & b;


或以下实现(取自EdaPlayGround的YOSIS 0.3.0的输出):



对于给定的目标,哪种方法可能不是最佳解决方案,但这是我们允许合成器根据所需的输出进行推断的方法。

使用针对Spartan 3E-100k FPGA的XST合成器,上述模块使用2个slice和4个LUT。

我认为Verilog(或任何其他HDL)应使设计人员不必进行此类选择,因此,如果设计人员允许其为给定的输出和给定的设置选择最方便的值,则合成器可以应用任何可用的优化方法。输入。如果真是这样,那么以前的设计可能已经过优化,看起来像这样:



针对与上述相同的FPGA,它使用了2个逻辑片和3个LUT。

对于此示例,我已经能够手动进行优化,但是考虑一个控制器模块,该控制器模块具有到数据路径模块的多个输出。可能存在来自控制器的输出信号,对于给定的控制器状态,该信号可能不在乎值。

例如:控制器从寄存器A或寄存器B向select输出信号,以及另一个使能寄存器C的load信号,因此可以在寄存器C中装入A或B,或保持其当前值。



如果load为0,则我不太在意select的值,因此每次在控制器描述中输出load = 0时,我都应该能够对“ select”输出“无关” 。

所以我的问题是:


有什么办法可以编写Verilog(不是SystemVerilog)描述,以便为组合块的输出提供“无关值”?
如果不是,这是语言上的限制吗?还是“您应该进行设计,以便不需要'无关'值”这个问题?




附录

令我惊讶的是,XST将`x`识别为有效输出。它是可综合的,并且似乎按照我预期的方式运行,从而使相同的电路可以实现2个slice和3个LUT。另一方面,YOSIS似乎忽略了它,并产生了与非优化设计相同的输出。

整流:我已经用另一种设计测试了XST:产生此真值表的电路:

a b | s0 s1 s2 s3
-----------------
0 0 |  0  d  d  d
0 1 |  1  0  d  d
1 0 |  1  1  0  d
1 1 |  1  1  1  0


可以通过多种方式编写相应的Verilog模块,而无需关心,可以通过以下几种方式进行编写:

module encoder (
  input wire a,
  input wire b,
  output reg [3:0] s
  );

  always @* begin
    case ({a,b})
      2'b00  : s = 4'b0111;
      2'b01  : s = 4'b1011;
      2'b10  : s = 4'b1101;
      2'b11  : s = 4'b1110;
      default: s = 4'b1111; 
    endcase
  end
endmodule


就最小化而言,这会产生最差的结果(在Spartan 3E FPGA中为2片,4个LUT)

可从以下真值表开始获得经过手工优化的版本:

a b | s0 s1 s2 s3
-----------------
0 0 |  0  0  0  0
0 1 |  1  0  1  0
1 0 |  1  1  0  0
1 1 |  1  1  1  0


在这里很容易观察到,无需单个逻辑门即可获得4个输出中的3个。因此,XST报告1个切片,1个LUT(计算s0所需的唯一一个)

module encoder (
  input wire a,
  input wire b,
  output reg [3:0] s
  );

  always @* begin
    case ({a,b})
      2'b00  : s = 4'b0000;
      2'b01  : s = 4'b1010;
      2'b10  : s = 4'b1100;
      2'b11  : s = 4'b1110;
      default: s = 4'b1110; // yes, same output as above
    endcase
  end
endmodule


如果使用将x用作“无关”的肮脏技巧:

module encoder (
  input wire a,
  input wire b,
  output reg [3:0] s
  );

  always @* begin
    case ({a,b})
      2'b00  : s = 4'b0xxx;
      2'b01  : s = 4'b10xx;
      2'b10  : s = 4'b110x;
      2'b11  : s = 4'b1110;
      default: s = 4'bxxxx; 
    endcase
  end
endmodule


设计是综合的,但结果并非最小。 XST报告1个切片,2个LUT。

在他的评论中,@ Tim链接中的文章对此很清楚:避免在设计中使用x。但是根据此示例,该语言不允许我们帮助合成器最小化电路。

节省一个或两个LUT可能没什么大不了的,但是如果节省下来,可以让该模块停留在一个切片中,则P&R可以减少将其放置在任何位置的工作。

最佳答案

当我使用Quartus II ver 15.0时,辅助“无关”输出就可以了,并生成了面积有效的电路。

例如,如果我合成此代码,则:

module test1 (
input wire a,
input wire b,
output reg [3:0] s
);

always @* begin
  case ({a,b})
    2'b00  : s = 4'b1000;
    2'b01  : s = 4'b0100;
    2'b10  : s = 4'b0010;
    2'b11  : s = 4'b0001;
    default: s = 4'b0000; 
  endcase
end
endmodule


Quartus生成了一个使用5个逻辑元件的电路。
not optimized

但是,如果我在上面的代码中使用“无关”分配:

module test1 (
input wire a,
input wire b,
output reg [3:0] s
);

always @* begin
  case ({a,b})
    2'b00  : s = 4'b1xxx;
    2'b01  : s = 4'b01xx;
    2'b10  : s = 4'b001x;
    2'b11  : s = 4'b0001;
    default: s = 4'b0000; 
  endcase
end
endmodule


产生仅使用两个逻辑元件的电路。有趣的是,尽管较少使用全部逻辑元件,但生成的电路似乎更复杂。
optimized

我想知道生成的电路是否正确。因此,我在Quartus的模拟器中使用了“无关”电路。结果是我们想要的最简单的电路。
enter image description here

关于verilog - 如何在Verilog中的组合模块中为输出分配“无关”值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29451175/

相关文章:

parsing - Verilog 门级解析器

vhdl - 是否可以设计一个基于锁存器的 FIFO 而不是 FF?

c - 将模块 2 的输出链接到模块 1 VERILOG 的 if else 语句

verilog - Verilog 中的 Casex 和 Casez

verilog - 使用其他两个模块的输出 (Verilog)

for-loop - for 循环 verilog 的更好替代方案

Verilog LRM 非确定性

verilog - 为什么我在 verilog 中收到 "Incompatible types at assignment"错误?

vhdl - 如何在 FPGA 中实现无限循环?

Verilog : Error using nested for loop 中的 FFT 实现