当前位置:   article > 正文

verilog初识-条件语句、循环语句、块语句_verilog if循环下多条语句

verilog if循环下多条语句

verilog初识-条件语句、循环语句、块语句

1.条件语句

1.1条件语句(if_else语句)

if语句用来判断给定的条件是否满足,根据判断的结果决定要执行的操作。verilog HDL提供了3种形式的if语句。

  • (1) if(表达式) 语句。
    如:
    if(a>b) out1= in1;
  • (2) if(表达式) 语句1;
    else 语句2;
    如:if(a>b) out1=in1;
    else out1=in2;
  • (3) if(表达式1) 语句1;
    else if(表达式2) 语句2;
    else if(表达式3) 语句3;

    else 语句n;
    如:
if(score>90) level=1;
else if(score>80) level=2;
else if(score>70) level=3;
else if(score>60) level=4;
else level=5;
  • 1
  • 2
  • 3
  • 4
  • 5
  • tips:
    • (1)条件语句必须在过程块语句中使用。所谓过程块语句指的是由initial和always语句引导的执行语句集合。除这两种块语句引导的begin end块中可以编写条件语句外,模块中其他地方都不能编写。
      如:
      always@(some_event)
      begin

      if(a>b) out=in1;
      ese if(a==b) out=in2;
      else out=in3;
      end
    • (2)if后面的表达式一般为逻辑表达式或关系表达式,系统对表达式的值进行处理,若表达式结果为0,x,z,按“假”处理,若为1,按“真”处理。
    • (3)在if和else后面可以包含一个内嵌的操作语句,也可以有多个操作语句,此时用begin和end将几个语句包含起来成为一个复合块语句。
      如:
	if(a>b)
		begin
			out1=in1;
			out2=in2;
		end
	else
		begin
			out1=in2;
			out2=in1;
		end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • (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;
    注:else总是与它上面最近的if配对。如果if与else的数目不一样,可以用begin_end块语句来确定配对关系。
    其结构如下:
    if()
    begin
    if()语句1;//(内嵌if)
    end
    else
    语句2;
    如:
    if(index>0)
    begin
    for(scani=0;scani<index;scani=scani+1)
    if(memory[scani]>0)
    begin
    $display(“…”);
    memory[scani]=0;
    end
    end
    else
    $display(“error-indexiszero”);
    tips:
    if语句通常只有两个分支可供选择,多于两个分支需要使用if嵌套。

    1.2.条件语句(case语句)

case语句是一种多分支语句,通常包含两个或多个分支语句。
其结构形式为:

  • (1)case(表达式)
    分支表达式: 语句1;

    默认项(default项): 语句n;
    endcase
  • (2)casez(表达式)
    分支表达式: 语句1;

    默认项(default项): 语句n;
    endcase
  • (3)casex(表达式)
    分支表达式: 语句1;

    默认项(default项): 语句n;
    endcase
    其中语句1,语句2,…,语句n可以是1条语句或多条语句,当为多条语句时,需要使用begin_end来将多条语句组合为一个语句块。
    特点:
    (1)case()里面的表达式也称控制表达式,常亮表达式,当控制表达式的值与分支表达式的值相等时,执行分支表达式后面对应的语句,如果所有分支表达式的值都没有与控制表达式的值相匹配,则执行dafault后面的语句。
    (2)每一个case分支表达式的值必须互不相同。
    (3)当case执行完分支语句,即终止其他case语句的执行。
    (4)case语句的所有表达式值的位宽必须相等,注意避免使用’bx,'bz来替代n’bx,n’bz,因为信号x和z的默认宽度为机器的字节宽度,通常是32位,而n是case控制表达式的位宽,二者通常情况下是不相等的。
    如:
    case(sig)
    1’bz: $display(“signal is floating”);
    1’bx: $display(“signal is unknown”);
    default: $display(“signal is %b”,sig);
    endcase
    (5)casez和casex可以用来处理比较过程中不必考虑的情况,其中casez语句用来处理不考虑高阻值z的比较过程,casex语句则将高阻值z和不定值x都视为不必关心的情况。所谓的不必关心的情况,即在表达式进行比较时,不讲该位的状态考虑在内。
    如(1):
    reg[7:0] sig;
    casez(sig)
    8’b1???: instruction1(sig);
    8’b0110???: instruction2(sig);
    8’b???11000: instruction3(sig);
    default:instruction4;
    endcase
    (2):
    reg[7:0] r,mask;
    mask = 8’bx00x00x1;
    casex(r^mask)
    8’b001011xx: stats1;
    8’b1100xx00: stats2;
    8’b0110xx11: stats3;
    default:stats4;
    endcase
  • tips:
    • (1)条件语句编写时,注意在if后面要有对应的case语句,在case_endcase内部需要有default语句,这样可以避免出现不必要的锁存器。
      如:
      always @(al or d)
      begin
      if(al) q=d;
      end
      此代码缺少else语句,因此在执行时会生成锁存器。
      正确的(避免不必要锁存器出现)代码为:
      always @(al or d)
      begin
      if(al) q=d;
      else q=0;
      end
      同理,如果在case_endcase语句内部没有default语句,也会生成锁存器。
    • (2)case语句的行为类似多路选择器。
      如:使用case语句实现四选一多路选择器:
module mux4_to_1(out,i0,i1,i2,i3,s1,s0);
//输入输出端口声明
output out;
input i0,i1,i2,i3;
input s1,s0;
//输出变量类型声明
reg out;
//任何输入信号变化,都会引起输出信号的状态更新
always@(s1 or s0 or i0 or i1 or i2 or i3)
begin
	case({s1,s0})
		2'b00: out = i0;
		2'b01: out = i1;
		2'b10: out = i2;
		2'b11: out = i3;
	default: out = 1'bx;
	endcase
end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2.循环语句

在verilog HDL中存在着4种类型的循环语句,用来控制执行语句的执行次数。

  • forever语句:连续的执行语句。
  • repeat语句:连续执行一条语句n次。
  • while语句:执行一条语句直至某个条件不满足。如果一开始条件就不满足,则语句一次也不执行。
  • for语句:根据设定的条件执行指定的次数

2.1 forever语句

forever语句,常用于产生周期性的波形,用作仿真测试信号。与always的不同之处在于它不能独立写在程序中,而是必须写在initial块中。
格式如下:
forever 语句;

forever
begin
多条语句;
end

2.2 repeat语句

格式如下:
repeat(表达式) 语句

repeat(表达式)
begin
多条语句;
end
在repeat语句中,其表达式通常为常量表达式。
如:使用repeat循环语句及加法和移位操作来实现一个乘法器:

paremeter size=8;longsize=16;
reg[size-1] opa,opb;
reg[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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

2.3 while语句

格式如下:
while(表达式) 语句;

while(表达式)
begin
多条语句;
end
如:统计1个八位二进制数中1的个数:

begin: count1s
	reg[7:0] tempreg;
	count = 0 ;
	tempreg = rega;
	while(tempreg)
		begin
			if(tempreg[0]) count = count + 1;
			tempreg = tempre >> 1;
		end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.4 for语句

格式如下:
for(表达式1;表达式2;表达式3)
语句;
表达式1对变量初始化,表达式2对变量满足的条件进行判断,如果满足,执行表达式3,否则结束循环。
最常见的形式如下:
for(循环变量赋初值;循环结束条件;循环变量增值)
如(1)初始化memeory:

begin: init_mem
	reg[7:0] tempi;
		for(tempi=0;tempi<memsize;tempi=tempi+1)
			memory[tempi]=0;
end
  • 1
  • 2
  • 3
  • 4
  • 5

(2)实现乘法器(与repeat语句中的例子执行结果相同)

parameter size=8,longsize=16;
reg[size:1] opa,opb;
reg[longsize:1] result;

begin:mult
	integer cnt;
	result = 0;
	for(cnt=1;cnt<=size;cnt=cnt+1)
		if(opb[cnt])
			result=result+(opa<<(cnt-1));
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3.块语句

3.1 块语句的类型

块语句包含两种类型:

  • 顺序块,如always,begin_end,语句块内部顺序执行
  • 并行块,如fork_join,语句块内部并发执行
3.2 块语句的特点

块语句具有3个特点:

  • 嵌套块
  • 命名块
  • 命名块的禁用
3.2.1 嵌套块

嵌套块,在块语句内部调用其他块语句。
如:

initial
begin
	x=1'b0;
	fork//内部嵌套
		#5 y=1'b1;//在第5个单位时间开始执行
		#10 z={x,y};//将x与y拼接,然后赋值给z,在第10个单位时间开始执行
	join
	#20 w={y,x};//在第20个单位时间开始执行
end

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
3.2.1 命名块

命名块,指的是给块赋予名字。其特点如下:

  • 命名块中可以声明局部变量;
  • 命名块是设计层次的一部分,命名块中声明的变量可以通过层次名引用进行访问;
  • 命名块可以被禁用,例如使用disable停止其执行。
    如:
module top;//指定模块名为top
	initial
	begin:block1//为顺序块命名为block1
		integer i;//整形变量i是block1命名块的静态局部变量,在其他模块或者命名块中可以使用层次名top.block1.i对其进行访问
		...
	end

	intial 
	fork:block2//为顺序块命名为block2
		reg i;//寄存器变量i是block2命名块的静态局部变量,在其他模块或者命名块中可以使用层次名top.block2.i对其进行访问
		...
	join
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
3.2.1 命名块的禁用

verilog通过关键字disable提供了一种中止命令块执行的方法。disable可以用来从循环中退出、处理错误条件以及根据控制信号来控制某些代码段是否被执行。对块语句的禁用导致紧跟在块后面的那条语句被执行。
使用上与C语言的break类似,但是break只能退出当前所在的循环,而disable可以禁用任意一个命名块。
如:

reg[15:0] flag;
integer i;

initial 
begin
	flag = 16'b0010_1110_0100_1000;
	i = 0;
	begin:block1
		while(i<16)
		begin
			if(flag[i])
			begin
				$display("encounted a true bit at element number %d",i);
				disable(block1);//当在寄存器中找到值为1的第一个位置,禁用block1
			end
			else	i=i+1;
			end
		end
	end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/101472
推荐阅读
相关标签
  

闽ICP备14008679号