.. . .. . .
units fs; ps = 1000 fs; ns = 1000 ps; us = 1000 ns; ms = 1000 us; sec = 1000 ms; min = 60 sec; hr = 60 min; end units 6、符号类型character通常用单引号括起来,如’Z’。 7、标准逻辑类型STD_LOGIC与bit类型相似,也是表示单个数字信号逻辑的,每个STD_LOGIC都有9种不同的状态。 8、枚举类型enumerate在状态机和复杂系统的描述中尤其有用。 9、错误等级severity_level共有四种状态可用:note、warning、error、failure。错误等级通常与assert语句配合使用。
? 复合类型 1、位矢量类型BIT_VECTOR是由多个位型数据组合起来的一组数据。例子如下: signal A_WORD : bit_vector(7 downto 0); A_WORD <= X\; 2、标准逻辑矢量型STD_LOGIC_VECTOR是由多个标准逻辑数据组合起来的。 3、字符串类型是由多个字符类型的数据组合起来的。 4、数组array是由多个相同类型的数据组成的集合。VHDL中有两种定义矩阵的方法,一种称为Constrained,另一种称为Unconstrained,两者之间的不同在于定义数组时索引值的围不同。Constrained在数组定义时就已经确定了索引值的取值围,例如: type WORD is ARRAY(3 downto 0) of STD_LOGIC; Unconstrained类型在定义数组时不给定具体的取值围,而是在用数组类型定义一个对象时才给定索引围,例如: type BIT_VECTOR is ARRAY(NATURAL range<>) of BIT; type STD_LOGIC_VECTOR is ARRAY(NATURAL range<>) of STD_LOGIC; type STRING is ARRAY(POSITIVE range<>) of CHARACTER;
在工程中,大型的数组一般用变量或常量定义,用信号定义时,会影响仿真速度。 在VHDL做工程仿真时,经常会用ARRAY类型对存储器进行建模。 多维数组没有对应的底层硬件逻辑,因此多用于仿真和建模。 数组的赋值方法为:
signal H_BYTE : STD_LOGIC_VECTOR(0 to 7); H_BYTE <= (7|6|0|1 => '1', 2 to 5 => '0');
5、记录型RECORD 并不是所有综合器都支持记录类型,组成集合的数据至少要有两种以上不同的类型。
2.3.3 文件类型(File)
目前常用的文件类型只有TEXT类型,IEEE的TEXTIO包集合中包含了TEXT文件常用的一些读写函数,方便设计者在开发时调用。综合器不支持,只能用于仿真。
S. . . . . ..
.. . .. . .
(1).首先需要声明TextIO的包集
use ieee.std_logic_textio.all; use std.textio.all; (2).声明输入、输出文件 file stim_a:text open read_mode is \; file resp_out:text open write_mode is \; (3).声明读写文件的行变量 variable line_in : line; line; variable line_out : (4).声明用于保存行变量中值的数据变量 variable a_tmp : integer; variable rsp_tmp : integer; (5).最后进行文件的读写。读文件时,先从文件中按行读出一行数据,再将行中的数据读到数据变量中。写文件时,先将数据变量组合成一行,再将行变量中的数据写入文件。需要注意的是只有variable型才是文件存取类型,不能使用signal型。TextIO包集中定义了一些常用的文件操作过程:
readline(file_var, line_var); --用于从文件file_var中读取一行数据到line_var read(line_var, data_var); --用于从line_var中读取数据保存到data_var中 writeline(file_var, line_var); --用于将line_var写入到file_var中 write(line_var, data_var); --用于将data_var写入到line_var中 endfile(file_var); --判断file_var是否已经到文件末尾
2.3.4 属性
属性是指实体、结构体、类型及信号的一些表现特征。大部分信号类属性仅用于仿真,只有两个信号类属性(EVENT和STABLE)是可以综合的。
2.4 运算符
类型 符号 支持的数据对象类型 逻辑运算符 AND, OR, NAND, NOR, XOR, BIT, BOOLEAN, STD_LOGIC XNOR, NOT 关系运算符 算术运算符 =, /= <, >, <=, >= +, -, **, ABS *, /, MOD, REM 任何数据类型 枚举和整数类型以及对应的一维数组 整数类型 整数类型,操作数必须是2的乘方 BIT型一维数组或布尔型一维数组 BIT或一维数组 整数类型 移位运算符 SLL, SRL, SLA, SRA, ROL, ROR 并置运算符 &, (,,,) 符号运算符 正负:+, - ? 关系运算符返回值一定是BOOLEAN类型。关系运算的比较按以下方式进行:从
最左边按位比较,直到发现不相等的元素(位),长数组大于短数组。如: \ > \; \ < \; ? IEEE中只定义了SIGNED和UNSIGNED类型的移位运算,其他类型可以换一种写S. . . . . ..
.. . .. . .
法实现:
A sll 2 描述为 A <= A(5 downto 0) & \; ? 算术运算符中真正能够综合的只有“+”、“-”、和“*”,对于“/”、“mod”、“rem”,在分母为2的乘方次常数时,可以将这些操作用位运算实现,因此是可以综合的。
2.5 VHDL的结构体描述方式
? 行为描述方式是从功能或算法方面对结构体进行描述,不需要包含任何结构信息。其抽象程度高,主要采用函数、过程、进程语句的形式来表示。 ? 数据流方式源于传统的布尔表达式设计思想,通过逻辑或算术表达式对信号或变量
赋值,表示信号在电路中的流动方向。数据流描述主要建立在并行信号赋值语句基础上。这种方式对硬件水平要求高,易于综合,但不利于描述复杂逻辑事件。 ? 结构化方式类似于文本方式的原理图设计。
Fpga相对于CPU模式的信号处理,最大的优势在于它能够并行地处理信号,而并发描述语句是实现并行信号处理的主要底层描述方法。
如果信号在多个进程中被赋值,这些驱动器的结果将会被连接在一起,形成多驱动的情况,应避免出现此情况。 Rtl级的VHDL也就是我们常说的可综合的那部分,所谓的rtl级建模,其实也就是用VHDL语言去描述实时电路的行为。在该层次上,最重要的思想就是“硬件意识”。
2.6 VHDL典型语句 2.6.1 赋值语句中的延时
在VHDL中存在惯性延时和传输延时两种类型。惯性延时的特性与信号脉冲持续时间有关,当信号持续时间小于惯性延时,输出信号将忽略该脉冲的存在。
传输延时不是默认的,必须用关键词TRANSPORT明确说明。传输延时常用于描述总线延时、连接线的延时及ASIC芯片中的路径延时。
不管哪种延时,都是电路固有的特性,与电路的材料、生产工艺、制作温度等相关。带入语句中的延时子句只能根据这些条件去模拟电路的延迟特性,而不能根据语句中的延时时间参数去综合生成具有指定延迟时间的电路。 换言之,延迟子句是不可综合的,综合器会忽略掉该延时。如a <= not b, a <= not b after 2ns, a <= transport not b after 2ns这三条语句最后生成的电路完全一样。
2.6.2 顺序语句
1、使用不带else子句的if语句时,电路可能会引入锁存器。 2、Case语句没有优先级,其when后面的选择值可以选择并列数值,如3|5。 3、For…loop循环语句中,循环变量在使用前不需要声明。循环可以采用递增模式、递减模式以及循环次数围三种方式。如: for 循环变量 in x'RANGE loop 顺序语句; end loop; 4、Wait语句的综合:wait on、wait for和wait语句是不可综合的。Wait until语句只有在条件表达式为时钟的边缘时,如wait until CLOCK = ‘1’时,是可综合的,否则也不可综合。由于在使用wait until语句时,process没有敏感信号列表,所以它必须是process的第一条语句。ISE中的XST,不支持任何wait语句的综合。
S. . . . . ..
.. . .. . .
5、空操作NULL语句类似于计算机汇编语句中的NOP指令,执行该语句不进行任何操作,只是使程序执行下一个操作。
6、变量的综合:根据变量在程序中的使用情况的不同,变量综合后的结果可能是连线(wire)、锁存器(Latch)或寄存器(Register)。在时序电路的顺序描述语句中,如果变量在被赋值之前被读取,那么综合后将产生一个寄存器;如果这种情况发生在组合逻辑电路中,那么综合后将会产生一个锁存器。
7、断言语句(ASSERT): VHDL的断言语句类似于C语言中的断言语句,它是人机对话的一种重要手段。语法结构为:
assert 条件表达式 [report 字符串信息] [severity 级别]; assert语句不描述任何硬件逻辑,通常综合器都会将其忽略,或给出一个警告,但它在系统调试时很有用,可以帮助设计者很快找到设计中出现的问题。
2.6.3 并发语句
1、进程语句
一个进程语句只允许描述对应于一个时钟信号的同步时序逻辑。一个进程中只能描述针对于同一时钟的同步时序逻辑,而异步时序逻辑必须由多个进程来表达。 同步电路可由结构体中的多个进程描述,这是因为进程之间的通信可以通过传递信号和共享变量值来实现。 除非使用决断函数,否则在多个进程中,不允许对同一个信号赋值,但在同一个进程中可以对一个信号多次赋值。 进程部是顺序语句,但进程语句本身是并行语句。
2、并行信号赋值语句
每一个信号赋值语句都相当于一条缩写的进程语句,而这条语句的所有输入信号都被隐性地列入此过程的敏感信号表中。
条件式信号代入语句是有优先级的,即使有多个条件为真,也只有第一个满足条件的表达式会被执行。条件信号赋值语句虽然可以写的很长,实际上是一条语句。 目标信号 <= 表达式1 when 条件1 else 表达式2 when 条件2 else 表达式n; 选择式信号代入语句,多路信号之间是并行的,没有优先级别。 with 选择表达式 select 目标信号 <= 表达式1 when 选择条件1, 表达式2 when 选择条件2, 表达式n when 选择条件n; 3、元件说明和元件例化语句
元件说明语句的功能是将一个现成的设计实体定义或声明为一个元件;元件例化语句,它的功能是将调用的元件或模块的端口信号与结构体中的相应端口信号进行正确的连接,从而达到引用元件的目的。其中标号名(也称为例化名)相当于电路板中的一个插座名。
4、生成语句
生成语句的典型应用是生成存储器阵列和寄存器阵列。从软件运行结果来看,for…
S. . . . . ..
.. . .. . .
generate语句的循环变量虽然有顺序性,但最终结果是完全并行的。
5、块语句
块语句主要用于参数定义和信号的映射,包括Generic和Generic Map语句以及Port和Port Map语句。 使用VHDL进行建模时,一般设计者很少使用块语句,尤其是卫式表达式语句,而且很多商用的综合器不支持块语句。通常情况下,选用进程语句更加高效。从综合的角度看,block语句的存在毫无意义,因为将设计实体划分为多个块,只是形式上的改变并非功能上的改变。
2.7 并发语句的仿真模型
虽然并发语句在综合成底层电路后是并行的,但是并发语句的仿真是使用类似于PC机的处理器进行的,因此,理解并发语句的仿真模型,有助于更好的理解并发语句的执行过程。 VHDL的仿真器是由事件触发的,敏感信号列表中任一信号发生变化,并且变化信号满足触发条件时,仿真器就响应一次事件的处理。 事件的处理一般在离散的仿真时间点开始,仿真器将两个离散的时间点之间的间隔划分为多个增量时间,如图,每个增量时间安排一个任务,一个任务即一个并发描述语句或一个进程语句。这样,设计中的每一个并发描述语句或进程都被安排在一个增量时间中。
当前时间点的并发操作当前时间点内的增量时间离散仿真时间点9989991000D1D2D3…Dn1001当前时间点内的增量时间D1D2D3…图 1 离散仿真时间
事件处理的过程为:
按照增量时间顺序,对所有分配好的任务进行运算,但不进行最终的信号赋值,直到全部并发语句都处于挂起状态。 更新全部信号的值。 信号发生变化后,对信号敏感的进程会重新被触发,仿真器在下一个离散时间点进行事件的处理。
因此,虽然在仿真过程中,任务的处理是按照顺序进行的,但在用户看来,这些处理都是并行完成的。
2.8 子程序
子程序包含函数(Function)和过程(Procedure)两种,可以被反复调用,但是是非重入的程序。并且支持重载。子程序中出现的wait语句、信号声明和元件调用语句是不可综合的。 过程容易引起一些副作用,而且包含过程语句的工程也很难调试和维护,一般不用。
2.9 状态机FSM(Finite State Machine)
Moore型状态机的输出只与模块的当前状态有关;Mealy型状态机的输出与模块的当前状态和当前的输入信号都有关系。
? 工程设计中,建议使用枚举的方式定义状态机工作的不同状态,以便增强可读性。
S. . . . . ..
.. . .. . .
编码的过程中要注意,用枚举方式定义的状态只能用同类型的枚举数据赋值,而不能直接用数值赋值。采用枚举时,FPGA的综合器通常采用独热编码OHE(One Hot Encoding)的方式对枚举量进行编码。 ? 通常建议工程师选用多进程的描述方式,而不是单进程的方式。多进程的描述结构
通常将时序逻辑、组合逻辑甚至输出逻辑分布在不同的进程中描述。这种结构可以减少代码长度、增强代码的可读性,同时省去不必要的寄存器输出。
如果Moore型状态机的输出要寄存,则需要将输出控制语句用一个时序进程描述,但是要注意,寄存输出信号会增加一个周期的时延,如果要去除这一个周期的延时,则在进程中可以使用NEXT_STATE代替CURR_STATE做控制。 如果Mealy型状态机的输出要寄存,则需要保证输出信号的逻辑是完全同步的。一种好的方法是,在结构体中定义一组信号,用这一组信号将输出值传递到输出端口。
S. . . . . ..
XilinxFPGA设计基础(VHDL版) - 图文
![](/skin/haowen/images/icon_star.png)
![](/skin/haowen/images/icon_star.png)
![](/skin/haowen/images/icon_star.png)
![](/skin/haowen/images/icon_star.png)