- вторая ветвь тракта: отсчёты ФНЧ -> пересчёт в 48 828 Гц -> I2S на PCM5102A (dac_stream.v, i2s_transmitter.v), тест tb_dac_stream.v; - кнопка S1 (H11): усиление ветви ЦАП ступенями по +6 дБ, показ ступени светодиодом (gain_button.vhd), тест tb_gain_button.vhd; - микрофон через линию SN65LVDS: точка выборки MIC_SMP_CNT = 12 по измерению на плате (pdm_rx.vhd), в tb_top модель линии; - новая распиновка: MIC_CLK K8, MIC_DAT K9, ЦАП G1/G2/L4/L3, UART_TX C3 на встроенный мост BL616; - сборка под GW5A-25 ревизии A, настройки PnR (CPU/SSPI/READY как GPIO); - отладочный выход PLL 80 МГц на E3.
184 lines
5.5 KiB
VHDL
184 lines
5.5 KiB
VHDL
----------------------------------------------------------------------------------
|
|
-- 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;
|