《Verilog HDL数字系统设计与应用》 课件 FPGA-第4章-行为描述语言_第1页
《Verilog HDL数字系统设计与应用》 课件 FPGA-第4章-行为描述语言_第2页
《Verilog HDL数字系统设计与应用》 课件 FPGA-第4章-行为描述语言_第3页
《Verilog HDL数字系统设计与应用》 课件 FPGA-第4章-行为描述语言_第4页
《Verilog HDL数字系统设计与应用》 课件 FPGA-第4章-行为描述语言_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章行为描述的语法4行为描述语言行为描述是一种从抽象角度来表示硬件电路,通过表达输入与输出之间的关系来描述硬件行为的方法。行为描述直接根据电路外部行为进行描述,与硬件电路结构无关。VerilogHDL语法中的行为语句主要包括过程语句、块语句、条件语句和循环语句。这些语句的用法与C语言很类似,容易理解,但也存在一些不同之处,如块语句、casex和casez等。行为描述一般使用initial和always过程结构语句,其他行为语句只能出现在这两种过程结构语句中。

VerilogHDL的过程语句主要包括initial语句和always语句。在一个模块(module)中,使用initial和always语句的次数是不受限制的,而且每个initial和always都是并行执行的。initial语句通常用于仿真中的初始化,只在程序开始时执行一次。当触发方式满足后,always块内的语句一直重复执行。该语句可综合也可用于仿真,是一种被广泛采用的电路设计方式。4.1过程语句

initial语句主要用于仿真测试,在仿真0时刻开始对变量进行初始化或激励波形的产生。一个模块中可以有多个initial语句,每个initial语句都是同时从仿真0时刻开始并行执行。initial语句不能被综合,其格式如下:

initial begin/fork

语句1; 语句2;

……

语句n;

end/join

begin-end与fork-join块语句类似C语言中的{},区别在于begin-end是串行执行的而fork-join是并行执行的。4.1.1initial语句4.1过程语句4.1过程语句【例4.1】用initial过程语句对测量变量a的赋值。

'timescasle10ns/1nsmoduletest; reg[2:0]a; initialbegina=3'b000; #5a=3'b001;#5a=3'b010;#5a=3'b011;#5a=3'b100;end endmodule在例4.1中,'timescasle10ns/1ns表示模块仿真的时间单位为10ns,时间精度为1ns,并定义变量a,在initial语句中对a进行赋值。initial语句中的内容在仿真0时刻开始执行,并且只执行一次:仿真0时刻开始,a值为3'b000,经过50ns后a值为3'b001,再经过50ns后a值为3'b010,最后经过200ns后a值一直保持为3'b100。4.1过程语句4.1.2always语句只有当触发条件满足时,always语句才会不断重复的执行其后的块语句。always语句可被综合也可用于仿真,多个always语句间是并行执行的,与书写先后顺序无关。always语句格式如下: always@(敏感信号列表) begin

语句1;

语句2; ……

语句n; end敏感信号分为两种:一种为电平敏感型信号,一种为边沿敏感型信号。敏感信号之间用“or”或者“,”隔开。例如:电平敏感型信号always@(A,B)与always@(AorB)这两种书写格式表示的内容是一样。电平敏感型是指信号变量发生电平的变化,一般用于组合逻辑电路中。使用时应把可以引起always语句中的被赋值变量变化的所有信号都放入敏感信号列表中。4.1过程语句【例4.2】

用case语句描述一个3输入与非门。modulemy_nand(f,a,b,c);inputa,b,c; outputregf; always@(aorborc)//等价于always@(a,b,c) case({a,b,c}) 3'b000:f=1;3'b001:f=1;3'b010:f=1;3'b011:f=1;3'b100:f=1;3'b101:f=1;3'b110:f=1;3'b111:f=0;default:f=1'bx;endcase endmodule4.1过程语句在例4.2中,只要a、b、c任何一个输入信号发生变化,都会执行always语句一次。在case语句中,根据{a,b,c}的值来选择执行其中一个分支。用always语句设计组合逻辑电路时,需将所有输入变量都列入敏感信号列表中。可以用“*”来表示always过程语句中所有的输入信号变量,其书写格式有always*或always(*)。4.1过程语句例4.2中的程序可以写为modulemy_nand(f,a,b,c);inputa,b,c; outputregf; always@(*) case({a,b,c}) 3'b000:f=1;3'b001:f=1;3'b010:f=1;3'b011:f=1;3'b100:f=1;3'b101:f=1;3'b110:f=1;3'b111:f=0;default:f=1'bx;endcase endmodule边沿敏感型信号是指信号变量出现上升沿或者下降沿变化,主要用于时序逻辑电路中,有两种表示形式:posedge表示上升沿,negedge表示下降沿。4.1过程语句【例4.3】设计一个同步清零、同步置数的D触发器。 moduleDff(inputD,clk,reset,set,outputregQ); always@(posedgeclk) begin if(!reset)Q<=0; //同步清零,低电平有效 elseif(!set)Q<=1; //同步置数,低电平有效 else Q<=D; end endmodule在例4.3中,always语句的敏感信号列表为上升沿clk,当clk上升沿到来时,将执行always中的语句一次。执行always语句时会优先判断reset复位信号,如果复位信号无效,则判断set置数信号,这体现了清零的优先级高于置数的优先级的。当敏感信号列表中加入reset和set的边沿信号时,D触发器将变成异步清零、异步置数的D触发器,当三个敏感信号的其中之一满足触发条件时,always后的块语句执行一次,修改如下:always@(posedgeclk,negedgereset,negedgeset)4.1过程语句例如,下面的描述是错误的:always@(posedgeclk,negedgereset,negedgeset) begin if(reset)Q<=0; //应改为if(!reset) elseif(!set)Q<=1; else Q<=D; end语句的逻辑描述要与敏感信号列表中的有效电平一致。例如,采用reset信号下降沿为触发信号,则低电平为有效置数电平,在描述置数功能时切勿写成高电平有效。4.2块语句4.2.1串行块语句begin-end当语句有两条以上时,要用块语句将语句结合成一个整体,当块内只有一条语句时,块标识符就不需要了。块语句分为串行块语句begin-end和并行块语句fork-join两种。串行块内各条语句按它们在块内位置顺序执行,比如:begin b=a;//先执行 c=b; //后执行 end串行块语句begin-end块内的语句顺序执行:先将a的值赋值给b,再将b的值赋值给c,最后a,b,c的值相同。 begin-end也常用于仿真中的驱动波形的产生。4.2块语句【例4.4】采用begin-end语句产生3输入与非门的驱动波形。 `timescale1ns/1psmoduletest1_TF; rega,b,c; wiref; my_nanduut(.f(f),.a(a),.b(b),.c(c) ); initial begin {a,b,c}=3'b000; #100{a,b,c}=3'b000;#100{a,b,c}=3'b001; #100{a,b,c}=3'b010; #100{a,b,c}=3'b011; #100{a,b,c}=3'b100;#100{a,b,c}=3'b101; #100{a,b,c}=3'b110; #100{a,b,c}=3'b111; endendmodule4.2块语句并行块内各条语句各自独立地同时开始执行,即块内各条语句开始执行时间都是进入块内的时间,属于并发执行。比如:假设执行下面语句前a=1,b=2,c=3。 fork b=a; c=b; join

上述fork-join块语句执行完后,等式左边b和c同时得到等式右边的值,即:b=1,c=2。

在进行仿真时,fork-join并行块中每条语句前面的延时都是相对于该并行块的起始执行时间的。4.2.2并行块语句fork-join4.2块语句【例4.5】采用fork-join语句产生3输入与非门的驱动波形。 `timescale1ns/1psmoduletest1_TF; rega,b,c; wiref; my_nanduut(.f(f),.a(a),.b(b),.c(c) ); initial fork {a,b,c}=3'b000; #100{a,b,c}=3'b000;#200{a,b,c}=3'b001; #300{a,b,c}=3'b010; #400{a,b,c}=3'b011; #500{a,b,c}=3'b100;#600{a,b,c}=3'b101; #700{a,b,c}=3'b110; #800{a,b,c}=3'b111; joinendmodule4.3条件语句VerilogHDL提供两种条件语句:if-else语句和case语句,两种语句都属于顺序执行语句,而且必须在过程块如initial或always等内使用。4.3.1if-else语句

用if-else语句来判定所给条件是否满足,根据判定结果(真或假)决定执行给出的两种操作之一。与C语言中if语句类似,VerilogHDL提供三种形式的if语句。C语言中用{}将语句括起来,VreilogHDL语言则用begin-end将语句括起来。1、if(表达式)

语句;单分支语句,如果表达式为真,则执行语句,否则不执行语句。例如:if(a==b)out1<=int1;2、if(表达式)

语句1;else语句2;双分支语句,如果表达式为真,则执行语句1,否则执行语句2。例如:if(a==b)out1<=int1;elseout1<=int2;4.2块语句3、if(表达式1)

语句1;elseif(表达式2)语句2;elseif(表达式3)语句3;……elseif(表达式n)语句n;else语句n+1;

多分支语句:如果表达式1为真,则执行语句1,否则再判断表达式2;如果表达式2为真,执行语句2,否则再判断表达式3,以此类推,直到最后。例如:if(a==b)out1<=int1; elseif(a<b)out1<=int2; elseout1<=int3;

上述三种形式中的“表达式”一般为逻辑表达式、关系表达式或1位变量。if语句对表达式的值进行判断,若值为0、x或z则按“假”处理,若值为1则按“真”处理。尽量不要使用方式一,因为有if没有else会容易产生不必要的触发器用于保存if语句不成立时的值。4.2块语句语句可是单句,也可是多句,多句时用begin-end块语句括起来。比如: if(a>b)begina<=b;b<=c;end else beginc<=a;b<=c;end

注意:在end后面不需要加分号。

在if与else配对关系上,else总是与它前面最近if配对,且else不能单独出现,有else的地方必须要有一个if与它配对。4.2块语句比如:

下面为错误例子: if(a>b)out1<=int1;if(c==0)beginout1<=int2;endout2<=int3; else out2<=int4;

上述例子中由于书写格式不清晰,导致else配对出现错误和语法错误,可以将上面程序写成:if(a>b)beginout1<=int1;if(c==0)beginout1<=int2;endout2<=int3;endelse beginout2<=int4;end4.2块语句【例4.6】使用if-else语句设计八位数据选择器。moduleMUX8(out,in0,in1,sel); parameterN=8; outputreg[N:1]out; input[N:1]in0,in1; inputsel; always@(*) begin if(sel)out<=in0; elseout<=in1;endendmodule4.2块语句【例4.7】

设计一个带同步清零和加载端(低电平有效)的模60的BCD码计数器。 `timescale1ns/1ps modulecounter //模块声明采用Verilog-2001格式 (inputload,clk,reset, input[7:0]data, outputreg[7:0]BCDout, outputcout); always@(negedgeclk) //时钟下降沿触发always begin if(!reset) BCDout<=0; //同步复位,reset=1时复位 elseif(!load)BCDout<=data;//同步加载,load=1时加载 elsebegin if(BCDout[3:0]>=9)//个位在0~9内加1 beginBCDout[3:0]<=0; if(BCDout[7:4]==5)BCDout[7:4]<=0;//十位在0~5内加1 elseBCDout[7:4]<=BCDout[7:4]+1; end elseBCDout[3:0]<=BCDout[3:0]+1; end end assigncout=(BCDout==8'h59)?1:0; endmodule4.2块语句

case语句是一种多分支选择语句,使用case语句代替if-else语句可使读者更容易读懂代码,逻辑利用率和性能上都有所提高。case语句有case、casez、casex三种方式,casez忽视“z”而casex忽视“x”,使用方法有所不同。4.3.2case语句1.case语句case语句的使用格式如下:case(条件表达式)

值1:语句1; //case分支项

值2:语句2; ……

值n:语句n; default:语句n+1;//缺省项 endcase//结束case语句4.2块语句case语句执行过程:首先计算出条件表达式的值,按顺序将它和各分支项值进行比较,然后执行相匹配的分支语句;如果都不满足匹配条件,则执行default后面的语句。

若前面已列出了条件表达式所有可能的取值,则default语句可以省略;若未列全所有取值,最好不要省略default语句,否则会产生不必要的锁存器。说明:(1)case分支表达式值1~n必须互不相同,否则会出现矛盾现象,同一个值有多种执行语句。(2)执行完case分支语句后,则跳出case语句结构,终止case语句执行(无需像C语言要break才跳出分支)。(3)case语句条件表达式与分支值的位宽必须相等。4.2块语句【例4.8】

使用case语句实现一个有使能控制端res(低电平复位)的四选一数据选择器。modulemux(EN,IN0,IN1,IN2,IN3,SEL,OUT); inputEN;input[3:0]IN0,IN1,IN2,IN3;input[1:0]SEL; outputreg[3:0]OUT; always@(SELorENorIN0orIN1orIN2orIN3) begin if(EN==0)OUT={4{1'b0}}; elsecase(SEL) 0:OUT=IN0; 1:OUT=IN1; 2:OUT=IN2; 3:OUT=IN3; default:OUT=4'bx; endcase endendmodule4.2块语句【例4.9】

使用case语句描述的3人表决电路。 modulevote3 (inputa,b,c,outputregpass); always@(a,b,c)begin case({a,b,c}) //用case语句进行译码 3’b000:pass=1'b0; //表决不通过 3’b001:pass=1'b0; 3’b010:pass=1'b0; 3’b011:pass=1'b1; //表决通过 3’b100:pass=1'b0; 3’b101:pass=1'b1; //表决通过 3’b110:pass=1'b1; //表决通过 3’b111:pass=1'b1; //表决通过 default:pass=1'b0; endcase end endmodule4.2块语句2.casez语句与casex语句(1)在case语句中,条件表达式与分支值1~n的比较是一种全等(===)的比较,条件表达式与分支的值必须完全相等。(2)在casez语句中,条件表达式与分支值1~n的比较不是全等的比较,如果分支表达式某些位的值为高阻z,则不比较忽略考虑,只需关注其他位的比较结果。(3)在casex语句中,条件表达式与分支值1~n的比较不是全等的比较,如果分支表达式某些位的值为高阻z或者是未知状态x,则不比较忽略考虑,只需关注其他位的比较结果。例如:case(in)2'b1z:out=1; //只有in=2'b1z,才有out=1casez(in)2'b1x:out=1; //如果in=2'b1z或2'b1x,则out=1casex(in)2'b1z:out=1; //如果in=2'b1z、2'b1x、2'b11或2'b10,则out=14.2块语句此外,还有一种表示x或z的方式,即用表示无关值的符号“?”来表示。例如:casez(in) 2'b1?:out=1; //如果in=2’b10、2’b11、2’b1x或2’b1z,则out=1case、casez和casex语句的比较如表4.1所示。表4.1case、casez和casex语句的比较4.2块语句【例4.10】

用casez语句描述8-3编码器。modulecoder_83(inputx,input[7:0]data,outputreg[2:0]code);always

@(data)begincasez

(data)8'b1xxx_xxxx:code=3'b111;8'b01xx_xxxx:code=3'b110;8'b001x_xxxx:code=3'b101;8'b0001_xxxx:code=3'b100;8'b0000_1xxx:code=3'b011;8'b0000_01xx:code=3'b010;8'b0000_001x:code=3'b001;8'b0000_0001:code=3'b000;default:code=3'bx;endcaseendendmodule4.4循环语句VerilogHDL中的循环语句用于控制语句的执行次数。循环语句语句主要有以下4种:(1)for:有条件的循环语句;(2)repeat(n):连续执行循环语句n次;(3)while:执行一条语句直到某个条件不满足,如果条件不满足,则直接退出循环;(4)forever:永远连续执行语句,可以用作时钟等周期性波形的生成。4.4循环语句4.4.1for语句for

语句的格式如下(同C语言):for

(循环变量初始化;循环结束条件;循环变量增量)

执行语句;其中:循环变量初始化用于提供循环变量的初始值;循环结束条件一般为表达式用于指定循环结束的条件;循环变量增量通常为增加或减少循环变量的计数值;执行语句即需要循环的语句,有多条语句时用begin-end括起来。for语句的执行过程如下:(1)执行循环变量赋初值一次。(2)判断循环结束条件是否成立,如果不成立,则退出for循环;如果成

立,则执行循环语句,再执行循环变量增量语句。(3)重复过程(2)。4.4循环语句【例4.11】用for语句描述10人表决器。

module

responder(input[9:0]

vote,output

reg

result)

;

reg[2:0]

sum;

integer

i;

always

@(vote)beginsum=0

;

for(i=0;

i<=9;

i=i+1)if

(vote[i])

sum=sum+1;if

(sum>5)result=1;//若超过5人赞成,则result=1

elseresult=0;endendmodule4.4循环语句【例4.12】用for语句计算输入的九位数据中1的个数。

moduleget1(in,count); input[8:0]in; outputreg[3:0]count; integeri; always@(in) begin for(i=0;i<=8;i=i+1) if(in[i]==1'b1)count=count+1; end endmoudule一般情况下,综合器都支持for循环语句,而不支持其他三种循环语句。4.4循环语句repeat语句的格式如下:repeat(表达式)

语句或 repeat(表达式)begin多条语句endrepeat循环语句的执行过程为:先计算表达式的值,再根据其值决定循环次数;如果表达式的值不确定(x或z)则循环次数按0次处理。4.4.2repeat语

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论