2013-07-28 60 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;