夏老师的书
case语句中需要注意的点:
casez
用来处理不考虑高阻值Z的比较过程
reg [7:0] ir;
casez(ir)
8`b1???????:instruction1(ir);
8`b01??????:instruction2(ir);
8`b00010???:instruction3(ir);
8`b000001??:instruction4(ir);
endcase
casex
用来处理不考虑高阻值Z与不定值的比较过程
reg [7:0] ir;
casez(ir)
8`b1???????:instruction1(ir);
8`b01??????:instruction2(ir);
8`b00010???:instruction3(ir);
8`b000001??:instruction4(ir);
endcase
2.操作不当生成锁存器
在always块中,如果在给定的条件下变量没有赋值,这个变量将会保持原值,也就是说将生成一个锁存器。
///有锁存器
always @(al or d)
begin
if(al) q = d;
end
///无锁存器
always @(al or d)
begin
if(al) q = d;
else q = 0;
end
case语句中如果没有default语句,则除特殊值以外,其他值都会保持原值,便生成了锁存器。
///有锁存器
always @(sel [1:0] or a or b)
case(sel[1:0])
2`b00:q<=a;
2`b01 :q<=b;
endcase
///无锁存器
always @(sel [1:0] or a or b)
case(sel[1:0])
2`b00:q<=a;
2`b01 :q<=b;
default:q<= `b0;
endcase
3.循环语句
forever语句:常用于产生周期性的波形,用来作为仿真测试信号。与always的区别在于不能单独写在语句中,必须卸载initial块中。
repeat语句:通常是常量表达式。
//使用repeat语句实现乘法器
parameter size = 8,longsize = 16;
ref [size:1] opa,opb;
rge[longsize:1] result;
begin:mult
reg [longsize:1] shift)opa,shift_opb;
shift_opa = opa;
shift_opb = opb;
result = 0;
repeat(size)
begin
if(shift_opb[1])
result = result + shift_opa;
shift_opa = shift_opa <<1;
shift_opb = shift_opb >>1;
end
end
4.顺序块与并行块
顺序块中的语句是一条接一条按顺序执行的,只有之前的语句执行结束才能执行后面的语句(除了带内嵌延迟控制的非阻塞赋值语句);延迟是相对上一条语句执行完成的仿真时间的。
并行块(fork-join)语句并行执行,执行顺序是由各自语句内延迟或者时间控制决定的;语句的延迟是相对于块语句开始执行的时刻而言的。
//带延迟的顺序块
reg x,y;
reg[1:0] z,w;
initial
begin
x = 1`b0;
#5 y = 1`b1;
#10 z = {
x,y};
#20 w = {
y,x};
end
//并行块
reg x,y;
reg[1:0] z,w;
initial
fork
x = 1`b0;
#5 y = 1`b1;
#10 z = {
x,y};
#20 w = {
y,x};
join
注意竞争-冒险现象。