---------------------------------------------------------------------------------- -- Module Name: tb_gain_button -- Project Name: DigMic_prj -- Description: -- Тест кнопки усиления ЦАП. Такт уменьшен до 100 кГц: показ длится секунды, -- а в миллисекундах модуль считает сам, так что поведение то же. -- -- Проверяется: -- импульс короче времени дребезга -- не нажатие; -- дребезг на обоих фронтах даёт ровно один шаг, отпускание -- ни одного; -- ступени идут по кругу 1..GAIN_MAX -> 0; -- долгое удержание -- один шаг, без автоповтора; -- показ: N коротких вспышек, для 0 одна длинная, потом светодиод свободен; -- нажатие во время показа начинает показ заново с новым значением. ---------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use std.env.all; entity tb_gain_button is end entity tb_gain_button; architecture sim of tb_gain_button is constant CLK_HZ : integer := 100_000; constant CLK_T : time := 1 sec / CLK_HZ; constant GMAX : integer := 3; signal clk : std_logic := '0'; signal run : boolean := true; signal btn : std_logic := '0'; signal gain : unsigned(3 downto 0); signal show : std_logic; signal led : std_logic; begin clk <= not clk after CLK_T / 2 when run else '0'; dut : entity work.gain_button(rtl) generic map( SYS_CLK_HZ => CLK_HZ, GAIN_MAX => GMAX, BTN_ACTIVE => '1', DEBOUNCE_MS => 20 ) port map ( clk => clk, btn => btn, gain => gain, show => show, led => led ); stim_proc : process variable errors : integer := 0; variable want : integer := 0; -- Фронт кнопки с дребезгом: четыре отскока по 1-2 мс procedure bounce(level : std_logic) is begin for i in 1 to 4 loop btn <= level; wait for 2 ms; btn <= not level; wait for 1 ms; end loop; btn <= level; end procedure; procedure press is begin bounce('1'); wait for 100 ms; bounce('0'); wait for 50 ms; end procedure; procedure check_gain(expect : integer; what : string) is begin if to_integer(gain) /= expect then report what & ": gain " & integer'image(to_integer(gain)) & ", want " & integer'image(expect) severity error; errors := errors + 1; end if; end procedure; -- Вспышки до конца показа: для 0 одна длинная, иначе expect коротких procedure check_flashes(expect : integer) is variable n : integer := 0; variable t0 : time; variable w : time; variable wn : time; begin if expect = 0 then wn := 1000 ms; else wn := 150 ms; end if; if show /= '1' then report "no display after press" severity error; errors := errors + 1; return; end if; loop wait until led = '1' or show = '0'; exit when show = '0'; t0 := now; wait until led = '0'; w := now - t0; n := n + 1; if w < wn - 3 ms or w > wn + 3 ms then report "flash " & integer'image(n) & " lasts " & time'image(w) & ", want " & time'image(wn) severity error; errors := errors + 1; end if; end loop; if (expect = 0 and n /= 1) or (expect > 0 and n /= expect) then report "flashes " & integer'image(n) & " for gain " & integer'image(expect) severity error; errors := errors + 1; else report "gain " & integer'image(expect) & ": " & integer'image(n) & " flash(es) of " & time'image(wn); end if; end procedure; begin wait for 50 ms; check_gain(0, "after power-up"); assert show = '0' report "display active without a press" severity error; -- Короткий импульс -- помеха, не нажатие btn <= '1'; wait for 5 ms; btn <= '0'; wait for 100 ms; check_gain(0, "after 5 ms glitch"); if show /= '0' then report "glitch started a display" severity error; errors := errors + 1; end if; -- По кругу: 1, 2, 3, 0, 1 for k in 1 to GMAX + 2 loop press; want := (want + 1) mod (GMAX + 1); check_gain(want, "press " & integer'image(k)); check_flashes(want); end loop; -- Долгое удержание -- один шаг bounce('1'); wait for 2 sec; bounce('0'); wait for 50 ms; want := (want + 1) mod (GMAX + 1); check_gain(want, "long hold"); if show = '1' then wait until show = '0'; end if; -- Нажатие посреди показа: показ заново, с новым значением press; want := (want + 1) mod (GMAX + 1); wait for 700 ms; press; want := (want + 1) mod (GMAX + 1); check_gain(want, "press during display"); check_flashes(want); if errors = 0 then report "TEST PASSED"; else report "TEST FAILED: errors = " & integer'image(errors) severity error; end if; run <= false; stop; end process stim_proc; end architecture sim;