FPGA学习笔记(四)——VerilogHDL条件语句与循环语句
FPGA学习笔记(四)————Verilog HDL条件语句与循环语句
⽂章⽬录
1.if–else语句
其格式与C语⾔中的if–else语句类似,使⽤⽅法有以下3种:
//形式1:只有if的形式
if(表达式)  语句1;
if(表达式)
begin
表达式1;
end
/
/形式2:if--else形式
if(表达式)
语句或语句块1;
else
语句或语句块2;
//形式3:if--else嵌套形式
if ( 表达式1)    语句1;
else if ( 表达式2 )  语句2;
else if ( 表达式3 )  语句3;
........
else if ( 表达式m )  语句m;
else              语句n;
//例如:
if ( a > b )      out = int1;
else if ( a == b)  out1= int2;
else          out1 = int3;
表达式:⼀般为逻辑表达式或关系表达式,也可能是⼀位的变量。
系统对表达式的值进⾏判断,若为0,x,z,按“假”处理;若为1,按“真”处理,执⾏指定语句。
语句可是单句,也可是多句,多句时⽤“begin - end”语句括起来。对于if语句的嵌套,若不清楚if和else的匹配,最好⽤begin-end 语句括起来。
条件语句必须在过程块中使⽤:
always@(a,b,int1,int2)
begin
if(a>b)
begin
out1=int1;
out2=int2;
end
else
begin
out1=int2;
out2=int1;
end
end
允许⼀定形式的表达式简写⽅式:
if(expression) 等同于 if(expression == 1)
if(!expression) 等同于 if(expression!= 1)
if(!expression) 等同于 if(expression!= 1)
if语句的嵌套,即在if语句中⼜包含⼀个或多个if语句称为if语句的嵌套。应当注意if与else的配对关系,else总是与它上⾯的最近的if配对。
if-else 嵌套形式隐含优先级关系:
always@(sela or selb or a or b or c)
begin
if(sela)  q=a;
else if(selb) q=b;
else q=c;
end
2.case语句
Verilog语⾔提供的case语句直接处理多分⽀选择,通常⽤于描述译码器、数据选择器、状态机及微处理器的指令译码等,它的⼀般形式如下:
case(表达式)
分⽀表达式1:语句1;
分⽀表达式2:语句2;
···
分⽀表达式n:语句n;
default: 语句n+1; //如果前⾯列出了表达式所有可能取值,default语句可以省略
endcase
case括弧内的表达式称为控制表达式,case分⽀项中的表达式称为分⽀表达式。分⽀表达式则⽤这些控制信号的具体状态值来表⽰,因此分⽀表达式⼜可以称为常量表达式。
当控制表达式的值与分⽀表达式的值相等时,就执⾏分⽀表达式后⾯的语句;如果所有的分⽀表达式的值都没有与控制表达式的值相匹配,就执⾏default后⾯的语句。
分⽀表达式后⾯的语句也可以是由begin-end括起来的语句块。
default项可有可⽆,⼀个case语句⾥只准有⼀个default项。同样,case也只能在块语句中使⽤。
//case语句实现3-8译码器的部分代码如下:
wire[2:0] sel;
reg[7:0]  res;
always @ (sel or res)
begin
//case语句;
case (sel)
3’b000 : res=8’b00000001;
3’b001 : res=8’b00000010;
3’b010 : res=8’b00000100;
3’b011 : res=8’b00001000;
3’b100 : res=8’b00010000;
3’b101:  res=8’b00100000;
3’b110 : res=8’b01000000;
default:  res=8’b10000000;
endcase
end
case语句的所有表达式值的位宽必须相等,只有这样,控制表达式和分⽀表达式才能进⾏对应位的⽐较。⼀个经常犯的错误是⽤’bx,'bz来替代n’bx,n’bz,这样写是不对的,因为信号x,z的默认宽度是机器的字节宽度,通常是32位。
执⾏完case分项后的语句,则跳出该case语句结构,终⽌case语句的执⾏。
在case语句中,表达式与分⽀表达式1到分⽀表达式n之间的⽐较是⼀种全等⽐较(===),必须保证两者的对应位全等。如果表达式的值和分⽀表达式的值同时为不定值或者同时为⾼阻态,则认为是相等的
case01x z
01000
10100
x0010
z0001
case ( a )
2’b1x:out = 1;  // 只有a = 1x,才有out = 1
2’b1z:out = 0;    // 只有a = 1z,才有out = 0
...
endcase
case(select[1,2])
2'b00: result  = 0;
2'b01: result  = flaga;
2'b0x,
2'b0z: result  = flaga ? 'bx:0;
2'b10: result  = flagb;
2'bx0,
2'bz0: result  = 0;
default: result  = flagb ? 'bz:0;
endcase
//当多个分项可以共⽤⼀个语句或语句块。其分⽀表达式之间⽤“,”隔开。
case语句还有两种变种,即casez语句和casex语句。
casez:
忽略⽐较过程中值为z的位,即如果⽐较的双⽅(表达式的值与分⽀表达式的值)有⼀⽅的某⼀位的值是z,那么对这些位的⽐较就不予考虑,只需关注其他位的⽐较结果。
casex:
在casex语句中,则把这种处理⽅式进⼀步扩展到对x的处理,即将z和x均视为⽆关值。
casez01x z
01001
10101
x0011
z1111
//在分⽀表达式中,z常⽤?代替。
continue语句执行过程casez(a)
3'b1?? :  out1 = 1;//如果a=100、101、110、111或1xx,1zz等,都有out1 = 1。
3'b0?1 :  out2 = 1; //如果a=001、011、0x1、0z1,都有out2 = 1
.......
endcase
casex01x z
01011
10111
x1111
z1111
例如:
casex(a)
2'b1x:out=1;
.
.................
endcase
//如果a=10、11、1x、1z,都有out=1。
if语句条件不完备情况
如果if语句和case语句的条件描述不完备,会造成不必要的锁存器 。
⼀般不可能列出所有分⽀,因为每⼀变量⾄少有4种取值0,1,z,x。为包含所有分⽀,可在if语句最后加上else;在case语句的最后加上default语句。
回顾⼀下锁存器和寄存器的区别:
always@(a or b)
begin
if(a == 1’b1)
y = b;
end
always@(posedge clk)        begin
if(a == 1’b1)
y <= b;
end
//⽑刺通过D触发器被滤除