vhdl 语法总结5
六、 包集元件
1. 包集
经常使用的代码通常以component,或procedure的形式编写。这些代码被添加到package中,并在最后编译到目标library中。Package中还可以包含TYPE和CONSTANT的定义。语法格式如下:
package package_name is
(declaration)
end package_name;
package body package_name is
( and procedure deion)
end package_name;]
Example6.1 简单的程序包
library ieee;
use ieee.std_logic_1164.all;
———————————————————————-
package my_package is
type state is (st1, st2, st3, st4);
type color is (red, green, blue);
constant vec: std_logic_vector(7 downto0) := “1111_1111″;
end my_package;
Example6.2 内部包含函数的package
library ieee;
use ieee.std_logic_1164.all;
———————————————————————-
package my_package is
type state is (st1, st2, st3, st4);
type color is (red, green, blue);
contant vec: std_logic_vector(7 downto 0) := “1111_1111″;
positive_edge(signal s: std_logic) return boolean;
end my_package;
———————————————————————-
package body my_package is
positive_edge(signal s: std_logic) return booleanis
begin
return(s’event and s = ‘1′);
end positive_edge;
end my_package;
为了在QUARTUS II中使用这些package,要在当前project目录下新建一个文件夹,不妨起名为user_lib,把要编译的package放进此文件夹中,然后在AssignmentsàSettingàLibrary中设置相应的目录即可。在VHDL代码中要使用这些package,要在主程序中加入如下代码:
use work.package_name.all;
2. 元件component
一个元件是一段结构完整的常用代码,包括声明,实体和结构体,使用component可以使代码具有层次化的结构。
元件声明:
component comp_name is
port (
port_name1: signal_mode signal_type;
port_name2: signal_mode signal_type;
…
);
end component;
元件实例化:
label: comp_name port map (port_list);
元件的声明可以放在主代码中,即调用该元件的代码;或者将元件的声明放到package中,使用时在主代码中增加一条USE语句即可,这样避免了主代码中每实例化一个元件就要声明一次的麻烦。
3. 端口映射
在元件实例化过程中,有两种方法实现元件端口的映射:位置映射和名称映射。
component inverter is
port ( a: in std_logic;
b: out std_logic
);
end component;
…
U1: inverter port map(x, y);
此处采用的是位置映射法,x对应a,y对应b。
U1: inverter port map(a => x, b=> y);
此处采用的是名称映射法。对于不需要使用的端口可以断开,只需使用关键字open即可,但是输入端口不能指定为空连接。比如:
U2: my_circuit port map(x => a, y => b, w => open, z => b);
4. GENERIC参数映射
元件实例化时如果要通过GENERIC传递参数,则需进行GENERIC参数的映射。元件实例化的格式如下:
label: comp_name generic map(param_list) port map(port_list);
七、 函数和过程
和procedure统称为子程序,内部包含的都是顺序描述的VHDL语言.
八、 有限状态机
状态机的设计包含两个主要过程:状态机建模和状态的编码。
1.有限状态机的建模
有限状态机通常使用CASE语句来建模,一般的模型由两个进程组成,一个进程用来实现时序逻辑电路,另一个进程用来实现组合逻辑电路。
模型的构建:
(1) 分析设计目标,确定有限状态机所需的状态,并绘制状态图;
(2) 建立VHDL实体,定义枚举类型的数据类型;
(3) 定义状态变量,其数据类型为前面所定义的枚举数据类型;例:
TYPE STATE IS (STATE0, STATE1, STATE2, …);
SIGNAL CR_STATE, NEXT_STATE: STATE;
(4) 建立时序逻辑电路的实现进程;例:
PROCESS (CLK,RESET)
BEGIN
IF RESET=’1’ THEN
CR_STATE <= STATE0;
ELSIF CLK’EVENT AND CLK=’1’ THEN
CR_STATE <= NEXT_STATE;
END IF;
END PROCESS;
(5) 使用CASE语句建立组合逻辑电路的实现进程。例:
PROCESS(CR_STATE,INPUT)
BEGIN
CASE CR_STATE IS
WHEN STATE0 =>
IF INPUT = … THEN
NEXT_STATE <= STATE1;
END IF;
WHEN STATE1 =>
…
WHEN OHTERS => NEXT_STATE <= STATE0;
END CASE;
END PROCESS;
2.状态编码
状态编码包括二进制编码、枚举类型的编码和一位有效编码。利用一位有效编码(One-hot encoding)可以创建更有效地在FPGA结构中实现的有限状态机。每个状态可以使用一个触发器来创建状态机,并且可以降低组合逻辑的宽度。
有限状态机的可能状态由枚举类型所定义,即:
TYPE type_name IS(枚举元素1, 枚举元素2, …., 枚举元素n);
这个定义是通用的格式,时必须的。在该枚举类型定义语句之后,就可以声明信号为所定义的枚举类型:
TYPE STATE_TYPE IS(S1, S2, S3, S4, S5, S6, S7);
SIGNAL CS,NS: STATE_TYPE;
为了选择有限状态机的状态编码方式,需要指定状态矢量。也可以通过综合工具指定编码方式。当在程序中指定编码方式时,可以在枚举类型定义语句后指定状态矢量,例如,
定义二进制编码的状态矢量的语句是:
ATTRIBUTE ENUM_ENCODING: STRING;
ATTRIBUTE ENUM_ENCODING OF STATE_TYPE:TYPE IS “001 010 011 100 101 110 111”;
定义一位有效编码的状态矢量的语句为:
ATTRIBUTE ENUM_ENCODING:STRING;
ATTRIBUTE ENUM_ENCODING OF STATE_TYPE:TYPE IS ”0000001 0000010 0000100 0001000 0010000 0100000 1000000”;