假设我们要描述一个满足以下真值表的组合电路:
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
,则由于需要三态缓冲器,因此在复杂性和所用资源方面,所得电路甚至会更糟。因此,我不得不在设计时选择要输出的值(
1
或0
),而这些值不必产生最优化的电路: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个逻辑元件的电路。
但是,如果我在上面的代码中使用“无关”分配:
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
产生仅使用两个逻辑元件的电路。有趣的是,尽管较少使用全部逻辑元件,但生成的电路似乎更复杂。
我想知道生成的电路是否正确。因此,我在Quartus的模拟器中使用了“无关”电路。结果是我们想要的最简单的电路。
关于verilog - 如何在Verilog中的组合模块中为输出分配“无关”值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29451175/