EDA技术与VHDL设计(西电版)第5章 VHDL基本语句.ppt_第1页
EDA技术与VHDL设计(西电版)第5章 VHDL基本语句.ppt_第2页
EDA技术与VHDL设计(西电版)第5章 VHDL基本语句.ppt_第3页
EDA技术与VHDL设计(西电版)第5章 VHDL基本语句.ppt_第4页
EDA技术与VHDL设计(西电版)第5章 VHDL基本语句.ppt_第5页
已阅读5页,还剩214页未读 继续免费阅读

下载本文档

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

文档简介

第5章VHDL基本语句 5 1并行语句5 2顺序语句5 3常用语句的比较5 4组合逻辑电路的设计5 5时序逻辑电路的设计 5 1并行语句VHDL中既具有并行语句 如元件例化语句 也具有顺序语句 如IF语句 不同的语句使用在不同的地方 对于VHDL设计者来说 重要的是要知道哪些语句结构中需要使用并行语句 哪些语句结构中需要使用顺序语句 可以简单地概括为 结构体中除进程 PROCESS 函数 FUNCTION 和过程 PROCEDURE 结构内部以外的其他VHDL代码都是并行语句 如图5 1所示 需要注意的是 信号赋值语句既可以出现在进程中 也可以出现在结构体的并行语句部分 只是运行的含义不同 参考4 2 3节 图5 1结构体中的语句使用示例 5 1 1并行语句的特点并行语句是硬件描述语言的一大特点 它与C语言等计算机高级程序设计语言最大的不同是 并行语句在结构体中的执行是并行的 不会因为书写顺序的前后而产生执行顺序的先后 例5 1和例5 2结构体内都含有3条相同的并行语句 它们体现了在不同的描述顺序下 仍然能够综合出一致的电路结构 如图5 2所示 图5 2例5 1和例5 2综合后电路结构 例5 1 例5 2 正如图5 2的硬件电路图所表明的 只有当信号a或者b的值改变后才能执行赋值语句 x aANDb 即信号a或b的值改变之前信号x的值不会发生变化 同样 信号x的值改变之前 y的值也不会发生变化 信号c或y的值改变之前 z的值也不会发生变化 由此可以看出 VHDL代码的执行是由事件控制的 这就意味着并行VHDL语句可以按任意顺序书写 其设计的功能不变 例5 3再次显示了并行语句的特点 L13 L15这3条语句对应生成了3个加法器 见图5 3 即3个加法器同时在进行加法操作 没有顺序关系 而不是一个加法器顺序执行3条加法操作指令 VHDL代码最终实现的是具体的硬件电路 而不是在CPU中的逐条指令执行 这是VHDL语言相对于传统软件语言的不同 例5 3 图5 3例5 3综合后电路结构 在一个结构体内部 可以有一种或是几种类型的并行语句 并行语句之间通过信号进行信息的传递 图5 4所示是结构体中并行语句的结构示意图 从图中可以看到 VHDL支持的并行语句主要有进程语句 元件例化语句 包括类属参数传递映射语句 并行信号赋值语句 生成语句 并行过程 或函数 调用语句以及块语句 下面分别讲述每一种语句的结构和应用 图5 4并行语句结构示意图 5 1 2进程语句在一个结构体内可以有一个或多个进程 不同进程的地位是相同的 进程间的执行是并行的 独立的 由各自敏感信号的变化触发 一个进程有两个状态 等待状态和执行状态 在等待状态下 当任一敏感信号发生变化时 进程立即启动进入执行状态 当进程顺序执行到ENDPROCESS语句时 重新进入等待状态 等待下一次敏感信号的改变 进程语句内部结构由一系列顺序语句构成 能够很好地体现VHDL语言的行为描述能力 进程语句的语法格式已在3 5 3节中讲述 这里不再赘述 VHDL中的进程有两种类型 组合进程和时序进程 组合进程用于设计组合逻辑电路 时序进程用于设计引入了触发器的时序逻辑电路 在组合进程中 所有输入信号必须都包含到敏感信号参数表中 包括赋值符号 右边的所有信号以及IF语句 CASE语句的判断表达式中的所有信号 如果有一个信号没有包含在敏感信号参数表中 则当这个被忽略的信号变化时 该进程不会被激活 输出信号也不会得到新的赋值 时序进程又可分为同步和异步两类 同步进程只对时钟信号敏感 即仅在时钟的边沿启动 异步进程除了对时钟信号敏感外 还对影响异步行为的输入信号敏感 即该输入信号的变化也能启动进程 例5 4显示了一个带有异步复位信号reset的D触发器 当信号reset取值为 1 时 输出q立即被复位为 0 而不管此时是否有时钟信号clk的上升沿到来 即信号reset的变化也能够启动进程 当信号reset取值为 0 时 如果有时钟信号的上升沿到来 则输出q被赋值为d 仿真结果如图5 5所示 例5 4 图5 5例5 4异步复位D触发器时序仿真波形 例5 5是同步时序进程 只有时钟信号的上升沿到来时才能启动进程 即使信号reset发生改变 从 0 变化到 1 也不能启动进程 例5 5的仿真结果见图5 6 可以看到 当复位信号reset从 0 变为 1 时 由于此时并无时钟信号clk的上升沿到来 所以进程仍处于等待状态 输出q维持原值 当clk上升沿到来后 进程被启动 此时再判断信号reset的取值 如果为 1 则输入q被复位为 0 例5 5 图5 6例5 5同步复位D触发器时序仿真波形 电路系统有时既需要利用到时钟信号的上升沿又需要利用到下降沿 即在两个边沿时刻都需要处理数据 然而VHDL一般不允许对同一信号在时钟的两个边沿进行数据的赋值处理 且不论是在一个进程中 见例5 6 还是在不同的进程中 见例5 7 例5 6的本意是想实现当时钟信号clk上升沿到来时 将数据d1赋值给q 当时钟下降沿到来时 将数据d2赋值给q 编译后出现图5 7所示错误 显示无法在时钟的边沿实现寄存器的操作 例5 7省略了实体描述 它在不同的进程中对同一信号q赋值 可以看成是两条并行语句 一个进程可以看做一条并行语句 对同一信号赋值 这也是错误的 例5 6 例5 7 图5 7例5 6编译出现错误 例5 8是一个正确的示例 虽然它也同时用到了时钟信号的上升沿和下降沿 但由于不是对同一信号赋值所以能够通过编译 在时钟信号clk上升沿到来时刻 将输入信号d赋值给信号q1 而在时钟信号clk下降沿到来时刻 输出信号q得到信号q1的赋值 即输出信号q在时钟信号clk下降沿到来时刻才能得到输入信号d的值 仿真波形如图5 8所示 例5 8 图5 8例5 8时序仿真波形 5 1 3元件例化语句元件例化就是将预先设计好的设计实体定义为一个元件 然后利用特定的语句将此元件与当前设计实体中指定的端口连接 从而为当前设计实体引入一个新的低一级的设计层次 元件例化可以是多层次的 即在当前设计实体中调用的元件本身也是一个低层次的设计实体 它也可以通过调用其他的元件来实现 元件可以是一个已经设计好的设计实体 采用VHDL语言或者采用Verilog语言设计的实体 也可以是来自FPGA元件库中的元件 或是LPM模块 IP核等 元件例化语句一般由两部分组成 元件声明和元件例化 元件声明放在结构体说明语句部分 关键词ARCHITECTURE和BEGIN之间 元件例化放于结构体功能描述语句部分 关键词BEGIN后 其基本语法格式已在3 7节中讲述 这里不再赘述 5 1 4并行信号赋值语句并行信号赋值语句有三种形式 分别是简单信号赋值语句 条件信号赋值语句 WHEN ELSE语句 和选择信号赋值语句 WITH SELECT WHEN语句 这三种语句的共同点是 赋值目标都必须是信号 且语句在结构体内的执行是并行的 1 简单信号赋值语句简单信号赋值语句是VHDL并行语句结构中最基本的单元 在前面的章节中已经多次用到该语句 如例5 1 L12 L14 例5 2 L12 L14 和例5 3 L13 L15 都使用了简单信号赋值语句 需要注意的是 赋值符号 左右两边的数据类型必须一致 每一条简单信号赋值语句都相当于一条缩写的进程语句 而这条语句的所有输入 或读入 信号都被隐形地列入此缩写进程的敏感信号参数表中 任何输入信号的变化都将启动相关并行语句的赋值操作 而这种启动是完全独立于其他语句的 2 条件信号赋值语句 WHEN ELSE语句 例5 9是采用WHEN ELSE语句实现的4选1多路选择器 其元件图见图5 9 该设计实体有4个数据输入端a b c d 数据类型为STD LOGIC 有一个数据选择控制端sel 数据类型是STD LOGIC VECTOR 可以有 00 01 10 11 4个取值 当sel取值为 00 时 输出y被赋值a 当sel取值为 01 时 y被赋值b 当sel取值为 10 时 y被赋值c 当sel取值为 11 时 y被赋值d 仿真结果如图5 10所示 图5 94选1多路选择器 例5 9 图5 104选1多路选择器时序仿真波形 WHEN ELSE语句的功能与在进程中的IF语句功能相似 它通过判别条件是否为真来决定是否执行与该条件相对应的表达式的赋值 其一般语句格式如下 赋值目标 表达式1WHEN条件1ELSE表达式2WHEN条件2ELSE表达式3WHEN条件3ELSE 表达式n WHEN ELSE语句使用中要注意以下几点 1 WHEN条件ELSE 称为条件子句 条件子句后不需要加分号 或逗号 2 条件的判别是按照书写的顺序逐项进行测定的 一旦发现条件为TRUE 即将对应表达式的值赋予赋值目标 也就是说 执行赋值的表达式是第一个满足布尔条件为真所对应的表达式 3 当所有条件都不满足时 执行最后一条表达式的赋值 最后一条表达式没有条件子句 需要加分号 代表WHEN ELSE语句的结束 4 条件中允许使用不同的信号 这使得WHEN ELSE语句在设计时非常灵活 例5 10是一个简单的3选1数据选择器 再次显示了WHEN ELSE语句条件判别的顺序性 此例条件中的信号不同 分别是s1和s2 代表两个选择控制端 当s1和s2同时取值 1 时 由于书写的顺序性 导致第一条子句具有最高的优先级 即y获得的赋值是a 图5 11是利用Quartus 软件综合后的电路结构 由两个2选1选择器构成 当选择控制端s2取值 1 时 第一个选择器输出b 则第2个选择器在a和b这两个数据中选择 当选择控制端s1也取值 1 时 第2个选择器输出a 功能与WHEN ELSE语句的优先级相同 时序仿真波形见图5 12 虽然WHEN ELSE语句的条件判别具有顺序性 但其实质是生成硬件电路 语句本身是并行的 即当有多条WHEN ELSE语句时 由各自的敏感信号 语句的所有输入信号 如例5 10中的a b c s1 s2 触发 总结来说 在多条WHEN ELSE语句之间 书写顺序并不重要 但在WHEN ELSE语句内部 顺序是重要的 决定了赋值的结果 例5 10 图5 11例5 103选1数据选择器综合后电路结构 图5 12例5 103选1数据选择器时序仿真波形 3 选择信号赋值语句 WITH SELECT WHEN语句 例5 11是利用WITH SELECT WHEN语句实现的4选1多路选择器 从中可以发现选择信号赋值语句与条件信号赋值语句类似 都是根据条件选择相应的表达式对目标信号进行赋值的 例5 11 选择信号赋值语句的一般格式如下 WITH选择表达式SELECT赋值目标 表达式1WHEN选择值1 表达式2WHEN选择值2 表达式n 1WHEN选择值n 表达式nWHENOTHERS WITH SELECT WHEN语句使用中要注意以下几点 1 关键词WITH后的选择表达式是选择信号赋值语句的敏感量 每当选择表达式的值发生变化时 就将启动语句对各子句的选择值进行对比 当发现有满足条件的子句时 就将此子句中的表达式的值赋给目标信号 2 选择值需要覆盖选择表达式的所有可能取值 如果不能将其覆盖 最后必须加上WHENOTHERS子句 3 选择信号赋值语句对子句选择值的对比具有同期性 不像条件信号赋值语句那样按照书写顺序从上至下逐条测试 因此 选择信号赋值语句中的选择值不能出现重复的情况 4 与条件信号赋值语句相比 选择信号赋值语句只允许一个选择表达式 而条件信号赋值语句允许在条件中使用不同的信号 5 特别注意选择信号赋值语句的每一子句结尾用逗号分割 最后一条子句结尾用分号表示结束 而条件信号赋值语句每一子句的结尾没有任何标点 只有最后一条子句的结尾用分号表示结束 5 1 5块语句块语句 BLOCK语句 是并行语句 内部所包含的语句也是并行语句 块语句可以将结构体中的并行语句进行分割和组合 有利于对较长代码的管理和提高可读性 块语句有两种基本形式 简单块语句和保护块语句 1 简单块语句简单块语句的语句格式如下 标号 BLOCK 块声明部分 BEGIN并行语句 ENDBLOCK 标号 标号是设计者自定义的标识符 是块的名称 在关键词BLOCK前的标号是必需的 而在ENDBLOCK后的标号可以省略 块声明部分可以声明块的局部对象 包括数据类型 常量 信号 子程序等 块声明部分也不是必需的 例5 12是一个简单的块语句的示例 例5 12 ARCHITECTUREconstructOFexISBEGIN b1 BLOCKSIGNALy BIT BEGINy aANDb ENDBLOCK END 块语句 不管是简单块语句还是保护块语句 能够嵌套在另一个块语句中 例5 13显示了三个嵌套的块语句b1 b2和b3 其中块b2嵌套在块b1中 块b3嵌套在块b2中 块中声明的对象对这个块以及嵌套在其中的所有块都是可见的 且当子块声明的对象与父块声明的对象具有相同的名称时 子块将忽略父块的声明 例5 13 b1 BLOCKSIGNALs BIT 声明块b1中的信号sBEGINs aANDb 此处的信号s是块b1所声明的b2 BLOCKSIGNALs BIT 声明块b2中的信号sBEGINs cANDd 此处的信号s是块b2中声明的b3 BLOCKBEGINx s 此处的信号s是块b2中声明的ENDBLOCKb3 ENDBLOCKb2 y s 此处的信号s是块b1中声明的ENDBLOCKb1 2 保护块语句保护块语句是块语句中的特殊形式 它的基本格式如下 标号 BLOCK 保护表达式 块声明部分 BEGIN并行语句 ENDBLOCK 标号 保护块语句相比于简单块语句在关键词BLOCK后增加了一个特殊的表达式 称为保护表达式 保护表达式用于确定是否执行块中的保护语句 当保护表达式取值为真 TRUE 时 执行保护块内的保护语句 反之 则不执行 例5 14是一个带有同步复位信号reset的D触发器 当时钟上升沿到来时 保护表达式为真 则可以执行保护块内的保护语句 如果此时复位信号reset取值为 1 则q被赋值 0 例5 14 由于块语句的存在并不会对综合后的逻辑功能有任何的影响 综合器在综合时会忽略所有的块语句 它只是在一定程度上增加了程序的可读性 所以 在实际应用中 块语句很少被用到 5 1 6并行过程调用语句并行过程调用语句可以作为并行语句出现在结构体或块语句中 即在适用于并行语句结构的部分对过程进行调用 过程是子程序的一种类型 子程序的另一形式是函数 一般用来定义一个算法 它可以产生多个值或是不产生值 具体过程的相关知识请参见第7章 过程的调用既可以是并行的 也可以是顺序的 在结构体或是块语句中对过程的调用就是并行过程调用语句 在进程中对过程的调用就是顺序过程调用语句 过程的调用就是执行一个指定的过程 不管是哪种类型的过程调用 其调用的语句格式一般如下 过程名 形参名 实参表达式 形参名 实参表达式 形参名是待调用过程中已经声明的参数名 在调用过程时 形参名和连接符号 可以省略 类似于元件例化时端口映射语句PORTMAP的两种映射方式 名称映射和位置映射 例5 15中声明了一个过程halfadd 该过程用于实现半加器的功能 随后进行了两次调用 一次是并行过程调用 使用名称映射的方式 一次是在进程中的顺序调用 使用位置映射的方式 这两条过程调用语句是并行的 且完成的功能一致 例5 15 PROCEDUREhalfadd SIGNALa b INSTD LOGIC 声明一个名为halfadd的过程SIGNALsum OUTSTD LOGIC halfadd a a1 b b1 sum sum1 并行过程调用 PROCESS x1 x2 BEGINhalfadd x1 x2 s1 顺序过程调用ENDPROCESS 并行过程的调用可以获得被调用过程的多个复制电路 函数与过程类似 也可以实现并行调用和顺序调用 函数的调用将在第7章中讲述 5 1 7生成语句生成语句 GENERATE语句 与LOOP语句类似 可以实现某一段代码的重复多次执行 这意味着生成语句有一种复制作用 能够产生多个完全相同的元件 生成语句有FOR GENERATE和IF GENERATE两种使用形式 1 FOR GENERATE语句FOR GENERATE语句的格式如下 标号 FOR循环变量IN取值范围GENERATE并行语句ENDGENERATE 标号 需要注意的是 关键词前的标号是设计者自行定义的标识符 它是必需的 循环变量是自动由生成语句声明的 不需要事先声明 它仅是一个局部变量 根据取值范围自动递增或递减 取值范围必须是一个可计算的整数范围 它的语句格式有两种形式 分别是 1 表达式TO表达式 递增方式 2 表达式DOWNTO表达式 递减方式 FOR GENERATE语句中的并行语句可以是本节中讲述的任何并行语句 包括 进程语句 元件例化语句 并行信号赋值语句 块语句 并行过程调用语句 甚至是生成语句本身 如果FOR GENERATE语句中的并行语句是生成语句 这意味着生成语句允许存在嵌套结构 例5 16是一个利用FOR GENERATE语句实现两个4bit数组相与的简单示例 图5 13是Quartus 综合后的电路结构 可以看到生成了4个完全相同的与逻辑门电路 例5 16 图5 13例5 16电路结构 如果将例5 16稍作改动 如例5 17所示 增加了输入信号x作为循环变量取值范围的上限值 由于x的不确定性导致取值范围的不确定 使得编译综合时会出现图5 14所示错误 例5 17 例5 18也是一个错误的示例 综合时会认为输出信号z有多个驱动源 有多个赋值 正确的代码见例5 19 图5 14例5 17代码错误原因 例5 18 g1 FORiIN3DOWNTO0GENERATEz 1111 WHEN a i ANDb i 1 ELSE 0000 ENDGENERATE 例5 19 g2 FORiIN3DOWNTO0GENERATEz i 1 WHEN a i ANDb i 1 ELSE 0 ENDGENERATE 生成语句通常的作用是创建多个复制的元件 进程或块 例5 20利用FOR GENERATE语句实现了由D触发器构成的移位寄存器 在结构体gen shift中有两条并行的简单信号赋值语句 L17和L21 以及一条FOR GENERATE语句 L18 L20 FOR GENERATE语句能够产生4个完全一致的D触发器 图5 15是与例5 20相对应的电路结构原理图 例5 20 图5 154个D触发器构成的一个移位寄存器 例5 20使用一条FOR GENERATE语句就能够实现4条PORTMAP 语句的功能 使代码更加简练 而且可以通过改变循环变量i的取值范围描述任意长度的移位寄存器 2 IF GENERATE语句IF GENERATE语句的格式如下 标号 IF条件表达式GENERATE并行语句 ENDGENERATE 标号 IF GENERATE语句仅在条件表达式为真时才执行结构内部的并行语句 即条件表达式的结果是布尔型的 IF GENERATE语句与顺序语句IF不同的是 IF GENERATE语句中没有ELSE或ELSIF分支语句 从例5 20中可以看出 移位寄存器的输入端和输出端信号的连接无法用FOR GENERATE语句来实现 只能用两条并行信号赋值语句来完成 也就是说 FOR GENERATE语句只能处理规则的电路结构 对于串入 串出两个末端的不一样的电路结构无法实现 但是在实际中大多数情况电路的两端 输入和输出 总是具有不规则性 为了解决这种不规则电路的统一描述方法 可以采用IF GENERATE语句 例5 21使用FOR GENERATE和IF GENERATE语句的嵌套实现了一个任意长度的移位寄存器 例5 21 例5 21中 类属参量Length是移位寄存器的长度 由GENERIC语句声明 默认值是5 它同时也是信号z的数组长度 类属参量length也可以从外部传递取值 本例采用了FOR GENERATE语句和IF GENERATE语句嵌套的形式 二者可以相互嵌套 即也可以把FOR GENERATE语句嵌套在IF GENERATE语句中 本例在FOR GENERATE语句中 通过IF GENERATE语句判断循环变量i的取值 如果i 0 则是第一级的D触发器 如果i length 1 则是最后一级的D触发器 图5 16是综合后产生的RTL电路结构 与设计要求一致 图5 16例5 21实现的移位寄存器电路结构 5 2顺序语句顺序语句与并行语句共同构成了VHDL基本语句 顺序语句是VHDL在行为描述时普遍用到的语句 主要用在进程与子程序中 顺序语句是相对于并行语句而言的 它按照代码书写的顺序执行语句 仅指仿真执行 这一点与传统软件设计语言非常相似 但需要注意的是 顺序语句的本质仍然是实现硬件电路 而电路的本质是并行的 即电路中的所有元件都可以看做并行执行的单元 读者应从硬件电路的角度出发 理解顺序语句只是一种描述方式 顺序语句中几个常用的 重要的语句在语法意义上更贴近传统的程序设计语句 的语法 常用的顺序语句主要有 顺序赋值语句 IF语句 CASE语句 LOOP语句 EXIT语句 NEXT语句 WAIT语句和NULL语句等 数据对象 变量被限制用于顺序语句中 即它只能用在进程和子程序内部 作为局部变量 它与信号的用法相反 不能将数据带出进程或子程序 5 2 1顺序赋值语句前面的章节中已多次出现过赋值语句的使用示例 如 x aANDb y a 其中出现在并行语句结构部分的赋值语句属于并行赋值语句 如5 1 4节中介绍的并行信号赋值语句 而出现在进程和子程序内部的赋值语句可归为顺序赋值语句 由于在进程和子程序内部可以声明变量 因此顺序赋值语句包括信号赋值语句和变量赋值语句两类 即在顺序语句结构中允许对信号和变量两种数据对象进行赋值 反过来 由于变量不能把数据或信息带出声明它的进程和子程序 所以并行赋值语句只有并行信号赋值语句 即在并行语句结构部分只能对信号进行赋值 信号赋值和变量赋值的区别已在第4章中讲述 这里不再赘述 5 2 2IF语句IF语句是顺序语句中最重要与最常用的顺序语句 与传统程序设计中IF语句的语法含义一致 VHDL中的IF语句也是通过对判断表达式 或称条件 进行判断后有选择地执行相应分支的顺序语句 IF语句的形式一般有4种 单分支IF语句 双分支IF语句 多分支IF语句以及嵌套IF语句 其语句格式如下 IF条件THEN 单分支IF语句顺序语句 ENDIF IF条件THEN 双分支IF语句顺序语句 ELSE顺序语句ENDIF IF条件1THEN 多分支IF语句顺序语句 ELSIF条件2THEN顺序语句 ELSEIF条件3THEN顺序语句 ELSE顺序语句 ENDIF IF条件THEN 嵌套IF语句IF条件THEN ENDIF ENDIF 在前面的章节中已经多次使用过不同类型的IF语句 也对其基本用法有一定的介绍 下面对不同形式的IF语句进行总结和比较 1 单分支IF语句是一种不完整的条件语句 当判断表达式的值为真时 执行关键词THEN后的顺序语句 直到ENDIF结束 而当判断表达式的值为假时 跳过顺序语句不执行 直接结束IF语句 当条件为假时 不执行IF语句即保持原值不变 这意味着需要引入存储元件 因此 利用单分支IF语句能够构成时序逻辑电路 设计者在进行组合逻辑电路设计时需要特别注意 如果没有将电路中所有可能出现的判断条件考虑完全 就有可能被综合器综合出设计者不希望出现的组合与时序混合的电路 2 双分支IF语句是完整条件语句 当判断表达式的值为真时 执行关键词THEN后的顺序语句 而当判断表达式的值为假时 执行关键词ELSE后的顺序语句 这种结构的条件语句不会出现单分支IF语句不执行任何顺序语句的情况 所以不会产生存储元件 一般用于组合逻辑电路的设计 3 多分支IF语句通过关键词ELSIF设定多个判断条件 语句首先判断第一个条件 即关键词IF后的条件 如果满足则执行对应的顺序语句 如果不满足 则判断第二个条件 即第一个ELSIF后的条件 如果第二个条件满足 则执行与它对应的顺序语句 如果不满足 则继续判断第三个条件 以此类推 可以看出 多分支IF语句中任一分支对应的顺序语句的执行条件是以上各分支条件均不满足 而该分支条件满足 在所有的条件都不满足的情况下 如果语句中有ELSE分支 则执行该分支 如果没有 则不作任何操作 直接结束多分支IF语句 例5 4就是一个利用多分支IF语句实现带异步复位信号的D触发器的示例 4 嵌套IF语句与多分支IF语句一样能够产生比较丰富的条件描述 嵌套IF语句中任一分支顺序语句的执行 要求以上各分支的条件都满足 使用嵌套IF语句需要注意ENDIF的数量应与嵌入条件的数量一致 例5 5是一个利用嵌套IF语句实现同步复位的D触发器 例5 22是一个利用多分支IF语句和嵌套IF语句实现含有异步清零信号和同步使能信号的4位十进制加法计数器 清零信号clr与时钟信号clk无关 即只要清零信号clr取值为 1 不需要等待时钟信号clk上升沿的到来就能够启动进程 执行赋值语句 cqi 0 这种独立于时钟控制的清零信号被称为异步清零信号 计数使能信号en必须在时钟信号clk上升沿到来的前提下 取值为 1 才有效 才能够进行加法计数 这种依赖于时钟信号的使能信号被称为同步使能信号 图5 17是加法计数器时序仿真结果 可以看到 当clr取值为 1 时 计数结果q立即清零 当en取值为 1 时 还必须等待时钟信号clk上升沿的到来 计数结果q才能重新加1 总结来说 时序电路中总有一些必要的控制信号 如清零信号 使能信号 置数信号等 如果它们是独立的 不依赖于时钟信号的 就是异步信号 反之 则是同步信号 例5 22 图5 174位十进制加法计数器时序仿真结果 5 2 3CASE语句CASE语句也是顺序语句中最重要 最常用的语句之一 其功能对应于VHDL并行语句WITH SELECT WHEN 它的语句格式如下 CASE表达式ISWHEN选择值1 顺序语句1 WHEN选择值2 顺序语句2 WHENOTHERS 顺序语句n ENDCASE 执行CASE语句时 首先计算表达式的值 然后寻找与其相同的选择值 执行对应的顺序语句 如果表达式的值与选择值1相等 则执行顺序语句1 如果与选择值2相等 则执行顺序语句2 如果所有选择值与表达式的值均不相等 则执行WHENOTHERS分支下的顺序语句n 在使用CASE语句时需要特别注意以下几点 1 选择值的取值必须在表达式的取值范围内 且数据类型必须匹配 2 各个选择值不能有重复 只允许出现一次 3 如果选择值不能将表达式的所有取值列举完全 最后必须加上WHENOTHERS子句 代表以上所列所有选择值中未能列出的其他可能取值 4 WHENOTHERS子句只能出现一次 5 符号 不是操作符 它的含义相当于 THEN 或 于是 例5 23仍然以4选1多路选择器为例说明CASE语句的使用 L20中的关键词NULL表示不做任何操作 例5 23 CASE语句中每一个选择值对应的顺序语句允许有多条赋值语句 如例5 24 但WITH SELECT WHEN语句只允许有一条赋值语句 例5 24 CASEctlISWHEN 00 xxx 0000 y 0000 ENDCASE 选择值的表示方式除了将每个值一一列举以外 也可以指定一个选择范围 如用关键词 TO 和 DOWNTO 表示 例5 25显示了几种选择值的表示方式 例5 25 需要注意的是 如果例5 25中信号a的数据类型是BIT VECTOR或者STD LOGIC VECTOR类型 则不允许用指定范围的形式来确认选择值 如例5 26是一个错误的示例 如果需要对矢量指定取值范围 则必须先把BIT VECTOR和STD LOGIC VECTOR数据类型转换为整数类型 例5 26 CASEaISWHEN 0000 bbbb 3 正确 其他剩余可能取值ENDCASE 例5 27是利用CASE语句实现带有异步复位信号的D触发器的示例 显示了CASE语句的分支中可以嵌套IF语句 例5 27 5 2 4LOOP语句LOOP语句的功能是循环执行一条或多条语句 在第3章中例3 16已经简单介绍过FOR LOOP语句 它是LOOP语句中的一类 LOOP语句主要有三种基本形式 FOR LOOP WHILE LOOP以及条件跳出形式 1 FOR LOOP语句FOR LOOP语句的格式如下 标号 FOR循环变量IN循环次数范围LOOP顺序语句 ENDLOOP 标号 关键词FOR后的循环变量是一个临时变量 属于FOR LOOP语句的局部变量 由语句自动定义 不必事先声明 这个变量只能作为赋值源 不能被赋值 使用时应当注意 在FOR LOOP语句范围内不能再使用其他与此循环变量同名的标识符 循环次数范围用来规定FOR LOOP语句中的顺序语句被执行的次数 循环变量从循环次数范围的初值开始 每执行完一次顺序语句后递增1 直至达到循环次数范围指定的最大值 FOR LOOP语句循环的范围应以常量表示 是一个确定的值 综合器不支持没有约束条件的循环 这是因为VHDL的循环语句与C等程序设计语言不同 在VHDL中的每一次循环都将产生一个硬件模块 随着循环次数的增加 硬件资源将大量消耗 所以在VHDL设计中要谨慎使用循环语句 例5 28显示了通过4次循环产生了4个相同的逻辑与电路 例5 28综合后的电路结构如图5 18所示 例5 28 图5 18例5 28综合后电路结构 例5 29利用FOR LOOP语句实现一个带异步清零信号的串入并出的8位移位寄存器 请读者注意变量与移位方向的关系 仿真结果如图5 19所示 例5 29 图5 19移位寄存器时序仿真结果 2 WHILE LOOP语句与高级程序设计语言中的WHILE循环结构一样 VHDL中的条件循环是通过WHILE LOOP语句实现的 它的一般格式如下 标号 WHILE循环条件LOOP顺序语句 ENDLOOP 标号 当循环条件不满足 即循环条件表达式取值为FALSE 时 跳出WHILE LOOP语句循环 例5 30中 当i 10时 一直重复执行LOOP内的顺序语句 例5 30 WHILE i 10 LOOPIFclk EVENTANDclk 1 THENq q 1 ENDIF ENDLOOP 例5 31利用WHILE LOOP语句实现了一个8位奇偶校验电路 当元素 1 的个数为偶数时 输出信号q取值为 1 反之 q为 0 需要注意的是 WHILE LOOP语句循环条件中的变量需要事先进行显式的声明 如例5 31中的变量i 仿真结果见图5 20 例5 31 图5 20奇偶校验电路时序仿真结果 3 条件跳出语句前面讲述的FOR LOOP和WHILE LOOP循环语句是通过循环次数或循环条件来限定执行循环次数的 当需要人为地跳出本次或整个循环语句 转去执行下一次循环或循环语句之外的其他操作语句时 可以采用NEXT语句 跳出本次循环 和EXIT语句 跳出整个循环 1 NEXT语句 NEXT语句在LOOP语句执行中进行无条件的或有条件的转向控制 其格式如下 NEXT标号 NEXT LOOP标号 WHEN条件表达式 可以看到 NEXT标号 LOOP标号以及WHEN子句都是可选项 因此 可以将NEXT语句具体分为4种形式 NEXT NEXTLOOP标号 NEXTWHEN条件表达式 NEXTLOOP标号WHEN条件表达式 第一种语句格式是无条件跳出循环 即当LOOP内的顺序语句执行到NEXT语句时就无条件终止本次循环 跳回到LOOP语句处 重新开始下一次循环 第二种语句格式的作用与第一种类似 只是当有多重LOOP语句嵌套时 可以跳到指定标号的LOOP语句处 重新开始执行循环操作 第三种语句格式带有条件表达式 即如果条件表达式的取值为TRUE 则执行NEXT语句跳出本次循环 进入下一次循环 否则不执行NEXT语句 第四种语句格式既带有条件表达式 又带有LOOP标号 如果条件表达式取值为TRUE 则执行NEXT语句 跳转到LOOP标号处 否则 不执行NEXT语句 例5 32中使用了带有条件表达式的NEXT语句 当条件表达式为真 即ctl i 0 时 跳出本次循环 循环变量i加1 进行下一次循环 如果ctl 11111111 则每次循环都不会被强行跳出 最后的结果是y x 如果ctl 00000000 则每次循环都会跳出 不能执行y i x i 的赋值语句 最后的结果是y仍然等于初值 00000000 例5 32的仿真结果如图5 21所示 例5 32 图5 21例5 32仿真结果 例5 33是LOOP语句的嵌套 用LOOP标号进行区别 L1和L2 当i j时 满足条件表达式 NEXT语句被执行 跳出内循环L2 从外循环L1重新开始执行下一次循环 例5 33 L1 WHILEi 10LOOPL2 WHILEj 10LOOPNEXTL1WHENi j 当i j时 跳转到标号L1处ENDLOOPL2 ENDLOOPL1 2 EXIT语句 在LOOP语句中 使用EXIT语句可跳出并结束整个循环 注意 不是当次循环 继续执行LOOP语句后的其他顺序语句 EXIT语句的语法格式如下 EXIT标号 EXIT LOOP标号 WHEN条件表达式 可以看到 EXIT语句的格式与NEXT语句的格式一致 通过是否选用可选项 如 LOOP标号 WHEN条件表达式 等也可将其分为4种形式 这里不再赘述 读者可自行归纳总结 例5 34是一个使用EXIT语句的示例 用于比较两个矢量是否相等 当二者相等时 输出信号result取值为 1 反之 为 0 仿真结果见图5 22 例5 34 图5 22例5 34仿真结果 5 2 5WAIT语句在进程 或过程 中 WAIT语句具有和敏感信号参数一致的作用 可以用来触发进程 或过程 需要注意的是 如果一个进程中包含了WAIT语句 就不能再使用敏感信号了 否则综合时会出现图5 23所示错误 图5 23进程中同时包含敏感信号和WAIT语句的错误提示 WAIT语句有4种不同的形式 分别是 WAIT WAITON信号1 信号2 WAITUNTIL条件表达式 WAITFOR时间 第一种形式仅有关键词WAIT 表示当代码执行到此处时 将一直处于等待状态 因为它没有启动进程的条件 第二种形式称为敏感信号等待语句 可以有一个或多个敏感信号 当进程处于等待状态时 任何敏感信号的变化都能触发进程的启动 第三种形式称为条件等待语句 只有当条件表达式的取值为TRUE时 才能启动进程的执行 WAITUNTIL语句必须是进程中的第一条语句 第四种形式称为时间等待语句 当代码执行到WAIT语句时 必须要等待指定的时间后才能自动地恢复代码的执行 例5 35中 两段代码是完全等价的 敏感信号x和y中的任一个发生变化就会触发进程的执行 例5 35 PROCESS x y ISPROCESSBEGINBEGINz xANDy z xANDyENDPROCESS WAITONx y ENDPROCESS 例5 36是利用WAITUNTIL语句实现的带有同步复位信号的D触发器 WAITUNTIL语句需要满足两个条件 进程才能被启动 一是条件表达式中的信号发生了改变 二是信号改变后条件表达式取值为真 所以 例5 36进程的启动条件是时钟信号clk上升沿的到来 仿真结果见图5 24 例5 36 图5 24例5 36的D触发器仿真波形 例5 37使用了两条WAITFOR语句 其时间都是一个常数 分别是10ns和5ns 也就是说 当进程执行到第一条WAIT语句时将等待10ns 一旦时间到 就继续执行其后的赋值语句 clk 0 这意味着 clk为高电平的时间将持续10ns 紧接着再次执行第二条WAIT语句等待5ns 即clk为低电平的时间将持续5ns WAITFOR语句经常用于仿真时产生输入激励信号 具体可参见第8章 例5 37 PROCESSBEGINclk 1 WAITFOR10ns clk 0 WAITFOR5ns ENDPROCESS 实际上 上述4种形式的WAIT语句 一般只有WAITUNTIL语句能够被综合器所接受 也就是说其余的形式只能用在VHDL仿真器中 5 2 6NULL语句在VHDL语法中 NULL语句用来表示一种只占位置的空操作 即它不执行任何操作 唯一的功能是使逻辑运行流程跨入下一步语句的执行 NULL语句经常用在CASE语句中 表示除了列出的选择值所对应的操作行为外 其他未列出的选择值所对应的空操作行为 从而能够满足CASE语句对表达式所有可能取值全部列举的要求 如例5 38所示 当ctl取值为 100 101 110 111 这4种情况时 不作任何操作 例5 38 CASEctlISWHEN 000 yyyyNULL ENDCASE 需要指出的是 很多情况下在CASE语句中使用NULL语句并不是最佳的选择 有时反而会引入不必要的锁存器模块 需要设计者仔细思考 5 3常用语句的比较如前所述 VHDL中的语句可分为并行语句和顺序语句两大类 不管是哪一种类型的语句 不管是采用行为描述还是结构描述 其实质都是进行电路的描述 最后的结果都是生成硬件电路 不同的语句有一定相关性 下面就几个常用语句进行比较 帮助读者进一步掌握语句的特点和使用 例5 39 例5 40 例5 39中使用的IF语句的每个分支之间具有优先级 即条件的判定是按照书写的顺序执行的 这点与WHEN ELSE语句相似 采用IF语句描述的例5 39综合后得到的RTL电路如图5 25所示 类似于级联的结构 而CASE语句的每个分支是平等的 即每个选择值同时被测试比较 这也是为什么CASE语句的选择值不允许有相同的值出现的原因 所以采用CASE语句描述的例5 40综合后得到的是一个多路选择器 如图5 26所示 图5 25例5 39综合后电路结构 图5 26例5 40综合后电路结构 5 3 2IF语句与WHEN ELSE语句的比较IF语句与WHEN ELSE语句有相同的功能 在执行时 条件是按照书写的先后顺序逐条判断的 一旦发现条件为真 即刻执行相应的顺序语句或表达式 可以称WHEN ELSE语句是顺序语句IF的并行版本 二者的区别如下 1 IF语句属于顺序语句 只能用于进程 过程和函数中 WHEN ELSE语句属于并行语句 不能用在进程 过程和函数中 2 相对于IF语句而言 WHEN ELSE语句中的关键词ELSE是不可缺少的 且WHEN ELSE语句不能嵌套 3 IF语句既可以描述组合逻辑电路也可以描述时序逻辑电路 不完整的IF语句是引入存储元件的关键 WHEN ELSE语句多用于组合逻辑电路描述 更贴近逻辑电路的实际工作情况 5 3 3CASE语句与WITH SELECT WHEN语句的比较顺序语句CASE与并行语句WITH SELECT WHEN具有相似的功能 对选择值的测试具有同时性 这意味着选择值的取值不能重复 如果选择值不能覆盖所有可能的取值 则最后必须要加上 WHENOTHERS 子句 可以称WITH SELECT WHEN语句是顺序语句CASE的并行版本 二者的区别如下 1 CASE语句中每一分支所对应的顺序语句允许有多条赋值语句 但WITH SELECT WHEN语句只允许有一条赋值语句 2 相对于CASE语句可以使用NULL语句来表示空操作 WITH SELECT WHEN语句也可以使用UNAFFECTED来表示空操作 如例5 41所示 与NULL语句相同 UNAFFECTED语句也有可能产生不必要的锁存模块 需要慎重使用 例5 41 WITHctlSELECTy 000 WHENctl 000 111 WHENctl 111 dWHENctl 001 UNAFFECTEDWHENOTHERS 5 4组合逻辑电路的设计组合逻辑电路是一种不含存储元件的电路 其输出完全由输入决定 常见的组合逻辑电路包括三态门电路 编码器 译码器 多路选择器 全加器等 本节通过几个组合逻辑电路设计的实例让读者进一步理解VHDL语句 5 4 1三态门电路和双向端口的设计三态门是驱动电路常用的器件 其输出除了高 低电平两种状态外 还有第三种状态 高阻态 处于高阻态时 其输出相当于断开状态 没有任何逻辑控制功能 三态门的输出逻辑状态的控制是通过一个输入控制端en来实现的 当en为高电平时 三态门呈现正常的逻辑 0 和逻辑 1 的输出 当en为低电平时 三态门输出呈现高阻状态 即断开状态 相当于该逻辑门与它相连接的电路处于断开的状态 三态门的逻辑符号如图5 27所示 三态门主要用于总线的连接 通常在总线上接有多个器件 每个器件通过控制端进行选通 当器件没有被选中时 它就处于高阻状态 相当于没有接在总线上 不影响其他器件的工作 图5 28是利用三态门实现总线传输的示例 在任何时刻只有一个三态门的控制端取值为 1 则通过使n个三态门控制端依次为 1 就可以实现依次传输 而不是线与 图5 27三态门逻辑符号 图5 28三态门实现总线传输 例5 42是一个三态门电路的描述示例 在VHDL中用大写字母 Z 表示高阻态 一个 Z 代表一个逻辑位 虽然对于关键词 VHDL语法并不区分大小写 但当把 Z 作为一个高阻态赋值给一个数据类型为STD LOGIC的数据对象时 必须是大写 这是因为在IEEE库中对STD LOGIC数据类型的预定义中已经将高阻态明确确定为大写字母 Z 图5 29是经过综合后的RTL电路结构 图5 30是三态门的仿真波形 当控制端en为低电平时 输出为高阻态 例5 42 图5 29三态门电路结构 图5 30三态门仿真结果 双向端口是通过控制三态门来实现的 如图5 31所示 当控制端en取值为 1 时 三态门导通 数据可以从上面的OUTPUT端口输出 当控制端取值为 0 时 三态门断开 即上面的OUTPUT端口被断开 数据只能够从下面的INPUT端口输入 例5 43是一个双向端口的设计示例 其中定义了双向端口q和三态输出端口x 需要注意的是 当控制端en取值为 0 时 双向端口q作为输入口使用 其输出必须设置为高阻态 否则待输入的外部数据会和端口处原有输出数据发生 线与 导致数据无法正确读入 图5 32是综合后的电路结构 图5 33是仿真结果 使用Quartus 进行仿真时 当双向端口处于输出状态时 在端口上会表现为高阻态 具体的输出数据需要通过q 0 q 7 来观察 图5 31三态门控制双向端口示意图 例5 43 图5 32例5 43综合后的RTL电路结构 图5 33例5 43仿真结果 5 4 2编码器和译码器的设计在数字电路中 需要建立特定的信息与二进制码间的联系 如果用若干位二进制码代表特定意义的信息 就称为编码 即输入为特定信息 输出为相应的二进制码 常见的编码形式有 8421BCD编码 8线 3线编码 8线 3线优先编码 10线 4线优先编码等 如果需要编码的信息量是N 则需要m位二进制码 满足N 2m 编码的逆过程就是译码 即将输入的二进制码还原成事先规定的 具有特殊意义的输出信号 例5 44是一个8线 3线

温馨提示

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

评论

0/150

提交评论