1.锁存器的无意综合
锁存器的生成方式有两种;一种是有意的,另一种是无意或意外的。无意综合出的锁存器会浪费硅片面积,并有可能影响到电路的功能。因此,懂得什么样的 Verilog 描述会被综合工具综合出锁存器是很重要的。如果设计者不懂得这些关系,就会对期望得到组合逻辑的描述却综合出锁存逻辑的情况感到很惊讶。
三种用来描述可综合组合逻辑的方法;
0)原语网表;
1)由连续賦值语句描述的布尔方程;
2)电平敏感周期性行为
是不是这些方法都会导致电路中生成锁存器呢?
- 综合要点 一个无反馈的组合原语网表可综合成无锁存的组合逻辑。
无反馈的组合原语网表将综合成无锁存功能的组合逻辑。综合工具可能不允许原语网表含有反馈结构(如交叉耦合的与非门),含反馈的描述可能会被标为一个错误条件,且不可综合。描述组合逻辑的一组连续赋值语句中一定不能有反馈存在。
- 综合要点 一组无反馈的连续賦值语句可以综合成无锁存的组合逻辑。
一个带反馈的条件操作符(?:)的连续赋值语句(如赋值的目标变量出现在操作符表达式中)会综合出一个锁存器。这是一种有意生成锁存器的方法,如静态随机存取存储器 SRAM@ ,它是可综合的。
- 综合要点 一个带反馈的条件操作符的连续赋值语句会综合出一个锁存器。
- 锁存器的无意综合(例)
下面代码描述了一个 4 输入或门。具有周期性行为的算法将输出初始化为 0,然后依次测试输入。若输入为 1,则设置输出为 1 并终止测试。该描述被综合为组合逻辑。综合过程去掉了循环变量 k,实际中也没有相应的计数硬件。应该注意的是,输出变量y被声明为寄存器变量,但是并没有被综合为存储元件。
module or4_behav #(parameter word_length = 4)(
output reg y, input [word_length-1:0] x_in);
integer k;
always @x_in begin:check_for_1
y=0;
for(k=0;k<=word_length-1;k=k+1)
if(x_in[k] == 1)begin
y=1;
disable check_for_1;
end
end
endmodule
现在再分析一下 or4_behav_latch 模块的描述,它的事件控制表达式对 x_in[0] 信号不敏感,这就会无意地综合出锁存输出一一忽略 x_in[0] 信号的变化导致隐含了一个锁存功能,电路仅在 x_in[3:1] 信号变化时才激活周期性行为.并给输出賦值。
module or4_behav_latch #(parameter word_length = 4)(
output reg y, input [word_length - 1 : 0] x_in);
integer k;
wire y_gate;
always @(x_in[3:1]) begin:check_for_1 //不完整的敏感表
y=0;
for(k=0;k<=word_length-1;k=k+1)
if(x_in[k] == 1)begin
y=1;
disable check_for_1;
end
end
endmodule
模块 or4_behav 和 or4_behav_latch 的实现电路如图 1 、2 所示。在 or4_behav_latch 模块中 x_in[0] 的值被锁存,锁存器由 x_in[1], x_in[2], x_in[3] 的或值来控制。当三者中任何一个输入为 1 时,x_in[0] 将传递到或门得到 y 。如果三者的值都变为0,则 x_in[0] 将被锁存,y 不受 x_in[0] 变化的影响。图 3 是两个模块的仿真结果,其中,y_gate 信号对应图 2 中的电路输出结果 y_gate 为 x_in[1], x_in[2], x_in[3] 驱动的3输入或门的输出信号,这些波形说明了 or_behav_latch 模块的锁存行为。
测试代码
`timescale 1 ps/ 1 ps
module tb_or4;
reg [3:0] x_in;
wire y_behav;
wire y_latch;
reg y_gate;
or4_behav_latch latch(.x_in(x_in),.or4(y_latch));
or4_behav behav(.x_in(x_in),.y(y_behav));
initial
begin
x_in[3:0]=4'b0000;
#5 x_in=4'b1000;
#5 x_in=4'b1010;
#5 x_in=4'b0001;
#5 x_in=4'b0000;
#5 x_in=4'b0001;
#5 x_in=4'b1000;
#5 x_in=4'b1100;
#5 x_in=4'b0000;
#5 x_in=4'b0001;
#5 x_in=4'b0000;
#5 x_in=4'b0001;
#20 $stop;
end
always@(x_in[3:1])
if(x_in[1] | x_in[2] | x_in[3] )
y_gate = 1'b1;
else
y_gate = 1'b0;
endmodule
4 输入 OR 门:
(图1)由电平敏感周期性行为综合的电路
(图2)由含有锁存器的模型综合的电路
(图3)两种电路的仿真结果
为了避免实现的逻辑中产生锁存,在赋值表达式的右逻辑发生变化的所有情况下,都必须给行为中包含的所有变量进行賦值。如果不这么做,则会在生成的设计中产生不希望的锁存。因此,所有用以实现组合逻辑的电平敏感行为电路的输入信号,都必须包含于事件控制表达式中。行为中赋值语句右边的操作数就是输入信号。同样,在行为中其变化会影响到目标寄存器变量赋值的任何控制信号,都应被认为是该行为的输入信号。记住:如果一个电平敏感行为的敏感表不完整,一些变量就不会在愉入信号的所有状况下被
赋值,也就意味着需要存储器来实现。实际上,由于不完整的敏感表带来的风险如此巨大,HDL 语言增加了一个通配符 * 来隐含形成一个完整的敏感表。在电平敏感行为的敏感表中可以使用@(*)和@*的形式,以代替设计者逐个填写敏感信号的繁琐工作。在电平敏感周期性行为中,赋值语句的右表达式中任意信号都不再出现于其左表达式中如果忽略这条规则,则行为中隐含了反馈并会综合出锁存器,而不再是无反馈的组合逻辑。
- 综合要点 组合逻辑的 Verilog 描述给输出賦值时,必须考虑所有可能的输入值。
当一个 case 语句或 if 语句没有对所有可能的输人值指定输出时,即未完整定义case 或 if 语句,可能会生成非预期的锁存器。(例如,在未定义的输人条件下,输出将保持原值。)不管是显式地说明还是用 default 条件说明,必须保证 case 和条件分支(if)语句是完整的。如果在一个连续值语句中,与条件操作符相联系的表达式把目标变量(表达式的左边项)赋给它本身,该语句将综合出一个锁存器,但是不完整的条件操作符将会引发语法错误。