变量:VHDL语言顺序语句中的重要对象

本文将论述VHDL语言中变量的重要特征。

 

在本系列的上篇文章中,我们讨论了顺序语句有助我们以更直观的方式对数字系统进行描述。变量是非常有用的对象,更加便于电路行为的描述。本文将探讨变量的重要特性。另外还将就若干实例展开讨论,以阐明变量和信号之间的差异。首先让我们对VHDL信号进行回顾。

 

单个信号的多个赋值

 

VHDL使用信号表示电路互连和导线。例如,图1中的电路。 

 变量:VHDL语言顺序语句中的重要对象

图1

 

该电路VHDL代码的体系结构为:

1 architecture Behavioral of circuit1 is 

2 signal sig1: std_logic;

3 begin

4 sig1 <= ( a and b );

5 out1 <= ( sig1 or c );

6 out2 <= (not d);

 

7 end Behavioral;

 

如您所见,信号包含指向硬件的清晰映射:它变成一条或一组导线。为一个信号赋多个值是否可行?例如,考虑下列代码段:

 

                    sig1 <= ( a and b );

 

sig1 <= (c or d);

                  

如果这两个赋值位于代码的并行部分,则二者可同步执行。我们可以考虑图2所示代码的等效硬件。

 变量:VHDL语言顺序语句中的重要对象

图2

 

图2表明,为代码并行部分中的一个信号赋多个值并非明智之举,因为各赋值间可能相互冲突。举例说明,如果A=C=0且B=D=1,第一行应赋值sig1 = (0和1) =0,第二行应尝试赋值sig1 = (0或1)=1。因此,在代码的并行部分,VHDL不允许向一个代码提供多个赋值。如果这两个赋值处于代码的顺序部分将如何处理?编译器可能在某一过程内接受多个赋值,但即便在这种情况下,仅最后一个赋值有效,前面的所有赋值将被忽略。要解释这种情况,应注意过程可以被视为一个黑箱,黑箱的内部运算可通过一些抽象行为描述给出。这一描述使用顺序语句。过程黑箱和外部世界的连接通过信号实现。该过程可能会读取这些信号的值或为这些信号赋一个值。因此,VHDL使用信号将代码的顺序部分与并行域相连接。由于信号已经与代码的并行域相连,所以无法将多个值赋与同一信号。因此,在面对一个信号的多个赋值时,VHDL仅将最后一个赋值视为有效赋值。

更新信号的值

 

过程的黑箱译码揭示了过程当中信号赋值的另一个重要属性:在某一过程中,当我们为一个信号赋一个值时,信号的这一新值不会立即生效。信号值仅在当前过程运行结束后更新。下列实例进一步阐明了这一点。该实例使用VHDL“if”语句。请注意在未来的文章中我们将列举更多此类语句的实例;但因为与其它编程语言的条件结构相似,下列代码应当易于理解。您可参见上篇文章中对该语句的简短描述。

 

实例:为计数范围为0-5的计数器编制VHDL代码。

 

下文提供了一种有效VHDL描述:

                    1 library IEEE;

2 use IEEE.STD_LOGIC_1164.ALL;

 

3 entity SigCounter is

4    Port ( clk : in  STD_LOGIC;

5   out1: out integer range 0 to 5);

6 end SigCounter;

 

7 architecture Behavioral of SigCounter is

 

8 signal sig1 : integer range 0 to 6;

9 begin

10 process(clk)

11 begin

12 if (clk'event and clk='1') then

13 sig1 <= sig1+1;

14 if (sig1=6) then

15 sig1 <= 0;

16 end if;

17 end if;

18 out1 <= sig1;

19 end process;

 

20 end Behavioral;

 

在此实例中,sig1被定义为体系结构声明部分中整数类的信号。依据时钟的每次上升沿,信号sig1的值将增加1。当sig1的值达到6时,第14行中“if”语句的条件将被定值为“true”,sig1将会选择0作为值。因此,最终传输至输出端口out1的sig1值将始终选择范围从0-5的值。换言之,似乎第14行的“if”语句永远不会允许sig1取6为值。下面我们来更仔细地了解下代码的操作。

假设在上次过程运行中sig1设置为5。基于时钟的下一个上升沿,将执行第12行“if”语句中的语句。第13行将为sig1的当前值(5)加1,并将结果赋给sig1。所以sig1的新值为6;但我们应注意信号sig1的值只有在当前过程运行结束后更新。因此,在此次过程运行中,第14行中“if”语句中的条件将被定值为“false”,相应的“then”分支语句将被忽略。sig1的值将在过程正文的末尾被更新为6。虽然在我们计划sig1的取值范围为0-5,但可以取6为值。

同理,在时钟的下一上升沿,第13行将7赋值给sig1。但是,信号值更新将被延迟,直到我们达到过程正文的末尾。在此次过程运行中,第14行“if”语句的条件变为“true”,因此,第15行将sig1值设置为0。如你所见,在此次过程运行中,同一信号有两个赋值。依据上节的论述,仅最后一个赋值有效,例如,sig1的新值将为0。sig1将在过程运行结束后取此新值。如你所见,sig1将在0-6而非0-5的范围内选值!您可在下列代码的ISE仿真中进行验证。

 变量:VHDL语言顺序语句中的重要对象

图3

 

因此,在过程中使用信号时,我们应注意信号的新值将在当前过程运行结束后生效。忽视这一特性往往会导致错误,对于刚接触VHDL的新用户而言尤其如此。

 

综上所述,信号可为电路的互连建模。如果我们为过程中的信号赋予多个值,则仅最后一个赋值有效。而且该已赋值不会立即生效,而是在过程运行结束后生效。

 

变量:另一个重要的VHDL对象

 

正如此前一篇文章中所述,顺序语句可实现电路的算法描述。这一描述的代码在某种程度上与计算机编程语言编写的代码相似。在计算机编程中,“变量”用于储存程序参考并使用的信息。使用变量,我们可以更轻松地在计算机程序设计时描述一种算法,因此,除信号外,VHDL还允许用户在过程中使用变量。信号和变量均可用于代表一个值,但二者间存在若干差异。变量不一定映射到单个互连中。此外,我们还可以将几个值赋给一个变量,新值将立即更新。在下文中,我们将对这一属性进行详细说明。

在开始前,注意变量仅可在顺序单元(如,过程)中声明(本文未涉及的“共享”变量为唯一例外)。要熟知VHDL变量,需考虑下列定义变量var1的代码段。

                    1 process(clk)

2 variable var1 : integer range 0 to 5;13

3 begin

4 var1 := 3;

5 ...

6 end process;

                  

与信号相似,变量可以属于任何数据类型(参见本系列以往的文章了解不同数据类型的详细信息)。变量用于储存中间值,在过程外无法访问。而且,如上述代码第4行所示,变量赋值使用“:=”符号,而信号赋值使用“<=”。

 

一个变量的多个赋值

 

考虑下列代码。在此案例中定义了std_logic类型的变量var1。然后在第12、13和14行中为此变量赋三个值。

                    1 library IEEE;

2 use IEEE.STD_LOGIC_1164.ALL;

 

3 entity VarTest1 is

4    Port ( in1, in2, in3 : in  STD_LOGIC;

5                  out1 : out  STD_LOGIC);

6 end VarTest1;

 

7 architecture Behavioral of VarTest1 is

 

8 begin

 

9 process(in1, in2, in3)

10 variable var1: std_logic; 

11 begin

12 var1 := in1;

13 var1 := (var1 and in2);

14 var1 := (var1 or in3);

15 out1 <= var1;

16 end process;

 

17 end Behavioral;

 

图4显示了Xilinx ISE所生成的上述代码的RTL原理图。

 变量:VHDL语言顺序语句中的重要对象

图4

 

要验证已生成的原理图和过程中所描述行为的匹配非常简单;但是,该实例显示了指向硬件的变量映射在某种程度上比信号的映射更加复杂。这是因为顺序语句可描述电路的行为。如您所见,在本实例中,虽然两个赋值使用同一变量名称(如var1),但第13和14行的每个变量赋值运算均已创建一条新导线。

 

更新变量值

 

变量可立即更新。通过修改上述计时器的代码并用变量代替信号,我们可以对这一属性进行验证。此代码显示如下:

                    1 library IEEE;

2 use IEEE.STD_LOGIC_1164.ALL;

 

3 entity VarCounter is

4    Port ( clk : in  STD_LOGIC;

5   out1: out integer range 0 to 5);

6 end VarCounter;

 

7 architecture Behavioral of VarCounter is

 

8 begin

9 process(clk)

10 variable var1 : integer range 0 to 6;

11 begin

12 if (clk'event and clk='1') then

13 var1 := var1+1;

14 if (var1=6) then

15    var1 := 0;

16 end if;

17 end if;

18 out1 <= var1;

19 end process;

 

20 end Behavioral;

                  

虽然变量的新值可立即生效,但输出值将在0-5的范围内。如下列ISE仿真结果所示。

 变量:VHDL语言顺序语句中的重要对象

图5

 

综述

 

信号模拟电路连接。如果我们赋多个值给过程中的信号,则仅最后一个赋值有效。而且,所赋值将在当前过程动行结束时生效,不会即刻更新。

单个变量可生成若干电路连接。

我们可以为同一变量赋多个值,所赋新值将立即生效。

与信号相同,变量可以是任何数据类型。

在过程中,变量为本地变量。变量用于储存中间值,无法在过程外部访问。

变量的赋值使用“:= ”符号,而信号赋值使用“<=”。

 

  • 变量:VHDL语言顺序语句中的重要对象已关闭评论
    A+
发布日期:2019年03月03日  所属分类:参考设计