也就是相当于存在着一个透明锁存器把该信号的变化暂存起来,待敏感电平列表中某一个信号变化时再起作用,纯组合逻辑电路不可能做到这一点。这样,综合后所得电路已经不是纯组合逻辑电路了。这时综合器会发出警告提示设计中插入了锁存器,如下所示:
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,综合器就把它解释成无关状态,因而综合器为其生成的硬件电路最简洁。
例4.7:指令译码电路的设计实例(利用电平敏感的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); //模块声明
output [7:0] out;
input [2:0] opcode;
input [7:0] a,b; //端口声明
reg [7:0] out; //寄存器声明
always @(opcode or a or b) begin //用电平敏感的always块描述组合逻辑
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
例4.8:比较后重组信号的组合逻辑(利用task和电平敏感的always块设计)。
module sort4(ra,rb,rc,rd,a,b,c,d); //模块声明
output [t:0] ra, rb, rc, rd;
input [t:0] a, b, c, d; //端口声明
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 //用电平敏感的always块描述组合逻辑
{va,vb,vc,vd}={a,b,c,d};
sort2(va,vc); //信号重组
sort2(vb,vd);
sort2(va,vb);
sort2(vc,vd);
sort2(vb,vc);
{ra,rb,rc,rd}={va,vb,vc,vd};
end
task sort2; //x与y互换任务
inout [t:0] x,y;
reg [t:0] tmp;
if(x > y) begin
tmp = x; //使用临时变量tmp保存x的值
x = y;
y = tmp;
end
endtask
endmodule
例4.11:3-8编码器的设计实例。
编码器设计方案一。
module encoder1(none_on,out,in); //模块声明
output none_on;
output [2:0] out;
input [7:0] in; //端口声明
reg [2:0] out;
reg none_on; //寄存器声明
always @(in) begin: local //in有变化时,触发
integer i; //变量声明
out = 0;
none_on = 1; //初始化
for( i=0; i<8; i=i+1 ) begin //for循环语句
if( in[i] ) begin //将in中值为1的位编码
out = i;
none_on = 0;
end
end
end
endmodule
编码器设计方案二。
module encoder2 ( none_on,out2,out1,out0,h,g,f,e,d,c,b,a); //模块声明
input h,g,f,e,d,c,b,a;
output none_on,out2,out1,out0; //端口声明
wire [3:0] outvec; //向量声明
assign outvec = //使用assign语句实现输出向量赋值
h ? 4'b0111 : g ? 4'b0110 : f ? 4'b0101:
e ? 4'b0100 : d ? 4'b0011 : c ? 4'b0010 :
b ? 4'b0001 : a ? 4'b0000 : 4'b1000;
assign none_on = outvec[3]; //使用assign语句进行编码
assign out2 = outvec[2];
assign out1 = outvec[1];
assign out0 = outvec[0];
endmodule
编码器设计方案三。
module encoder3 ( none_on,out2,out1,out0,h,g,f,e,d,c,b,a); //模块声明
input h,g,f,e,d,c,b,a;
output none_on,out2,out1,out0; //端口声明
wire [3:0] outvec; //向量声明
assign {none_on,out2,out1,out0} = outvec; //与上例的编码方式一致
always @( a or b or c or d or e or f or g or h) begin
if(h) outvec=4'b0111; //使用if_else语句实现向量赋值
else if(g) outvec=4'b0110; //共9个分支,其中向量的低3位有8种编码方式
else if(f) outvec=4'b0101;
else if(e) outvec=4'b0100;
else if(d) outvec=4'b0011;
else if(c) outvec=4'b0010;
else if(b) outvec=4'b0001;
else if(a) outvec=4'b0000;
else outvec=4'b1000;
end
endmodule
例4.12:多路器的设计实例。
使用assign赋值语句、case语句或if-else语句可以生成多路器电路。如果条件语句(case或if-else)中分支条件是互斥的话,综合器能自动地生成并行的多路器。
多路器设计方案一。
modul emux1(out,a,b,sel); //模块声明
output out;
input a,b,sel; //端口声明
//使用assign语句检查输入信号sel的值
assign out = sel ? a : b; //当sel为1时,out为a;否则为b
endmodule
多路器设计方案二。
module mux2( out,a,b,sel); //模块声明
output out;
input a,b,sel; //端口声明
reg out;
always @(a or b or sel) begin //用电平触发的always块来设计多路器的组合逻辑
case( sel ) //使用case语句检查输入信号sel的值
1'b1: out = a; //如果为1,输出out为a
1'b0: out = b; //如果为0,输出out为b
default: out = 'bx; //默认状态
endcase
end
endmodule
多路器设计方案三。
module mux3( out,a,b sel); //模块声明
output out;
input a, b, sel; //端口声明
reg out;
always @( a or b or sel ) begin
if( sel ) //使用if_else语句检查输入信号sel的值
out = a; //如果为1,输出out为a
else
out = b; //如果为0,输出out为b
end
endmodule