VHDL中信號與變量的差異


      在VHDL中,使用信號(signal)或變量(variable)可以實現動態數值的傳遞,二者功能雖然類似,但在實現方式上卻有着很大的區別。對於初學者,理解信號和變量的差異是十分重要的。

1. 信號(signal)

      信號是邏輯電路中的連接線,可以用於元件間和元件內部電路各單元間的連接。

      信號使用”<=“符號賦值。

      在順序描述語句中,信號的賦值不是即時更新的。只有在相應的進程、函數或過程完成之后,信號的值才會進行更新。


2. 變量(variable)

      變量只用於局部電路的描述,只能在process、function和procedure內部使用。

      變量使用”:=“符號賦值。

      變量的賦值是立即生效的,可以在下一行代碼中立即使用新的變量值。


3. 信號與變量賦值的生效時刻

      信號與變量的一個重要差異是賦值是否立即生效。對變量的賦值是立即生效的,而在順序描敘語句中對信號的賦值則不會立即生效,只有當信號所在的process內的操作全部完成一遍后,信號的值才會更新。

      下面通過兩個例子說明信號與變量賦值的生效時刻。如下面所示的兩個計數器:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;

entity counter is
    port(    rst : in std_logic;
            clk : in std_logic;
            clk_cnt_1 : out std_logic_vector(3 downto 0);
            clk_cnt_2 : out std_logic_vector(3 downto 0)
    );
end counter;

architecture Behavioral of counter is

    signal s_cnt : std_logic_vector(3 downto 0) := (others => '0');

begin

p_signal_counter:
    process(rst, clk)
    begin
        if rst = '0' then
            clk_cnt_1 <= (others => '0');
            s_cnt <= (others => '0');
        elsif clk' event and clk = '1' then
            s_cnt <= s_cnt + 1;
            clk_cnt_1 <= s_cnt;
        end if;
    end process;

p_variable_counter:    
    process(rst, clk)
    variable v_cnt : std_logic_vector(3 downto 0) := (others => '0');
    begin
        if rst = '0' then
            clk_cnt_2 <= (others => '0');
            v_cnt := (others => '0');
        elsif clk' event and clk = '1' then
            v_cnt := v_cnt + 1;
            clk_cnt_2 <= v_cnt;
        end if;
    end process;

end Behavioral;

 

其中,p_signal_counter中使用信號v_cnt做計數,並更新clk_cnt_1;p_variable_counter中使用變量v_cnt做計數,並更新clk_cnt_2。仿真結果如圖1所示。



 

圖1

      由圖1可見,clk_cnt_1得計數值比clk_cnt_2的值小1,clk_cnt_1更新的比clk_cnt_2慢,因為v_cnt是信號,"s_cnt <= s_cnt + 1;"對其的賦值需要等到p_signal_counter執行完畢后才生效,而v_cnt是變量,"v_cnt := v_cnt + 1;"對其的賦值是立即生效的。更進一步地把上面的計數器改寫如下:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;

entity counter is
    port(    rst : in std_logic;
            clk : in std_logic;
            clk_cnt_1 : out std_logic_vector(3 downto 0);
            clk_cnt_1_before_update : out std_logic_vector(3 downto 0);
            clk_cnt_2 : out std_logic_vector(3 downto 0);
            clk_cnt_2_before_update : out std_logic_vector(3 downto 0)
    );
end counter;

architecture Behavioral of counter is

    signal s_cnt : std_logic_vector(3 downto 0) := (others => '0');

begin

p_signal_counter:
    process(rst, clk)
    begin
        if rst = '0' then
            clk_cnt_1 <= (others => '0');
            clk_cnt_1_before_update <= (others => '0');
            s_cnt <= (others => '0');
        elsif clk' event and clk = '1' then
            clk_cnt_1_before_update <= s_cnt;
            s_cnt <= s_cnt + 1;
            clk_cnt_1 <= s_cnt;
        end if;
    end process;

p_variable_counter:    
    process(rst, clk)
    variable v_cnt : std_logic_vector(3 downto 0) := (others => '0');
    begin
        if rst = '0' then
            clk_cnt_2 <= (others => '0');
            clk_cnt_2_before_update <= (others => '0');
            v_cnt := (others => '0');
        elsif clk' event and clk = '1' then
            clk_cnt_2_before_update <= v_cnt;
            v_cnt := v_cnt + 1;
            clk_cnt_2 <= v_cnt;
        end if;
    end process;

end Behavioral;

 

其中,分別用clk_cnt_1_before_update和clk_cnt_2_before_update來觀測s_cnt和v_cnt在其更新語句前的狀態,仿真結果如圖2所示。



圖2


      由圖2可見,clk_cnt_1_before_update與clk_cnt_1相同,說明"s_cnt <= s_cnt + 1;"語句執行后s_cnt並沒有更新;而clk_cnt_2_before_update的值比clk_cnt_2的值小1,說明"v_cnt := v_cnt+ 1;"語句執行后v_cnt立即得到了更新。


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM