![人工智能硬件电路设计基础及应用](https://wfqqreader-1252317822.image.myqcloud.com/cover/533/43738533/b_43738533.jpg)
2.1 常量、信号和变量
在VHDL程序中,所有的数据信息都需要存储在一个数据容器中,动态数据用信号(signal)和变量(variable)存储,静态数据用常量(constant)存储。本节将介绍常量、信号和变量,并比较信号与变量的异同。
2.1.1 常量
在VHDL语言中,使用constant标识符定义用来存储静态数据的数据容器被称为常量。
常量的值在定义后就不可改变,不可以对常量进行赋值。定义常量的语法规范如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_29_1.jpg?sign=1738921284-ASMH71VIAI5vsP7tG9Q4MQWyAshhzCuA-0-1c435725785d7ebe5717da839c4656ca)
其中,identifier_list为常量名,subtype_indication为常量的类型,conditional_expression为常量的初始值。
常量定义示例如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_29_2.jpg?sign=1738921284-OU0ChxFxd871crWtV7XGsIGaN20xMqB3-0-ccc294529e63b91bf128f57235543641)
常量可以在包集、实体和结构体中声明。声明了包含常量声明的包集后,VHDL程序内就可以直接调用常量进行赋值、运算等操作。同样,实体的所有结构体都可以调用实体内声明的常量;结构体中声明的常量仅可在结构体内部调用。
2.1.2 信号
在VHDL语言中,信号可以看作逻辑电路中的连线。电路的输入输出端口、电路内部各个单元的连接都需要用到信号。与常量不同,信号存储的数据是可以更改的。对信号进行赋值使用符号<=。定义信号的语法规范如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_29_3.jpg?sign=1738921284-9jutpCHID7kS1d0iOf0OtIgT3uDTmCqB-0-a26b00a91c3b120a69aac0c8fa902c94)
其中,identifier_list为信号名,subtype_indication为信号的类型,signal_kind为信号种类,conditional_expression为信号的初始值。
信号定义及赋值示例如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_30_1.jpg?sign=1738921284-jEHbI5GxIUGC7zxpqYyhv9YTLTHcEspf-0-afd3a396628c66f0ca9dffc0a50733e0)
信号一般在实体和结构体中声明。实体中声明的信号可以在实体的所有结构体重调用;结构体中声明的信号仅可在结构体内部调用。
在顺序语句中,如函数(function)等,更改信号的值不会立刻生效,信号只有在相应的函数、进程、过程结束时才会更新信号的值。
2.1.3 信号赋值语句
信号赋值语句是实现对信号进行赋值的语句,修改一个或多个信号驱动的输出波形。信号赋值语句可以分为3种,分别是简单信号赋值语句、条件信号赋值语句、选择信号赋值语句。
简单信号赋值语句的语法结构如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_30_2.jpg?sign=1738921284-GkUBxj9IrNuashFbrHE14MxwNKrUV3cY-0-98acfec0068cbbffc13ec8f7d69eae91)
其中,signal_name是需要赋值的目标信号;waveform是目标信号新的输出波形。
条件信号赋值语句的语法结构如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_30_3.jpg?sign=1738921284-dxGYpe88WcB38rHonSDHZFhmdBDvRJWI-0-dc95f62f5c78e92c2efdce7988b94361)
其中,signal_name是需要赋值的目标信号;condition是对目标信号赋予新输出波形的条件;waveform是对应的condition为真时,目标信号新的输出波形。
选择信号赋值语句的语法结构如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_30_4.jpg?sign=1738921284-PPi509Be6US3rpMcijA41sdcNh2HCIud-0-c9684d8e18fb00a5ab78dde1968b0ebd)
其中,expression是进入赋值分支的判断表达式;signal_name是需要赋值的目标信号;choices是构成表达式的取值列表,并且必须涵盖表达式的所有可能取值;waveform是对应choices的目标信号的新的输出波形。
信号赋值语句可作为并行语句使用,也可作为顺序语句使用。需要注意的是,信号的赋值需要等到process结束时才会生效。
例2.1 信号赋值语句示例
示例一中,将信号a和信号b的异或操作和与操作的结果分别赋值给信号s和信号c,实现半加器的功能。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_31_1.jpg?sign=1738921284-br7KAzYgRUt1FAEnAOkaBtdlYYf43DcO-0-d3efbfbc389cb337b7b5c5c4c76f9cbf)
示例二中,通过条件赋值语句实现4位优先级编码器。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_31_2.jpg?sign=1738921284-vWZL91A17aQWVWhe9qmqAbOnDplomzKn-0-674c09af728cfa071b985c548cb5182f)
示例三中,将command作为判断表达式,根据command的值实现各种基础的门电路,如command为“000”时,选择赋值语句为输入与门;command为“100”时,选择赋值语句为异或门。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_31_3.jpg?sign=1738921284-kpmWnp1TXiVKY3j1EshC75rvj56uDWb9-0-a69949b80c311e0adc8c0844a38d95a0)
2.1.4 变量
变量是另外一种存储动态数据的容器。与信号不同,变量只能在函数、进程和过程的内部使用,在局部电路中使用。另外,对变量进行赋值,变量的值是立即生效的。对变量进行赋值,使用符号:=。定义变量的语法规范如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_32_1.jpg?sign=1738921284-xlyCb5Lu5KJebWeiea2wBtyhttOm4noL-0-e25a72ce47db61e977435726c92299a4)
其中,shared可以定义共享变量,identifier_list为信号名,subtype_indication为信号的类型,signal_kind为信号种类,generic_map_aspect为类属映射表,conditional_expression为信号的初始值。
变量定义及赋值示例如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_32_2.jpg?sign=1738921284-RWKLocbScg2NjJPQf2PvEVg5qRcAmshW-0-3ebdcab7ad827727a4e7adeca2f49a15)
信号一般在函数、进程和过程中声明和调用。但是,共享变量可以在包集、实体和结构体中声明,也可以在相应的部分调用信号。
2.1.5 变量赋值语句
变量赋值语句是实现对变量进行赋值的语句,将变量的当前值修改为一个新的值。变量赋值语句可以分为两种,分别是简单变量赋值语句、选择变量赋值语句。
简单变量赋值语句的语法结构如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_32_3.jpg?sign=1738921284-PaIT3zXypxGCVYuVF2Eew0shW5q28Ccz-0-e845cb3cb0e8eaf849191097488259bd)
其中,variable_name是需要赋值的目标变量;expression是目标变量新值的表达式形式。
选择信号赋值语句的语法结构如下。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_33_1.jpg?sign=1738921284-EEJzzbgDebrT8b2rlZU8J3IcJEyjphdF-0-c9dd3c7afe18a30d64881800ad2d4dbf)
其中,expression_select是进入赋值分支的判断表达式;variable_name是需要赋值的目标变量;choices构成表达式的取值列表,并且必须涵盖表达式的所有可能取值;expression是对应choices的目标变量新值的表达式形式。
变量赋值语句是顺序语句的一种,只能在process、function和procedure内部使用,且变量的赋值是立即生效的。
例2.2 变量赋值语句示例
示例一定义了记录类型bit_record和该类型的变量a,定义了bit类型变量e和integer类型变量i。语句1和语句2是对bit_record类型变量a的bit_field和int_field赋值;语句3是将变量a包含的值赋给变量e和变量i。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_33_2.jpg?sign=1738921284-LAXcwArgeseIxS7gKMWhY5lERQWR3jiT-0-7c1e53127aa24c6072de4f4ae1cd32cb)
示例二与2.1的示例三实现相同的功能。但此处的data_out必须是变量,且示例二的选择变量赋值语句必须在process、function或prcedure中执行。
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_33_3.jpg?sign=1738921284-SnpDcYnv11gXVQXVBiVYauUETe0T44ll-0-4ae3eb50ed5994ddf12db7526929e2d9)
2.1.6 比较信号和变量
信号和变量之间的区别如表2.1所示。在顺序代码中,变量即时更新,信号却要到顺序代码段结束才会更新,这是实际项目中在信号和变量中做出选择需要考虑的因素之一。
表2.1 信号和变量的比较
![](https://epubservercos.yuewen.com/B3251C/23020659009785406/epubprivate/OEBPS/Images/43035_34_1.jpg?sign=1738921284-RCzJJAwvlctlky4WLqGgakTzLI1DVzu2-0-d723b7f91810439732793471902f5571)