VHDL-comment créer une horloge dans un banc d'essai?

comment créer une horloge dans un banc d'essai? J'ai déjà trouvé une réponse, mais d'autres sur le débordement de la pile ont suggéré qu'il existe d'autres moyens ou de meilleurs pour y parvenir:

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;

(source ici)

18
demandé sur alexdavey 2013-07-28 06:47:07

4 réponses

Ma technique préférée:

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

j'étends Habituellement cela avec un finished signal pour me permettre d'arrêter l'horloge:

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

Gotcha alerte: Il faut faire attention si vous calculez half_period à partir d'une autre constante en divisant par 2. Le simulateur a un réglage de "résolution temporelle", qui est souvent exprimé par défaut en nanosecondes... Dans ce cas, 5 ns / 2 sort 2 ns donc vous finissez avec une période de 4ns! Réglez le simulateur sur picosecondes et tout sera bien (jusqu'à ce que vous avez besoin de fractions d'une picoseconde pour représenter votre temps d'horloge de toute façon!)

20
répondu Martin Thompson 2013-07-28 20:13:17

si plusieurs horloges sont générées avec des fréquences différentes, alors la génération d'horloge peut être simplifiée si une procédure est appelée appel de procédure concurrent. La question de la résolution temporelle, mentionnée par Martin Thompson, peut être atténuée un peu en utilisant un temps faible et élevé différent dans la procédure. Le banc d'essai avec la procédure de génération d'horloge est:

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;

la résolution de temps est imprimée sur le terminal pour information, en utilisant le concurrent assert last dans le test banc.

Si le

les formes d'onde pour les horloges sont indiquées dans la figure ci-dessous.

Waveforms for clk_166 and clk_125

un générateur d'horloge plus avancé peut également être créé dans la procédure, qui peut ajuster la période au fil du temps pour correspondre à la fréquence demandée malgré la limitation par la résolution de temps. Ceci est illustré ici:

-- 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;

réutiliser à nouveau dans un paquet sera bien.

15
répondu Morten Zilmer 2013-07-29 12:49:53

attribution simultanée du signal:

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 -foo.vhdl

ghdl -r toto --stop-time=10ns --onde=foo.ghw

ghdl:info: simulation arrêté par --stop-temps

gtkwave foo.ghw

enter image description here

les simulateurs simulent des processus et ils seraient transformés en un processus équivalent à votre énoncé de processus. Le temps de Simulation implique l'utilisation de l'attente ou de l'après au moment de la conduite événements pour les clauses de sensibilité ou les listes de sensibilité.

8
répondu user1155120 2015-07-27 07:45:08

comment utiliser une horloge et faire des assertions

cet exemple montre comment générer une horloge, donner des entrées et affirmer des sorties pour chaque cycle. Un compteur simple est testé ici.

L'idée clé est que le process blocs s'exécuter en parallèle, de sorte que l'horloge est générée en parallèle avec les entrées et les assertions.

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;

Le compteur devrait ressembler à ceci:

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;

connexes: https://electronics.stackexchange.com/questions/148320/proper-clock-generation-for-vhdl-testbenches

1