进程语句
begin
进程语句包含在结构体中,一个结构体可以有多个进程语句,多个进程语句间是并行的,并可访问结构体或实体中定义的信号。因此进程语句称为并行描述语句。
进行语句结构内部所有语句都是顺序执行的
进程语句的启动是由process后敏感信号表中所标明的敏感信号触发来的。
各进程间的通信是由信号来传递的
语法如下:
标记:
process(敏感信号表)
变量说明语句;
begin
一组顺序语句;
end process 标记;
标记:为进程标号
敏感信号表:是进程用来读取所有敏感信号(包括端口)的列表。
变量说明:主要包括变量的数据类型说明、子程序说明等
从begin到end process之间是一组顺序执行语句。
敏感信号表
所 谓敏感信号表:就是用来存放敏感信号的列表。在进程语句中,敏感信号指那些发生改变后能引起进程语句执行的信号。敏感信号表中可以使用一个或多个信号,当 其中一个或多个信号值改变时,就在进程内部引起语句执行。敏感信号表也可忽略,但程序中必须有其他形式的敏感信号激励。例如wait、wait for、wait until和wait on。
进程语句的启动
在VHDL语言中,进程有两种工作状态:等待和执行。当敏感信号表中的信号没有变化时,进程处于等待状态;当敏感信号表中的信号有变化时,进程处于执行状态
进程语句的同步
同一个结构体中不仅可以有多个进程存在,同一个结构体中的多个进程还可以同步。VHDL中通常采用时钟信号来同步进程,具体方法是:结构体中的几个进程共用同一个时钟信号来进行激励。
并发信号赋值语句
信号赋值语句在进程内部出现时,它是一种顺序描述语句。
信号赋值语句在结构体的进程之外出现时,它将以一种并发语句的形式出现。它们在结构体中是并行执行的。
注意:并发信号赋值语句是靠事件来驱动的,因此对于并发信号赋值语句来说,只有当赋值符号“<=”右边的对象有事件发生时才会执行该语句。
条件信号赋值语句
语法结构:
目标信号<=表达式1 when 条件1 else
表达式2 when 条件2 else
表达式3 when 条件3 else
…
表达式n-1 when 条件n-1 else
表达式n;
VHDL 语言程序执行到该语句时,首先要进行条件判断,之后才进行信号赋值。如果满足条件,就将该条件前面那个表达式的值赋给目标信号;如果不满足条件按,就继续 判断,直到最后一个表达式,如果前面的条件均不满足就无条件的赋值给最后一个表达式,因为最后一个表达式赋值无需条件。
选择信号赋值语句
语法结构:
with 表达式 select
目标信号<=表达式1 when 选择条件1,
表达式2 when 选择条件2,
...
表达式n when 选择条件n;
该语句在赋值之前需要对条件进行判断,附和条件则赋值,否则继续判断,直到最后一个语句。选择赋值语句需要把表达式的值在条件中都列举出来。
元件例化语句
在VHDL中,引用元件或者模块的说明采用component语句,他的作用是在结构体说明部分说明引用的元件或者模块,是元件说明语句。
语法格式:
component 引用的元件名
generic 参数说明;
port 端口说明;
end componet;
引用的元件名 :
是将一个设计现成的实体定义为一个元件,是已经设计好的实体名,用来制定要在结构体中使用的元件名称
如果结构体中要进行参数的传递,那么component语句中需要类属参数说明–可选项;
引用元件端口的说明,是已经设计好的实体端口名表;
元件说明语句在architecture和begin之间。
元件例化引用
采用componet语句对要引用的原件进行说明后,为了引用的元件正确地嵌入到高一层的结构体描述中,就必须把被引用的元件端口信号于结构体中相应端口信号正确地连接起来,这就是元件例化语句要实现的功能。
语法结构:
标号名:元件名
generic map(参数映射)
prot map(端口映射);
其中标号:是元件例化语句的惟一标识,结构体中的标号名应该是惟一的
generic map语句:它的功能是实现对参数的赋值操作,从而可以灵活地改变引用元件的参数,为可选项
prot map:它的功能是把引用元件的端口信号与实际连接的信号对应起来,从而进行元件的引用操作。
VHDL中,为了实现引用元件的端口信号与结构体中的实际信号相连接,往往采用两种映射方法:
1、位置映射方法:指port map语句中实际信号的书写顺序于componet语句中端口说明的信号书写语句顺序一致
2、名称映射方法:指在port map中将引用的元件的端口信号名称赋值给结构体中要使用例化元件的各个信号
(名称映射语句的书写要求不是十分严格,只要把映射的对应信号连接起来就可以,顺序可以颠倒)。
生成语句
规则结构
某些电路部分是由同类元件组成的阵列,这些同类元件叫规则结构,例如:随机RAM、只读ROM、移位寄存器等规则结构一般用生成语句来描述。
生成语句有两种形式:for_generate和if_generate
for_generate主要用来描述规则
if_generate主要用来描述结构在其端部表现出的不规则性,例如边界条件的特殊性
for_generate语句
标号:for 循环变量 in 离散范围 generate
并行处理语句;
end generate 标号;
标号:用来作为for_generate语句的唯一标识符,可选项;
循环变量:它的值在每次循环中都将发生变化;
离散范围:用来指定循环变量的取值范围,循环变量的取值将从取值范围最左边的值开始并且递增到取值范围的最右边,实际上限定了循环次数
for_generate与for_loop语句很类似,但二者有区别。for_loop语句的循环体中的处理语句是顺序的,而for_generate语句中处理的语句是并行处理的,具有并发性。
if_generate语句
标号:if 条件 generate
并行处理语句;
end generate 标号;
if_generate语句是并行处理语句,其中不允许出现else子语句
初学VHDL,对一些问题总是感到困惑。比如,同样的赋值语句,在什么场合是并行的,什么时候又是顺序的?信号与变量有什么区别,为什么在PROCESS 里,对信号赋值的结果要等到进程挂起才起作用,而变量赋值却立刻起作用?其实,从语句产生的电路这个角度,可以更深刻地理解这些问题,下面是我自己摸索的 一些理解方法,有不妥之处请大虾们指正!
同样a <= b的赋值语句,会形成什么电路,起关键作用的是敏感信号。
a) 如果a <= b是在进程之外,那么隐含的敏感信号就是b,那么,这个赋值语句就形成一条连线。
b) 如果是在一个同步进程中,如if (rising_edge(CLK)) then a <= b,这时候,就会形成一个触发器,因为敏感信号是时钟边沿。
c) 如果敏感信号是一个电平信号,那么会形成一个锁存器。如一个不完整的if条件:if (cond = ‘1’) then a <= b;
从形成的电路的角度,并行语句最终会有两种形式:
a) 并联或不相联的逻辑门或组合电路。因为是并联或不相联的,当然是同时执行,这个好理解。
b) 由同一个时钟边沿驱动的D触发器,不论D触发器之间是并联、串联或者不相连的。为什么呢?因为触发器是在同一个时钟边沿同时翻转的,也就是同时执行,所以本质上就是并行。
顺序语句只有一种情况,就是形成串联的逻辑门或组合电路。
其实,了解了上一点并行语句和顺序语句所生成的电路,这个问题就好理解了。因为在同步进程里的并行语句,大多是形成b的情况,就是多个由同一时钟驱动的触 发 器。由于从触发器的输入到翻转、输出需要一定的延时,这个延时基本就是进程执行完毕的时间,所以,触发器翻转后的输出在同一个时钟边沿中是看不到的,因为 它还没翻转过来呢。这就是信号赋值要等到进程挂起才生效的原因。
那为什么变量赋值却能立刻生效呢?这是因为,变量其实是为了帮助在同步进程中生成一些逻辑门或组合电路用的。看一看代码:var1 := not i1; var2 := var1 and i2 ; sig <= var2; 生成的RTL,就会看到,两个变量赋值语句其实生成了一个非门、一个与门。而且,输入信号i1和i2到var2这段是个组合电路,是不受时钟边沿控制的, 而到信号赋值语句sig <= var2,才形成一个D触发器。所以,这两个变量赋值语句生成了一个串联的非门和与门,那当然var2取到的是var1赋值后的值了。
最后顺便提一下为什么变量必须只能在进程内可见,我猜可能是为了防止在同步进程中输出异步信号,造成混乱吧。因为如果变量是外部可见的,如上面的 var2,那么var2的值就可以异步输出到进程外了。所以限制变量只能进程内可见后,要输出变量的值就只能赋值给一个信号,在同步进程中,就是加了一个 触发器了。
VHDL中并发描述语句有WHEN和GENERATE。除此之外,仅包含AND, NOT, +, *和sll等逻辑、算术运算操作符的赋值语句也是并发执行的。在BLOCK中的代码也是并发执行的。
从本质上讲,VHDL代码是并行执行的。只有PROCESS, FUNCTION, PROCEDURE内部的代码才是顺序执行的。但是当它们作为一个整体时,与其他模块之间又是并行执行的。并发代码称为“数据流”代码。
通常我们只能用并发描述语句来实现组合逻辑电路,为了实现时序逻辑电路,必须使用顺序描述语句。事实上,使用顺序描述语句可以同时实现组合逻辑电路和时序逻辑电路。