16. 即将提到的 描 述 数 字 电 路 的 VHDL’ 非 常 接 近。 该 小 组 计 划 将 其 成 为 标 准 [ V Tfa94
93
] 〔1〕。
1.
6 一个 VHDL 的描述实例
图 1 .2 所示是 1 位加法器的逻辑图 , 其 V HDL 的描述如下所示 :
图 1 .2 1 位加法器逻辑图
ENTI TY one - bit - adder IS
∶
POR T ( a , b , c - in IN Bit ;
∶
c - ou t , sum O UT Bit ) ;
END one - bit - adder ;
ARCHI TECT URE logic OF one - bit - adder IS
∶
SIG NAL int Bit ;
BEGIN
int < = a XOR b AFT ER 10 ns;
c - out < = ( a AND b) OR ( int AND c - in ) AFT ER 20 ns;
sum < = int XOR c - in AFT ER 10 ns;
END logic;
1 . VHDL 的 CAD 工具
7
许多公司都提供 VHDL 工具 , 其中包括 VHDL 的创始 者 ( 例 如 In termetrics 公司 , 不 过
该公司的 VHDL 分部已被 Valid 公 司收 购 , 而 此后 不久 , Valid 公司 又 并入 Cadence 公司 ) ,
也包括一些大型 EDA 的公 司 ( 例 如 Cadence, Men tor Graphics , ViewLogic, Synopsys 等 ) ,
还包括一些专 门领 域的 公司 ( 例如 CLSI , Model- T echnology , Van tage 等 ) 。V HDL 模 拟 器
和综合器已经是商业软件 , 可以在多种工作平台上运行 ( V HDL 描述 不是 100 % 可以被综 合
的 , 不同公司提供的工具软件在描述风格和构造方面会有不同的指南和限制 , 满足这些要求
的 VHDL 描述才能被该公司提供的工具所综合 ) 。
VHDL 技 术 小 组 ( h ttp∶ / www . vhdl . com/ V HDLVendors/ Vendors . h tm ) 已 对 许 多
/
VHDL 商家的工具软件作过编译。
〔1 〕 目前仍 在制 定中。 — —译 者注
—
5
19. 型说明流过该端口的数据类型。
POR T ( [ SIGNAL ] 名字 : [ 模式 ] 子类型标识 [ BUS ] [∶ 静态表达式 ] , … ) ;
=
因为关键字 PORT 之后必须是信号类 , 所以略去关键字 SI GNAL 也不会 引起歧义。 如
果该端口和多个输出端相连 , 就要使用关键字 BUS。
从双连符 (-- ) 到本行 之末 的一段 文字 是 V HDL 的注 释。
注释对 VHDL 正文的意义没有影响。举例如下。
图 2 .2 半加器
下面是图 2 .2 所示半加器的 VHDL 描述。
-- 只有端口说明的实体说明
ENT I TY half - adder IS -- V HDL 不区分大小写
∶
POR T ( x , y IN Bit ; -- 所有端口为 SIGNAL 对象类型 , 可忽略
∶
sum , carry OUT Bit ) ;
END ENTITY half - adder ;
-- 有类属和端口说明的实体说明
ENT I TY andg IS
∶ ∶
GENERIC ( t pd - hl , tpd - lh Time = 1 ns; -- 典型延迟
∶ ∶
n Positive = 2 ) ; -- 与门的输入端数目
∶
POR T ( inpu t Bit - Vector ( 1 TO n) ; -- 模式省略 , 默认为 IN 模式
∶
output O UT Bit ) ;
END ENTITY andg ;
-- 没有类属和端口说明的实体说明
ENT I TY testbench IS
END test bench ;
2 .2 .
2 端口模 式
在电子线路级别之上观察 1 个设计时 , 把连接点和数据流向联系起来通常会带来方便。
为满足此要求 , VHDL 提供了下述端口模式 :
IN ( 流入实体 ) ,
OU T ( 流出实体 ) ,
INOU T ( 双向端口 : 既可流入 , 又可流出 ) ,
BUFFER ( 也是双向端口 , 但限定该端口只能有 1 个源 ) 。
VHDL 对于 端口 的读 写规则 如下 : 只 有在端 口模 式为 I N , INOU T 或 BU FFER 时 , 才
能从该端口读入数据 ; 只有在 端口 模式 为 OU T , INO U T 或 BUFF ER 时 , 才 能 向该 端口 写
数据。模式为 BU FFER 的端口和 模式 为 INOU T 的 端口 相似 之 处是 : 它 们既 可 读又 可写 ;
不同之处是 : BUFF ER 端口只能有 1 个源 ( 不管它的子类型是否是决断类型 ) 。
VHDL’ 允许使用属性 ′
93 Driving - Value 从 OU T 或 INO U T 端 口 读 取信 号 的驱 动 值
( 或贡献值 ) 。
2 .2 .
3 实体说 明部分
实体说明中的说明部分定义的项目是该实体接口中的公共信息 , 举例如下 :
8
20. -- 有实体说明项目的实体说明
ENT I TY ram IS
∶
POR T ( addr IN Bit - Vector (15 DOWNTO 0 ) ;
∶
data OU T Bit - Vector ( 31 DOWNTO 0 ) ;
∶
sel IN Bit ) ;
TYPE instruction IS ARRAY ( 1 TO 5 ) of Natural ;
TYPE program IS ARRA Y ( Natural RANGE < > ) OF instruction ;
U SE Work .timing - pkg ;
∶
PROCEDUR E initialization ( SIG NAL con ten t Bit - Vector ( 31 DOWNTO 0 ) ) IS
BEGI N
con ten t < = ( OTHERS = > ′1′) AFTE R some - delay ;
END PROCED URE initialization ;
END ENTITY ram ;
2 .2 .
4 实体语 句部分
实体说明中的语句是每一设计实体接口的共同部分 , 它们仅可以是下述并行语句 : 并行
断言语句、并行过程调用语句或被动进程语句。所有这些语句必须是被动语句 , 即其中不含
信号赋值。举例如下 :
-- 有实体说明项目和语句的实体说明
U SE Work .my - pkg .ALL ; -- 假设 my - pkg 包含 word 类型说明
ENT I TY latch IS
∶
P OR T ( din IN word ; -- word 类型必须定义在 1 个程序包中
∶
dou t OU T word ; -- 例如 my - pkg 程序包 , 程序包对该实体可见
∶
load , clk IN Bit ) ;
∶ ∶
CONSTANT set up Time = 12 ns;
U SE Work .timing - pkg .ALL ; -- 假设程序包 timing - pkg 包括 CheckTiming 过程
BEGIN
CheckTiming ( set up , din , load , clk ) ;
END latch ;
2 .3 结构体
结构体是次级设计单元 , 在其对应的初级设 计单元 实体 说明 被编译 并且 被并入 设计 库
之后 , 它就可以单独地被编译并且被并入该设 计库 之中。结 构体 描述 1 个设 计的结 构或 行
为 , 把 1 个设计的输入和输出之间的关系建立起来。1 个 设计实体 可以有 多个结构 体 , 分 别
代表该器件的不同实现方案。
结构体的描述格式为 ( 其中的黑体字为 V HDL’ 的语法要求 ) :
93
ARCHI TECT URE 结构体名 OF 实体名 IS
-- 说明语句
BEGIN
9
21. -- 并行语句
END [ ARCHITECTURE ] [ 结构体名 ] ;
例如 :
ARCHI TECT URE behavl OF half - adder IS
∶
CONSTA NT delay : Time = 5 ns ;
BEGIN
p1 : PROCESS -- p1 为可选的进程标号
BEGI N
sum < = x XOR y AFTE R delay ;
carry < = x AND y AFT ER delay ;
WAI T O N x , y ;
END PROCESS p1 ;
END ARCHITECTURE behavl ;
上述例子中 有 1 个 进 程 语 句。 在 该 进 程 语 句 中 , 有 2 个 信 号 赋 值 语 句 和 1 个 等 待
( WA IT) 语句。此进程语句描述了数据的传送和定时关系 , 它们合起来构成半加器的行为。
前文已经提到 , 可以为 1 个实体说明写上 几个 结构体。 结构 体描述 中的 实体名 把结 构
体和实体说明联系了起来。下面是 1 个实体具有 2 个结构体的实例 :
--
-- 下面的模型与 VHDL’ 相符 , 已用 V- System / Windows V4 .2 e 进行过模拟
93
--
ENT I TY coun t2 IS -- 该实体有 2 个结构体
∶ ∶
GENERIC ( tpd Time = 10 ns ) ;
∶
POR T ( clock I N Bit ; ∶
q1 , q0 OUT Bit ) ;
END ENTITY count2 ;
-- count2 的一个结构体 , 另一个在下面
ARCHI TECT URE arch1 OF coun t2 IS
BEGIN
∶
count - up PROCESS ( clock )
∶ ∶
VARIABLE coun t - value Natural = 0 ;
BEGI N
IF clock = ′1′THEN -- 时钟上升沿
∶
count - value = ( coun t - value + 1) MOD 4 ;
q1 < = bit′ ( coun t - value / 2 ) AFT ER tpd ;
Val
q0 < = bit′ ( coun t - value MOD 2 ) AF TER t pd ;
Val
END IF ;
END PROCESS count - up ;
END ARCHITECTURE arch1 ;
-- T 型触发器 , 用作 count2 另一个结构体的元件
ENT I TY t - ff IS
∶ ∶
GENERIC ( t pd Time = 5 ns ) ; -- 默认延迟时间
10
22. ∶
POR T ( clk I N Bit ; q IN OUT Bit = ′ ;
∶ ∶ 0′)
END ENTITY t - ff ;
ARCHI TECT URE only OF t - ff IS
BEGIN
PROCESS ( clk )
BEGI N
IF clk = ′1′T HEN
q < = NOT q A FTE R t pd ;
END IF ;
END PROCESS;
END ARCHITECTURE only ;
-- count2 的另一个结构体
ARCHI TECT URE arch2 OF coun t2 IS
∶
SIG NAL ff0 , ff1 , inv Bit ;
BEGIN
t - ff1: ENTITY Work .t - ff ( only ) -- VHDL’ 中的直接实体例化
93
GENERIC MAP ( tpd => 4 ns) -- 有效的延迟值
PORT MAP ( clk = > clock, q = > ff0 ) ; -- 名字关联
t - ff2: ENTITY Work .t - ff ( only )
GENERIC MAP ( 4 ns)
PORT MAP ( inv, ff1 ) ; -- 位置关联
∶
inveter inv < = NOT ff0 A FTE R 2 ns;
q0 < = ff0 ;
q1 < = ff1 ;
END ARCHITECTURE arch2 ;
2 .4 标识符的命名规则
VHDL’ 中关于标识符的语 法规则 被 VHDL’ 全 部接 受并 加以 扩展。 为了 对二 者
87 93
加以区分 , 前者称为短标识符 , 后者称为扩展标识符。
2 .4 .
1 短标识 符
VHDL 的短标识符为遵守以下规则的字符序列 :
有效字符 : 英文字母 (′ -′ ,′ -′ ) 、
a′ z′ A′ Z′ 数字 (′ -′ ) 和下划线 (′ ′。
0′ 9′ - )
必须以英文字母打头。
下划线 (′ ′ 的前后都必须有英文字母或数字。
- )
短标识符不区分大小写。
下面的字符序列可看作同一短标识符的不同表示形式 :
half - adder Half - adder Half - Adder HALF - ADDER
11
24. 对象类别 标识符表 : 子类型标识 [∶ 初值 ] ;
=
举例 :
∶ ∶
CONSTANT delay1 , delay2 Time = 10 ns ;
∶
VARIABLE sum Real ;
∶
SIGNAL clock Bit ;
F ILE inpu t Text IS IN ″
∶ STD - INP UT″;
绝大多数情况下 , 在说明 1 个常 数时 必须 给 它 1 个初 始 值。但 是 , 在 非常 特 殊的 情 况
下 , 在程序包中说明 1 个常数时 , 可以不给它指定初始值。这样的常数叫作缓定常数。
如果 在同一个 对象说 明语句中 给多个 对象指定 了 1 个 初始值 , 则 这些对象 都获得 此
同一初始值。例如 , 在上面的常数说明语句中 , delay1 和 delay2 各自的初始值都是 10
ns。
如果在说明信号或变量时没有指定初始值 , 系统则认为它取默认值 , 即该 类型的最 左
值或最小值。例如 , 在上面的信号 clock 的说明语句中 , clock 的默认的初始值为′ 。
0′
可以用函数调用的方式给对象赋初值。例如 :
CONS TAN T const1∶ Integer∶ your - function ( True , 3 ) ;
=
2 .6 数据类型和子类型
VHDL 有很强的数据类型。正是由于这些数据类型 , 才使得 VHDL 能够创 建高层次 的
系统和算法模型。属于强类型语言的 VHDL 的特点在于 : 每一个对象 具有 1 个 类型且只 能
具有那个类型的值 ; 施加于某对象上的操作的类型必须与该对象的类型匹配 , 即定义 1 个操
作时必须指明其操作对 象的 类 型。V HDL 的 强类 型特 性 使得 能尽 早地 发现 类 型不 匹配 方
面的错误。例如 , 把不同类型的信号连接起来 就是 非法的。 对象 的类型 在说 明该对 象时 已
被确定。
VHDL 有许多预定义类型 , 用户可以不必显式 说明而 直接 使用 它们。这 些预定 义类 型
在标准 ( STANDARD) 程 序 包 中 , 见 附录 6。 预定 义 类 型包 括 : 整 数 类 型 In teger , 浮 点 类 型
Real, 枚举类型 Boolean , Bit, Severit y - Level 和 Character , 以及物理类型 Time。
2 .6 .
1 标量类 型
标量类型包括 : 整数类型、浮点数类型、 举类 型和物 理类 型。V HDL 还 允许设 计者 为
枚
自己定义数据类型。举例如下 :
TYPE twos - comp IS RA NGE - 32768 TO 32767 ;
TYPE word - index IS RAN GE 15 DOWNTO 0 ;
TYPE voltage IS RANGE 0 .0 TO 10 .0 ;
类型说明中的关键字 RANGE 限定该类 型的取 值范 围 , 该类 型的对 象的 取值如 果超 出
此范围 , 则为非法。举例如下 :
TYPE Std - ULogic IS ( ′U′ -- 未定
′
X′ -- 强制未知
13
25. ′0′ -- 强制 0
′1′ -- 强制 1
′
Z′ -- 高阻
′W′ -- 弱未知
′L′ -- 弱 0
′H′ -- 弱 1
′
-′ -- 无关
); -- 程序包 Std - Logic - 1164 中的预定义类型
TYPE Bit IS ( ′ , ′ ;
0′ 1′) -- STANDARD 程序包中预定义的类型
TYPE QSim - State IS ( ′ , ′ , ′ , ′
X′ 0′ 1′ Z′) -- Men tor Graphics 预定义的类型
TYPE Severit y - Level IS ( Note , Warning , Error , Failure) ; -- STANDARD 程序包中预定义的类型
TYPE t raffic - lights IS ( red , yellow, green ) ;
请注意 , 短标识符不区分大小写 , 而字符 文字 区分 大小写 , 因 此 , 字符 文字 a” 字符 文
“ 和
字“A”不同。枚举类型中的标识符不区分大小写 , 因此类型 Severity - Level 中的标识 符 note
和 Note, NOT E 相同。
物理类型定义规定 1 个取值范围、 个基本单位和若干个 (0 至多个 ) 次级单位。次级单
1
位是基本单位的整数倍。例如 :
TYPE resistance IS RA NGE 1 TO 10 e9
U NI TS
oh m ; -- 基本单位
kohm = 1000 ohm ; -- 次级单位为基本单位的整数倍
END U NITS;
2 .6 .
2 复合类 型
复合类型包括数组和记录。数组用于定义同一 类型 值的 集合 , 记录 用于 定义可 能不 同
类型值的集合。
数组可以是一维 ( 有 1 个下标 ) 数组或多维 数组 ( 有 多个下 标 ) 。此外 , 数 组类型 还可 分
为限定性数组和非限定性数组 : 限定性数组下标的取值范围在该数组类型定义时就被确定 ;
而非限定性数组下标的取值范围随后才确定。举例如下 :
TYPE Bit - Vector IS ARRAY ( Natural RANGE < > ) OF Bit ; -- STANDARD 程序包中预定义的
类型
TYPE word IS ARRAY ( 31 DOWNTO 0 ) OF Bit ;
TYPE memory IS ARRAY ( address ) O F word ; -- 即 : 地址可以为 In teger 类型
TYPE matrix IS ARRAY ( 1 TO 8 , 1 TO 8 ) OF R eal ;
TYPE St ring IS ARRAY ( Positive RANGE < > ) OF Character ; -- 预定义的类型
TYPE lpc - coef IS ARRAY ( Natural RANGE < > ) OF Real ;
可以把 < > ”
“ 看作下标范围的占位符 , 在今 后用到 该数 组类 型时再 填入 具体的 数值 范
围。例如 , 1 个对象要被说明为具有 8 个元素的向量就可以写作 :
∶
VARIABLE item lpc - coef ( 7 DOWNTO 0 ) ;
14
26. 在 VHDL 中 , 类型 Bit 和 Bit - Vector 分别是字符 ( ′ ,′ 和 字符数 组 , 它 们仅和逻 辑
0′ 1′)
运算有关 , 而没有任何数字值的意义。
记录类型的实例如下 :
TYPE mon th - name ( Jan , Feb , Mar , Apr , May , Jun , Jul , Aug , Sep , Oct , Nov , Dec ) ;
TYPE date IS R ECORD
∶
day Integer RAN GE 1 TO 31 ;
∶
mon th mont h - name ;
∶
year Integer RANGE 0 TO 3000 ;
END R ECORD;
可以对 1 个复合类型的信号整体赋值 , 也可以对其子元素分别赋值。例如 , 如果我们把
today 说明为 date 类型 ( 前面已将 date 说明为记录类型 ) 的变量 :
∶
VARIABLE today date ;
那么 , 整体赋值
∶
today = ( 15 , May , 1995 ) ;
和下述分别赋值等价 :
∶
today .day = 15 ;
today .month∶ May ;
=
∶
today .year = 1995 ;
也可以采用名字关联的 方法。 在此 情况 下 , 子 元素 出现 的前 后 顺序 就 没有 什 么 关系。
例如 :
∶
today = ( mon th = > May , day = > 15 , year = > 1995 ) ;
对于只包含单个元素的聚集来说 , 必须使用名字关联的方法进行赋值 , 其目的是把它和
被括号括起来的表达式区别开来。例如 , 有如下的说明 :
TYPE single IS RECORD
∶
a Integer ;
END R ECORD;
SIGNAL s single ; 〔 1〕
∶
下面是对信号 s 赋值的几个例子 :
s <= 1; -- 不合法
s <= ( 1 ) ; -- 不合法
s < = ( a => 1 ) ; -- 命名关联 , 合法
s .a < = 1 ; -- 指定域名字 , 合法
对于我们所讨论的问题 , 下面的 1 段测试程序比上面的实例表述得更为清楚 :
〔1 〕 原文误 为 signal , 译 者已作 改正 。— — 译者 注
—
15
27. ENTI TY tests IS END;
ARCHI TEC TUR E record - type O F tests IS
TYPE mon th - name ( Jan , Feb , Mar , Apr , May , Jun , Jul , Aug , Sep , Oct , Nov , Dec ) ;
TYPE date IS R ECORD
∶
day In teger RA NGE 1 TO 31 ;
∶
mon th mon th - name ;
∶
year Integer RANGE 0 TO 3000 ;
END R ECORD date ;
TYPE single IS RECORD
∶
a Integer ;
END R ECORD single;
BEGIN
PROCESS
∶
VARIABLE birt hday , graduation - day , today date ;
∶
VARIABLE s single;
BEGIN
-- 复合变量整体赋值
∶
bir thday = ( 12 , Apr , 1964 ) ;
-- 复合变量的子元素分别赋值
∶
graduation - day .day = 19 ;
graduation - day .mon th∶ Jul;
=
∶
graduation - day .year = 1995 ;
-- 名字关联 , 顺序不重要
∶
today = ( mon th = > May , day = > 15 , year = > 1995 ) ;
-- 单元素复合类型变量必须采用名字关联
∶
s = ( a => 1 ) ; -- 正确
-- 或指定域
∶
s .a = 2 ; -- 正确
-- 下面 2 个赋值不好 , 可能引发编译错误 : 赋值类型不兼容
∶
s = 3; -- 错误
∶
s = ( 4 ); -- 错误
WAIT ;
END PROCESS ;
END ARCHITECTURE record - t ype ;
给数组赋值有几种不同的方法 , 举例如下 :
-- 下面的 V HDL 代码包括不同的类型赋值格式 , 编译无错。
LIBRARY I EEE ;
USE I EEE .S td - Logic - 1164 .ALL ;
ENTI TY typecast IS
∶
P OR T ( in1 , in2 IN Std - Logic; ∶
ou t1 O UT St d - Logic ) ;
END ENTITY typecast ;
16
28. ARCHI TEC TUR E test OF typecast IS
BEGIN
PROCESS( in1 , in2 ) ;
∶
VARIABLE temp Std - Logic - Vector( 1 DOWNTO 0 ) ;
BEGIN
-- 将数组值赋值给变量 temp 的不同方法
∶
temp = ( in1 , in2 ) ;
∶
temp = in1 & in2 ;
∶
temp = St d - Logic - Vector′ in1 , in2 ) ;
(
∶
temp = St d - Logic - Vector′ in1 & in2 ) ;
(
∶
temp = St d - Logic - Vector ( 1 DOWNTO 0 )′ in2 , in1 ) ;
(
∶
temp = St d - Logic - Vector ( 1 DOWNTO 0 )′ in2 & in1 ) ;
(
-- 用 CASE 语句描述 1 个异或门
CASE Std - Logic - Vector′ in1 , in2 ) IS
( -- 此处需要类型赋值
WHEN ″00″= > out1 < = ′
0′;
WHEN ″01″= > out1 < = ′
1′;
WHEN ″10″= > out1 < = ′
1′;
WHEN ″11″= > out1 < = ′
0′;
WHEN OTHERS = > out1 < = ′
X′;
END CASE ;
END PROCESS ;
END ARCHITECTURE test ;
2 .6 .
3 存取类 型
存取类型实际上是指针类型 , 它被用来在对象之间建立联系 , 或者给新对象分配或释放
存储空间。在普通 VHDL 的程序中很少用到存取类型 , 许多关于 V HDL 的书中甚至不介绍
这种类型。本 书 在 这 里 提 到 它 , 也 仅 仅 是 为 了 完 整 性。 欲 知 详 情 , 请 参 阅 IEE E 标 准 的
VHDL 语言参考手册 [ LRM93 ] 。
在 IEE E St d - 1076 的程序包 TEX TIO 中 , 有 1 个预 定义 的存 取类型 Line ( 用户 也可 以
定义自己的存取类型 ) :
TYPE Line IS ACCESS St ring ;
这表示类型为 Line 的变 量 是 指向 字 符串 值 的指 针。 只有 变 量才 可 以是 存 取 类型 , 例
如:
VARIABLE line - buffer∶ Line;
2 .6 .
4 文件类 型
文件类型用于在主系统环境中定义代表文件 的对象 , 文 件对 象的值 是主 系统文 件中 值
的序列。
17
29. 在 IEE E Std - 1076 的程序包 T EXT IO( 见附录 7 〔1〕 中 , 有 1 个预定义的文件类型 T ext
)
( 用户也可以定义自己的文件类型 ) :
TYPE Text IS F ILE OF String ; -- TEXT IO 程序包中预定义的文件类型
TYPE input - t ype IS FI LE OF Character ; -- 用户自定义的文件类型
这表示类型为 Text 的文件是可 变长度 的 ASCII 码 记录 文件。 在程 序 包 T EXTIO 中 ,
有 2 个预定义的标准文本文件 :
FILE input Text O PEN read - mode IS ″
∶ STD - IN PU T″;
FILE ou tput Text OPEN write - mode IS ″
∶ STD - OUTP UT″;
从 VHDL’ 到 V HDL’ 在使用文件方 面有很大的变化 , 因此 , 要注意这 2 个版本 的
87 93
文件说明和文件使用的不同之处。
VHDL 的输入和输出能力很有限。为了扩展输入和 输出 能力 , 某些 公司 出售专 门的 程
序包。下面的 1 段测试程序是 Andrew Fenner 写的 , 已使用 V- System / W indows 模拟器 和
Q uick VHDL 模拟器测试过 , 写此程序时他是都柏林城市大学电子工程学院四年级的学生。
----------------------------------------------------------------------------------------------------------------
-- purpose
∶ T he purpose of t he program is to provide an example of the
-- file accessing features of VHDL using the 1993 version .
--
-- T he program asks for the name of the file to be opened . If the file
-- does not exist , t he program asks for the name of the file again and
-- again un til the name exists . If t he file cannot be opend for any
-- ot her reason t hen t he program stops .
--
-- T he program reads t he data in line by line . The data is t hen read out
-- of the line . T he data is two integers . T he in tegers are then multiplied .
-- An out put line is t he created . T his line contains the values multiplied
-- and t he result along wit h some string data .
--
-- X1 * X2 = Result
--
-- T his con tinues till t he end of t he input file . T he outpu t is writ ten to a
-- file called ou tput .dat in t he base directory .
----------------------------------------------------------------------------------------------------------
LIBRARY I EEE ;
USE I EEE .S td - Logic - 1164 .ALL ;
USE St d .Tex tio .ALL ;
ENTI TY test file IS
-
END ENTITY test - file ;
〔1 〕 原书误 为附 录 8。 — — 译者注 。
—
18
30. ARCHI TEC TUR E test1 OF test - file IS
-- All t he reading and writing of t he file takes place in t his function
-- T his function takes the name of the file to be opened as an input
∶
FU NCT ION read - file ( file - name IN St ring ) R ETU RN Boolean IS
-- open the file with t he name read in from t he keyboard
∶ ∶
VARIABLE status File - Open - Stat us = Open - OK ;
∶
F ILE in - file Text O PEN Read - Mode IS file - name ;
F ILE temp - file Text O PEN Write - Mode IS ″ tput .dat″
∶ ou ;
∶ ∶
VARIABLE int1 In teger = 0 ;
∶ ∶
VARIABLE int2 In teger = 0 ;
∶ ∶
VARIABLE result - int In teger = 0 ;
-- variables required to read in file name
∶
VARIABLE in - line, lin , ou t - line Line ;
∶
VARIABLE file - name2 String ( 1 TO 60 ) ;
VARIABLE out2∶ St ring ( 1 TO 58 ) ;
∶
VARIABLE out - 3 - char St ring ( 1 TO 3 ) ;
∶
VARIABLE ok Boolean ;
∶ ∶
VARIABLE x In teger = 1 ;
∶
VARIABLE charact Character ;
BEGIN
-- Close the file t hen open it again . If the file is not closed then an error
-- occurs when you test to see if it is opened correctly .
File - Close ( in - file ) ;
File - Open ( stat us , in - file , file - name, R ead - Mode ) ;
-- If t he file did not open correctly
WHI LE NOT ( status = Open - OK ) LOOP
IF ( status = Name - Error ) THEN
out2∶ ″ ∶
= Enter the name of the inpu t file again D pat h name .asm″;
W rite ( lin , out2 , Left , 0 ) ;
W riteLine ( Ou tput , lin ) ;
ReadLine ( Input , in - line ) ;
Read ( in - line, charact , ok ) ;
-- get the name of the file
∶
x = 1;
WHI LE ( x < 61 ) LOOP
file - name2 ( x )∶ nul ;
=
x∶ x + 1 ;
=
END LOOP ;
∶
x = 1;
WHI LE ( ok ) LOOP
file - name2 ( x)∶ charact ;
=
∶
x = x + 1;
19
31. Read ( in - line, charact , ok ) ;
END LOOP ;
-- open the file with t he new name given
File - Open ( status, in - file, file - name2 , Read - Mode ) ;
ELSE
ASSER T false R EPORT ″T he file cannot be opened ″SEVERI TY Failure;
END I F;
END LOO P;
-- Read in the first line of the file
ReadLine ( in - file , in - line ) ;
-- continue un til the end of the file is reached
∶
r1 WHIL E NOT E ndFile ( in - file ) LOOP
-- read in the two integers from t he file
Read ( in - line, in t1 , ok ) ;
Read ( in - line, in t2 , ok ) ;
-- multiply t he read in data
result - in t = int1 * int2 ;
∶
-- make up a line of out put in the given format
W rite ( out - line, int1 , Lef t , 0 ) ; -- integer 1
ou t - 3 - char ( 1)∶ ′ ;
= ′
ou t - 3 - char ( 2)∶ ′ ′
= * ; -- * sign
ou t - 3 - char ( 3)∶ ′ ;
= ′
W rite ( out - line, out - 3 - char , Left , 0 ) ;
W rite ( out - line, int2 , Lef t , 3 ) ; -- integer 2
ou t - 3 - char ( 2)∶ ′ ′
= = ;
W rite ( out - line, out - 3 - char , Left , 0 ) ; -- = sign
W rite ( out - line, result - int , Lef t , 0 ) ; -- result
-- write ou tput line to file
W riteLine ( temp - file, out - line ) ;
-- read in the nex t line
ReadLine ( in - file , in - line ) ;
END LOO P;
RE TUR N T rue;
END F UNCT ION read - file ;
BEGIN
PROCESS
∶
VARIABLE result Boolean ;
-- variables required to read in file name
∶
VARIABLE in - line , lin Line;
∶
VARIABLE file - name St ring ( 1 TO 60 ) ;
∶
VARIABLE out2 St ring ( 1 TO 58 ) ;
∶
VARIABLE ok Boolean ;
20
32. ∶ ∶
VARIABLE x In teger = 1 ;
∶
VARIABLE charact Character ;
BEGIN
-- reads in t he program from a file at 0 ns . Prompt the user
-- the name of the file , and read in t he data from that file
I F ( Now = 0 ns ) THEN
-- read in the file name for t he first time
ou t2 = ″Please en ter t he name of t he inpu t file D path name .asm ″
∶ ∶ ;
W rite ( lin , out2 , Left , 0 ) ;
W riteLine (out put , lin ) ;
ReadLine ( input , in - line ) ;
Read ( in - line, charact , ok ) ;
-- get the name of the file
WHI LE (ok ) LOO P
file - name ( x)∶ charact ;
=
∶
x = x + 1;
Read ( in - line, charact , ok ) ;
END LOOP ;
--
-- call t he function to read the file
--
∶
result = read - file ( file - name ) ;
END IF ;
WAI T ;
END PROCESS ;
END ARCHITECTURE test1 ;
2 .6 .
5 子类型
1 个类型说明定义了 1 个值域 , 它和任何其它类型说明定义的值域完全不同。有时候 1
个对象可能取值的值域是某个类型说明定义的值域的子集 , 这 就要用到 VHDL 提供的子 类
型的概念。子类型和其父类型完全兼容。但是 , 如果某 个对 象被 说明为 某个 特定的 子类 型
时 , 它的取值范围就不允许超出该子类型的值域 , 即使这个值处在其父类型的值域范围之内
也不允许。为了增加可重用性 , 只要有可能定义为子类型时 , 就不要将其定义为新类型。
子类型可以是对其父类型施加限制条件 ; 也可以是简单地对其父类型重新起个名字 , 而
没有增加任何新意义。下面的简单实例用于说明子类型的用法 :
-- 子类型测试程序
ARCHI TEC TUR E subtype - test O F tests IS
SUBTY PE data IS Bit - Vector (31 DOWNTO 0 ) ; -- 下标约束
SUBTY PE operand IS data; -- operand 只是 data 的另一个名字 , 它们等价
TYPE x - int IS RA NGE 1 TO 50 ;
TYPE y - in t IS RANGE 1 TO 30 ;
21
33. SUBTY PE z - int IS x - int RANGE 1 TO 30 ;
SUBTY PE a - int IS x - in t RA NGE 3 TO 32 ;
SUBTY PE b - in t IS z - int RANGE 5 TO 20 ; -- 允许定义子类型的子类型
∶ ∶
SIGNAL x x - int = 1 ;
∶ ∶
SIGNAL y y - int = 2 ;
∶ ∶
SIGNAL z z - in t = 3 ;
∶ ∶
SIGNAL a a - int = 4 ;
∶ ∶
SIGNAL b b - in t = 5 ;
BEGIN
z <= x; -- 正确 , 因为 z - int 为 x - int 的 1 个子类型
-- 但若 x 越出 z - int 的界 , 则将导致运行错误
a < = z; -- 正确 , 因为同一类型的不同子类型兼容
b < = a; -- 正确 , 因为同一类型的不同子类型兼容
-- 但若 a 越出 b - int 的界 , 则将导致运行错误
y < = x; -- 错误 , 导致编译错误 , 因为 x 与 y 类型不同
y < = y - int ( x) ; -- 正确 , 因为 x - int 与 y - in t 为密切相关的数据类型 , 允许类型标记转换
-- 但若 x 越出 y - int 的界 , 则将导致运行错误
END ARCHITECTURE sub type - test ;
标准程序包 St d - Logic - 1164 [ 附录 8 〔 1〕 中含有如下子类型说明 :
]
∶
FU NCT ION Resolved ( s Std - ULogic - Vector ) R ETU RN Std - ULogic;
SUBTY PE St d - Logic IS Resolved St d - ULogic ;
子类型 Std - Logic 恰好就是子类型 Resolved Std - U Logic 的另一个名 字 , 仅 是简单一 点
而已。下面 2 个信号说明是等价的 , 请参看决断函数一章。
∶
SIGNAL res1 Std - Logic ;
∶
SIGNAL res1 R esolved Std - ULogic ;
标准程序包 Std - Logic - 1164 中 还含 有如 下 子类 型说 明 , 它们 具有 不 同的 取 值范 围 约
束条件 :
SUBTY PE X01 IS Resolved St d - ULogic RA NGE ′
X′TO ′ ;
1′ -- ( ′ , ′ , ′ ;
X′ 0′ 1′)
SUBTY PE X01Z IS Resolved Std - ULogic RA NGE ′
X′TO ′ ;
Z′ -- ( ′ , ′ , ′ , ′ ;
X′ 0′ 1′ Z′)
SUBTY PE UX01 IS Resolved St d - ULogic RAN GE ′
U′TO ′ ;
1′ -- (′ , ′ , ′ , ′ ) ;
U′ X′ 0′ 1′
SUBTY PE UX01 Z IS Resolved St d - ULogic RAN GE ′
U′TO ′ ;
Z′ -- (′ , ′ , ′ , ′ , ′ ;
U′ X′ 0′ 1′ Z′)
其中 , 子类型 X01 的另一等价形式如下 :
SUBTYPE X01 IS Std - Logic RANGE ′
X′TO ′ ;
1′ -- ( ′ , ′ , ′ ;
X′ 0′ 1′)
2 .7 类型转换
VHDL 属于 强类型 语言 , 每 一个 对象只 能有 1 种 类型 , 并 且只 能取该 类型 的值。赋 值
〔1 〕 原书误 为附 录 7。 — — 译者注 。
—
22
34. 时 , 若值类型和对 象 类型 不 一 致 , 需要 使 用 显 式 类型 转 换。 VHDL 中没 有 隐 式 类 型转 换。
同一父类型的诸子类型相互兼容。
2 .7 .
1 用类型 标记实现 类型转换
类型标记实际上 是类 型 的 名 字。例 如 , Real 就 是 用 于 把 整数 转 换 为 浮 点数 的 类 型 标
记。类型标记转换仅适用于关系密切的标量类 型 , 即整数 和浮 点数。枚 举类 型不能 使用 类
型标记的方法进行类型转换。举例如下 :
假定有 :
V ARIABLE ∶ In teger ;
i
V ARIABLE r∶ Real ;
则下列赋值语句可以正常工作 :
∶
i = In teger ( r) ;
∶
r = Real ( i) ;
请注意 , 把浮点数转换为整数时会发生舍 入现象。 如果某 浮点 数的 值恰好 处于 2 个 整
数的正中间时 , 转换的结果可能向任意方向靠拢。
已经定义了以整数或浮点数为基类型的标 量数据 类型 的加法 运算 符。但是 , 所 有操 作
数必须属于同一数据类型 ( 或者同一基类型的子类型 ) 。在下面 的实例中 , x 不能 与 y 相加 ,
除非其中之一转换为另一个数的类型。
PROCESS ( clk )
TYPE tpx IS RANGE 3 .5 TO 12 .8 ;
TYPE tpy IS RAN GE 5 .7 TO 20 .9 ;
∶
VARIABLE x t px ;
∶
VARIABLE y tpy RANGE 10 .2 TO 15 .6 ;
∶
VARIABLE z tpy ;
BEGIN
∶
z = tpy (x ) + y ;
END PROCESS ;
程序包 Numeric - Bit 中定义了有符号数 Signed 和无符号数 U nsigned 类型 , 与其关系 密
切的数据类型是 Bit - Vector , 可以用类型标记方法实现它们之间的类型转换。与此 类似 , 程
序包 Numeric - St d 中定义的有符号 数和 无符 号数 类 型与 数据 类型 St d - Logic - Vector 关 系
密切 , 它们也可以用类型标记方法实现类型转换。
2 .7 .
2 用户创 建的类型 转换
函数可以用来实 现类型转 换。程序 包 St d - Logic - 1164 , N umeric - Bit 和 N umeric - Std
中定义了许多类型转换函数。下面是 1 个把 Std - U Logic 值转换为 Bit 值的类型转 换函数。
参阅程序包 Std - Logic - 1164 [ 见附录 8 ] , 可以看到更多的类型转换函数。
∶
FU NCT ION To - Bit ( s Std - ULogic; xmap Bit = ′
∶ ∶ 0′) RE TUR N Bit IS
BEGIN
23
35. CASE s IS
WHEN ′ | ′
0′ L′= > R ETUR N (′ ) ;
0′
WHEN ′ | ′
1′ H′= > RET URN (′ ) ;
1′
WHEN OTHERS = > RE TURN xmap ;
END CASE ;
END ;
下面的实例以不同的方式调 用转 换函 数 To - Bit。请 注意 , 在函 数调 用时 , 第二 个参 数
可以被略去不写。此时 , 该参数 取默认值。在下面的 例子中 , 若 s 的取 值为 ′ , ′ , ′ , ′
0′ 1′ L′
H′之一 , 则 b1 , b2 , b3 将得到的值是与 s 相同的值 ′ 或′ 。若 s 的取值 是 St d - U Logic 类
0′ 1′
型中的其它值时 , b1 , b2 的值将是 ′ , 而 b3 的值将是 ′ 。当然 , 用户可以写出自己的类型
0′ 1′
转换函数。
LIBRARY I EEE ;
USE I EEE .S td - Logic - 1164 .ALL ;
ENTI TY typeconv IS END ;
ARCHI TEC TUR E arch O F typeconv IS
SIGNAL s Std - ULogic = ′ ;
∶ ∶ 0′
SIGNAL b1 , b2 , b3∶Bit = ′ ;
∶ 1′
BEGIN
b1 < = To - Bit ( s) ;
b2 < = To - Bit ( s, ′ ) ;
0′
b3 < = To - Bit ( s, ′ ) ;
1′
END;
常数也可用于类型转换。就模拟效率而言 , 它 比类型 转换 函数 效率更 高。下面 以实 例
说明使用常数把类型为 Std - U Logic 的值转换 Bit 类型的值 :
LIBRARY I EEE ;
USE I EEE .S td - Logic - 1164 .ALL ;
ENTI TY typeconv IS END ;
ARCHI TEC TUR E arch O F typeconv IS
TYPE typeconv - typ IS ARRAY ( Std - ULogic ) OF Bit ;
CO NSTANT typeconv - con∶ typeconv - typ∶= ( ′ | L′ = > ′ ,
0′ 0′ ′ |′ = > ′ ,
1′ H′ 1′ OT HE RS
=> ′ ) ;
0′
SIGNAL b∶Bit ;
∶
SIGNAL s Std - ULogic ;
BEGIN
b < = typeconv - con ( s) ;
END;
2 .8 词法单元
2 .8 .
1 注释
VHDL 中的注释是以双连符 (-- ) 打头直到本行末尾的 1 段文字。注释不是 VHDL 设计
24