Verilog HDL基础之:条件语句

if语句是用来判定所给定的条件是否满足,根据判定的结果(真或假)决定执行给出的两种操作之一。Verilog HDL语言提供了3种形式的if语句。

(1)无分支。

语法形式:

 

if (表达式) 语句;

 

例如:

if (a > b) out1 = int1; //若a大于b,将int1赋予out1

 

(2)单级分支。

语法形式:

 

if(表达式)语句1;

else 语句2;

 

例如:

if(a>b) out1=int1; //若a大于b,将int1赋予out1;否则,将int2赋予out1

else out1=int2;

 

(3)多级分支

语法形式:

 

if(表达式1) 语句1;

else if(表达式2) 语句2;

else if(表达式3) 语句3;

...

else if(表达式m) 语句m;

else 语句n;

 

例如:

if(a>b) out1=int1; //若a大于b,将int1赋予out1

else if(a==b) out1=int2; //否则,如果a等于b,将int2赋予out1

else out1=int3; //否则,将int3赋予out1

 

关于if语句有如下6点说明:

(1)3种形式的if语句中,在if后面都有“表达式”,一般为逻辑表达式或关系表达式。系统对表达式的值进行判断,若为0、x或z,按“假”处理;若为1,按“真”处理,执行指定的语句。

(2)第二、第三种形式的if语句中,在每个else前面有一分号,整个语句结束处有一分号。

这是由于分号是Verilog HDL语句中不可缺少的部分,这个分号是if语句中的内嵌套语句所要求的。如果无此分号,则出现语法错误。

但应注意,不要误认为上面是两个语句(if语句和else语句)。它们都属于同一个if语句。else子句不能作为语句单独使用,它必须是if语句的一部分,与if配对使用。

(3)在if和else后面可以包含一个内嵌的操作语句,也可以有多个操作语句,此时用begin和end这两个关键词将几个语句包含起来成为一个复合块语句如下所示。

 

if(a>b)begin //使用begin_end语句实现多个赋值操作

out1=int1;

out2=int2;

end

else begin

out1=int2;

out2=int1;

end

 

注意

在end后不需要再加分号,因为begin_end内是一个完整的复合语句,不需再附加分号。

 

(4)允许一定形式的表达式简写方式,例如:

 

if(expression) 等同于 if( expression == 1 )

if(!expression) 等同于 if( expression != 1 )

 

(5)if语句的嵌套。

在if语句中又包含一个或多个if语句,称为if语句的嵌套,一般形式如下:

 

if(expression1)

if(expression2) 语句1 (内嵌if)

else 语句2

else if(expression3) 语句3 (内嵌if)

else 语句4

 

应当注意if与else的配对关系,else总是与它上面的最近的if配对。如果if与else的数目不一样,为了实现程序设计者的企图,可以用begin_end块语句来确定配对关系,例如:

 

if() begin

if() 语句1 (内嵌if)

end

else 语句2

 

这时begin_end块语句限定了内嵌if语句的范围,因此else与第一个if配对。注意begin_end块语句在if_else语句中的使用,因为有时begin_end块语句的不慎使用会改变逻辑行为,如下所示:

 

if(index>0) //内嵌for语句,无else分支

for(scani=0;scaniindex;scani=scani+1) //内嵌if语句

if(memory[scani]>0) begin //使用begin_end语句,有else分支

$display(...);

memory[scani]=0;

end

else //此处为内嵌if语句的分支

$display(error-indexiszero);

...

尽管程序设计者把else写在与第一个if(外层if)同一列上,希望与第一个if对应,但实际上else是与第二个if对应,因为它们相距最近。正确的写法如下:

 

if(index>0) begin //内嵌for语句,有else分支

for(scani=0;scaniindex;scani=scani+1) //内嵌if语句

if(memory[scani]>0) begin //使用begin_end语句,无else分支

$display(...);

memory[scani]=0;

end

end

else //此处为外部if语句的分支

$display(error-indexiszero);

 

(6)if_else例子。

下面这段程序用if_else语句来检测变量index以决定modify-seg1、modify-seg2、modify-seg3中哪一个的值应当与index相加作为memory的寻址地址。并且将相加值存入寄存器index以备下次检测使用。程序的前10行定义寄存器和参数。

 

reg [31:0] instruction, segment_area[255:0]; //定义寄存器

reg [7:0] index;

reg [5:0] modify_seg1, modify_seg2, modify_seg3;

parameter //定义参数

segment1=0, inc_seg1=1,

segment2=20, inc_seg2=2,

segment3=64, inc_seg3=4,

data=128;

//检测寄存器index的值

if(indexsegment2) begin //index<20时,执行下列操作

instruction = segment_area[index + modify_seg1];

index = index + inc_seg1;

end

else if(indexsegment3) begin //20<index<64时,执行下列操作

instruction = segment_area[index + modify_seg2];

index = index + inc_seg2;

end

else if (indexdata) begin //64<index<128时,执行下列操作

instruction = segment_area[index + modify_seg3];

index = index + inc_seg3;

end

else //index>128时,执行下列操作

instruction = segment_area[index];

 

case语句

case语句是一种多分支选择语句,if语句只有两个分支可供选择,而实际问题中常常需要用到多分支选择。Verilog语言提供的case语句直接处理多分支选择。case语句通常用于微处理器的指令译码,它的一般形式如下:

(1)case (表达式) case分支项> endcase

(2)casez(表达式) case分支项> endcase

(3)casex(表达式) case分支项> endcase

case分支项>的一般语法格式如下:

 

分支表达式: 语句

缺省项(default项): 语句

 

关于case语句的几点说明如下。

(1)case括弧内的表达式称为控制表达式,case分支项中的表达式称为分支表达式。控制表达式通常表示为控制信号的某些位,分支表达式则用这些控制信号的具体状态值来表示,因此分支表达式又可以称为常量表达式。

(2)当控制表达式的值与分支表达式的值相等时,就执行分支表达式后面的语句。如果所有的分支表达式的值都没有与控制表达式的值相匹配的,就执行default后面的语句。

(3)default项可有可无,一个case语句里只能有一个default项。下面是一个简单的使用case语句的例子。该例子中对寄存器rega译码以确定result的值。

 

reg [15:0] rega;

reg [9:0] result;

case(rega)

16 d0: result = 10 b0111111111; //rega等于0时

16 d1: result = 10 b1011111111; //rega等于1时

16 d2: result = 10 b1101111111; //rega等于2时

16 d3: result = 10 b1110111111; //rega等于3时

16 d4: result = 10 b1111011111; //rega等于4时

16 d5: result = 10 b1111101111; //rega等于5时

16 d6: result = 10 b1111110111; //rega等于6时

16 d7: result = 10 b1111111011; //rega等于7时

16 d8: result = 10 b1111111101; //rega等于8时

16 d9: result = 10 b1111111110; //rega等于9时

default: result = bx; //rega不等于上面的值时

endcase

 

(4)每一个case分项的分支表达式的值必须互不相同,否则就会出现矛盾现象(对表达式的同一个值,有多种执行方案)。

(5)执行完case分项后的语句,则跳出该case语句结构,终止case语句的执行。

(6)在用case语句表达式进行比较的过程中,只有当信号的对应位的值能明确进行比较时,比较才能成功,因此要详细说明case分项的分支表达式的值。

(7)case语句的所有表达式的值的位宽必须相等,只有这样控制表达式和分支表达式才能进行对应位的比较。一个经常犯的错误是用bx、bz 来替代nbx、nbz,这样写是不对的,因为信号x、z的缺省宽度是机器的字节宽度,通常是32位(此处 n 是case控制表达式的位宽)。

 

case语句与if语句的区别主要有以下两点。

(1)与case语句中的控制表达式和多分支表达式相比,if结构中的条件表达式更为直观一些。

(2)对于那些分支表达式中存在不定值x和高阻值z时,case语句提供了处理这种情况的手段。下面的两个例子介绍了处理x、z值case语句。

例1:case语句1。

case (select[1:2])

2 b00: result = 0; //select[1:2]等于00时

2 b01: result = flaga; //select[1:2]等于01时

2 b0x,

2 b0z: result = flaga? bx: 0; //select[1:2]等于0x和0z时,执行表达式

2 b10: result = flagb; //select[1:2]等于10时

2 bx0,

2 bz0: result = flagb? bx :0; //select[1:2]等于x0和z0时,执行表达式

default: result = bx; //select[1:2]不等于上面的值时

endcase

 

例2:case语句2

 

case(sig)

1 bz: $display(signal is floating); //sig为高阻时,打印输出

1 bx: $display(signal is unknown); //sig为不定状态时,打印输出

default: $display(signal is %b, sig); //为其他时,即0或1时,打印输出

endcase

 

针对电路的特性,Verilog HDL提供了case语句的其他两种形式用来处理不必考虑的情况(dont care condition)。其中casez语句用来处理不考虑高阻值z的比较过程,casex语句则将高阻值z和不定值都视为不必关心的情况。

所谓不必关心的情况,即在表达式进行比较时,不将该位的状态考虑在内。这样在case语句表达式进行比较时,就可以灵活地设置,以对信号的某些位进行比较。如表3.10所示为case、casez、casex 的真值表:

表3.10 case语句真值表

case

0

1

x

z

0

1

0

0

0

1

0

1

0

0

x

0

0

1

0

z

0

0

0

1

casez

0

1

x

z

0

1

0

0

1

1

0

1

0

1

x

0

0

1

1

z

1

1

1

1

casex

0

1

x

z

0

1

0

1

1

1

0

1

1

1

x

1

1

1

1

z

1

1

1

1

 

下面给出两个例子来分别说明casez语句和casex语句。

例3:casez语句。

 

reg[7:0] ir;

casez(ir)

8 b1???????: instruction1(ir); //只判断ir的最高位

8 b01??????: instruction2(ir); //只判断ir的高2位

8 b00010???: instruction3(ir); //只判断ir的高5位

8 b000001??: instruction4(ir); //只判断ir的高6位

endcase

 

例4:casex语句。

 

reg[7:0] r, mask;

mask = 8bx0x0x0x0;

casex(r^mask) //判断r^mask的结果

8 b001100xx: stat1; //不考虑低2位

8 b1100xx00: stat2; //不考虑第3、4位

8 b00xx0011: stat3; //不考虑第5、6位

8 bxx001100: stat4; //不考虑高2位

Endcase

 

其他条件语句

上面提到的if语句和case语句都只能应用于always语句内部。如果需要在always语句之外应用条件语句,可以采样这样的语法结构:

 

assign data = (sel)? a : b;

 

上面的语句的含义相当于:

if (sel = 1)

data = a;

else

data = b;

  • 8
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VerilogHDL是一种硬件描述语言,用于设计数字电路。门电路是数字电路中最基本的电路,它可以实现与、或、非等逻辑运算。下面介绍VerilogHDL基础门电路设计实验原理。 实验目的:掌握VerilogHDL语言编写基本门电路的方法。 实验原理: 1. VerilogHDL语言的基本结构 VerilogHDL语言的结构包括模块、端口、信号、赋值语句等。其中,模块是VerilogHDL的基本组成单元,端口用于连接不同模块的信号,信号用于传递数据和控制信息,赋值语句用于对信号进行赋值操作。 2. 门电路的基本原理 门电路是数字电路的基本单元,它实现逻辑运算,包括与、或、非等。与门、或门和非门的真值表分别如下: 与门: A | B | Y --|---|-- 0 | 0 | 0 0 | 1 | 0 1 | 0 | 0 1 | 1 | 1 或门: A | B | Y --|---|-- 0 | 0 | 0 0 | 1 | 1 1 | 0 | 1 1 | 1 | 1 非门: A | Y --|-- 0 | 1 1 | 0 3. 基本门电路的VerilogHDL实现 以与门为例,其VerilogHDL代码如下: ``` module and_gate(input A, input B, output Y); assign Y = A & B; endmodule ``` 其中,module定义了一个模块,input定义了输入端口,output定义了输出端口,assign用于对信号进行赋值操作。 以或门为例,其VerilogHDL代码如下: ``` module or_gate(input A, input B, output Y); assign Y = A | B; endmodule ``` 以非门为例,其VerilogHDL代码如下: ``` module not_gate(input A, output Y); assign Y = ~A; endmodule ``` 4. 门电路的组合 多个门电路可以组合在一起实现更复杂的逻辑运算,如与非、或非、异或等。以与非门为例,其VerilogHDL代码如下: ``` module nand_gate(input A, input B, output Y); wire w1; and_gate and(A, B, w1); not_gate not(w1, Y); endmodule ``` 其中,wire定义了一个中间信号,and_gate和not_gate分别实现了与和非的逻辑运算。 实验步骤: 1. 打开VerilogHDL开发环境,新建一个工程,命名为gate_design。 2. 在工程中新建一个VerilogHDL文件,命名为and_gate.v,输入与门的VerilogHDL代码。 3. 在工程中新建一个VerilogHDL文件,命名为or_gate.v,输入或门的VerilogHDL代码。 4. 在工程中新建一个VerilogHDL文件,命名为not_gate.v,输入非门的VerilogHDL代码。 5. 在工程中新建一个VerilogHDL文件,命名为nand_gate.v,输入与非门的VerilogHDL代码。 6. 编译并综合所有的VerilogHDL文件,生成门电路的网表文件。 7. 下载网表文件到FPGA开发板中,验证门电路的功能。 总结: VerilogHDL是设计数字电路的重要工具,可以用于实现基本门电路和复杂逻辑运算。掌握VerilogHDL语言的基本结构和门电路的基本原理,可以编写出实用的数字电路。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值