2013-07-28 87 views
16

我應該如何在測試平臺中創建時鐘?我已經找到了一個答案,但是別人在堆棧溢出表明,有實現這一目標的替代或更好的方法:VHDL - 我應該如何在測試平臺中創建時鐘?

LIBRARY ieee; 
USE ieee.std_logic_1164.ALL; 

ENTITY test_tb IS 
END test_tb; 

ARCHITECTURE behavior OF test_tb IS 

    COMPONENT test 
     PORT(clk : IN std_logic;) 
    END COMPONENT; 

    signal clk : std_logic := '0'; 
    constant clk_period : time := 1 ns; 

BEGIN 

    uut: test PORT MAP (clk => clk);  

    -- Clock process definitions(clock with 50% duty cycle is generated here. 
    clk_process :process 
    begin 
     clk <= '0'; 
     wait for clk_period/2; --for 0.5 ns signal is '0'. 
     clk <= '1'; 
     wait for clk_period/2; --for next 0.5 ns signal is '1'. 
    end process; 

END; 

(來源here

+0

此方法就好了。 – Qiu

+0

http://electronics.stackexchange.com/questions/148320/proper-clock-generation-for-vhdl-testbenches –

回答

17

我偏愛的技巧:

signal clk : std_logic := '0'; -- make sure you initialise! 
... 
clk <= not clk after half_period; 

我通常用finished信號擴展這個讓我停止時鐘:

clk <= not clk after half_period when finished /= '1' else '0'; 

疑難雜症警報: 護理需要採取如果你用另一個常數除以2來計算half_period。仿真器具有「時間分辨率」設置,該設置通常默認爲n anoseconds ...在這種情況下,5 ns/2出來是2 ns,所以你最終得到4ns的時間!將模擬器設置爲皮秒,一切都會好(直到你需要幾分之一皮秒來表示你的時鐘時間)

7

併發信號分配:

library ieee; 
use ieee.std_logic_1164.all; 

entity foo is 
end; 
architecture behave of foo is 
    signal clk: std_logic := '0'; 
begin 
CLOCK: 
clk <= '1' after 0.5 ns when clk = '0' else 
     '0' after 0.5 ns when clk = '1'; 
end; 

ghdl -a foo.vhdl
ghdl -r富--stop時間爲10ns = = --wave foo.ghw
ghdl:信息:■ imulation通過--stop時停止
gtkwave foo.ghw

enter image description here

模擬器模擬程序,它會轉化爲等價的過程對您的過程聲明。模擬時間意味着在駕駛敏感性條款或敏感性列表事件時使用等待或之後。

12

如果生成多個不同頻率的時鐘,那麼如果調用一個過程,則可以簡化時鐘生成作爲併發程序調用。馬丁湯普森提到的時間分辨率問題可以通過在程序中使用不同的高低時間來減輕。試驗檯具有用於時鐘產生程序是:

library ieee; 
use ieee.std_logic_1164.all; 

entity tb is 
end entity; 

architecture sim of tb is 

    -- Procedure for clock generation 
    procedure clk_gen(signal clk : out std_logic; constant FREQ : real) is 
    constant PERIOD : time := 1 sec/FREQ;  -- Full period 
    constant HIGH_TIME : time := PERIOD/2;   -- High time 
    constant LOW_TIME : time := PERIOD - HIGH_TIME; -- Low time; always >= HIGH_TIME 
    begin 
    -- Check the arguments 
    assert (HIGH_TIME /= 0 fs) report "clk_plain: High time is zero; time resolution to large for frequency" severity FAILURE; 
    -- Generate a clock cycle 
    loop 
     clk <= '1'; 
     wait for HIGH_TIME; 
     clk <= '0'; 
     wait for LOW_TIME; 
    end loop; 
    end procedure; 

    -- Clock frequency and signal 
    signal clk_166 : std_logic; 
    signal clk_125 : std_logic; 

begin 

    -- Clock generation with concurrent procedure call 
    clk_gen(clk_166, 166.667E6); -- 166.667 MHz clock 
    clk_gen(clk_125, 125.000E6); -- 125.000 MHz clock 

    -- Time resolution show 
    assert FALSE report "Time resolution: " & time'image(time'succ(0 fs)) severity NOTE; 

end architecture; 

時間分辨率被打印的終端的信息,使用最後在測試臺併發斷言。

如果clk_gen程序放在一個單獨的程序包中,那麼從測試臺到測試臺的重新使用就變得非常簡單。

時鐘波形如下圖所示。

Waveforms for clk_166 and clk_125

一種更先進的時鐘發生器還可以在程序中,其可以調節期間隨着時間的推移所請求的頻率儘管時間分辨率的限制相匹配創建。這是顯示在這裏:

-- Advanced procedure for clock generation, with period adjust to match frequency over time, and run control by signal 
procedure clk_gen(signal clk : out std_logic; constant FREQ : real; PHASE : time := 0 fs; signal run : std_logic) is 
    constant HIGH_TIME : time := 0.5 sec/FREQ; -- High time as fixed value 
    variable low_time_v : time;     -- Low time calculated per cycle; always >= HIGH_TIME 
    variable cycles_v : real := 0.0;    -- Number of cycles 
    variable freq_time_v : time := 0 fs;   -- Time used for generation of cycles 
begin 
    -- Check the arguments 
    assert (HIGH_TIME /= 0 fs) report "clk_gen: High time is zero; time resolution to large for frequency" severity FAILURE; 
    -- Initial phase shift 
    clk <= '0'; 
    wait for PHASE; 
    -- Generate cycles 
    loop 
    -- Only high pulse if run is '1' or 'H' 
    if (run = '1') or (run = 'H') then 
     clk <= run; 
    end if; 
    wait for HIGH_TIME; 
    -- Low part of cycle 
    clk <= '0'; 
    low_time_v := 1 sec * ((cycles_v + 1.0)/FREQ) - freq_time_v - HIGH_TIME; -- + 1.0 for cycle after current 
    wait for low_time_v; 
    -- Cycle counter and time passed update 
    cycles_v := cycles_v + 1.0; 
    freq_time_v := freq_time_v + HIGH_TIME + low_time_v; 
    end loop; 
end procedure; 

通過一個包再次重用將是很好的。

0

如何使用時鐘並做斷言

這個例子說明如何產生時鐘,並提供輸入和輸出斷言爲每個週期。這裏測試一個簡單的計數器。

關鍵的想法是process塊並行運行,所以時鐘與輸入和斷言並行生成。

library ieee; 
use ieee.std_logic_1164.all; 

entity counter_tb is 
end counter_tb; 

architecture behav of counter_tb is 
    constant width : natural := 2; 
    constant clk_period : time := 1 ns; 

    signal clk : std_logic := '0'; 
    signal data : std_logic_vector(width-1 downto 0); 
    signal count : std_logic_vector(width-1 downto 0); 

    type io_t is record 
     load : std_logic; 
     data : std_logic_vector(width-1 downto 0); 
     count : std_logic_vector(width-1 downto 0); 
    end record; 
    type ios_t is array (natural range <>) of io_t; 
    constant ios : ios_t := (
     ('1', "00", "00"), 
     ('0', "UU", "01"), 
     ('0', "UU", "10"), 
     ('0', "UU", "11"), 

     ('1', "10", "10"), 
     ('0', "UU", "11"), 
     ('0', "UU", "00"), 
     ('0', "UU", "01") 
    ); 
begin 
    counter_0: entity work.counter port map (clk, load, data, count); 

    process 
    begin 
     for i in ios'range loop 
      load <= ios(i).load; 
      data <= ios(i).data; 
      wait until falling_edge(clk); 
      assert count = ios(i).count; 
     end loop; 
     wait; 
    end process; 

    process 
    begin 
     for i in 1 to 2 * ios'length loop 
      wait for clk_period/2; 
      clk <= not clk; 
     end loop; 
     wait; 
    end process; 
end behav; 

計數器是這樣的:

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; -- unsigned 

entity counter is 
    generic (
     width : in natural := 2 
    ); 
    port (
     clk, load : in std_logic; 
     data : in std_logic_vector(width-1 downto 0); 
     count : out std_logic_vector(width-1 downto 0) 
    ); 
end entity counter; 

architecture rtl of counter is 
    signal cnt : unsigned(width-1 downto 0); 
begin 
    process(clk) is 
    begin 
     if rising_edge(clk) then 
      if load = '1' then 
       cnt <= unsigned(data); 
      else 
       cnt <= cnt + 1; 
      end if; 
     end if; 
    end process; 
    count <= std_logic_vector(cnt); 
end architecture rtl;