1 LIBRARY library_name; 2 USE library_name.package_name.package_parts;
ENTITY entity_name IS GENERIC(参数名:数据类型:=设定值 ...); PORT (port_name1: port_mode data_type; port_name2: port_mode data_type; ...); END entity_name;
OUT
模式无法回读到电路内部,Buffer
模式可以,但是 buffer 不能连接到其他类型的端口,即不能把该模块作为子模块例化,一般使用中间缓冲信号,解决回读问题。1 ARCHITECTURE 结构体名 OF 实体名 IS 2 说明语句 3 BEGIN 4 功能描述语句 5 ...... 6 END 结构体名;
三种数据对象,声明信号 signal
1 signal name : type [range] [:= initial_vaule];
还有 常量 constant 声明:
1 constant name : type := value;
还有 变量 variable 声明
1 variable name : type [range] [:= initial_vaule];
bit & bit_vector
1 signal x : bit; 2 signal y : bit_vector (3 DOWNTO 0); 3 4 x<='1'; 5 y<="0011"
std_logic & std_logic_vector
Boolean
TIME
1 CONSTANT t_delay:TIME:=30 ns
integer
real
character & string
1 --integer range 2 TYPE student IS RANGE 0 TO 100; 3 4 --enumerated(枚举) 5 TYPE state IS (state0,state1,state2,state3); 6 7 --Array 8 TYPE matrix IS ARRAY (0 TO 3) OF std_loogic_vector;
有时在定义端口时,需要把端口定义为矢量阵列。但是在 Entity
中不允许使用 type
定义,所以我们必须自己定义包集 (package),然后使用 use
声明使用该用户自定义的包集,最后才能在 Entity 中使用这种新定义的类型。
在 VHDL 中,不同类型的数据是不能直接进行算术/逻辑运算的,所以必要时必须进行类型转换操作。
函数名称 | 函数功能 |
TO_STDLOGICVECTOR() | 由BIT_VECTOR转为STD_LOGIC_VECTOR型 |
TO_BITVECTOR() | 与上相反 |
TO_STDLOGIC() | 由BIT型转为STD_LOGIC型 |
TO_BIT | 与上相反 |
CONV_STD_LOGIC_VECTOR(a,位长) | 由整型转为STD_LOGIC_VECTOR型 |
CONV_INTEGER() | 与上相反 |
VHDL 语法虽然枯燥无味,但是只有对数据类型、运算操作符及其属性有了深刻认识,才能写出高质量和高效率的代码。
VHDL提供了6种预定义的预算符:
赋值 assignment
逻辑 logical
算术 arithmetic
关系 relational
并置 concatenation
assignment
一共三种:
logical
进行逻辑运算,操作数必须是 bit, std_logic, std_ulogic 类型或者他们的扩展,即 bit_vector, std_logic_vector, std_ulogic_vector 类型
arithmetic
comparison
一共有6种:= /= > < >= <=
concatenation
用于位的拼接。
HDL对应的是硬件电路,而硬件电路时刻工作,所以它的代码是并发执行的。只有process、function、procedure中的代码是顺序执行的,而这些模块作为共同整体时,它们之间也是并行的。
在并发代码中可以使用下列各项:
when
when/else syntax:
1 assignment WHEN condition ELSE 2 assignment WHEN condition ELSE 3 ...;
with/select/when syntax:
1 WITH 选择信号表达式 SELECT 2 assignment WHEN value, 3 assignment WHEN value, 4 ...;
generate
常和 for/if 一起使用,因为描述对象是电路,电路是固定的,功能也是静态的,所以一种用途是生成相同元件的多次实例化,第二种用途是生成结构相同的多次赋值、组合逻辑。两种用途目的都是减少代码量,增加可读性和可维护性
block
为了把较长的代码分成几个较小的区域,便于阅读和维护,在每个块内都能对局部信号、数据类型和常量定义
1 块标号:BLOCK[(块保护表达式)] 2 [说明部分] 3 BEGIN 4 并行语句 5 END BLOCK [块标号];
VHDL 本质是并发执行的代码,但是在 process
, function
, procedure
内部的代码是顺序执行的,当它们作为一个整体时,相互之间也是并发执行的。
顺序代码并非只能与时序逻辑 (sequential logic
) 对应,同样也可以用它们来实现组合逻辑 (combinational logic
)。
这里主要讨论顺序代码,也就是这 3 个块中的代码,包括 if
, wait
, case
, loop
语句。
process
在一个结构体中允许放置多个进程语句,这些进程也都是并行的,每个进程内部由一系列顺序语句构成
1 [进程标号:] PROCESS [敏感信号参数表] IS 2 [进程说明部分] 3 BEGIN 4 顺序描述语句 5 END PROCESS [进程标号];
1 IF conditions THEN assignment; 2 ELSIF conditions THEN assignments; 3 ...... 4 ELSE assignments; 5 END IF;
case 和 when 的区别在于,case 允许在每个测试条件下执行多个赋值操作,而 when 只能执行一个赋值操作。
1 CASE 表达式 IS 2 WHEN value => assignment; 3 WHEN value => assignment; 4 ... 5 WHEN OTHERS => assignments; 6 END CASE;
常用格式有两种
loop
1 [loop标号:] LOOP 2 顺序语句; 3 END LOOP[loop 标号];
for/loop
1 [LOOP标号:] FOR 循环变量 IN 循环参数范围 LOOP 2 顺序语句; 3 END LOOP[LOOP 标号];
LOOP不能自己跳出循环,也不能自己跳到另一个循环,有时候需要加入其它控制语句
1 [标识:] EXIT [LOOP 标识] [WHEN condition]; 2 3 [标识:] NEXT [另一个LOOP 标识] [WHEN condition];
/*****注释*****/
*一组在逻辑上互相独立的程序或程序段在执行过程中,其执行时间在客观上互相重叠