VerilogHDL数字系统设计及实践第章Verilog行为描述

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

3.2.2always语句 类似于initial语句,各个always语句同样是从仿真0时刻开始并行执行,但不同之处在于 always语句在执行完所有内部的语句后会立刻从头开始重新执行,并循环往复,一直到仿真 结束。因为always循环执行这一特性,通常我们需要给它加上时序控制,否则其会变成一个 无限循环过程,从而造成仿真死锁,
计算功能 选择信号sel 2’b00 2’b01 2’b10 2’b11 a+b a-b a|b a&b
思考与练习
8. 有如下一段代码 initial begin b = 1’b0; #0 b = 1’b1; c = #1 b; end 请问c的最终值是多少? 9. 有如下一段代码 initial while(enable) #20 clk = ~clk; 请将上面的代码用always和wait语句改写,实现同样的行为。 10. 有一个模块fadder_4,其功能为4位全加器,输入端口为A[3:0](加数1),B[3:0] (加数2),输出端口为S[3:0](和),C(进位)。请写一个testbench测试此全加器, 要求测试所有加数的组合。 11. 请设计一个门控时钟信号,周期为20个时间单位,占空比30%,门控信号为enable, 当门控信号为高,输出时钟信号,当门控信号为低,无时钟输出为低。要求时钟切换时 无毛刺。
3.9 时序控制
//example_3_2:一个带异步复位的电平敏感锁存器 module latch_rst ( input i_reset, input i_clk, input i_d, output reg o_q ); always@( i_reset or i_clk or i_d ) begin i_d if (i_reset) o_q = 1’b0; i_clk else if (clk) o_q = d; end endmodule i_reset 其综合后的 结构为一个 带异步复位 的锁存器:
3.8 循环语句
3.8.2 for循环 for循环的关键字为for,格式为: for ( 初始条件表达式; 终止条件表达式; 控制变量表达式 ) 语句; for循环的运行方式与C语言中的for语句相同,即首先执行初始表达式,然后每 次开始新的循环时计算终止条件表达式,如果终止条件表达式的值为真,则执行for 循环中的语句一次。执行完一次循环后,无条件执行控制变量表达式,然后重新开 始下一次循环。如果终止条件表达式的值为假,则结束循环,跳出for语句。 3.8.3 repeat循环 repeat循环的关键字为repeat,其格式为: repeat ( 循环次数表达式 ) 语句; repeat循环最大的特点是执行固定次数的循环,它不能根据某个条件表达式来决定 循环执行与否。其中循环次数必须是一个常量,变量或者表达式。同样,如果一次循 环需要执行多条语句,则需要用begin..end或fork…join组合为块语句。
3.5 条件语句
条件语句可以根据某个判定条件来确定后面的语句是否执行。条件语句使用的关 键字为“if”和“else” if (条件表达式) 条件为真执行的语句; 或: if (条件表达式) 条件为真执行的语句; else 条件为假执行的语句;
或: if (条件表达式1) 条件为真执行的语句1; else if (条件表达式2) 条件为真执行的语句2; else if (条件表达式3) 条件为真执行的语句3; …… else 条件为假执行的语句1;
Verilog HDL 数字系统设计及实践
第3章 Verilog行为描述
学习指南
• 【知识目标】 • (1) 了解initial和always语句的概念; • (2) 了解块语句及过程赋值语句的概念和形式; • (3) 理解条件语句,多路分支语句和循环语句的功能特点; • (4) 理解各种时序控制的机制及形式。 • 【技能目标】 • (1) 能够建立各种基本的行为模型。 • 【重点难点】 • (1) 非阻塞赋值与阻塞赋值的区别; • (2) 各种时序控制机制的特点及应用。
3.2 结构化过程语句
Leabharlann Baidu
结构化过程语句包含两种:initial语句和always语句,它们也是行为描述方式的基本语句。 所有行为描述的其他语句(如过程赋值语句)必须包含在这两种语句当中。 3.2.1initial语句 一条initial语句从仿真的0时刻开始执行,但是只执行一次。如果initial语句中包含了多 条行为语句,那么需要用begin和end将其组合成块语句如果只包含了单条行为语句则不 必使用begin和end。
3.8 循环语句
3.8.4 forever循环 forever语句的关键字为forever,其格式为: forever 语句; forever循环是永久循环,不需要任何条件表达式,也不做任何计算与判断。 Forever 无条件的做无限次循环,直到仿真结束。同样循环语句如果为一组,需要 begin…end或fork…join组合为块语句。
case语句在执行的时候,首先计算表达式的值,然后按顺序将它与各个分支表达 式的值进行比较,当找到相等的分支表达式后,执行对应的语句然后跳出case语句。 如果和所有的分支表达式的值都不相等,则执行 default 分支的默认语句。若没有 default分支,则直接退出
3.7 条件语句和多路分支语句的比较
思考与练习
6. 上题的代码改写如下 initial begin a = 1’b0; b = 1’b0; c = 1’b1; b <= #10 1’b1; c <= #5 1’b0; d <= #15 {a,b,c}; end 请问每条语句执行的仿真时刻是多少?仿真结束后,各变量值是多少? 7. 请设计一个可选择的计算单元,输入a,b位宽为8,输出结果ret为9位,如下图
3.1 Verilog的基本描述形式
对于模块内具体电路功能逻辑的描述,通常有下面3种方式: (1).数据流描述方式:使用连续赋值语句对数据流行为进行描; (2).行为描述方式:使用结构化过程语句对时序行为进行描述。其中结构化过程 语句包括 两种语句:initial语句和always语句。 (3).层次化描述方式:使用原语或模块的实例化对电路结构进行描述(其中原语 包括内建门级原语,开关级原语,用户自定义原语
3.4 过程赋值语句
过程赋值语句指在 initial 语句或 always 语句中对变量进行赋值的语句,它们 只能对寄存器、整数等变量进行赋值。这些变量数据在被赋值后,值保持不 变,直到下一个过程赋值语句对它们赋新的值。 阻塞赋值语句:阻塞赋值语句用“=”作为赋值符。阻塞语句按顺序执行, 在下一条语句执行之前,上一条赋值语句必须执行完毕。 非阻塞赋值语句:非阻塞语句用“<=”作为赋值符。非阻塞赋值语句不会阻 塞同一个块语句中的其他语句的执行。注意非阻塞赋值语句的赋值符与关系 操作符的小于等于符号是一样的,它在不同的语法环境下被解释成不同的语 法含义。
注意:if与else的配对关系,else总是与它之前的最近一个没有else的if配对。尤其 在if嵌套的语句中,配对关系易混淆,需注意区分以避免逻辑错误。
3.6 多路分支语句
case语句的关键字为“case”,“default”和“endcase”。其格式如下: case ( 表达式 ) 分支表达式1:语句1; 分支表达式2:语句2; …… default:默认语句; endcase
并行块: 并行块中的语句是并行执行的,一旦仿真进入到并行块,则块里面的所有语句都同 从并行 的仿真时刻同时开始执行。若使用延迟语句,则每条语句的延迟值是 都是相对于并行块开始执行的仿真时刻而言的,与前后语句的执行顺序无关。 块语句的其他特点: 块语句可以嵌套,顺序块与并行块可以混合使用 。 块语句可以被命名,称为命名块。在命名块中我们可以声明局部变量,但只 能在块内使用。
(1)if…else语句带有优先级,而case语句则没有,是并行的关系。 (2)在嵌套的 if…else语句中,每一个条件判断是一种层层递进的形式,最前面的if 判断语句具有最高的优先级。在 case语句中,各个条件判断则是一种并列形式,与 条件表达式的顺序无关。
3.8 循环语句
Verilog语言中有四种类型的循环语句:while,for,repeat和forever。它们都 只能在initial或always语句模块中使用。 3.8.1while循环 while循环的关键字为while,其格式为: while ( 条件表达式 ) 语句; 当条件表达式为真,则循环执行里面的语句,如果条件表达式为假,则中止循 环并跳出while。
3.9 时序控制
时序控制是Verilog语言中比较重要的语句。在Verilog设计中通过各种时序控制语句可 以指定过程语句执行的时刻,从而实现特定的与时间有关的电路时序功能。Verilog提供 了两种类型的时序控制方法:基于延迟的时序控制和基于事件的时序控制。 3.9.1延迟控制 基于延迟的时序控制用在表达式中,用于指定语句开始执行到执行完成之间的时 间间隔。其形式为 # [延迟值],其中延迟值可以是常数,变量或表达式。基于延迟的 时间控制通常可分为两种形式:常规延迟和内嵌延迟。 (1).常规延迟 常规延迟控制语句将指定延迟的语句放在赋值语句的最左边,用来给赋值语句指 定一个延迟值,其语法格式如下: #[延迟值] 语句; (2).内嵌延迟 延迟控制也可以放到赋值语句中,写在赋值语句等号的右边。
3.9 时序控制
(2). 电平敏感事件控制 前面提到的边沿敏感事件控制是以信号值变化的边沿为标志,即一定要等到 指定信号的某个值的变化边沿才会触发执行。而电平敏感事件控制则是以信号值本 身的状态为敏感标志,相当于判断某个事件为真还是为假。电平敏感事件控制使用 的关键字为“wait”,其格式为: wait (事件) 语句; 当事件为真时,后面的语句才会执行,否则会一直等待。例如: wait (enable) data = d; wait (counter > 16) flag = 1; 仿真会一直监视括号内的表达式的值,当其值为真时,后面的语句得以执行。 (3). 时序控制语句在可综合代码中应用 在进行电路综合的时候,延迟控制语句会被综合工具自动忽略,即当作没有延迟处 理。而事件控制语句并不是所有的使用形式都可以被综合。事件控制语句通常与 always语句联合使用,用来构建时序逻辑中常见的电路单元。
3.3 顺序块和并行块
块语句的作用是可以将两条或更多的过程语句组合在一起,变成像一条过程语句一样 的语法结构。块语句可以分为两种:一种是begin...end语句,块里面的语句顺序执行, 称为顺序块;另一种是fork…join语句,块里面的语句并行执行,称为并行块。 顺序块: 顺序块中的各条语句是按顺序执行的,前一条语句执行完后才能执行后一条 语 句,所以每条语句的延迟值是对前一条语句的仿真时间而言的。
3.9 时序控制
3.9.2事件控制 基于事件的时序控制是指通过事件的发生来触发语句的执行。在Verilog语言中, 一个事件通常是指一个变量、线网信号或表达式的值发生变化。所以语句的执行在指 定变量的值发生变化的时刻开始,从而提供了更灵活和复杂的时序控制方法。基于事 件的控制大致可以分为:边沿敏感事件控制和电平敏感事件控制。 (1). 边沿敏感事件控制 边沿敏感事件控制用符号@来说明,其格式为: @ 事件 语句; 或: @ (事件1 or 事件2 ... or 事件n) 语句; 或: @ (事件1, 事件2, ..., 事件n) 语句; 例如: @clock a = ~a; @(posedge clk) data = d;
latch_rst D EN CLR Q o_q
图3.2 带异步复位的锁存器
思考与练习
1. 设计一个时钟信号,周期为20个时间单位,占空比30%。 2. 请将一个位宽为8,地址范围为64的寄存器数组进行初始化,所有位均设置为1。 3. 设计一个带同步复位的D触发器。(清零端低电平有效,在时钟上升沿执行清零操 作) 4. 请描述如下的一个电路模型:在每一个时钟上升沿检查输入信号pwd(位宽为8), 如果其值为55H或者AAH,输出信号flag为1,并显示pwd的值,否则flag为0,并显示 “error!”。 5. 看下面的一段代码 initial begin a = 1’b0; b = 1’b0; c = 1’b1; #10 b = 1’b1; #5 c = 1’b0; #15 d = {a,b,c}; end 请问每条语句执行的仿真时刻是多少?仿真结束后,各变量值是多少?
相关文档
最新文档