This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
第 4章 VHDL 设计基础
VHDL 语言可以用于描述任何数字逻辑电路与系统,可以在各种开发平台上使用,包括标准 PC 机和工作站环境,它支持自顶向下 (Top-to-Down) 设计和自底向上 (But
类属参数说明语句是以关键词 GENERIC引导一个类属参数表,在表中提供时间值或数据线的宽度等静态信息,类属参数表说明用于设计实体和其外部环境通信的参数和传递信息,类属在所定义的环境中的地位与常数相似,但性质不同。常数只能从设计实体内部接受赋值,且不能改变,但类属参数却能从设计实体外部动态地接受赋值,其行为又类似于端口 PORT ,设计者可以从外面通过类属参数的重新定义,改变一个设计实体或一个元件的内部电路结构和规模。
LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY andn IS GENERIC ( n : INTEGER ); -- 定义类属参量及其数据类型 PORT(a : IN STD_LOGIC_VECTOR(n-1 DOWNTO 0);-- 用类属参量限制矢量长度 c : OUT STD_LOGIC); END; ARCHITECTURE behav OF andn IS BEGIN PROCESS (a) VARIABLE int : STD_LOGIC; BEGIN int := '1'; FOR I IN a'LENGTH - 1 DOWNTO 0 LOOP IF a(i)='0' THEN int := '0'; END IF; END LOOP; c <=int ; END PROCESS; END;
3) 端口表( PORT )
端口表是对设计实体外部接口的描述,即定义设计实体的输入端口和输出端口。端口即为设计实体的外部引脚,说明端口对外部引脚信号的名称、数据类型和输入输出方向。端口表的组织结构必须有一个名字、一个通信模式和一个数据类型。在使用时,每个端口必须定义为信号( signal ),并说明其属性,每个端口的信号名必须唯一,并在其属性表中说明数据传输通过该端口的方向和数据类型。
端口表的一般格式为: PORT ( [SIGNAL] 端口名: [ 方向 ] 子类型标识 [BUS]
[ : =静态表达式 ] ,…);
(1) 端口名
端口名是赋予每个外部引脚的名称。在 VHDL 程序中有一些已有固定意义的保留字。
除开这些保留字,端口名可以是任何以字母开头的包含字母、数字和下划线的一串字符。
为了简便,通常用一个或几个英文字母来表示。如: D 、 Y0 、 Y1等。而 1A 、 Begin 、 N#3 是非法端口名。
定义语句位于 ARCHITECTURE 和 BEGIN 之间,用于对构造体内部所使用的信号、常数、数据类型和函数进行定义,结构体的信号定义和实体的端口说明一样,应有信号名称和数据类型定义,但不需要定义信号模式,不用说明信号方向,因为是结构体内部连接用信号。
(3) 并行处理语句
并行处理语句位于语句 BEGIN 和 END 之间,这些语句具体地描述了构造体的行为。在刚开始,设计者往往采用行为描述法。
(1) 行为描述 :不包括任何电路的结构信息 ,仅描述输入输出间的逻辑关系 (如真值表 )
【例 5-7】ARCHITECTURE behavior OF fulladd_v2 ISsignal temp_sum: STD_LOGIC_VECTOR(2 dow
nto 0);BEGIN temp_sum<=Ci&Ai&Bi;process(temp_sum) begin CASE temp_sum is when "000" => S<='0';Co<='0'; when "001" => S<='1';Co<='0';… when "111" => S<='1';Co<='1'; when others =>null; end case; end process;END ARCHITECTURE behavior;
例 4-4‘1’ 个数计数器结构体的行为描述
ARCHITECTURE behavior OF ones_cnt ISBEGINPROCESS(A) VARIABLE NUM: INTEGER range 0 to 3;BEGIN NUM:=0;FOR I IN 0 TO n LOOP IF A(I) = ‘1’THEN NUM:=NUM + 1; END IF; END LOOP; CASE NUM IS WHEN 0 => C<=”00”; WHEN 1 => C<=”01”; WHEN 2 => C<=”10”; WHEN 3 => C<=”11”; END CASE;END PROCESS;END behavior;
LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;ENTITY fualladd_v3 ISPORT (Cin,Ain,Bin:IN STD_LOGIC; Si,Cout:OUT STD_LOGIC);END fualladd_v3;ARCHITECTURE structural OF fualladd_v3 IS COMPONENT halfadd_v1 PORT (Ai,Bi:IN STD_LOGIC; S,Co:OUT STD_LOGIC); END COMPONENT;COMPONENT or_2 PORT (Ai,Bi:IN STD_LOGIC; C:OUT STD_LOGIC); END COMPONENT;SIGNAL C1,C2,C3:STD_LOGIC;BEGINu0:halfadd_v1 PORT MAP(Ain,Bin,C1,C2);u1:halfadd_v1 PORT MAP(C1,Cin,Si,C3);u2:OR_2 port map(c2,c3,cout);END ARCHITECTURE structural;
例 4-7 所示的结构体中,设计任务的程序包内定义了一 2 输入或门 OR2 和一个半加器 halfadd_v1 元件( COMPONENT )。把该程序包编译到库中,可通过 USE 从句来调用这些元件,并从 WORK 库中的 Gatespkg 程序包里获取标准化元件。
PACKAGE HANDY IS -- 程序包首开始 SUBTYPE BITVECT3 IS BIT_VECTOR(0 TO 2);-- 定义子类型 SUBTYPE BITVECT2 IS BIT_VECTOR(0 TO 1); FUNCTION MAJ3(X:BIT_VECTOR(0 TO 2)) RETURN BIT; -- 定义
函数首 END HANDY; PACKAGE BODY HANDY IS FUNCTION MAJ3(X:BIT_VECTOR(0 TO 2)) -- 定义函数体 RETURN BIT IS BEGIN RETURN (X0 AND X1) OR (X0 AND X2) OR (X1 AND X2); END MAJ3; END HANDY; -- 程序包首结束
FOR ALL:EDGE_TRIGGERED_D USE ENTITY EDGE_TRIG_D(BEHAVIOR); -- 模块指针COMPONENT INVG PORT(I:IN STD_LOGIC; O:OUT STD_LOGIC);END COMPONENT;FOR ALL:INVG USE ENTITY INV(BEHAVIOR); -- 模块指针COMPONENT AND3G PORT(I1,I2,I3:IN STD_LOGIC; O:OUT STD_LOGIC);END COMPONENT;FOR ALL:AND3G USE ENTITY AND3(BEHAVIOR); -- 模块指针
COMPONENT OR2G PORT(I1,I2:IN STD_LOGIC; O:OUT STD_LOGIC);END COMPONENT;FOR ALL:OR2G USE ENTITY OR2(BEHAVIOR); -- 模块指针BEGIN C1: EDGE_TRIGGERED_D PORT MAP(CLK,X,R,Y0,NY0); C2: EDGE_TRIGGERED_D PORT MAP(CLK,ONE,R,Y1,OPEN); C3:INVG PORT MAP(X,NX); C4:AND3G PORT MAP(X,Y0,Y1,A0); C5:AND3G PORT MAP(NY0,Y1,NX,A1); C6:OR2G PORT MAP(A0,A1,Z);END STRUCTURAL;
SIGNAL 信号名:数据类型、约束条件 :=表达式; 举例如下: SIGNAL sys_clk0 : BIT := '0' ; —系统时钟变量 SIGNAL sys_out : BIT := '1' ; —系统输出状态变量 SIGNAL address : bit_vector(7 downto 0) ;—地址宽度
在 VHDL 语言中,可由用户自定义的数据类型有:枚举类型( ENUMERATED TYPE );整数类型( INTEGER TYPE );实数( REAL TYPE )、浮点数( FLOATING TYPE )类型;数组类型( ARRAY TYPE );存取类型( ACCESS TYPE );文件类型( FILE TYPE );记录类型( RECORD TYPE );时间类型( TIME TYPE )。
(1) 枚举类型
它是 VHDL 语言中最重要的一种用户自定义数据类型,在以后的状态机等应用中有重要作用。在数字逻辑电路中,所有数据都是用‘ 1’ 或者‘ 0’来表示的,但人们在考虑逻辑关系时,只有数字往往是不方便的。枚举类型实现了用符号代替数字。例如:在表示一周七天的逻辑电路中,往往可以假设“ 000” 为星期天,“ 001” 为星期一,这对阅读程序不利。为此,可以定义一个叫“ WEEK” 的数据类型,例如: TYPE WEEK IS ( SUN , MON , TUE , WED , THU , FRI , SAT );由于上述的定义,凡是用于代表星期二的日子都可以用 TUE来代替,这比用代码“ 010” 表示星期二直观多了,使用时也不易出错。枚举类型数据格式如下: TYPE 数据类型名 IS (元素,元素,…);
(2) 整数类型和实数类型
整数类型在 VHDL 语言中已存在,这里指的是用户自定义的整数类型,实际上可以认为是整数的一个子类。例如,在一个数码管上显示数字,其值只能取0-9 的整数。如果由用户定义一个用于数码显示的数据类型,那么可以写为: TYPE DIGIT IS INTEGER 0 TO 9 ; 同理,实数类型也如此,例如: TYPE CURRENT IS REAL RANGE -1E4 TO 1E4 ; 据此,可以总结出整数或实数用户自定义数据类型的格式为: TYPE 数据类型名 IS 数据类型定义约束范围;
逻辑运算符的书写格式为:①A<=B AND C AND D AND E ; -- 用 VHDL 程序规范书写的
语句;
A=B·C·D·E --等效的布尔代数书写的逻辑方程;
②A<=B OR C OR D OR E ; -- 用 VHDL 程序规范书写的语句;
A=B+C+D+E --等效的布儿代数书写的逻辑方程;
③A<=(B AND C)OR(D AND E) -- 用 VHDL 程序规范书写的语句;
A= ( B·C ) + ( D·E ) --等效的布尔代数书写的逻辑方程。
例 4-15 逻辑运算符举例
SIGNAL a , b , c : STD_LOGIC_VECTOR (3 DOWNTO 0) ; SIGNAL d , e , f , g : STD_LOGIC_VECTOR (1 DOWNTO 0) ; SIGNAL h , I , j , k : STD_LOGIC ; SIGNAL l , m , n , o , p : BOOLEAN ;a<= b AND c; --b 、 c 相与后向 a赋值, a 、 b 、 c 的数据类型同属 4 位长的
位矢量 d<=e OR f OR g ; -- 两个操作符 OR 相同,不需括号 h<=(i NAND j)NAND k ; -- NAND 不属上述三种算符中的一种,必须加括号 l<=(m XOR n)AND(o XOR p); -- 操作符不同,必须加括号 h<=i AND j AND k ; -- 两个操作符都是 AND ,不必加括号 h<=i AND j OR k ; -- 两个操作符不同,未加括号,表达式错误 a<=b AND e ; -- 操作数 b 与 e 的位矢长度不一致,表达错误 h<=i OR l ; -- i 的数据类型是位 STD_LOGIC ,而 l 的数据类型是布尔量 B
下面先以一个例子来说明 WAIT 语句的用法: WAIT ON X,Y until Z=0 FOR 100ns ; 该语句的功能是:当执行到该语句时进程将被挂起,但如果 X 或者 Y 在接下来 100ns秒之内发生了改变,进程便立即测试条件“ Z=0” 是否满足。若满足,进程将会被激活;若不满足,进程则继续被挂起。
WAIT -- 无限等待; WAIT ON --敏感信号量变化; WAIT UNTIL 表达式 -- 表达式成立,进程启动; WAIT FOR 时间表达式 --时间到,进程启动。
WAIT ON 语句的完整书写格式为: WAIT ON 信号 [ ,信号,… ] ; WAIT ON 语句后面跟着的是一个或多个信号量,例如: WAIT ON A , B ; 该语句表明,它等待信号量 A 或者 B 发生变化, A
或者 B 中只要一个信号量发生变化,进程将结束挂起状态,而继续执行 WAIT ON 语句的后继语句。
(1)WAIT ON
例 4-17 WAIT ON 语句的使用
P1:PROCESS(A,B) P2: PROCESS BEGIN BEGIN Y<=A AND B; Y<= A AND B; END PROCESS; WAIT ON A,B; END PROCESS; 该例 4-17 中两个进程 P1 、 P2 的描述是完全等价的,
只是 WAIT ON 和 PROCESS 中所使用的敏感信号量的书写方法有区别。在使用 WAIT ON 语句的进程中,敏感信号量应写在进程中 WAIT ON 语句的后面;在不使用 WAIT ON 语句的进程中,敏感信号量只应在进程开头的 PROCESS后跟的括号中说明。如果在 PROCESS语句中已有敏感信号量说明,那么在进程中不能再使用WAIT ON 语句。
(2)WAIT UNTIL
WAIT UNTIL 语句的完整书写格式为: WAIT UNTIL 表达式; WAIT UNTIL 语句后面跟的是布尔表达式,当进程执
WAIT FOR 语句的完整书写格式为: WAIT FOR 时间表达式; WAIT FOR 语句后面跟的是时间表达式,当进程执行到
该语句时将被挂起,直到指定的等待时间到时,进程再开始执行 WAIT FOR 语句的后继语句。
2 . IF 语句
IF 语句根据指定的条件来确定语句执行顺序,共有 3 种类型。
(1) 用于门闩控制的 IF 语句 这种类型的 IF 语句的一般书写格式为: IF 条件 THEN
〈顺序处理语句〉 END IF ;当程序执行到该 IF 语句时,就要判断 IF 语句所指定的条
件是否成立。如果条件成立, IF 语句所包含的顺序处理将被执行;如果条件不成立,程序跳过 IF 包含的顺序处理语句,执行 IF 语句的后续语句。
例 4-18 用 IF 语句描述 4 位等值比较器LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY EQCOM_2 IS PORT(A,B: IN STD_LOGIC_VECTOR (3 downto 0); EQ: OUT STD_LOGIC); END EQCOM_2; ARCHITECTURE func OF EQCOM_2 IS BEGIN PROCESS(A,B) BEGIN EQ <= ‘0 IF A=B THEN EQ <= ‘1’; END IF; END PROCESS; END func;
(2) 用于 2 选 1 的 IF 语句
这种类型的 IF 语句的一般书写格式为: IF 条件 THEN
〈顺序处理语句甲〉 ELSE
〈顺序处理语句乙〉 END IF ;当 IF 语句指定的条件满足时,执行顺序处理语句甲;当条
件不成立时,执行顺序处理语句乙。用条件选择不同的程序执行路径。
例 4-19 用 IF 语句来设计的 2 选 1 电路,每路数据位宽为 4 。
LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY mux2 IS PORT(A,B,SEL : IN STD_LOGIC _VECTOR (3 downto 0); C : OUT STD_LOGIC_ VECTOR (3 downto 0); END mux2; ARCHITECTURE func OF mux2 IS BEGIN PROCESS (A,B,SEL) BEGIN IF(SEL='0') THEN C<=A; ELSE C<=B; END IF; END PROCESS; END func;
当条件 1 成立时,执行顺序处理语句 1 ;当条件 2成立时,执行顺序处理语句 2 ;当条件 N 成立时,执行顺序处理语句 N ;当所有条件都不成立时,执行顺序处理语句 N+1 。
IF 语句指明的条件是布尔量,有两个选择,即“真”( TRUE )和“假”( FALSE ),所以 IF 语句的条件表达式中只能是逻辑运算符和关系运算符。
IF 语句可用于选择器、比较器、编码器、译码器、状态机的设计,是 VHDL 语言中最基础、最常用的语句。
例 4-20 用 IF 语句描述的四选一电路 ,
LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY mux4 IS PORT( INPUT : IN STD_LOGIC_VECTOR(3 DOWNTO 0); SEL : IN STD_LOGIC_VECTOR(1 DOWNTO 0); Q : OUT STD_LOGIC); END mux4; ARCHITECTURE func OF mux4 IS BEGIN PROCESS(INPUT,SEL) BEGIN IF(SEL=”00”)THEN Q<=INPUT(0); ELSIF(SEL=”01”)THEN Q<=INPUT(1); ELSIF(SEL=”10”)THEN Q<=INPUT(2); ELSE Q<=INPUT(3); END IF; END PROCESS; END func;
3 . CASE 语句
CASE 语句常用来描述总线行为、编码器和译码器的结构,从含有许多不同语句的序列中选择其中之一执行。 CASE 语句可读性好,非常简洁。 CASE 语句的一般格式为: CASE 条件表达式 IS
WHEN 条件表达式的值 => 顺序处理语句; END CASE ; 上述 CASE 语句中的条件表达式的取值满足指定的条
LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; ENTITY mux4 IS PORT(A,B,I0,I1,I2,I3: IN STD_LOGIC; Q: OUT STD_LOGIC); END mux4; ARCHITECTURE mux4_behave OF mux4 IS SIGNAL SEL: INTEGER RANGE 0 TO 3; BEGIN PROCESS(A,B,I0,I1,I2,I3) BEGIN SEL<=A; IF(B=’1’)THEN SEL<=SEL+2; END IF; CASE SEL IS --CASE 语句条件表达式 SEL WHEN 0=>Q<=I0; -- 当条件表达式值 =0时,执行代入语 Q<=I0 WHEN 1=>Q<=I1; -- 当条件表达式值 1时,执行代入语 Q<=I1 WHEN 2=>Q<=I2; -- 当条件表达式值 =2时,执行代入语 Q<=I2 WHEN 3=>Q<=I3; -- 当条件表达式值 =3时,执行代入语 Q<=I3 END CASE; END PROCESS; END mux4_behave;
例 4-21 表明,选择器的行为描述也可以用 CASE 语句。要注意的是,在 CASE 语句中,没有值的顺序号,所有值是并行处理的。这一点不同于 IF 语句,在 IF 语句中,先处理最起始的条件;如果不满足,再处理下一个条件,因此在 WHEN选项中,不允许存在重复选项。另外,应该将表达式的所有取值都一一列举出来,否则便会出现语法错误。
例 4-22 设计一个执行能执行加减算术运算和相等和不等比较的 alu 运算器单元
LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;ENTITY alu IS PORT( a, b : IN STD_LOGIC_VECTOR (7 DOWNTO 0); opcode: IN STD_LOGIC_VECTOR (1 DOWNTO 0); result: OUT STD_LOGIC_VECTOR (7 DOWNTO 0) );END alu;ARCHITECTURE behave OF alu IS CONSTANT plus : STD_LOGIC_VECTOR (1 DOWNTO 0) := b"00"; CONSTANT minus : STD_LOGIC_VECTOR (1 DOWNTO 0) := b"01"; CONSTANT equal : STD_LOGIC_VECTOR (1 DOWNTO 0) := b"10"; CONSTANT not_equal: STD_LOGIC_VECTOR (1 DOWNTO 0) := b"11";BEGINPROCESS (opcode,a,b)BEGIN CASE opcode IS WHEN plus => result <= a + b; -- a 、 b 相加 WHEN minus => result <= a - b; -- a 、 b 相减 WHEN equal => -- a 、 b 相等IF (a = b) THEN result <= x"01"; ELSE result <= x"00"; END IF; WHEN not_equal => -- a 、 b 不相等 IF (a /= b) THEN result <= x"01"; ELSE result <= x"00"; END IF; END CASE;END PROCESS;END behave;
LOOP 语句的书写格式有两种:(1)FOR LOOP 格式书写格式如下: FOR 变量名 IN 离散范围 LOOP
顺序处理语句; END LOOP ;在 FOR LOOP 格式中 ,循环变量的值在每次循环中都会发
生变化 ,离散范围表示循环变量在循环过程中的取值范围。
例 4-23 FOR-LOOP 语句的应用:设计一个在 10 位数据中统计 1 的个数的电路
LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;ENTITY number1_check ISPORT(a: IN STD_LOGIC_VECTOR(9 DOWNTO 0); y: OUT INTEGER RANGE 0 TO 10);END number1_check ARCHITECTURE example_LOOP OF number1_check ISSIGNSL count: INTEGER RANGE 0 TO 10;BEGIN P1:PROCESS(a)BEGIN count <=0; FOR i IN 0 TO 9 LOOP IF a(i)='1' THEN count <= count +1; END IF; END LOOP; y <= count; END Process P1; END example_LOOP;通过例 4-23得出下列结论:①循环变量 (i) 在信号说明、变量说明中不能出现,信号、变量不能代入到循环变量中。②全局变量、信号可以将局部变量的值带出进程 (count 的值由 y 从 P1 进程中代出 ) 。(2)WHILE LOOP 书写格式如下: WHILE 条件 LOOP 顺序处理语句; END LOOP ; 在该 LOOP 语句中,如果条件为“真”,则进行循环;如果条件为“假”,则循环结束。
例 4-24 WHILE-LOOP 语句的应用举例:设计一个 8 位优先权信号检测电路
LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;ENTITY parity_check ISPORT(a: IN STD_LOGIC_VECTOR(7 DOWNTO 0); y: OUT STD_LOGIC);END parity_check;ARCHITECTURE example_while OF parity_check ISBEGIN P1: PROCESS(a) VARIABLE tmp: STD_LOGIC; tmp:='0'; i:= 0; WHILE (i < 8) LOOP tmp:= tmp XOR a(i); i := i+1 ; END LOOP; y <= tmp; END PROCESS P1;END example_While;
5 . NEXT 语句
NEXT 语句的书写格式为:NEXT ; -- 第一种语句格
式NEXT LOOP 标号; -- 第二种语句格
式NEXT LOOP 标号 WHEN 条件表达式; -- 第三种语句
格式NEXT 语句用于当满足指定条件时结束本次循环迭代,而转
入下一次循环迭代。 [ 标号 ] 表明下一次循环的起始位置。如果 NEXT 语句后面既无“标号”也无“ WHEN 条件”说明,那么只要执行到该语句就立即无条件地跳出本次循环,从 LOOP 语句的起始位置进入下一次循环,即进入下一次迭代。
LIBRARY IEEE ; USE IEEE.STD_LOGIC_1164.ALL ; ENTITY mux41 IS PORT (s4 , s3, s2 , s1 : IN STD_LOGIC; z4 , z3, z2 , z1 : OUT STD_LOGIC); END mux41 ; ARCHITECTURE activ OF mux41 IS SIGNAL sel : INTEGER RANGE 0 TO 15; BEGIN PROCESS (sel , s4 , s3 , s2 , s1 ) BEGIN sel<= 0 ; -- 输入初始值 IF (s1 ='1') THEN sel <= sel+1 ; ELSIF (s2 ='1') THEN sel <= sel+2 ; ELSIF (s3 ='1') THEN sel <= sel+4 ; ELSIF (s4 ='1') THEN sel <= sel+8 ; ELSE NULL; -- 注意,这里使用了空操作语句 END IF ; z1<='0' ; z2<='0'; z3<='0'; z4<='0'; -- 输入初始值 CASE sel IS WHEN 0 => z1<='1' ; -- 当 sel=0时选中WHEN 13 => z2<='1' ; -- 当 sel 为 1 或 3时选中 WHEN 4 To 72 => z3<='1'; -- 当 sel 为 2 、 4 、 5 、 6 或 7时选中 WHEN OTHERS => z4<='1' ; -- 当 sel 为 8~ 15 中任一值时选中 END CASE ; END PROCESS ; END activ ;
ENTITY sync_device IS PORT(ina,clk: IN BIT; outb:OUT BIT); END sync_device; ARCHITECTURE example OF sync_device IS BEGIN P1:PROCESS(clk) BEGIN 0utb<=ina AFTER 10ns; END PROCESS P1; END example;
主要 端口接口表; ] -— 对该块用到的客体加以说明。可以说< 块说明部分 > -— 明的项目有 USE 子句,子程序说明及BEGIN -— 子程序体,类型说明及常数说明、信 < 并行语句 A> -— 号说明和元件说明< 并行语句 B>
END Block[ 块标号 ] ;
例 4-27 块语句实例
ENTITY halfadder IS — 实体名 halfadderPORT(a,b : IN Bit; S,C : OUT Bit); — 端口说明END ENTITY half;ARCHITECTURE addr1 OF half adder IS — 结构体 1 的名字为 addr1BEGIN S <= a XOR b; C <= a AND b;END ARCHITECTURE addr1;ARCHITECTURE addr2 OF halfadder IS — 结构体 2 的名字为 addr2BEGIN example : Block — 块名 example PORT(a , b : IN Bit; — 端口接口表, S , c : OUT Bit); — 参数的定义 PORT MAP (a , b , s , c); —信号的映射BEGIN P1 : PROCESS (a , b) IS — 进程 1 的标号 P1 BEGIN S <= a XOR b; END PROCESS P1 ; P2 : PROCESS (a , b) IS — 进程 2 的标号 P2 BEGINC <= a and b; END PROCESS P2;END Block example;END ARCHITECTURE addr2;
PROCEDURE bitvector_to_integer (z : IN STD_LOGIC_VECTOR; X_flag:OUT BOOLEAN; Q:INOUT INTEGER) IS BEGIN Q:=0; X_flag:=FALSE;FOR I IN z’RANGE LOOP Q:=Q*2; IF (z(i)=’1’)THEN Q:=Q+1; ELSIF (z(i)/=’0’)THEN X_flag:=TRUE; EXIT ; END IF;END LOOP;END bitvector_to_integer;
函数语句的书写格式为: FUNCTION 函数名 (参数 1 ;参数 2 ;…) RETURN 数据类型 IS
[ 定义语句 ] ; BEGIN
[ 顺序处理语句 ] ; RETURN[返回变量名 ] ; END [函数名 ] ; 在 VHDL 语言中, FUNCTION 语句中括号内的所有参
数都是输入参数或称输入信号。因此,在括号内指定端口方向的“ IN” 可以省略。 FUNCTION 的输入值有调用者拷贝到输入参数中,如果没有特别指定,在 FUNCTION 语句中按常数处理。通常各种功能的 FUNCTION 语句的程序都集中在包集合中。
例 4-29 将整数转换为 N 位位矢量的函数ENTITY PULSE_GEN IS GENERIC(N:INTEGER;PER:TIME); PORT(START:IN BIT;PGOUT:OUT BIT_VECTOR(N-1 DOWNTO 0); SYNC:INOUT BIT);END PULSE_GEN;ARCHITECTURE ALG OF PULSE_GEN IS FUNCTION INT_TO_BIN (INPUT:INTEGER;N:POSITIVE) RETURN BIT_VECTOR IS VARIABLE FOUT:BIT_VECTOR(0 TO N-1); VARIABLE TEMP_A:INTEGER:=0; VARIABLE TEMP_B:INTEGER:=0;BEGIN TEMP_A:=INPUT; FOR I IN N-1 DOWNTO 0 LOOP TEMP_B:=TEMP_A/(2**I); TEMP_A:=TEMP_A REM (2**I); IF(TEMP_B=1) THEN FOUT(N-1-I):=’1’; ELSE FOUT(N-1-I):=’0’; END IF;END LOOP;RETURN FOUT; END INT_TO_BIN;BEGIN PROCESS(START,SYNC)VARIABLE CNT:INTEGER:=0; BEGINIF START’EVENT AND START=’1’THENCNT:=2**N-1;END IF;PGOUT<=INT_TO_BIN(CNT,N)AFTER PER;IF CNT/=-1 AND START=’1’THEN SYNC<=NOT SYNC AFTER PER; CNT:=CNT-1;END IF; END PROCESS;END ALG;
在例 4-29 中,首先在结构体中定义了一个函数 INT_TO_BIN ,该函数的功能就是将一个整数转换为N 位位矢量结构。该函数中有两个参数 INPUT 和 N ,它们在函数体中被当作是常量。在进程语句调用该函数时,分别将实参 CNT 和 N 的值传递给函数的两个参数 INPUT 和 N ,最后函数的返回值传递 PGOUT ,完成函数的调用。
选择型信号赋值语句的格式为:WITH 表达式 SELECT目标信号 <= 表达式 1 WHEN 条件 1, 表达式 2 WHEN 条件 2, 表达式 3 WHEN 条件 3, … 表达式 N WHEN 条件 N, 表达式 N+1 WHEN OTHERS; 选择信号代入语句类似于 CASE 语句,它对表达式进
END GENERATE [ 标号名 ] ;FOR-GENERATE 形式的生成语句用于描述多重模式,结
构中所列举的是并发处理语句。这些语句并发执行,而不是顺序执行的,因此结构中不能使用 EXIT 语句和 NEXT 语句。
标号: IF 条件 GENERATE
< 并发处理的生成语句 >
END GENERATE[ 标号名 ] ;IF-GENERATE 形式的生成语句用于描述结构的例外的情况,比如边界处发生的特殊情况。 IF-GENERATE 语句在 IF条件为“真”时,才执行结构体内部的语句,因为是并发处理生成语句,所以与 IF 语句不同。在这种结构中不能含有 ELSE 语句。
GENERATE 语句典型的应用范围有:计算机存贮阵列、寄存器阵列、仿真状态编译机。
例 4-30 八位锁存器 74LS373 的 VHDL 设计
LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL; ENTITY SN74373 IS PORT (D : IN STD_LOGIC_VECTOR( 8 DOWNTO 1 ); OEN ,G : IN STD_LOGIC; Q : OUT STD_LOGIC_VECTOR(8 DOWNTO 1)); END ENTITY SN74373;ARCHITECTURE two OF SN74373 IS SIGNAL sigvec_save : STD_LOGIC_VECTOR(8 DOWNTO 1); BEGIN PROCESS(D, OEN, G , sigvec_save) BEGIN IF OEN = '0' THEN Q <= sigvec_save; ELSE Q <= "ZZZZZZZZ"; END IF; IF G = '1' THEN Sigvec_save <= D; END IF; END PROCESS; END ARCHITECTURE two;
LIBRARY IEEE ;--7段数码显示译码器的 VHDL 源程序 USE IEEE.STD_LOGIC_1164.ALL ; ENTITY SEG7_LUT IS PORT ( iSW : IN STD_LOGIC_VECTOR(3 DOWNTO 0); HEX7_D: OUT STD_LOGIC_VECTOR(6 DOWNTO 0) ) ; END ; ARCHITECTURE one OF SEG7_LUT IS BEGIN PROCESS( iSW ) BEGIN CASE iSW IS WHEN "0000" => HEX7_D <= "1000000"; --// gfe,dcba共阳级 WHEN "0001" => HEX7_D <= "1111001"; --// ---a---- WHEN "0010" => HEX7_D <= "0100100"; --// | | WHEN "0011" => HEX7_D <= "0110000"; --// f b WHEN "0100" => HEX7_D <= "0011001"; --// | | WHEN "0101" => HEX7_D <= "0010010"; --// ---g---- WHEN "0110" => HEX7_D <= "0000010"; --// | | WHEN "0111" => HEX7_D <= "1111000"; --// e c WHEN "1000" => HEX7_D <= "0000000"; --// | |WHEN "1001" => HEX7_D <= "0011000"; --// ---d----.h WHEN "1010" => HEX7_D <= "0001000" ; WHEN "1011" => HEX7_D <= "0000011" ; WHEN "1100" => HEX7_D <= "1000110" ; WHEN "1101" => HEX7_D <= "0100001" ; WHEN "1110" => HEX7_D <= "0000110" ; WHEN "1111" => HEX7_D <= "0001110" ; WHEN OTHERS => NULL ; END CASE ; END PROCESS ; END ;
4 .实验报告 详细叙述实验内容 (1)(2)(3) 的的设计原理及 ED
A 设计流程;包括程序设计、软件编译、硬件测试,给出各层次仿真波形图并完成时序分析;最后给出硬件测试流程和结果。
LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;ENTITY fulladder ISPORT (Ci,Ai,Bi:IN STD_LOGIC; S,Co:OUT STD_LOGIC);END fulladder;ARCHITECTURE logicfunc OF fulladder ISsignal x:STD_LOGIC;BEGINs<=Ai XOR Bi XOR Ci ;x<=(Ai AND Bi);Co<=x OR(Ci AND Ai)OR(Ci AND Bi);END logicfunc;
例 4-35 4 位加法器的 VHDL 程序设计
LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;ENTITY adder4 ISPORT( CIN:IN STD_LOGIC; X3,X2,X1,X0:IN STD_LOGIC; Y3,Y2,Y1,Y0:IN STD_LOGIC; S3,S2,S1,S0:OUT STD_LOGIC; COUT :OUT STD_LOGIC);END adder4;ARCHITECTURE structure OF adder4 IS SIGNAL C1,C2,C3:STD_LOGIC; COMPONENT fulladder PORT(Ci,X,Y:IN STD_LOGIC; S,Co :OUT STD_LOGIC); END COMPONENT;BEGIN STAGE0:fulladder PORT MAP(Ci,X0,Y0,S0,C1); STAGE1:fulladd PORT MAP(C1,X1,Y1,S1,C2); STAGE2:fulladd PORT MAP(C2,X2,Y2,S2,C3); STAGE3:fulladd PORT MAP(Ci=>C3,Co=>COUT,X=>X3,Y=>Y3,S=>S3);END structure;
BCD码加法器与 4 位二进制数加法运算电路不同。这里是两个十进制数相加,和大于 9时应产生进位。设被加数为 X 、加数为 Y 、自低位 BCD码加法器的进位为 C-1 。先将 X 、 Y 及 C-1按二进制相加,得到的和记为 S 。设 X 、 Y 及 C-1按十进制相加,产生的和为 Z ,进位为 W 。显然, S=X+Y ,若 S ≤9 ,则 S 本身就是 BCD码, S 的值与期望的 Z值一致,进位 W 应为 0 ;但是,当 S > 9时, S 不再是 BCD码。此时,须对 S 进行修正,取 S 的低四位按二进制加 6 ,丢弃进位,就能得到期望的 Z值,而此时进位 W 应为 1 。按此规则可将计算过程描述如下。
例 3-36 一位 BCD 码加法器实体
ENTITY adder_BCD ISPORT (X,Y: in STD_LOGIC_VECTOR(3 DOWNTO 0); S:out STD_LOGIC_VECTOR(4 DOWNTO 0));END adder_bcd;ARCHITECTURE logicfunc OF adder_bcd ISsignal z: STD_LOGIC_VECTOR(4 DOWNTO 0);BEGINZ<=(‘0’&X)+Y;Adjust<=’1’ when z>9 else ‘0’;s<=Z when (Adjust<=’0’) else z+6 ;x<=(Ai AND Bi);Co<=x OR(Ci AND Ai)OR(Ci AND Bi);END logicfunc;
END IF;QB(7 DOWNTO 0) <= REG8(7 DOWNTO 0);CN <=REG8(8);END PROCESS;
END BEHAV;
例 4-38 CNT2 的 VHDL 代码
LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;ENTITY CNT2 IS PORT ( CLK : IN STD_LOGIC;
Q : OUT STD_LOGIC_VECTOR (1 DOWNTO 0));
END CNT2;ARCHITECTURE behav OF CNT2 IS SIGNAL COUNT : STD_LOGIC_VECTOR (1 DOWNTO 0);BEGIN PROCESS( CLK ) BEGIN IF CLK'EVENT AND CLK = '1' THEN COUNT <= COUNT + 1; END IF;
4-6 分析下面 VHDL 源程序,根据 QuartusⅡ的仿真结果说明该电路的功能。LIBRARY ieee;USE ieee.std_logic_1164.all;USE ieee.std_logic_unsigned.all;ENTITY mul3_3v IS
PORT (A, B : IN STD_LOGIC_VECTOR(2 downto 0); M : OUT STD_LOGIC_VECTOR(5 downto 0));
END mul3_3v;ARCHITECTURE a OF mul3_3v IS SIGNAL temp1 : STD_LOGIC_VECTOR(2 downto 0); SIGNAL temp2 : STD_LOGIC_VECTOR(3 downto 0); SIGNAL temp3 : STD_LOGIC_VECTOR(4 downto 0); BEGIN
temp1 <= A WHEN B(0)='1' ELSE "000"; temp2 <= (A & '0') WHEN B(1)='1' ELSE "0000"; temp3 <= (A & "00") WHEN B(2)='1' ELSE "00000"; M <= temp1+temp2+('0' & temp3); END a;
4-7 分析下面 VHDL 源程序,根据 QuartusII 的仿真结果说明该电路的功能。LIBRARY ieee; USE ieee.std_logic_1164.all;USE ieee.std_logic_unsigned.all;ENTITY divider IS
PORT(CLKI : IN STD_LOGIC; CLKO : OUT STD_LOGIC );
END divider_v ;ARCHITECTURE a OF divider_v ISSIGNAL cou : STD_LOGIC_VECTOR(7 DOWNTO 0);BEGINPROCESSBEGIN
WAIT UNTIL CLKI = '1'; cou <= cou+1;END PROCESS;
CLKO <= cou(7);END a;
4-8 分析下面 VHDL 源程序,根据 QuartusII 的仿真结果说明该电路的功能。LIBRARY ieee;USE ieee.std_logic_1164.all;ENTITY shift4 IS
PORT(Di, Clk : IN STD_LOGIC; Q3,Q2,Q1,Q0 : OUT STD_LOGIC );
END shift4 ;ARCHITECTURE a OF shift4 ISSignal tmp : STD_LOGIC_VECTOR(3 DOWNTO 0); BEGINPROCESS (Clk)
BEGINIF (Clk'Event AND Clk='1') THEN tmp(3)<=Di; FOR I IN 1 To 3 LOOP tmp(3-I)<= tmp(4-I); END LOOP;END IF;
END PROCESS;Q3<=tmp(3); Q2<=tmp(2); Q1<=tmp(1); Q0<=tmp(0);END a;