行为级建模
目录
(1)repeat 循环执行语句或语句块确定的次数,目前不可综合,多用于验证代码。
2.1、数据流描述
(在数字电路中,信号经过组合逻辑时类似信号的流动,信号从输入流向输出,不会再其中存储,且出入变化时,会在一定的时间后引起输出的变化)
连续赋值语句(使用assign关键字)
使用语法:
< assign > [strength][#delay] <net_name> = <expression>;
其中[strength][#delay]是可选项,<net_name>为定义的网线名,<expression>是赋值表达式。
注意:
- 只有线网型变量才能在assign语句中被赋值;
- 并行性
- 连续赋值语句可以是显性或隐性
- 表达式<expression>中可使用条件操作符或函数返回值
- 定义延时(wire out; assign #5 out = in1 && in2;)
- 定义线网变量强度
2.2、结构化过程语句
(1)initial语句
initial语句在仿真一开始(0时刻)就立即开始执行,每个initial语句只执行一次。(initial语句常用于验证模块,是不可综合的)
- “begin…end”中的语句是“串行”执行的;
- “fork… jion”中的语句是“并行”执行的。
(2)always语句
Always语句从仿真0时刻开始顺序执行语句块中行为语句,执行完最后一条语句后,又开始执行该语句中的第一条语句,如此循环往复,直到整个仿真结束。(always语句往往只有和一定的时序(或事件)控制结合在一起才有用,即在整个仿真过程中,只要满足触发条件就可重复执行。)
注意:
- 在always中被赋值的变量只能是寄存器型变量;
- 没有加时序控制的always语句是没有意义的。
延时触发描述的always语句不可综合,即always #delay <描述语句>是不可综合描述,一般用在测试平台;而基于事件的时序(边沿触发、或电平触发)则是可综合描述。
(3)时序控制
Verilog提供了三种过程时序控制方法:简单延迟(“#”)、基于事件(“@”)的时序控制和等待语句(wait)
①简单延迟赋值用于initial或always语句块中,不可综合
基于延迟的时序控制一般用 # delay_time,非0延迟放于赋值语句的左边,即:
< # delay_time > LHS = RHS ;
或将其嵌入赋值语句之中,即:
LHS = < # delay_time > RHS ;
②基于事件的时序控制,其中的时间是指某个寄存器或线网型变量的值发生了变化,用来触发后面申明的语句或语句块的执行。基于事件的时序控制使用符号@来说明,使语句继续执行的时间则是信号发生了正或负向沿跳变或信号值发生了变化。
③)等待语句使用关键字wait,表示wait后面的条件为真才触发后面的语句或语句块执行。(wait用于行为级代码中电平敏感的时序控制)
(4)过程赋值语句块
①阻塞赋值使用“=”作为赋值操作符,顺序块中的阻塞赋值语句按顺序执行,赋值执行完成后再执行顺序块内下一条语句。
阻塞赋值语法表达为:LHS = RHS;
其中在阻塞赋值语句中LHS只能为寄存器变量。(如果多个阻塞赋值语句出现在同一always块中,前面的语句执行完后才会执行下一句中右边表达式的计算)
②非阻塞赋值使用“<=”作为赋值操作符,其语法表达为:LHS <= RHS;其中,RHS表达式在赋值开始时刻进行计算,在赋值操作结束时更新LHS。与阻塞赋值不同的是,非阻塞赋值语句操作期间,允许语句块中其他的Verilog语句、包括其他非阻塞语句同时进行操作,即:
- 如有多个非阻塞赋值语句顺序出现在begin…end语句块中,前面的语句的执行并不阻塞后面语句的执行,赋值操作是并发的,语句前后执行的次序不存在相关;
- 只能在过程语句块内使用。
(5)顺序语句块与并行语句块
顺序语句块使用关键字begin…end封装:语句块中的语句按给定次序顺序执行。每条语句中的时延值与其前面的语句执行的仿真时间有关。(使用“=”赋值时,语句块内的语句按书写的次序执行;使用“<=”赋值时,语句块内的多条语句可并发执行)
并行语句块使用关键字fork…join封装,其中的所有语句在各自定义的延迟之后立即计算执行,即如果语句前有延时,延时的长度都是相对该快的开始时间而言;因此并行块内的语句顺序无关紧要。(注意:fork…join块是典型的不可综合语句)
2.3、条件语句
- 只有if的形式
- if…else形式
- if…else嵌套形式
2.4、分支语句
(1)case
使用关键字case和endcase封装,内部缺省分支项使用关键字default表示。(default可选,但建议添加,否则会出现if…else不配套的问题)
(2)casex和casez
casex语句将分支条件中的所有x、z都看作“不关心”的值,casez语句将分支条件中的所有z都看作“不关心”的值,忽略值为z的位;其分支表达式中可用?代替z。
(3)使用注意
- 一条case(casex、casez)语句不能有两条或两条以上default分支项。Case语句可以嵌套使用。
- 描述组合逻辑时,如果分支语句中没有default语句,case语句通常会综合出不必要的锁存器,因此通常用default作为最后一条case语句以捕捉非法的情况;
- 条件语句是带优先级的,而分支语句是不带优先级的。
2.5、循环语句
(1)repeat 循环执行语句或语句块确定的次数,目前不可综合,多用于验证代码。
如:
repeat(loop_number)
statement_block;// statement_block为欲循环执行的一条语句
其中loop_number必须是一个常量、变量或表达式,表示执行的循环次数。
(2)forever 无穷循环
可用一个单独的always语句块来实现其功能(不可综合)
退出循环只能采用强制退出的方法。
(3)while 通过控制某个变量的取值来控制循环次数
控制条件为假,则跳出循环(一般不可综合,只有存在某个@(posedge clock)语句来终止循环时它才可以综合)
使用语法表示为:
While (condition_statement)
Statement_block;
其中控制条件condition_statement可为任意的逻辑表达式。
(4)for 可以实现所有的循环结构(可综合)
使用语法为:
for(循环变量初值;循环终止条件;更新循环变量)
statement_block;
for循环常用于对数组或存储器变量进行初始化。