E N D
第一部分 VHDL基础 电工电子实验中心 2006-4-17
第一章 概述 • 随着集成电路制造技术的发展,使得出现了大规模、超大规模PLD(Programmatic Logic Device,可编程逻辑器件)的出现,对传统的数字系统的设计方法提出了巨大的挑战,同时也促成了EDA(Electronic Design Automation,电子设计自动化)的技术诞生和发展。它主要是以HDL(Hardware Description Language,硬件描述语言)来表达设计意图,以CPLD(Complex Programmable Logic Device)或FPGA(Field Programmable Gate Array)作为硬件实现载体,以计算机为设计开发工具,以EDA软件为开发环境的现代电子设计方法。 • 目前成为IEEE(The Institute of Electrical and Electronics Engineers,美国电气与电子工程师学会)HDL语言标准的有:ALTERA公司的VHDL、Candence公司的从C语言发展来得Verilog HDL。 • VHDL的英文全名是VHSIC(Very High Speed Integrated Circuits)Hardware Description Language,于1983年由美国国防部(The United States Department of Defense )提出,并由IEEE进一步发展,在1987年12月作为IEEE-STD—1076标准发布,93年被更新卫IEEE-STD-1164标准,目前已经被广泛应用。
第二章 VHDL程序的基本结构 • 例1 一个2选1得选择器得逻辑描述 • LIBRARY IEEE; --库说明语句 • USE IEEE.STD_LOGIC_1164.ALL; --程序包说明语句 • ENTITY MUX_21 IS • PORT(A,B,SEL : IN STD_LOGIC; ――实体部分 • Y : OUT STD_LOGIC); • END; • ARCHITECTURE BEV OF MUX_21 IS • BEGIN • PROCESS(SEL,A,B) • BEGIN • IF (SEL = '0' ) THEN • Y <= A; ――结构体部分 • ELSE • Y <= B; • END IF; • END PROCESS; • END;
2.1 实体:集成电路的外部说明(如图黑色框外面得管脚说明); 实体一般格式为: ENTITY实体名 IS PORT(端口名{,端口名}:端口模式 数据类型; 端口名{,端口名}:端口模式 数据类型); END; IEEE1076标准包中定义了以下常用的端口模式: IN输入,只可以读 OUT输出,只可以写 BUFFER输出(构造体内部可再使用) INOUT双向,可以读或写
2.2 结构体:集成电路的内部实现(图示黑色框内部得具体电路)。 2.2.1 结构体一般格式: • ARCHITECTURE结构体名 OF 实体名 IS • [结构体说明部分]; • BEGIN • [并发处理语句]; • END结构体名; • 说明语句 • 说明语句用于对结构体内部使用的信号、常数、数据类型和函数进行定义。 • 并发处理语句 • 语句同时被执行,没有位置先后之分。
2.2.2 结构体的3种描述方法:行为描述、数据流描述和结构化描述 2.2.3 结构体的子结构描述 在规模较大的电路设计中,全部电路都用唯一的一个模块来描述是非常不方便的。为此,电路设计者总希望将整个电路分成若干个相对比较大的模块来进行电路的描述。这样,一个构造体可以用几个子结构,既相对比较独立的几个模块来构成。VHDL语言可以有以下三种形式的子结构描述语句:
2.3.3.1 子程序 • VHDL提供两种子程序:函数(FUNCTION)和过程(PROCEDURE) 过程 过程的定义形式如下: PROCEDURE<过程名称><接口表> IS BEGIN <过程语句部分>; END过程名称;
函数 函数的定义形式如下: FUNCTION<函数名称><接口表>RETURN<数据类型>IS [定义语句]; BEGIN <函数语句部分>; END 函数名称; 下面是一个比较器的例子: FUNCTION max(a, b: INTEGER) RETURN INTEGER IS BEGIN IF (a>=b)THEN RETURN a; ELSE RETURN b; END IF; END max; 一个函数定义好后,可以在其它地方调用。
2.3.3.2 BLOCK语句 • 采用BLOCK语句描述局部电路的书写格式如下: • 块结构名: • BLOCK • BEGIN • … • … • … • END BLOCK块结构名;
2.3.3.3进程语句(PROCESS) • 采用PROCESS语句描述局部电路的书写格式如下: • [进程名]:PROCESS(信号1,信号2…) • BEGIN • … • … • … • END PROCESS;
2.3库(LIBRARY) • 库是经编译后的数据的集合,用来存放程序包定义、实体定义、结构体定义和配置定义,使设计者可以共享已经编译过的设计结果。在VHDL语言中,库的说明总是放自在设计单元的最前面: • 库说明语句的语法形式为: • LIBRARY库名; --说明使用什么库 • USE包集合名; --说明使用库中哪一个包集合
这样一来,在设计单元内的语句就可以使用库中的数据。VHDL语言允许存在多个不同的库,但各个库之间是彼此独立的,不能互相嵌套。主要有:STD,WORK,IEEE,用户自定义库。这样一来,在设计单元内的语句就可以使用库中的数据。VHDL语言允许存在多个不同的库,但各个库之间是彼此独立的,不能互相嵌套。主要有:STD,WORK,IEEE,用户自定义库。 • 其中最常用的是IEEE库:IEEE库中包含IEEE标准的程序包,包括STD_LOGIC_1164、STD_LOGIC_UNSIGNED、NUMERIC_BIT、 NUMERIC_STD以及其他一些程序包。其中STD_LOGIC_1164是最主要的程序包,大部分可用于可编程逻辑器件的程序包都以这个程序包为基础。
第三章 VHDL的数据类型和运算操作符 3.1 VHDL语言的对象 • 1)常量:一般格式: • CONSTANT常数名:数据类型:=表达式; • 例:CONSTANT Vcc: REAL: =5.0;
2)变量: • 一般格式: • VARIABLE变量名 数据类型 约束条件:=表达式; • 例:VARIABLE count: INTEGER RANGE 0 TO 255 := 10; • —定义计数变量范围
3)信号:用于连接线。 • 一般格式:SIGNAL信号名: 数据类型; • 信号除了没有方向的概念以外几乎和端口概念一致。 • 例:SIGNAL q_out : STD_LOGIC :=’0’; • q_out <= q_out + 1 AFTER 5ns;
信号与变量的区别: • 信号赋值可以有延迟时间,变量赋值无时间延迟; • 信号除当前值外还有许多相关值,如历史信息等,变量只有当前值; • 进程对信号敏感,对变量不敏感; • 信号可以是多个进程的全局信号,但变量只在定义它之后的顺序域可见; • 信号可以看作硬件的一根连线,但变量无此对应关系。
3.2 VHDL语言的数据类型 在VHDL语言中,信号、变量、常数都是需要指定数据类型的,VHDL提供的数据类型可归纳如下:
3.3 VHDL语言的运算操作符 • 如同别的程序设计语言一样,VHDL中的表达式是由运算符将基本元素连接起来的式子。VHDL的运算符可分为4组: • 算数运算符、关系运算符、逻辑运算符和其他运算符以及它们的优先级别如下表所示:
对常用的运算符进行说明: • 通常,在一个表达式中有两个以上的算符时,需要使用括号将这些操作分组。如果一串操作的算符相同,且是AND、OR、XOR这三个算符中的一种,则不需要使用括号,如果一串操作中的算符不同或有除这三种算符之外的算符,则必须使用括号。如: • a AND b AND c AND d • (a OR b) NAND c • 关系运算符=、/=、<、<=和>=的两边类型必须相同,因为只有相同的数据类型才能比较,其比较的结果为BOOLEAN型。 • 连接运算符用于一维数组,“&”符号右边的内容连接之后形成一个新的数组,也可以在数组后面连接一个新的元素,或将两个单元素连接形成数组。连接操作常用于字符串。
3.4 VHDL语句。 • VHDL语句是并发语言,大部分语句是并发执行的。但在进程、过程、块语句和子程序(包括函数)中,还有许多顺序执行语句,按出现的次序执行各条语句。下面介绍几种常用语句。
1. IF语句。IF语句是根据所制定的条件来确定执行那些语句。 • 基本结构: • IF 条件 THEN • 顺序处理语句; • ELSE • IF条件 THEN • 顺序处理语句; • ELSIF条件 THEN • 顺序处理语句; • END IF; • END IF;
2. CASE语句。 其书写格式为: • CASE表达式 IS • WHEN条件表达式 => 顺序处理语句; • END CASE; • 条件句中的“=>”不是操作符,只相当于“THEN”作用。
例子:用两种语句实现3-8译码器。结构体是行为描述:按算法的路径来描述。所以行为描述在EDA工程中称为高层次描述或高级描述。例子:用两种语句实现3-8译码器。结构体是行为描述:按算法的路径来描述。所以行为描述在EDA工程中称为高层次描述或高级描述。 • LIBRARY IEEE; --库文件声明 • USE IEEE.STD_LOGIC_1164.ALL; • ENTITY IF_38 IS --实体 • PORT(A,B,C,G1,G2A,G2B : IN STD_LOGIC; -- 端口说明 • Q_OUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); • END; • ARCHITECTURE BEV OF IF_38 IS -- 结构体? • SIGNAL INPUT : STD_LOGIC_VECTOR(2 DOWNTO 0); -- 声明一个信号 • BEGIN • INPUT <= C&B&A; -- 位信号连接成位向量 • PROCESS(G1,G2A,G2B,INPUT) -- 进程开始,捕捉这四个信号变化。 • BEGIN --进程是一个死循环,由敏感信号的变化来启动进程。 • IF(G1='1' AND G2A = '0' AND G2B = '0') THEN -- 条件使能判断 • CASE INPUT IS --译码开始 • WHEN "000" => Q_OUT <= "11111110";-- 注意IF和CASE语句的结构。 • WHEN "001" => Q_OUT <= "11111101"; • WHEN "010" => Q_OUT <= "11111011"; • WHEN "011" => Q_OUT <= "11110111"; • WHEN "100" => Q_OUT <= "11101111"; • WHEN "101" => Q_OUT <= "11011111"; • WHEN "110" => Q_OUT <= "10111111"; • WHEN "111" => Q_OUT <= "01111111"; • WHEN OTHERS => Q_OUT <= "XXXXXXXX"; • END CASE; • ELSE • Q_OUT <= "11111111"; • END IF; • END PROCESS; • END;
3. 通用模块、元件调用语句(COMPONENT),端口映射语句(PORT MAP)。(这个不是顺序语句,是并行语句)。 • 例子:用半加器构成全加器。 • 半加器的结构体是数据流描述:描述了数据流程的运动路径、运动方向和运动结果(布尔方程)。 • 全加器的结构体是结构化描述,由子模块来搭建。
半加器 • LIBRARY IEEE; • USE IEEE.STD_LOGIC_1164.ALL; • ENTITY H_D IS --半加器 • PORT(A,B : IN STD_LOGIC; • S,CO : OUT STD_LOGIC); • END; • ARCHITECTURE D_STREAM OF H_D IS • SIGNAL C,D : STD_LOGIC; • BEGIN --结构体为数据流描述 • C <= A NAND B; • D <= A OR B; • CO <= NOT C; • S <= C AND D; • END;
全加器 • LIBRARY IEEE; • USE IEEE.STD_LOGIC_1164.ALL; • ENTITY H_D_F_D IS --全加器 • PORT(A_F,B_F,CIN: IN STD_LOGIC; • S_F,CO_F : OUT STD_LOGIC); • END; • ARCHITECTURE STRCTURE OF H_D_F_D IS • COMPONENT H_D --半加器模块声明 • PORT(A,B : IN STD_LOGIC; • S,CO : OUT STD_LOGIC); • END COMPONENT; • SIGNAL E,F,G: STD_LOGIC; • BEGIN --结构体为结构化描述 • U1: H_D PORT MAP(A => A_F,B => B_F,S => E,CO => F); • --端口映射,元件例化。 • U2: H_D PORT MAP(A => CIN,B => E,S => S_F,CO => G); • CO_F <= F OR G; • END;
4. FOR ,WHILE ,NEXT,EXIT语句。 • Next,exit语句类似于C中的continue和break; • FOR 语句一般格式: • [ LOOP标号:] FOR循环变量IN起始值TO 结束值LOOP • 顺序语句; • NEXT [LOOP 标号] [WHEN 条件表达式]; • EXIT [LOOP 标号] [WHEN 条件表达式]; • END LOOP [LOOP标号];
WHILE语句的一般格式: • [ LOOP标号:]WHILE条件表达式 LOOP • 顺序语句; • NEXT [LOOP 标号] [WHEN 条件表达式]; • EXIT [LOOP 标号] [WHEN 条件表达式]; • END LOOP [LOOP标号];
下面以FOR语句举例: • 两个4位矢量的比较程序。 • LIBRARY IEEE; • USE IEEE.STD_LOGIC_1164.ALL; • ENTITY COMP IS • PORT(A,B : IN STD_LOGIC_VECTOR(3 DOWNTO 0); • C_B,C_E,C_L : OUT STD_LOGIC); • END; • ARCHITECTURE BEV OF COMP IS • SIGNAL C_B_C,C_E_C,C_L_C:STD_LOGIC; • BEGIN • PROCESS(A,B) • BEGIN • JUDGE: FOR I IN 3 DOWNTO 0 LOOP • IF (A(I) > B(I) ) THEN --从高位开始比较,大于便退出。 • C_B <= '1'; • C_E <= '0'; • C_L <= '0'; • EXIT JUDGE; • ELSIF (A(I) < B(I)) THEN -- --从高位开始比较,葱小于便退出。 • C_B <= '0'; • C_E <= '0'; • C_L <= '1'; • EXIT JUDGE; • ELSE -- 只有在全相等的时候才输出。 • C_B_C <= '0'; • C_E_C <= '1'; • C_L_C <= '0'; • END IF; • END LOOP; • END PROCESS; • C_B <= C_B_C; • C_E <= C_E_C; • C_L <= C_L_C; • END;
时序电路设计中对时钟的处理。 • 对于常见的触发方式的描述: • PROCESS(clock) • BEGIN • 对触发方式的描述 • END PROCESS; • 5.1 上升沿触发: • IF CLOCK’EVENT AND CLOCK = ‘1’ THEN • ……. • END IF; • 或 • IF RISING_EDGE(CLOCK) THEN • ……. • END IF;
5.2 下降沿触发: • IF CLOCK’EVENT AND CLOCK = ‘0’ THEN • ……. • END IF; • 5.2 高电平触发: • WAIT UNTILL CLOCK = ‘1’; • 5.3 低电平触发: • WAIT UNTILL CLOCK = ‘0’;
例子:带有使能端,以及异步清零端的10进制计数器。例子:带有使能端,以及异步清零端的10进制计数器。 • LIBRARY IEEE; • USE IEEE.STD_LOGIC_1164.ALL; • USE IEEE.STD_LOGIC_UNSIGNED.ALL; ――为了实现向量的加法运算。 • ENTITY COUNT_10 IS • PORT(CLK ,EA,RST : IN STD_LOGIC; • Q_OUT : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)); • END; • ARCHITECTURE BEV OF COUNT_10 IS • SIGNAL C_COUNT : STD_LOGIC_VECTOR(3 DOWNTO 0); • BEGIN • PROCESS(CLK,EA,RST) • BEGIN • IF(RST = '1' ) THEN ――判断清零端 • C_COUNT <= "0000"; • ELSIF(EA = '1') THEN ―― 判断使能端 • IF ( CLK'EVENT AND CLK = '1') THEN ――RST=’1’ ,EA =’1’ 开始记数 • IF (C_COUNT = "1001") THEN ―― 如记到9后,输出全零 • C_COUNT <= "0000"; • ELSE ―― 否则,继续累加。 • C_COUNT <= C_COUNT + 1; • END IF; • END IF; • END IF; • END PROCESS; • Q_OUT <= C_COUNT; • END;