目录
1.always块语言指导原则
使用过always块进行可综合的代码设计时需要注意以下几个问题。
(1)每个always块只能有一个事件控制“@(event-expression)”,而且要紧跟在always关键字后面。
(2)always块可以表示时序逻辑或组合逻辑,也可以用always块表示电平敏感的透明锁存器又同时表示组合逻辑。但是不推荐使用这种描述方法,因为这容易产生错误和多余的电平敏感的透明锁存器。
(3)带有posedge或negedge关键字的事件表达式沿触发的时序逻辑;没有posedge或negedge关键字的表示组合逻辑或电平敏感的锁存器,或者两种都表示。在表示时序和组合逻辑的时间控制表达式中如有多个沿和多个电平,其间必须用关键字“or”连接。
(4)每个表示时序逻辑的always块只能由一个时钟跳变沿触发,置位或复位最好也由该时钟跳变沿触发。
(5)每个在always块中赋值的信号都必需定义成reg型或整型。整型变量缺省为32bit,使用Verilog操作符可对其进行二进制求补的算术运算。综合器还支持整型量的范围说明,这样就允许产生不是32位的整型量,句法结构为:
integer [<msb>:<lsb>] <identifier>
(6)always块中应该避免组合反馈回路。每次执行always块时,在生成组合逻辑的always块中赋值的所有信号必须都有明确的值;否则需要设计者在设计中加入电平敏感的锁存器来保持赋值前的最后一个值。
只有这样,综合器才能正常生成电流。如果不这样做,综合器会发出警告,提示设计中插入了锁存器。如果在设计中存在综合器认为不是电平敏感锁存器的组合回路时,综合器会发出错误信息(例如设计中有异步状态机时)。
用always块设计纯组合逻辑电路时,在生成组合逻辑的always块中,参与赋值的所有信号都必须有明确的值,即在赋值表达式右端参与赋值的信号都必须在always @(敏感电平列表)中列出。
如果在赋值表达式右端引用了敏感电平列表中没有列出的信号,那么在综合时,将会为该信号产生一个隐含的透明锁存器。这是因为该信号的变化不会立即引起所赋值的变化,而必须等到敏感电平列表中某一个信号变化时,它的作用才显现出来。
也就是相当于存在着一个透明锁存器把该信号的变化暂存起来,特敏感电平列表中某一信号变化时再起作用,纯组合逻辑电路不可能做到这一点。这样综合所得电路已经不是纯组合逻辑电路了。这是综合器会发出警告提示设计中插入了锁存器,如下所示:
input a,b,c;
reg e,d;
always @(a or b or c)
begin
e = d & a & b;//因为d没有在敏感电平列表中,所以d变化时,e不能立刻变化,要等到a或b或c变化时才能体现出来,这就是说实际上相当于存在一个电平敏感的透明锁存器在起作用,把d信号的变化所存其中
d = e | c;
end
(7)对一个寄存器型(reg)或整型(integer)变量的赋值值允许在一个always块内进行,如果在另一always块也对其赋值,这是非法的。
(8)把某一信号值赋为'bx,综合器就把它解释成无关状态,因而综合器为其生成的硬件电路最简洁。
2.可综合风格的Verilog HDL模块实例
(1)组合逻辑电路设计
8位带进位端的加法器的设计实例。
module adder_8(cout,sum,a,b,cin);
input cin;
input [7:0] a,b;
output cout;
output [7:0] sum;
assign {cout,sum} = a+b+cin;
endmodule
指令译码电路的设计实例(利用电平敏感的always块来设计组合逻辑)。
'define plus 3'd0
'define minus 3'd1
'define band 3'd2
'define bor 3'd3
define unegate 3'd4
module alu(out,opcode,a,b);
input [2:0] opcode;
input [7:0] a,b;
output [7:0] out;
reg [7:0] out;
always @(opcode or a or b)
begin
case(opcode)
'plus: out = a + b;
'minus: out = a - b;
'band: out = a & b;
'bor: out = a | b;
'unegate: out = ~a;
default: out = 8'hx;
endcase
end
endmodule
比较后重组信号的组合逻辑(利用task和电平敏感的always块设计)。
module sort4(ra,rb,rc,a,b,c,d);
input [t:0] a,b,c,d;
output [t:0] ra,rb,rc,rd;
reg [t:0] ra,rb,rc,rd;
reg [t:0] va,vb,vc,vd;
parameter t = 3;
always @(a or b or c or d)
begin
{va,vb,vc,vd} = {a,b,c,d};
sort2(va,vc);
sort2(vb,vd);
sort2(vc,vd);
sort2(vb,vc);
{ra,rb,rc,rd} = {va,vb,vc,vd};
end
task sort2;
begin
inout [t:0] x,y;
reg [t:0] tmp;
if(x>y)
begin
tmp = x;
x = y;
y = tmp;
end
end
endtask
endmodule
比较器的设计实例(利用赋值语句设计组合逻辑)。
module compare(equal,a,b);
input [size-1:0] a,b;
output equal;
parameter size = 1;
assign eequal = (a==b)?1:0;
endmodule
奇偶校验位生成器设计。
module parity(even_numbits,odd_numbits,input_bus);
input [7:0] input_bus;
output even_numbits,odd_numbits;
assign odd_numbits = ^input_bus; //当input_bus中1的个数为奇数时,输出为1
assign even_numbits = ~odd_numbits; //此时输出even_numbits为0
endmodule
三态输出驱动器设计。
module tristl(in,out,enable);
input in,enable;
output out;
assign out = enable?in:'bz;
endmodule
//
module trist2(in,out,enable);
input in,enable;
output out;
bufifl mybuf1(in,out,enable);//bufifl是一个Verilog门级原语(primitive)通过实例例化该原语,实现三态门的调用
endmodule