null6.1 数据对象 信号和变量在前面的许多例子中已多次出现,但都没有作更详细的解释,以下对它们作进一步的说明。
在VHDL中,数据对象有三类,即
变量(VARIABLE);
常量(CONSTANT);
信号(SIGNAL)。
数据对象类似于一种容器,它接受不同数据类型的赋值,变量和常量可以从软件语言中找到对应的类型。然而信号的
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
现较特殊,它具有更多的硬件特征,是VHDL中最有特色的语言要素之一。6.1 数据对象第六章 VHDL设计进阶null6.1.1 常量(CONSTANT) CONSTANT 常数名:数据类型 := 表达式 ;
例:CONSTANT frt: STD_LOGIC_VECTOR:=“010110”;
CONSTANT datain: INTEGER := 15; 常量的定义和设置主要是为了使程序更容易阅读和修改。例如,将逻辑位的宽度定义为一个常量,只要修改这个常量就能很容易地改变宽度,从而改变硬件结构。在程序中,常量是一个恒定不变的值,一旦作了数据类型和赋值定义后,在程序中不能再改变,因而具有全局性意义。常量定义的一般表述为: VHDL要求所定义的常量数据类型必须与表达式的数据类型一致。null 常量定义语句所允许的设计单元有实体、结构体、程序包、块、进程和子程序。
常量的使用范围取决于它被定义的位置:
常量如果定义在程序包中,其具有最大的全局化特征,可以用在调用此程序包的所有设计实体中;
常量如果定义在设计实体中,其有效范围为这个实体定义的所有的结构体;
常量定义在设计实体的某一结构体中,则只能用于此结构体;
常量定义在结构体的某一单元,如一个进程中,则这个常量只能用在这一进程中。
这就是常数的可视性规则。null6.1.2 变量(VARIABLE) 在VHDL语法规则中,变量是一个局部量,只能在进程和子程序中使用。变量不能将信息带出对它作出定义的当前结构中。变量的赋值是一种理想化的数据传输,是立即发生的,不存在任何延时的行为。变量的主要作用是在进程中作为临时的数据存储单元。
定义变量的一般表述如下:
VARIABLE 变量名 : 数据类型 := 初始值 ;例:VARIABLE a: INTEGER RANGE 0 TO 15;
VARIABLE d: STD_LOGIC;null 变量作为局部量,其适用范围仅限于定义了变量的进程或子程序的顺序语句中。在这些语句结构中,同一变量的值将随变量赋值语句前后顺序的运算而改变。
变量定义语句中的初始值可以是一个与变量具有相同数据类型的常数值,这个表达式的数据类型必须与所赋值的变量一致。此初始值不是必需的。变量数值改变通过变量赋值来实现,表述形式如下:
目标变量名:=表达式;null6.1.3 信号(SIGNAL) 信号是描述硬件系统的基本数据对象,它类似于连接线。信号可以作为设计实体中并行语句模块间的信息交流通道。
信号作为一种数值容器,不但可以容纳当前值,也可以保持历史值。与触发器的记忆功能有很好的对应关系,只是不必注明信号上数据流动的方向。
信号定义的语句格式与变量相似,信号定义也可以设置初始值,它的定义格式如下:SIGNAL 信号名: 数据类型 := 初始值 ;null 信号初始值的设置不是必需的,而且初始值仅在VHDL的行为仿真中有效。与变量相比,信号的硬件特征更为明显,它具有全局性特征。 信号的赋值语句表达式如下:
目标信号名<=表达式; “表达式”可以是一个运算表达式,也可以是数据对象(变量、信号或常量)。 信号的赋值可以在进程语句中,也可以在进程语句之外。在进程中同一个信号可以存在多个赋值语句,但只有最后的赋值语句有效;在进程之外,同一个信号只能使用一个赋值语句。null6.1.4 进程中的信号与变量赋值语句 以下对信号和变量这两种数据对象在赋值上的异同点作一些比较
分析
定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析
,以便对它们有更深刻的理解。
从硬件电路系统来看,变量和信号相当于逻辑电路系统中的连线和连线上的信号值;常量相当于电路中的恒定电平,如GND或VCC接口。从行为仿真和VHDL语句功能上看,信号与变量具有比较明显的区别,其差异主要表现在接受与保持信号的方式和信息保持与转递的区域大小上。null表6-1 信号与变量赋值语句功能的比较进程PROCESS:完成一个进程需要一个时间δ
变量值:在PROCESS启动时更新;
信号值:在PROCESS结束时更新。null【例6-1】
LIBRARY IEEE ;
USE IEEE.STD_LOGIC_1164.ALL ;
ENTITY DFF3 IS
PORT ( CLK,D1 : IN STD_LOGIC ;
Q1 : OUT STD_LOGIC);
END ;
ARCHITECTURE bhv OF DFF3 IS
BEGIN
PROCESS (CLK)
VARIABLE QQ : STD_LOGIC ;
BEGIN
IF CLK'EVENT AND CLK = '1' THEN
QQ := D1 ;
END IF;
Q1 <= QQ;
END PROCESS ;
END ;null【例6-2】
. . .
ARCHITECTURE bhv OF DFF3 IS
SIGNAL QQ : STD_LOGIC ;
BEGIN
PROCESS (CLK)
BEGIN
IF CLK'EVENT AND CLK ='1' THEN
QQ <= D1 ;
END IF;
Q1 <= QQ;
END PROCESS ;
END ;null 比较例6-1和例6-2。是典型的D触发器的VHDL描述,相比之下,例6-1仅将例6-2中定义的信号换成了变量,其综合的结果完全一样,也是图6-1所示的D触发器。这表明,在不完整的条件语句中,单独的变量赋值语句与信号赋值语句都能产生相同的时序电路,此时,变量已不是简单的数据临时储存结构。null【例6-3】
LIBRARY IEEE ;
USE IEEE.STD_LOGIC_1164.ALL ;
ENTITY DFF3 IS
PORT ( CLK,D1 : IN STD_LOGIC ;
Q1 : OUT STD_LOGIC);
END ;
ARCHITECTURE bhv OF DFF3 IS
SIGNAL A,B : STD_LOGIC ;
BEGIN
PROCESS (CLK)
BEGIN
IF CLK'EVENT AND CLK = '1' THEN
A <= D1; B <= A; Q1 <=B;
END IF;
END PROCESS ;
END ;【例6-4】
LIBRARY IEEE ;
USE IEEE.STD_LOGIC_1164.ALL ;
ENTITY DFF3 IS
PORT ( CLK,D1 : IN STD_LOGIC ;
Q1 : OUT STD_LOGIC);
END ;
ARCHITECTURE bhv OF DFF3 IS
BEGIN
PROCESS (CLK)
VARIABLE A,B : STD_LOGIC ;
BEGIN
IF CLK'EVENT AND CLK = '1' THEN
A <= D1; B <= A; Q1 <=B;
END IF;
END PROCESS ;
END ;图6-2 例6-3的RTL电路图6-1例6-4的RTL电路null 例6-3和例6-4说明了信号和变量在延时特性上的差别。 例6-3中的三个赋值语句都必须在遇到END PROCESS后的δ时刻内执行,所以它们具有了近乎并行执行的特性,即语句A<=D1中的A和语句B<=A中的A并非是同一时刻的值,B<=A与D1<=B中的B也非同时刻的B,它们都相差一个δ时间。因此在同一时刻中,A被更新的值是上一时钟周期的D1(即当前时钟上升沿以前的值),B被更新的值是上一时钟周期的A,而Q1被更新的值也是上一时钟周期的B1。故此程序综合后只能是图6-2的电路。
null 例6-4就不同了。由于A、B是变量,它们具有临时保留数据的特性,而且它们的赋值更新是立即发生的,因而有了明显的顺序性。当三条赋值语句顺序执行时,变量A和B就有了传递数据的功能。语句执行中,先将D1的值传给A,再通过A传给B,最后在一个δ时刻后,由B传给Q1。在这些过程中,A和B只担当了D1数据的暂存单元。Q1最终被更新的值是上一时钟周期的D1。则例6-4的综合结果就应该是图6-1的单个D触发器了。null 对于例6-3中信号赋值行为的理解必须把握表6-1中的信号行为特性的三个重要方面:
(1)信号的赋值需要有一个δ延时,例如当执行到A<=D1时,D1向A的赋值是在一个δ延时后发生的。
(2)在进程中,所有赋值语句(包括变量赋值),都必须在一个δ延时中完成,而且在进程中的所有信号赋值语句在进程启动的一瞬间立即执行赋值操作,但须在一个δ延时后完成赋值,并且必须在遇到“END PROCESS”语句时发生。
(3)当在进程中存在同一信号有多个赋值源时,实际完成赋值发生更新的信号是最接近“END PROCESS”语句的信号。6.2 双向和三态控制电路信号赋值例解 引入三态门有许多实际的应用,如CPU设计中的数据和地址总线的构建,RAM或堆栈的数据端口的设计等。利用VHDL,在FPGA开发设计中引入三态控制电路是完全可以实现的。在设计中,如果用STD_LOGIC数据类型‘Z’对一个变量赋值,即会引入三态门,并在控制下可使其输出呈高阻态,等效于使三态门禁止输出。
6.2.1 三态门设计
例6-9是一个8位三态控制门电路的描述,当使能控制信号为‘1’时,8位数据输出,为‘0’时输出呈高阻态,语句中将高阻态数据“ZZZZZZZZ”向输出端口赋值,其综合结果示于图6-8。6.2 双向和三态控制电路信号赋值例解null【例6-9】
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY tri_s IS
port ( enable : IN STD_LOGIC;
datain : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
dataout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END tri_s ;
ARCHITECTURE bhv OF tri_s IS
BEGIN
PROCESS(enable,datain)
BEGIN
IF enable = '1' THEN dataout <= datain ;
ELSE dataout <="ZZZZZZZZ" ;
END IF ;
END PROCESS;
END bhv;图6-8 8位3态控制门电路null 使用中,首先将某信号定义为STD_LOGIC数据类型,将‘Z’赋给这个变量来获得三态控制门电路。但应注意,由于‘Z’在综合中是一个不确定的值,不同的综合器可能会给出不同的结果,不要将‘Z’用作比较值、表达式或操作数。
当把表示高阻态的‘Z’值赋给一个数据类型为STD_LOGIC的变量或信号时,‘Z’必须是大写,因为在IEEE库中对数据类型STD_LOGIC的预定义已经将高阻态确定为大写‘Z’。
在以原理图为顶层设计的电路中使用三态门时只需调用三态门元件即可。 null6.2.2 双向端口设计(INOUT) 用INOUT模式设计双向端口也必须考虑三态的使用,因为双向端口的设计与三态端口的设计十分相似,都必须考虑端口的三态控制。这是由于双向端口在完成输入功能时,必须使原来呈输出模式的端口呈高阻态,否则,待输入的外部数据势必会与端口处原有电平发生“线与”,导致无法将外部数据正确地读入而实现“双向”的功能。 考察比较例6-10和例6-11两个双向端口的VHDL设计实例。null【例6-10】
library ieee;
use ieee.std_logic_1164.all;
entity tri_state is
port (control : in std_logic;
in1: in std_logic_vector(7 downto 0);
q : inout std_logic_vector(7 downto 0);
x : out std_logic_vector(7 downto 0));
end tri_state;
architecture body_tri of tri_state is
begin
process(control,q,in1)
begin
if (control = '0') then x <= q ;
else q <= in1; x<="ZZZZZZZZ" ;
end if;
end process;
end body_tri;null【例6-11】
(以上部分同上例)
process(control,q,in1)
begin
if (control='0') then x <= q ; q <= "ZZZZZZZZ";
else q <= in1; x <="ZZZZZZZZ";
end if;
end process;
end body_tri; 比较例6-10和例6-11 ,它们都将q定义为双向端口,将x定义为三态控制输出口。它们的区别仅在于,例6-10当利用q的输入功能将q端口的数据读入并传输给x(即执行x<=q)时,没有将q端口设置成高阻态输出,从而导致了如图6-9所示的综合结果。nullnull 这是一个错误的逻辑电路,从它的仿真波形图(图6-10)可以清楚地看到,当control为‘0’时,x无法得到正确的输出结果。从图6-9还发现,尽管在程序的实体部分已经明确地定义了q为双向端口,但显示在电路中的综合结果却只是一个输出端口,而且在电路中还被插入了一个锁存器。
例6-10变成时序电路的原因:其中的IF语句是一个完整的条件语句,但这仅是对x而言的,对q并非如此,即在control的两种不同条件下(‘1’和‘0’)都给出了x的输出数据,而q只在control为‘1’时执行赋值命令,为‘0’时,没有给出q的操作说明,这是一个非完整条件语句。null 例6-11中仅增加了语句q<=“ZZZZZZZZ”就解决了两个重要的问题:
(1)使q在IF语句中有了完整的条件描述,从而克服了时序元件的引入。
(2)在q履行输入功能时,将其设定为高阻态输出,使q成为真正的双向端口(图6-11)。从例6-11的仿真波形图(图6-12)可见,无论control为‘1’或‘0’,q和x都能得到正确的输出结果。nullnull 为构成芯片内部的总线系统,必须设计三态总线驱动器电路,这可以有多种表达
方法
快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载
,但必须注意信号多驱动源的处理问题。
例6-12和例6-13都试图描述一个8位4通道的三态总线驱动器,而例6-12描述的程序是不能完成该功能的。6.2.3 三态总线电路设计nullLIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY tristate2 IS
port ( input3, input2, input1, input0 :
IN STD_LOGIC_VECTOR (7 DOWNTO 0);
enable : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
output : OUT STD_LOGIC_VECTOR (7 DOWNTO 0));
END tristate2 ;
ARCHITECTURE multiple_drivers OF tristate2 IS
BEGIN
PROCESS(enable,input3, input2, input1, input0 )
BEGIN
IF enable = "00" THEN output <= input3 ;
ELSE output <=(OTHERS => 'Z');
END IF ;
IF enable = "01" THEN output <= input2 ;
ELSE output <=(OTHERS => 'Z');
END IF ;
IF enable = "10" THEN output <= input1 ;
ELSE output <=(OTHERS => 'Z');
END IF ;
IF enable = "11" THEN output <= input0 ;
ELSE output <=(OTHERS => 'Z');
END IF ;
END PROCESS;
END multiple_drivers;【例6-12】图6-13 例6-12错误的综合结果 处于同一进程敏感表中的输入信号同时变化时,VHDL只对进程结束前的那一条赋值语句进行赋值操作,而忽略其他所有等价语句。
建议同一进程中最好只放一个IF语句结构。nulllibrary ieee;
use ieee.std_logic_1164.all;
entity tri is
port (ctl : in std_logic_vector(1 downto 0);
datain1, datain2,datain3, datain4 :
in std_logic_vector(7 downto 0);
q : out std_logic_vector(7 downto 0) );
end tri;
architecture body_tri of tri is
begin
q <= datain1 when ctl="00" else (others =>'Z') ;
q <= datain2 when ctl="01" else (others =>'Z') ;
q <= datain3 when ctl="10" else (others =>'Z') ;
q <= datain4 when ctl="11" else (others =>'Z') ;
end body_tri;【例6-13】null图6-14 例6-13正确的综合结果 在结构体中的每一条并行语句都等同于一个独立运行的进程,他们独立监测各并行语句中作为敏感信号的输入值。
要设计能产生独立控制的多通道的电路结构,必须使用并行语句结构。null6.3 IF语句概述 在以上出现的许多示例中都含有不同表达方式的IF语句。IF语句是VHDL设计中最重要和最常用的顺序条件语句,以下对IF语句的语法表达方式作一个概述。
IF语句作为一种条件语句,它根据语句中所设置的一种或多种条件,有选择地执行指定的顺序语句。 IF语句中至少应有一个条件句,“条件句”可以是一个BOOLEAN类型的标识符,或者是一个判别表达式,判别表达式输出的值,即判断结果的数据类型是BOOLEAN。 IF语句根据条件句产生的判断结果是true或是false,有条件地选择执行其后的顺序语句。null(1)IF 条件句 Then
顺序语句
END IF ;IF语句的语句结构有以下四种: 该条件语句的执行情况是,当执行到此句时,首先
检测
工程第三方检测合同工程防雷检测合同植筋拉拔检测方案传感器技术课后答案检测机构通用要求培训
关键词IF后的条件表达式的布尔值是否为真,如果条件为真,于是(THEN)将顺序执行条件句中列出的各条语句,直到ENDIF,即完成全部IF语句的执行。如果条件检测为假,则跳过以下的顺序语句不予执行,直接结束IF语句的执行。这种语句形式在以上已出现过多次,是一种非完整性条件语句,通常用于产生时序电路。null(2)IF 条件句 Then
顺序语句
ELSE
顺序语句
END IF ; 与第(1)种IF语句相比,第(2)种IF语句的差异仅在于当所测条件为false时,并不直接跳到ENDIF结束条件句的执行,而是转向ELSE以下的另一段顺序语句进行执行。所以第(2)种IF语句具有条件分支的功能,就是通过测定所设条件的真假以决定执行哪一组顺序语句,在执行完其中一组语句后,再结束IF语句的执行。这是一种完整性条件语句,它给出了条件句所有可能的条件,因此通常用于产生组合电路。null(3)IF 条件句 Then
IF 条件句 Then
...
END IF
END IF; 第(3)种IF语句是一种多重IF语句嵌套式条件句,可以产生比较丰富的条件描述,既可以产生时序电路,也可以产生组合电路,或是两者的混合。如例4-23的移位寄存器。该语句在使用中应注意,ENDIF结束句应该与嵌入条件句数量一致。null(4)IF 条件句 Then
顺序语句
ELSIF 条件句 Then
...
ELSE
顺序语句
END IF; 第(4)种IF语句与第(3)种一样,也可以实现不同类型电路的描述,在以上的许多示例中部用到了这种语句。该语句通过关键词ELSIF设定多个判定条件,以使顺序语句的执行分支可以超过两个。这一类型的语句有一个重要特点,就是其任一分支顺序语句的执行条件是以上各分支所确定条件的相与(即相关条件同时成立),即语句中顺序语句的执行条件具有向上相与的功能。null【例6-14】2选1数据选择器
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY control_stmts IS
PORT (a, b, c: IN BOOLEAN;
output: OUT BOOLEAN);
END control_stmts;
ARCHITECTURE example OF control_stmts IS
BEGIN
PROCESS (a, b, c)
VARIABLE n: BOOLEAN;
BEGIN
IF a THEN n := b;
ELSE n := c;
END IF;
output <= n;
END PROCESS;
END example;null【例6-15】8线-3线优先权编码器
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY coder IS
PORT ( din : IN STD_LOGIC_VECTOR(0 TO 7);
output : OUT STD_LOGIC_VECTOR(0 TO 2) );
END coder;
ARCHITECTURE behav OF coder IS
SIGNAL SINT : STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
PROCESS (din)
BEGIN
IF (din(7)='0') THEN output <= "000" ;
ELSIF (din(6)='0') THEN output <= "100" ;
ELSIF (din(5)='0') THEN output <= "010" ;
ELSIF (din(4)='0') THEN output <= "110" ;
ELSIF (din(3)='0') THEN output <= "001" ;
ELSIF (din(2)='0') THEN output <= "101" ;
ELSIF (din(1)='0') THEN output <= "011" ;
ELSE output <= "111" ;
END IF ;
END PROCESS ;
END behav;null 在一个结构体中,允许放置任意多个进程语句结构,而每一进程的内部是由一系列顺序语句来构成的。
PROCESS语句结构包含(或者说引导)了一个代表着设计实体中部分逻辑行为的、独立的顺序语句描述的进程。与并行语句的同时执行方式不同,顺序语句可以根据设计者的要求,利用顺序可控的语句完成逐条执行的功能。顺序语句与C或PASCAL等软件编程语言中语句功能有类似的顺序执行的功能。6.4 进程语句归纳 null 但必须注意,在VHDL中,所谓顺序仅仅是指语句按序执行上的顺序性,但这并不意味着PROCESS语句结构在综合后所对应的硬件逻辑行为也具有相同的顺序性。
PROCESS结构中的顺序语句,及其所谓的顺序执行过程只是相对于计算机中的软件行为仿真的模拟过程而言的,这个过程与硬件结构中实现的对应的逻辑行为是不完全相同的。PROCESS结构中既可以有时序逻辑的描述,也可以有组合逻辑的描述,它们都可以用顺序语句来表达。null PROCESS语句结构的一般表达格式如下:
[进程标号: ] PROCESS [ ( 敏感信号参数表 ) ] [IS]
[进程说明部分]
BEGIN
顺序描述语句
END PROCESS [进程标号];6.4.1 进程语句格式 每一个PROCESS语句结构可以赋予一个进程标号。进程说明部分定义该进程所需的局部数据环境。顺序描述语句部分是一段顺序执行的语句,描述该进程的行为。null PROCESS中
规定
关于下班后关闭电源的规定党章中关于入党时间的规定公务员考核规定下载规定办法文件下载宁波关于闷顶的规定
了每个进程语句在当它的某个敏感信号(由敏感信号参量表列出)的值改变时都必须立即完成某一功能行为,这个行为由进程语句中的顺序语句定义,行为的结果可以赋给信号,并通过信号被其他的PROCESS或BLOCK读取或赋值。当进程中定义的任一敏感信号发生更新时,由顺序语句定义的行为就要重复执行一次,当进程中最后一个语句执行完成后,执行过程将自动返回到进程的第一个语句,以等待下一次敏感信号变化。 null 一个结构体中可以含有多个PROCESS结构,每一PROCESS结构对于其敏感信号参数中定义的任一敏感参量的变化,可以在任何时刻被激活或者称为启动。而在一结构体中,所有被激活的进程都是并行运行的,这就是为什么PROCESS结构本身是并行语句的道理,PROCESS语句必须以语句END PROCESS[进程标号];结尾,对于目前常用的综合器来说,其中进程标号不是必需的,敏感表旁的[IS]也不是必需的。null6.4.2 PROCESS 组成 PROCESS语句结构是由3个部分组成的,即进程说明部分、顺序描述语句部分和敏感信号参数表。null (1)进程说明部分主要定义一些局部量,可包括数据类型、常数、变量、属性、子程序等。但需注意,在进程说明部分中不允许定义信号和共享变量。
(2)顺序描述语句部分可分为赋值语句、进程启动语句、子程序调用语句、顺序描述语句和进程跳出语句等,它们包括以下几个方面。
※ 信号赋值语句:在进程中将计算或处理的结果向信号赋值。
※ 变量赋值语句:在进程中以变量的形式存储计算的中间值。
※ 进程启动语句:当PROCESS的敏感信号参数表中没有列出任何敏感量时,进程的启动只能通过进程启动语句WAIT语句。这时可以利用WAIT语句监视信号的变化情况,以便决定是否启动进程。WAIT语句可以看成是一种隐式的敏感信号表。 null ※ 子程序调用语句:对己定义的过程和函数进行调用并参与计算。
※ 顺序描述语句:包括IF语句、CASE语句、LOOP语句和NULL语句等。
※ 进程跳出语句:包括NEXT语句、EXIT语句,用于控制进程的运行方向。
(3)多数VHDL综合器要求敏感信号表必须列出本进程中所有输入信号名。null VHLD程序可从3个方面判断它的功能和执行情况。
※ 基于CPU的纯软件的VHDL行为仿真运行方式。
※ 基于VHDL综合器的综合结果所可能实现的运行方式。
※ 基于最终实现的硬件电路的运行方式。
6.4.3 进程要点null1. PROCESS为一无限循环语句 在同一结构体中的任一进程是一个独立的无限循环程序结构,但进程中却不必放置诸如软件语言中的返回语句,它的返回是自动的。
进程只有两种运行状态,即执行状态和等待状态。进程是否进入执行状态,取决于是否满足特定的条件,如敏感变量是否发生变化。如果满足条件,即进入执行状态,当遇到END PROCESS语句后即停止执行,自动返回到起始语句PROCESS,进入等待状态。 对进程的认识和进行进程的设计需要注意几方面的问题:null2. PROCESS中的顺序语句具有明显的顺序/并行运行双重性 在PROCESS中,一个执行状态的运行周期与任何外部因素都无关,与PROCESS语法结构中的顺序语句的多少都没有关系,其执行时间从行为仿真的角度看只有一个VHDL模拟器的最小分辨时间δ;但从综合和硬件运行的角度看其执行时间是0,与信号的传输延时无关,与被执行的语句的实现时间也无关。即在同一PROCESS中,10条语句和1000条语句的执行时间是一样的。null3. 进程必须由敏感信号的变化来启动 进程的启动必须由敏感信号表中定义的任一敏感信号的变化来启动,否则必须有一个显式的WAIT语句来激励。这就是说,进程既可以通过敏感信号的变化来启动,也可以由满足条件的WAIT语句而激活;
反之,在遇到不满足条件的WAIT语句后进程将被挂起。因此,进程中必须定义显式或隐式的敏感信号。如果一个进程对一个信号集合总是敏感的,那么,就可以使用敏感表来指定进程的敏感信号。但是,在一个使用了敏感表的进程(或者由该进程所调用的子程序)中不能含有任何等待语句。null4. 进程语句本身是并行语句 虽然进程语句引导语句属于顺序语句,但同一结构体中的不同进程是并行运行的,或者说是根据相应的敏感信号独立运行的。
任何一条信号的并行赋值语句都是一个简化的进程语句,其输入表式中的各信号都是此“进程语句”的敏感信号。
5. 信号是多个进程间的通信线 结构体中多个进程能并行同步运行,很重要的一个原因是进程之间的通信是通过信号来实现的。所以相对于结构体来说,信号具有全局特性,它是进程间进行并行联系的重要途径。因此,在任一进程的进程说明部分不允许定义信号。null 时序电路必须由进程中的顺序语句描述,而此顺序语句必须由不完全的条件语句构成。尽管在同一进程中可顺序放置多个条件语句,但是只能放置一个含有时钟边沿检测语句的条件语句。即一个进程中只能描述针对于同一时钟的同步时序逻辑,而异步时序逻辑必须由多个进程来表达。6. 一个进程中只允许描述对应于一个时钟信号的同步时序逻辑 null【例6-16】两级二选一
ENTITY mul IS
PORT (a, b, c, selx, sely : IN BIT;
data_out : OUT BIT );
END mul;
ARCHITECTURE ex OF mul IS
SIGNAL temp : BIT;
BEGIN
p_a : PROCESS (a, b, selx)
BEGIN
IF (selx = '0') THEN temp <= a;
ELSE temp <= b;
END IF;
END PROCESS p_a;
p_b: PROCESS(temp, c, sely)
BEGIN
IF (sely = '0') THEN data_out <= temp;
ELSE data_out <= c;
END IF;
END PROCESS p_b;
END ex;null图6-15 例6-16的综合结果null【例6-17】试设计一个异步清零的7分频器,要求分频时钟的占空比为4/7。
解:规定输入时钟信号为CLK,,异步清零信号为RST,低电平复位,输出的分频时钟为CLK_DIV7。library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity div_7 is
port ( clk : in std_logic;
rst : in std_logic;
clk_div7 : out std_logic);
end div_7;
architecture behav1 of div_7 is
begin
process (clk, rst)
variable cnt7b : std_logic_vector(2 downto 0);
beginnull if rst = '0' then
cnt7b := "000";
elsif clk'event and clk = '1' then
if(cnt7b = "110") then
cnt7b := "000";
else
cnt7b := cnt7b +1;
end if;
end if;
if rst = '0' then
clk_div7 <='0';
elsif clk'event and clk = '1' then
if(cnt7b > 2) then
clk_div7 <= '1';
else
clk_div7 <= '0';
end if;
end if;
end process ;
end behav1;--计数器--置占空比电平null 大部分并行语句的执行和实现是同时发生的,但也有一些语句并非如此。如进程语句和并行赋值语句,前者的行为在以上已做了说明,即除非几个进程都拥有完全相同的敏感信号,否则不可能出现完全并行运行的情况;后者的情况与进程十分类似。6.5并行语句例解 设以下是在同一结构体中的两个赋值语句,尽管它们属于并行语句,但在绝大多数情况下并不可能同时执行,除非a或b和c同时发生一个事件,即它们的值同时发生变化。data1 <= a AND b;
data2 <= c;null 并行赋值与顺序赋值都会有一个δ延时。以上面第一个语句为例,当a或b发生一个事件时立即进行a、b间的逻辑运算(此运算的仿真时间为0),同时启动延时为δ的模拟定时器,当δ时间结束后,data1才获得a AND b的运算值,即在此时data1才被更新。
再来考察另一个示例。例6-17中有两个赋值语句,它们的赋值目标信号分别是x和select,它们对应的语句被执行的条件是各自赋值符号右边的信号s0、s1或a、b、c、d发生一个事件。假设在某一稳态条件下 s0=0,s1=0;a、b、c、d都为0,这时x为a。 data1 <= a AND b;
data2 <= c;null【例6-17】数据选择
ARCHITECTURE dataflow OF mux IS
SIGNAL seiect : INTEGER RANGE 15 DOWNTO 0;
BEGIN
select <=0 WHEN s0=‘0’ AND s1=‘0’ ELSE
1 WHEN s0=‘1’ AND s1=‘0’ ELSE
2 WHEN s0=‘0’ AND s1=‘1’ ELSE
3;
x<=a WHEN select =0 ELSE
b WHEN select =1 ELSE
c WHEN select =2 ELSE
d;
…………null 现在假设a发生了一个事件,变为1,这时上面的select赋值语句并不会被执行,因为此句并不对a敏感。这时只会执行第二句赋值语句,因为此句对a敏感,这时会将a的值1赋值给x,使x从原来的0更新为1。
如果这时发生了一个事件,s0从0变为1。由于第一个赋值语句是对s0敏感的,所以即被执行。当此并行语句被执行时,所有条件表达式中含有s0的都将被更新为新值,并算出新值作为条件判断依据。于是,随着s0为1,s1为0,信号select被赋予1,这个新值将导致处于第二个赋值语句中的select发生一个事件,于是这条语句将使用select的新值去选择x的赋值,即将输入端口b的值赋给x。null 延时是VHDL仿真需要的重要特性设置,为设计建立精确的延时模型,可以使用VHDL仿真器得到接近实际的精确结果。
在FPGA/CPLD设计过程中,源文件一般不需要建立延时模型,因为EDA软件可以使用门级仿真器对选定的FPGA或CPLD适配所得的时序仿真文件进行精确仿真。本节讨论的问题主要是针对行为仿真延时建模的。
VHDL中有两类延时模型能用于行为仿真建模,即固有延时和传输延时。6.6 仿真延时null6.6.1 固有延时
固有延时也称为惯性延时,是任何电子器件都存在的一种延时特性。固有延时的主要物理机制是分布电容效应。分布电容产生的因素很多,分布电容具有吸收脉冲能量的效应。
当输入器件的信号脉冲宽度小于器件输入端的分布电容对应的时间常数时,或者说小于器件的惯性延时宽度时,即使脉冲有足够高的电平,也无法突破数字器件的阈值电平实现信号输出的目的,从而在输出端不会产生任何变化。 为了使器件对输入信号的变化产生响应,就必须使信号脉冲宽度大于器件的固有延时。null 在VHDL仿真和综合器中,有一个默认的固有延时量,它在数学上是一个无穷小量,被称为δ延时,或称仿真δ 。这个延时量的设置仅为了仿真,它是VHDL仿真器的最小分辨时间,并不能完全代表器件实际的惯性延时情况,在VHDL程序的语句中如果没有指明延时的类型与延时量,就意味着默认采用了这个固有延时量δ延时。在大多数情况下,这一固有延时量近似地反映了实际器件的行为。null 在当前所有可用的仿真器中,固有模式是最通用的一种,为了在行为仿真中比较逼真地模仿电路的这种延时特性,VHDL中含有固有延时模型的赋值语句可由下式表达: z <= x XOR y AFTER 5ns ;--惯性延时为5ns z <= x XOR y ;--默认为一个δ延时 表示此赋值电路的惯性延时为5ns,即要求信号值x XOR y变化的稳定时间不能少于5ns,换句话说,x XOR y的值在发生变化5ns后才被赋给z,此前x或y的任何变化都是无效的。对于下句:则表明,x XOR y的值在δ时间段后才被赋给z。null 下式表示一赋值延时模型的固有延时是20ns,即表明当A有一个事件后,其导致这一事件的电平的维持时间必须大于20ns,在固有延时定时器被启动20ns后,B端口才有可能输出信号(获得更新)。
z <= A AFTER 20ns ;——固有延时模型 如果A在稳态时是‘0’,
有事件发生后,A由‘0’变为‘1’
,并假设A的维持时间是l0ns,
则以上的固有延时模型的信号
波形如图5-15所示。按照20ns延时量,输出信号B的上升沿应该出现在30ns处,而其下降沿出现在40ns处。但实际上B输出信号没有任何变化。这是由于在固有延时模型的赋值语句中A的维持时间小于20ns造成的。null6.6.2 传输延时
另一种延时模型是传输模型。传输延时表达的是输入与输出之间的一种绝对延时关系。传输延时并不考虑信号持续的时间,仅表示信号传输推迟或延迟了一个时间段,这个时间段即为传输延时。对于器件,传输延时由半导体延时特性决定;对于连线,传输延时是由连线的介质结构、传输阻抗特性和信号频率特性决定的。 表达传输延时的语句可如以下例句所示: z <= TRANSPORT x AFTER 10 ns;其中关键词TRANSPORT表示语句后的延时量为传输延时量。null 对于此模型,设A的持续时间为10ns,其输入输出波形如图5-16所示。图中,与A的输入波形相比,B的输出波形正好延时了20ns,尽管A的脉宽只有10ns,但在30ns和40ns处仍然能看到对应的B的输出信号。
应该注意,虽然产生传输延时与固有延时的物理机制不一样,但在行为仿真中,传输延时与固有延时造成的延时效应是一样的。在综合过程中,综合器将忽略AFTER后的所有延时设置。null6.6.3 仿真 由于综合器不支持延时语句,在综合后的功能仿真中,仿真器仅对设计的逻辑行为进行了模拟测定,而没有把器件的延时特性考虑进去,仿真器给出的结果也仅仅是逻辑功能。按理说,功能仿真就是假设器件间的延迟时间为零的仿真。然而事实并非如此,由于无论是行为仿真还是功能仿真,都是利用计算机进行软件仿真,即使在并行语句的仿真执行上也是有先后的,在零延时条件下,当作为敏感量的输入信号发生变化时,并行语句执行的先后次序无法确定,而不同的执行次序会得出不同的非惟一的仿真结果,最后将导致矛盾的和错误的仿真结果。这种错误仿真的根本原因在于零延时假设在客观世界中是不可能存在的。 null 为了解决这一矛盾,VHDL仿真器和综合器将自动为系统中的信号赋值配置一足够小面又能满足逻辑排序的延时量,即仿真软件的最小分辨时间,这个延时量就称为仿真δ ,或称δ延时,从而使并行语句和顺序语句中的并列赋值逻辑得以正确执行。
仿真中,δ延时的引入由EDA工具自动完成,无需设计者介入。x <= 9 ;
y <= x ;
z <= x AFTER 5ns ; 最后一句为在5ns后将x赋予z,关键词AFTER后是延迟时间值。综合器在综合过程中将略去所设的延时值。null作业:P153
7、 8、9、 10