三、 并发代码
VHDL中并发描述语句有WHEN和GENERATE。除此之外,仅包含AND, NOT, +, *和sll等逻辑、算术运算操作符的赋值语句也是并发执行的。在BLOCK中的代码也是并发执行的。 从本质上讲,VHDL代码是并行执行的。只有PROCESS, FUNCTION, PROCEDURE内部的代码才是顺序执行的。但是当它们作为一个整体时,与其他模块之间又是并行执行的。并发代码称为“数据流”代码。
通常我们只能用并发描述语句来实现组合逻辑电路,为了实现时序逻辑电路,必须使用顺序描述语句。事实上,使用顺序描述语句可以同时实现组合逻辑电路和时序逻辑电路。 在并发代码中可以使用以下各项: ? 运算操作符
? WHEN语句(WHEN/ELSE或WITH/SELECT/WHEN) ? GENERATE语句 ? BLOCK语句 使用运算操作符
运算类型 运算操作符 NOT, AND, NAND,OR 逻辑运算 NOR, XOR, XNOR 操作数类型 BIT, BIT_VECTOR, STD_LOGIC, STD_LOGIC_VECTOR STD_ULOGIC, STD_ULOGIC_VECTOR 算术运算符 比较运算符 移位运算符 并置运算符 +, —, *, /, ** =, /=, <, >, <=, >= sll, srl, sla, sra, rol, ror &,(, , ,) INTEGER, SIGNED, UNSIGNED 任意数据类型 BIT_VECTOR STD_LOGIC, STD_LOGIC_VECTOR, STD_ULOGIC STD_ULOGIC_VECTOR, SIGNED, UNSIGNED WHEN语句 WHEN语句是一种基本的并发描述语句,有两种形式:WHEN/ELSE和WITH/SELECT/WHEN。 WHEN/ELSE语法结构: assignment WHEN condition ELSE assignment WHEN condition ELSE …; WITH/SELECT/WHEN语法结构 WITH identifier SELECT assignment WHEN value, assignemnt WHEN value, …;
当使用WITH/SELECT/WHEN时,必须对所有可能出现的条件给予考虑,使用关键字OTHERS,如果在某些条件出现时不需要进行任何操作,那应该使用UNAFFECTED。 例:
————————————-with WHEN/ELSE——————————————- Output <= “000” WHEN (inp = ‘0’ OR reset = ‘1’) ELSE “001” WHEN ctl = ‘1’ ELSE “010”;
———————————–with WITH/SELECT/WHEN——————————– WITH control SELECT
Output <= “000” WHEN reset, “111” WHEN set,
UNAFFECTED WHEN OTHERS;
对于WHEN语句,WHEN value的描述方式有以下几种: WHEN value –针对单个值进行判断 WHEN value1 to value2 –针对取值范围进行判断 WHEN value1 | value2 | … –针对多个值进行判断 GENERATE语句
GENERATE语句和顺序描述语句中的LOOP语句一样用于循环执行某项操作,通常与FOR一起使用。语法结构如下:
label: FOR identifier IN range GENERATE (concurrent assignments) END GENERATE
GENERATE语句还有另一种形式:IF/GENERATE,此处不允许使用ELSE。IF/GENERATE可以嵌套在FOR/GENERATE内部使用。反之亦然。 Label1: FOR identifier IN range GENERATE ……
Label2: IF condition GENERATE (concurrent assignments) END GENERATE; ……
END GENERATE; 例:
SIGNAL x: BIT_VECTOR(7 DOWNTO 0); SIGNAL y: BIT_VECTOR(15 DOWNTO 0);
SIGNAL z: BIT_VECTOR(7 DOWNTO 0); ……
G1: FOR i IN x’RANGE GENERATE z(i) <= x(i) AND y(i+8); END GENERATE;
GENERATE中循环操作的上界和下界必须是静态的,在使用过程中还要注意多值驱动问题。 例:
OK: FOR i IN 0 TO 7 GENERATE
Output(i) <= ‘1’ WHEN (a(i) AND b(i)) = ‘1’ ELSE ‘0’; END GENERATE;
————————————————————————— NotOK: FOR i IN 0 TO 7 GENERATE
accum <= “1111_1111” WHEN (a(i) AND b(i)) = ‘1’ ELSE “0000_0000”; END GENERATE;
—————————————————————- NotOK: FOR i IN 0 TO 7 GENERATE Accum <= accum + 1 WHEN x(i) = ‘1’; END GENERATE;
—————————————————————- 块语句(BLOCK)
VHDL中有两种BLOCK:simple BLOCK和guarded BLOCK。 n Simple BLOCK
Simple BLOCK仅仅是对原有代码进行区域分割,增强整个代码的可读性和可维护性。语法结构如下: label:BLOCK [ declarative part] BEGIN
(concurrent statement) END BLOCK label;
—————————————————————————————————- ARCHITETURE example… BEGIN …
block1: BLOCK BEGIN
…
END BLOCK block1; …
block2: BLOCK BEGIN …
END BLOCK block2; …
END example;
—————————————————————————————– 例: b1: BLOCK
SIGNAL a: STD_LOGIC; BEGIN
a <= input_sig WHEN ena = ‘1’ ELSE ‘z’; END BLOCK b1;
———————————————————————————————————————- 无论是simple BLOCK还是guarded BLOCK,其内部都可以嵌套其他的BLOCK语句,相应的语法结构如下: label1: BLOCK
[顶层BLOCK声明部分] BEGIN
[顶层BLOCK并发描述部分] label2: BLOCK
[嵌套BLOCK声明部分] BEGIN
[嵌套BLOCK并发描述部分] END BLOCK label2;
[顶层BLOCK其他并发描述语句] END BLOCK label1;
——————————————————————————————————— n Guarded BLOCK
多了一个卫式表达式,只有当卫式表达式为真时才能执行。语法结构如下: Label: BLOCK(卫式表达式)
[声明部分] BEGIN
(卫式语句和其他并发描述语句) END BLOCK label;
四、 顺序代码
在PROCESS, FUNCTION, PROCEDURE内部的代码都是顺序执行的,这样的语句包括IF,WAIT,CASE和LOOP。变量只能在顺序代码中使用,相对于信号而言,变量是局部的,所以它的值不能传递到PROCESS,FUNCTION和PROCEDURE的外部。 1. 进程(PROCESS)
进程内部经常使用IF,WAIT,CASE或LOOP语句。PROCESS具有敏感信号列表(sensitivity list),或者使用WAIT语句进行执行条件的判断。PROCESS必须包含在主代码段中,当敏感信号列表中的某个信号发生变化时(或者当WAIT语句的条件得到满足时),PROCESS内部的代码就顺序执行一次。语法结构如下: [label: ] PROCESS (sensitivity list)
[VARIABLE name type [range] [ := initial_value; ]] BEGIN
(顺序执行的代码) END PROCESS [label];
如果要在PROCESS内部使用变量,则必须在关键字BEGIN之前的变量声明部分对其进行定义。变量的初始值是不可综合的,只用于仿真。在设计同步电路时,要对某些信号边沿的跳变进行监视(时钟的上升沿或下降沿)。通常使用EVENT属性来监视一个信号是否发生了变化。
2. 信号和变量
信号可在PACKAGE,ENTITY和ARCHITECTURE中声明,而变量只能在一段顺序描述代码的内部声明。因此,信号通常是全局的,变量通常是局部的。赋予变量的值是立刻生效的,在后续的代码中,此变量将使用新的变量值,而信号的值通常只有在整个PROCESS执行完毕后才开始生效。 3. IF语句
IF/ELSE语句在综合时可能会产生不必要的优先级解码电路。IF语句语法结构如下: IF conditions THEN assignments; ELSIF conditions THEN assignments; ELSE assignments; END IF;
———————————————————————————————— 例:
IF (x < y) temp := “1111_1111”;