《逻辑与计算机设计基础(原书第5版)》——2.9 硬件描述语言—VHDL

2.9 硬件描述语言—VHDL

由于硬件描述语言用来描述和设计硬件,故在使用该语言编程时,应牢记底层的硬件实现,特别是当你的设计将用来综合时。例如,如果忽略将要生成的硬件,那么你可能会用低效的硬件描述语言设计出一个大且复杂的门级结构,而实际上只需少量门的简单结构即可实现。出于这种原因,我们开始重点讲述用VHDL语言详细地描述硬件,然后再进行更抽象的高层次的描述。
本章所选的实例用于说明VHDL是一个很好地描述数字电路的可选方法。首先,我们采用结构化的描述方法,用VHDL而不是原理图对图2-27中的二位大于比较器电路进行描述。这个例子介绍了VHDL的许多基本概念。
然后,我们采用高层次的行为描述方式设计这个电路,以进一步介绍VHDL的基本概念。
例2-16 二位大于比较器电路的VHDL结构描述
图2-28给出了图2-27中二位大于比较器电路的VHDL描述。这个实例可以用来说明VHDL的许多常见特性和电路的结构描述。

两条短线“--”和行末之间的语句称为注释(comment),图2-28中的描述一开始是两行注释,用以说明该程序的功能以及与图2-27的关系。为了便于说明该描述,在每行的右边采用注释标注了行号。作为一种语言,VHDL有其语法规则,它准确地描述了可以使用的合法结构。这个实例将介绍VHDL语法的一些内容,特别要注意描述中分号、逗号与冒号的用法。
首先,我们跳过第3、4行,将注意力集中到整个结构上。第6行声明了一个实体(entity),这是VHDL设计中的一个基本单元。像对原理图中的一个逻辑符号一样,在VHDL中我们需要对设计命名,定义其输入/输出端口,这些是实体声明(entity declar-ation)的职能。entity和is是VHDL中的关键词。用粗体标示的关键词有特殊的含义,不能用来命名实体、输入/输出端口或者信号。语句entity comparator_greater_than_structural is声明了一个名为comparator_greater_than_structural的设计。VHDL大小写不敏感(例如,用相同字母的大写或小写命名的名字和关键词不能区分)。COMPARATOR_greater_than_Structural和comparator_Greater_than_structural以及comparator_greater_than_Structural是相同的。
接下来,从第7~9行的端口声明(port declaration)用来定义输入和输出端口,就像在原理图中对逻辑符号所做的那样。对于这个设计实例,它有二个输入信号:A和B。这些信号通过模式in指定为输入端口。同样,A_greater_than_B通过模式out指定为输出端口。VHDL是一种强类型语言,所以输入和输出信号的数据类型必须事先声明。在此例中,输出信号的类型为std_logic(标准逻辑类型(standard logic))。类型声明指定了输入输出信号的值以及对这些信号可能执行的操作。标准逻辑类型有9个值,其中包括常用的二进制值0和1以及两个附加值X和U。X表示未知值,U表示未初始化。我们选择使用标准逻辑,因为一般的仿真工具都用到这些值。
输入A和B说明了VHDL的另一个概念,即std_logic_vector(标准逻辑向量)。两个输入中的每一个都是二位宽,因此把它们定义为std_logic_vector,而不是独立的std_logic信号。我们使用下标来对向量寻址。由于A包含两个编号为0和1的输入信号,1是最高有效位(最左边),故A的下标是由1降至0。这个向量的成员是A(1)和A(0)。同样,B包含两个编号为1和0的输入信号,故它的下标也是由1降至0。从第32行开始,注意std_logic_vector类型的信号是如何通过指定信号名与用括号括起的下标来引用的。如果希望向量的下标由小到大显示,那么在VHDL中可采用另一种不同的标记方法。例如,signal N:std_logic_vector(0 to 3)定义了信号N的第一位(最左边)为N(0),最后一位(最右边)为N(3)。也可以引用子向量(例如,N(1 to 2),表示引用N的中间两个信号N(1)和N(2))。
为了使用std_logic和std_logic_vector类型,有必要对该类型的值和操作进行定义。为方便起见,我们可以采用一个由预编译的VHDL代码组成的程序包(package)来完成预定义。包一般存放在称为库(library)的目录中,而库可被一些或所有用户共享。对于std_logic,基本包是ieee.std_logic_1164,这个包定义了std_logic与std_ulogic类型的值和基本的逻辑操作。为了使用std_logic,我们在第3行调用了包含包的ieee库,在第4行调用了ieee.std_logic_1164.all包,表示我们会用到ieee库中ieee.std_logic_1164包内的所有定义。另外,lcdf_vhdl库包含了func_prims包,该包用VHDL语言描述了基本的逻辑门、锁存器和触发器,我们通过all调用该包中的所有内容。lcdf_vhdl库的ASCII码格式可从本书的配套网站上下载。注意,第3、4行语句后紧跟着实体部分。如果另一个实体也将用到std_logic类型和fun_prims中的元件,那么库和使用语句必须重复放在实体声明之前。
实体声明以关键词end结束,其后紧跟实体名。到目前为止,对于这个电路我们已经讨论了与原理图中逻辑符号等效的VHDL描述
结构化描述 接下来,我们要描述电路的功能。实体功能的描述称作实体的结构体(architecture),因此第12行声明了实体comparator_greater_than_structural的结构体structural。以下将介绍结构体的详细语法。在此实例中,根据图2-27的电路图,我们采用与原理图等价的结构化描述(structural description)方式来设计电路。
首先,在第15~29行声明了我们将在描述中要用到的门类型。由于我们采用门来实现电路,所以声明了一个反相器NOT1,一个二输入与门AND2,一个三输入与门AND3和一个三输入或门OR3作为组件(component)。这些门的VHDL描述包含在包func_prims中,包func_prims包含了这些门的实体与结构体。组件声明中的名字与端口声明必须与其对应的实体完全一致。对于NOT1,端口指定的输入名为in1和输出名为out1。对于AND2,其组件声明部分中输入名为in1和in2,输出名为out1。类似地,对于AND3和OR3,其组件声明部分中输入名为in1、in2和in3,输出名为out1。
接下来,在根据电路图确定这些门的相互连接之前,我们需要对电路中的所有节点进行命名。输入和输出已经命名了。图2-27中的内部节点是两个反相器的输出以及三个与门的输出,这些输出节点声明为std_logic类型的信号。not_B1和not_B0是两个反相器的输出信号,and0_out、and1_out和and2_out是三个与门的输出信号。同样,端口中声明的所有输入和输出都是信号。在VHDL中有信号和变量。变量的赋值是立即有效的。相反,信号的赋值不即刻有效,它在未来的某个时间被赋值。这个时间可以是物理时间,例如当前时间之后的2 ns,也可以是增量时间(delta time),如一个信号在当前时间上加上一个增量时间后被赋值。增量时间可以看作一个无穷小的时间量。信号赋值的时间延迟对典型的数字模拟器的内部操作来说是必不可少的,当然,基于门延时可使电路仿真结果更接近实际。但为简单起见,我们通常是验证电路功能的正确性,而不是其性能或者延时问题。对于这样的功能仿真,将时延默认为增量时间是最容易的。因此,在电路的VHDL描述中不涉及时延,但在测试程序中可能出现。
在内部信号的声明之后,以关键词begin开始结构体的主体部分。这个电路的描述由两个反相器、一个二输入与门、两个三输入与门和一个三输入或门组成。第32行给出了第一个反相器的标号为inv_0,指示了这个反相器是NOT1组件。接着是端口映射(port map),将反相器的输入与输出端口映射到相连接的信号上。信号间的映射通过符号=>关联,符号左边是门的端口,右边是所连接的信号。例如,反相器inv_0的输入是B(0),输出是not_B0。
从第33~37行给出了剩下的5个门以及与它们的输入输出端口相连的信号。这5个门使用了另外一种方法来映射逻辑门的端口。这种方法没有显式地给出元件的输入输出名称,而是假定在端口映射中连接的信号顺序与引用的元件的端口顺序一致。这样我们可以按元件端口的顺序列举信号,从而隐式地指定信号之间的连接。例如在33行,B(1)连接到输入,not_B1连接到输出。结构体以关键词end加其结构名structural结束。 ■
数据流描述法 数据流描述法是根据功能而不是结构来描述电路的,它由并发赋值语句或与之等价的语句组成。只要语句右边的一个值改变,并发赋值语句就并发(也就是并行)执行。例如,任何时候一个布尔表达式右边的某个值发生变化时,其左边的信号就会被赋值。例2-17举例说明由布尔表达式组成的数据流描述的使用方法。
例2-17 二位大于比较器电路的VHDL数据流描述
图2-29给出了图2-27中二位大于比较器电路的VHDL数据流描述。这个例子用来说明由布尔表达式组成的数据流描述方法。该程序中的库、包的使用及实体声明部分与图2-28中的相同,故在此不再重复。数据流描述从第15行开始,信号B0_n与B1_n分别通过对输入信号B(0)和B(1)进行not操作实现赋值。在第17行,B1_n和A(1)组合通过and运算得到and0_out。信号and1_out、and2_out和A_greater_than_B在第18~20行中,采用类似方法得到,A_greater_than_B使用了or运算。大家可以看到,数据流描述比图2-28中的结构描述要简单得多。

赋值语句执行的顺序与这些语句在模型描述中出现的顺序无关,但与赋值语句右边信号变化的顺序有关。因此,如果将图2-29中的赋值语句按其他顺序重写,例如把第15行与第20行调换,程序的行为是完全一样的。 ■
行为描述 使用并发赋值语句的数据流模型可以认为是行为描述,因为它们描述了电路的功能而不是它的结构。正如我们将在第4章介绍的那样,VHDL还提供使用在过程中按顺序执行的赋值语句来描述行为的方法,这种方法被称为算法模型化。但即使是使用并发赋值语句的数据流模型,VHDL也能够提供比逻辑级更为抽象的电路描述。
例2-18 使用when-else的二位大于比较器的VHDL描述
在图2-30中,我们使用when-else语句而不是根据电路结构得到的类似布尔方程的语句来描述多路复用器。这种电路模型使用电路所期望的数学运算而不是布尔逻辑,来描述电路的行为(例如,当A大于B时输出为1,否则为0)。只要A或者B发生变化,when后的条件将重新计算并进行相应的赋值。 ■
例2-19 使用with-select的二位大于比较器的VHDL描述
with-select是when-else的一个变种,用该语句描述的模型见图2-31。在表达式中,决策变量位于with与select之间。由表达式的值来选择赋值,表达式的值位于when的后面,每一对表达式值和赋值用逗号分开。在这个例子中,A是一个信号,它的取值决定了分配给A_greater_than_B的值。对于这个例子,A用于选择B的一个函数当作合适的输出。当A=“00”时,0赋给输出,因为对于B的所有组合函数为0。当A=“01”,输出只在B=“00”时为1,这是两位B的或非函数。当A=“10”,输出在B(1)为0时等于1,在B(1)为1时等于0,因此赋值函数是B(1)的非。当A=“11”时,输出除B=“11”时均等于1,它是两位B的与非函数。最后,当A是其他值时(when others),输出赋值为‘X’。这里的others代表没有指定的标准逻辑组合,如A的一位既不是0也不是1,比如是U。

这个例子对于这个特定的电路来说显得有点不自然,结果是没有像以前的方法那样直观。但是,这个例子介绍了一种非常有用的,用一组条件选择多个函数的方法。我们将在后面的章节中看到使用这类方法的电路的例子,特别是在有关多路复用器的第3章和有关寄存器传输的第6章。

注意when-else允许用多个不同的信号来进行决策。例如,一个模型中可以用第一个when将一个信号作为条件,在else部分用另外一个when将另一个不同的信号作为条件,等等。相反,with-select仅允许一个单一的布尔条件(如:要么是第一个信号,要么是第二个信号,但不能是两个信号)。另外,对于典型的综合工具,when-else语句会比with-select语句综合出一个更复杂的逻辑结构,因为when-else依赖于多个条件。 ■
测试程序(测试平台,测试床) 我们在第2.8节已经简要介绍过测试程序是硬件描述语言的一种模型,它的目的是用来测试另外的模型,通常称之为被测设备(DUT),测试时给输入提供激励。更复杂的测试程序还要分析被测设备的输出以保证正确性。图2-32对二位大于比较器电路给出了一个简单的VHDL测试程序。这个测试程序有几个方面与所有测试程序是一样的。第一,实体声明部分没有任何输入或输出端口(第5~6行)。第二,测试程序的结构体为DUT声明了元件(第11~15行),然后对DUT进行实例化(第17行)。结构体还声明了将要连接到DUT的输入与输出信号(第9~10行)。最后,结构体向DUT加载各种输入组合以对其在不同条件下进行测试(第18~29行)。输入值用一个称为tb的进程进行加载,进程是一个按顺序执行的语句块。这个测试程序中的tb进程在模拟开始时启动,给DUT的输入赋值,在两次赋值之间等待10 ns模拟时间,然后以永久等待实现停机。为了简单明了起见,这个例子中的进程仅使用了少量的输入组合,但它确实测试了A与B之间关系的所有三种情况(A<B,A=B和A>B)。在第4章将更详细的介绍进程,那时会讲解大量的可用于进程的顺序语句。
至此,我们完成了组合电路的VHDL介绍。在第3章和第4章我们将用语言的另外一些特点来描述更复杂的电路,从而继续加深对VHDL的了解。

时间: 2024-10-31 13:28:10

《逻辑与计算机设计基础(原书第5版)》——2.9 硬件描述语言—VHDL的相关文章

《逻辑与计算机设计基础(原书第5版)》——导读

前言 本书的目的是为广大读者提供学习逻辑设计.数字系统设计和计算机设计的基础知识.本书第5版突出了课程内容方面的最新发展.从1997年的第1版开始,作者就不断对其进行修改,提供一种独一无二的将逻辑设计与计算机设计原理结合在一起的方法,并特别强调硬件.过去几年,教材一直紧跟行业的发展趋势,新增加了一些内容(如硬件描述语言),删除或者弱化了某些不太重要的内容,修改了某些内容以反映计算机技术和计算机辅助设计所发生的变化. 新版的变化 第5版反映了相关技术与设计实践方面的一些变化,与过去相比,要求计算机

Java核心技术 卷Ⅰ 基础知识(原书第10版)

Java核心技术系列 Java核心技术 卷Ⅰ 基础知识 (原书第10版) Core Java Volume I-Fundamentals (10th Edition) [美] 凯S.霍斯特曼(Cay S. Horstmann) 著 周立新 陈 波 叶乃文 邝劲筠 杜永萍 译 图书在版编目(CIP)数据 Java核心技术 卷Ⅰ 基础知识(原书第10版) / (美)凯S. 霍斯特曼(Cay S. Horstmann)著:周立新等译. -北京:机械工业出版社,2016.8 (Java核心技术系列) 书

《机器学习与R语言(原书第2版)》一 第2章 数据的管理和理解

本节书摘来自华章出版社<机器学习与R语言(原书第2版)>一书中的第2章,第2.1节,美] 布雷特·兰茨(Brett Lantz) 著,李洪成 许金炜 李舰 译更多章节内容可以访问"华章计算机"公众号查看. 第2章 数据的管理和理解 任何机器学习项目初期的核心部分都是与管理和理解所收集的数据有关的.尽管你可能发现这些工作不像建立和部署模型那样令人有成就感(建立和部署模型阶段就开始看到了劳动的成果),但是忽视这些重要的准备工作是不明智的.任何学习算法的好坏取决于输入数据的好坏.

《机器学习与R语言(原书第2版)》一1.3 机器如何学习

本节书摘来自华章出版社<机器学习与R语言(原书第2版)>一书中的第1章,第1.3节,美] 布雷特·兰茨(Brett Lantz) 著,李洪成 许金炜 李舰 译更多章节内容可以访问"华章计算机"公众号查看. 1.3 机器如何学习 机器学习的一个正式定义是由计算机科学家Tom M. Mitchell提出的:如果机器能够获取经验并且能利用它们,在以后的类似经验中能够提高它的表现,这就称为机器学习.尽管这个定义是直观的,但是它完全忽略了经验如何转换成未来行动的过程,当然学习总是说起

《面向对象的思考过程(原书第4版)》一2.3 尽可能提供最小化的用户接口

本节书摘来自华章出版社<面向对象的思考过程(原书第4版)>一书中的第2章,第2.3节,[美] 马特·魏斯费尔德(Matt Weisfeld) 著黄博文 译更多章节内容可以访问"华章计算机"公众号查看. 2.3 尽可能提供最小化的用户接口 当设计类时,通用规则是尽量不要让用户知道类内部的工作原理.为了达到这点,请遵守以下简单的规则:只提供给用户绝对需要的东西.实际上,这意味着类的接口要尽可能少.当你开始设计一个类时,先从最小化的接口开始.类的设计是迭代式的,所以随后即使你发现

ROS机器人程序设计(原书第2版).

机器人设计与制作系列 ROS机器人程序设计 (原书第2版) Learning ROS for Robotics Programming,Second Edition 恩里克·费尔南德斯(Enrique Fernández) 路易斯·桑切斯·克雷斯波(Luis Sánchez Crespo) 阿尼尔·马哈塔尼(Anil Mahtani) 亚伦·马丁内斯(Aaron Martinez) 著 刘锦涛 张瑞雷 等译 图书在版编目(CIP)数据 ROS机器人程序设计(原书第2版) / (西)恩里克·费尔南

《JavaScript和jQuery实战手册(原书第3版)》---第1章 编写第一个JavaScript程序 1.1 编程简介

本节书摘来自华章出版社<JavaScript和jQuery实战手册(原书第3版)>一书中的第1章,第1.1节,作者David Sawyer McFarland,姚待艳 李占宣 译,更多章节内容可以访问"华章计算机"公众号查看. 第1章 编写第一个JavaScript程序 HTML自身并没有太多智能:它不能做数学运算,不能判断某人是否正确填写了一个表单,而且不能根据Web访问者的交互来做出判断.基本上,HTML让人们阅读文本.观看图片或视频,并且单击链接转向拥有更多文本.图片

《机器学习与R语言(原书第2版)》一2.3 探索和理解数据

本节书摘来自华章出版社<机器学习与R语言(原书第2版)>一书中的第2章,第2.3节,美] 布雷特·兰茨(Brett Lantz) 著,李洪成 许金炜 李舰 译更多章节内容可以访问"华章计算机"公众号查看. 2.3 探索和理解数据 在收集数据并把它们载入R数据结构以后,机器学习的下一个步骤是仔细检查数据.在这个步骤中,你将开始探索数据的特征和案例,并且找到数据的独特之处.你对数据的理解越深刻,你将会更好地让机器学习模型匹配你的学习问题. 理解数据探索的最好方法就是通过例子.在

《Unity着色器和屏幕特效开发秘笈(原书第2版)》一2.7 创建透明材质

本节书摘来自华章出版社<Unity着色器和屏幕特效开发秘笈(原书第2版)>一书中的第2章,第2.7节,作者 [英]艾伦朱科尼(Alan Zucconi) [美]肯尼斯拉默斯(Kenneth Lammers),更多章节内容可以访问"华章计算机"公众号查看 2.7 创建透明材质 到现在为止,我们见到的着色器都有一个共同点-都用在实心材质上.如果你想提升游戏视觉效果,某些时候透明材质是个不错的选择,比如火焰效果或者窗户玻璃等.透明材质的制作相对复杂一点.在渲染实心物体之前,Uni