第三章基于Verilog HDL语言的设计(四)基于Verilog HDL语言的设计(四)本节课将讲解Verilog HDL行为建模方法,同学们需掌握并行块和顺序块、条件语句、循环语句、赋值语句等常见Verilog HDL语句的结构,这是行为建模的基础。
3.4.1 顺序块和并行块语句Verilog HDL中使用块语句将多条语句组合成一条复合语句。
复合语句块语句分为顺序块语句和并行块语句。
块语句分为顺序块语句和并行块语句顺序块格式:beginbegin 块名块内变量参数定义;执行语句1;执行语句2;块内变量、参数定义;执行语句1;……..end 执行语句2;……..end并行块 格式:fork执行语句1;fork块名块内变量、参数定义语句;执行语句2;…执行语句1;执行语句2;join…join例顺序块和并行块程序执行过程的区别例:顺序块:并行块:fork s=0;begin s=0;s 0;#2 s=1;#4s=0;#2 s=1;#2 s=0;#4 s 0;#7 s=1;#8s=0;#3 s=1;#1 s=0;#8 s 0;joinend3.4.2 条件语句if语句格式:(3)if(表达式1) <语句1>;(1)if(表达式) <>;else if(表达式2) <语句2>;语句;(2)if(表达式)……else if(表达式n)<语句1>;<语句n>; elseelse <语句2>;<语句n+1>;if后面的表达式,可以是逻辑表达式、关系表达式还可以是操作数。
若为0,x,z按“假”若为按“假”处理,若为1,按“真”处理,执行指定的语句()等价于()如if(a) 等价于if(a = =1)如果if和else后有多个执行语句,可以用begin… end块将其整合在一起b d块将其整合在起例:if(a > b)begin data_out1 <= a; data_out2 <= b; end elsedata out1<=b;data out2<=a;begin data_out1 b; data_out2 a;endif语句嵌套使用时,else与最近的if语句配对例:if(a >b)if(a>b)if ( c ) data_out <= c + 1;else data_out <= a + 1;l d t t1else data_out <= b;If-else数目不一致,最好使用begin-end块if(…)f()if(…) beginfor(…..) if(..)gfor(…..) if()begin if(..) begin语句组;endl语句组;endelse …….endelseelse …….如果不正确使用else,可能会生成不需要的锁存器。
module test (a,b,data_out);input a,b;p_output data_out;reg data_out;always @ (a or b)always@(a or b)beginif(a) data_out <= a;if(a)data out<=a;endendmoduleWarning (10240): Verilog HDL Always Construct warningat test11.v(7): inferring latch(es) for variable "data_out", which holds its previous value in one or more paths through the always constructthe always constructalways @ (a or b) beginif(a) data_out < a; if(a)data out<=a; else data_out <= b; enddif-else表达了一个条件选择的设计意图,它与条件运算符有重要的区别条件运算符可以出现在个表达式中9条件运算符可以出现在一个表达式中。
9if-else只能出现在always, initial块语句,或函数任务中,一般只能在行为建模中使用函数、任务中,般只能在行为建模中使用。
case语句如果选项数目很多,用if-else-if会不方便,可使用case语句。
语句格式:case(控制表达式)分支表达式1:语句1;…分支表达式n: 语句n;default: 默认语句;endcase各分支表达式值不能相同,如果多个不同的状态值有相同的执行语句,可以用逗号将各个状态隔开。
相同的执行语句可以用逗号将各个状态隔开例: case(select)2b00 : data_out <= data_in1;2'b00:data out<=data in1;2'b01 : data_out <= data_in2;2b10 : data_out < data_in3;2'b10:data out<=data in3;2'b11 : data_out <= data_in4;,,,,_;2'b0x,2'bx0,2'b1x,2'bx1,2'bxx: data out <= 4'bxxxx;2'b0z,2'bz0,2'b1z,2'bz1,2'bzz: data_out <= 4'bzzzz;default :$display("the control signal is invalid");endcased建议在case语句中最好加入default分支3.4.3 循环语句循环语句只能在initial,always块中使用。
下面介绍常用的循环句:for、forever、repeat 和while语句格式循环终止条件for语句语句格式:for(表达式1;表达式2;表达式3) 语句;改变循环控制变初始条件表达式量的赋值语句语句执行过程例:用for语句对存储器组进行初始化。
reg[7:0] my_memory[511:0];integer i;initialbeginfor(i=0; i<512; i=i+1)my_memory[i]<= 8’b0;end3.4 行为级建模例:用for语句对存储器组进行初始化。
reg[7:0] my_memory[511:0];integer i;initialbeginfor(i=0; i<512; i=i+1)my_memory[i]<= 8’b0;end设计练习:用for 语句描述的七人投票表决器module voter7(pass,vote);output pass;input[6:0] vote;i[60]reg[2:0] sum;integer i;integer i;reg pass;y@()always @(vote)beginsum=0;for(i=0;i<=6;i=i+1) //for 语句f(i0i6i i1)//fif(vote[i]) sum=sum+1;if(sum[2]) pass=1; //若超过4 人赞成,则pass=1 if(sum[2])pass=1;//4人赞成则else pass=0;endendmodulef循环般用于具有固定开始和结束条件的循环 for 循环一般用于具有固定开始和结束条件的循环,如果只有一个执行循环的条件,最好还是用while循环hil语句格式while 语句语句格式:while(条件表达式) 语句语句执行过程9先求解条件表达式的值,如果值为真(等于1)执行内嵌的执行语句(组)否则结束循环,执行内嵌的执行语句(组),否则结束循环。
9如果一开始就不满足条件表达式,则循环不执行module count(clk, data_out);input clk;input clk;output[12:0] data_out;reg[12:0]data out;reg [12:0] data_out;integer j;initial //data_out和j赋初值为0initial//data outbegin data_out = 0; j = 0;while(j<=100)begindata_out = data_out + j;data out=data out+j;j= j+1;end$display ("the sum is %d,j= %d",data_out,j); endforever语句语句格式:foreverforever语句;表示永久循环无条件地无限次执行其后的语句 表示永久循环,无条件地无限次执行其后的语句,相当于while(1),直到遇到系统任务$finish或$stop不能独立写在程序中,必须写在initial 结构中。
例:使用forever语句生成一个周期为20个时间单位的时钟信号。
g;reg clock;initialbeginbeginclock = 0;forever #10 clock = ~ clock;endrepeat语句语句格式:repeat(表达式))语句9repeat语句执行其表达式所确定的固定次数的循环操作。
9其表达式通常是常数,也可以是一个变量,或者一个信号,如果是变量或者信号,循环次数是循环开始时刻变量或信号的值,而不是循环执行期间的值。
3.4 行为级建模3.4.1 赋值语句Verilog HDL常用赋值方式有过程赋值和连续赋值两种过程赋值语句的更新对象是寄存器,整数,实数等,这些类型变量在被赋值后,可以保持不变,直到类变量在被赋值后可以保持不变到赋值进程又被触发,变量才被赋予新值。
连续赋值语句中,任何一个操作数的变化都会重新 连续赋值语句中,任何个操作数的变化都会重新计算赋值表达式,重新进行赋值。
module pipe(q3,d,clk); output [7:0] q3;p[]q;input [7:0] d;input clk;reg [7:0] q3,q2,q1;always @ (posedge clk) gbeginq1 = d;q2 = q1;q3 = q2;32endendmodulemodule pipe(q3,d,clk); output [7:0] q3;p[]q;input [7:0] d;input clk;reg [7:0] q3,q2,q1;always @ (posedge clk) gbeginq3 = q2;q2 = q1;q1 = d;1dendendmodule连续赋值常用于数据流行为建模。