Я новичок в разработке плат FPGA и basys3. У меня есть проект для счетчика на 7 сегментных дисплеях на плате. Мы получили 3 разных слоя в качестве дизайна.
cntr / cntr_rtl / cntr_top / cntr_top_stru c / io_ctrl / io_ctrl_rtl /
И в проекте он должен отображать 7 сегмент, управляемый переключателями: считать вверх / считать вниз / параметры удержания / сброса:
Приоритеты для этих переключателей:
сброс
удержание
направление счета
VHDL-файл верхнего уровня cntr_top.vhd
Имя порта Направление Описание
clk_i In Системные часы (100 МГц) )
reset_i In Асинхронный высокий активный сброс
sw_i (15: 0) В 16 переключателях
pb_i (3: 0) В 4 кнопках
ss_o (7: 0) Out Содержит значение для всех 7-сегментных цифр
ss_sel_o (3: 0) Out Выберите 7-сегментный ди git
io_ctrl clk_i In Системные часы (100 МГц)
reset_i In Асинхронный высокий активный сброс
cntr0_i (n: 0) In Di git 0 (из внутреннего лога c)
cntr1_i (n: 0) В Di git 1 (из целого rnal logi c)
cntr2_i (n: 0) в Di git 2 (из внутренней логики c)
cntr3_i (n: 0) в Di git 3 (из внутренней логики c)
sw_i (15: 0) В 16 переключателях (с платы ПЛИС)
pb_i (3: 0) В 4 кнопках (с платы ПЛИС)
ss_o (7: 0) Out на 7-сегментный дисплей платы FPGA
ss_sel_o (3: 0) Out Выбор 7-сегментного ди git
swclean_o (15: 0) Out 16 переключателей (для внутренней логики c)
pbclean_o (3: 0) Out 4 кнопки (для внутренней логики c)
cntr.vhd
clk_i In Системные часы (100 МГц)
reset_i In Асинхронный высокий активный сброс
cntrup_i In Считает, если сигнал равен '1'
cntrdown_i In Считает вниз если сигнал равен '1'
cntrreset_i In Устанавливает счетчик на 0x0, если сигнал равен '1'
cntrhold_i In Имеет значение счетчика, если сигнал равен '1'
cntr0_o (n : 0) Out Di git 0 (из внутренней логики c)
cntr1_o (n: 0) Out Di git 1 (из внутренней логики c)
cntr2_o (n: 0) Out Di git 2 (из внутренней логики c)
cntr3_o (n: 0) Out Di git 3 (из внутренней logi c)
Я также прикреплю файл к приложению. Теперь мой код работает и выполняет все функции правильно, но есть только одна проблема - это часть кода DEBOUNCE.
Я не использовал сигнал clk для кода, и я должен изменить его. Определенный данный тактовый сигнал должен быть использован.
Так что любой может дать мне предложение, как я могу исправить концепцию debounce в коде.
io_ctrl_rtl.vhd - код внизу:
library IEEE;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
architecture rtl of io_ctrl is
constant COUNTVALUE : std_logic_vector(16 downto 0):= "01100001101010000";
signal s_enctr : std_logic_vector(16 downto 0):="00000000000000000";
signal s_2khzen : std_logic :='0';
signal s_1hzen : std_logic :='0';
signal s_2khzcount : std_logic_vector(3 downto 0) := "0000";
signal swsync0 : std_logic_vector(15 downto 0):="0000000000000000";
signal pbsync0 : std_logic_vector(3 downto 0):="0000";
signal swsync1 : std_logic_vector(15 downto 0):="0000000000000000";
signal pbsync1 : std_logic_vector(3 downto 0):="0000";
signal swtmp : std_logic_vector(15 downto 0):="0000000000000000";
signal pbtmp : std_logic_vector(3 downto 0):="0000";
signal swdebounced : std_logic_vector(15 downto 0):="0000000000000000";
signal pbdebounced : std_logic_vector(3 downto 0):="0000";
signal s_ss_sel : std_logic_vector(3 downto 0) := "0000";
signal s_ss : std_logic_vector(7 downto 0) := "00000000";
begin -- rtl
-----------------------------------------------------------------------------
--
-- Synchronize the inputs
--
-----------------------------------------------------------------------------
p_sync: process (clk_i, reset_i)
begin
if reset_i = '1' then
swsync0 <= (others => '0');
pbsync0 <= (others => '0');
swsync1 <= (others => '0');
pbsync1 <= (others => '0');
elsif clk_i'event and clk_i = '1' then
swsync0 <= sw_i;
pbsync0 <= pb_i;
swsync1 <= swsync0;
pbsync1 <= pbsync0;
else null;
end if;
end process;
-----------------------------------------------------------------------------
--
-- Generate 1 KHz enable signal.
--
-----------------------------------------------------------------------------
p_slowen: process (clk_i, reset_i)
begin
if reset_i = '1' then
s_enctr <= (others => '0');
s_2khzen <= '0';
elsif clk_i'event and clk_i = '1' then
if s_enctr = COUNTVALUE then -- When the terminal counter is reached, set the release flag and reset the counter
s_enctr <= (others => '0');
s_2khzen <= '1';
s_2khzcount <= std_logic_vector(to_unsigned(to_integer(unsigned( s_2khzcount )) + 1, 4));
else
s_enctr <= std_logic_vector(to_unsigned(to_integer(unsigned( s_enctr )) + 1, 17)); -- As long as the terminal count is not reached: increment the counter.
if s_2khzen = '1' then
s_2khzen <= '0';
end if;
end if;
if s_2khzcount = "1010" then
s_1hzen <= not s_1hzen;
s_2khzcount <= "0000";
end if;
end if;
end process p_slowen;
-----------------------------------------------------------------------------
--
-- Debounce buttons and switches
--
-----------------------------------------------------------------------------
p_debounce: process (s_1hzen, reset_i)
variable dbouncecntr : integer:=0;
begin
if reset_i = '1' then
swdebounced <= "0000000000000000";
pbdebounced <= "0000";
dbouncecntr :=0; -- Change clocking the process with signal from sens list.
else
if (dbouncecntr = 0) then
swtmp <= swsync1;
pbtmp <= pbsync1;
dbouncecntr := dbouncecntr + 1;
elsif (dbouncecntr = 1) then
if (swtmp = swsync1) then
swdebounced <= swsync1;
end if;
if (pbtmp = pbsync1) then
pbdebounced <= pbsync1;
end if;
dbouncecntr := 0;
end if;
end if;
end process p_debounce;
swclean_o <= swdebounced;
pbclean_o <= pbdebounced;
-----------------------------------------------------------------------------
--
-- Display controller for the 7-segment display
--
-----------------------------------------------------------------------------
p_displaycontrol: process (clk_i, reset_i)
variable v_scancnt : std_logic_vector(1 downto 0):= "00";
variable v_output : std_logic_vector(3 downto 0):="0000";
begin
if reset_i = '1' then
v_scancnt := "00";
s_ss <= "00000000";
elsif clk_i'event and clk_i = '1' then
if s_2khzen = '1' then
case v_scancnt is
when "00" =>
v_output := cntr0_i;
s_ss_sel <= "0001";
when "01" =>
v_output := cntr1_i;
s_ss_sel <= "0010";
when "10" =>
v_output := cntr2_i;
s_ss_sel <= "0100";
when "11" =>
v_output := cntr3_i;
s_ss_sel <= "1000";
when others =>
v_output := "1111";
s_ss_sel <= "0001";
end case;
case v_output is --ABCDEFG,
when "0000" => s_ss <= "11111100"; --0
when "0001" => s_ss <= "01100000"; --1
when "0010" => s_ss <= "11011010"; --2
when "0011" => s_ss <= "11110010"; --3
when "0100" => s_ss <= "01100110"; --4
when "0101" => s_ss <= "10110110"; --5
when "0110" => s_ss <= "10111110"; --6
when "0111" => s_ss <= "11100000"; --7
when "1000" => s_ss <= "11111110"; --8
when "1001" => s_ss <= "11110110"; --9
when others => s_ss <= v_scancnt & "000000";
end case;
if v_scancnt = "11" then
v_scancnt := "00";
else
v_scancnt := std_logic_vector(to_unsigned(to_integer(unsigned( v_scancnt )) + 1, 2));
end if;
else null;
end if;
else null;
end if;
end process p_displaycontrol;
ss_o <= not s_ss;
ss_sel_o <= not s_ss_sel;
end rtl;
Код для: cntr_top_stru c .vhd
library IEEE;
use IEEE.std_logic_1164.all;
architecture rtl of cntr_top is
component cntr -- component of cntr
port (clk_i: in std_logic; -- 100 MHz system clock
reset_i: in std_logic; -- async high active reset
cntrup_i : in std_logic; --counts up if signal is '1'
cntrdown_i : in std_logic; --counts down if signal is '1'
cntrreset_i : in std_logic; --sets counter to 0x0 if signal is '1'
cntrhold_i : in std_logic; --holds count value if signal is '1'
cntr0_o: out std_logic_vector(3 downto 0); -- Digit 0 (from internal logic)
cntr1_o: out std_logic_vector(3 downto 0); -- Digit 1 (from internal logic)
cntr2_o: out std_logic_vector(3 downto 0); -- Digit 2 (from internal logic)
cntr3_o: out std_logic_vector(3 downto 0)); -- Digit 3 (from internal logic)
end component;
component io_ctrl ---- component io_crtl
port (clk_i: in std_logic; -- 100 MHz system clock
reset_i: in std_logic; -- async high active reset
cntr0_i: in std_logic_vector(3 downto 0); -- Digit 0 (from internal logic)
cntr1_i: in std_logic_vector(3 downto 0); -- Digit 1 (from internal logic)
cntr2_i: in std_logic_vector(3 downto 0); -- Digit 2 (from internal logic)
cntr3_i: in std_logic_vector(3 downto 0); -- Digit 3 (from internal logic)
swclean_o: out std_logic_vector(15 downto 0);
pbclean_o: out std_logic_vector(3 downto 0);
ss_o: out std_logic_vector(7 downto 0); -- Contain the Value for All 7-Segment Digits
ss_sel_o: out std_logic_vector(3 downto 0); -- Select a 7-segment digits
pb_i: in std_logic_vector(3 downto 0); --4 Buttons
sw_i: in std_logic_vector(15 downto 0) ); --16 Switches
end component;
-- Declare the signals that are used to connect the submodules.
signal s_cntr0 : std_logic_vector(3 downto 0);
signal s_cntr1 : std_logic_vector(3 downto 0);
signal s_cntr2 : std_logic_vector(3 downto 0);
signal s_cntr3 : std_logic_vector(3 downto 0);
signal s_cntrup : std_logic;
signal s_cntrdown : std_logic;
signal s_cntrreset : std_logic;
signal s_cntrhold : std_logic;
signal s_overflow : std_logic_vector(11 downto 0);
begin
--Instantiate the counter that is connected to the IO-Control
i_cntr_top1 : cntr
port map
(clk_i => clk_i,
reset_i => reset_i,
-- cntrdir_i => s_cntrdir, --swsync_o(13);
cntrup_i => s_cntrup, --swsync_o(13);
cntrdown_i => s_cntrdown, --swsync_o(12);
cntrreset_i => s_cntrreset, --swsync_o(15),
cntrhold_i => s_cntrhold, --swsync_o(14),
cntr0_o => s_cntr0,
cntr1_o => s_cntr1,
cntr2_o => s_cntr2,
cntr3_o => s_cntr3);
--Instantiate the IO control to which it is connected
i_io_ctrl : io_ctrl
port map
(clk_i => clk_i,
reset_i => reset_i,
swclean_o(12) => s_cntrdown,
swclean_o(13) => s_cntrup,
swclean_o(15) => s_cntrreset,
swclean_o(14) => s_cntrhold,
swclean_o(11 downto 0) => s_overflow(11 downto 0),
cntr0_i => s_cntr0,
cntr1_i => s_cntr1,
cntr2_i => s_cntr2,
cntr3_i => s_cntr3,
ss_o => ss_o,
ss_sel_o => ss_sel_o,
sw_i => sw_i,
pb_i => pb_i);
end rtl;
cntr_top.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity cntr_top is
port (clk_i : in std_logic; -- First Data Bit
reset_i : in std_logic; -- Second Data Bit
sw_i : in std_logic_vector (15 downto 0); -- 16 Switches Input
pb_i : in std_logic_vector(3 downto 0); -- 4 Buttons Input
ss_o : out std_logic_vector(7 downto 0); -- Contain the Value for All 7-Segment Digits
ss_sel_o : out std_logic_vector(3 downto 0)); -- Select a 7-segment digits
end cntr_top;
io_ctrl.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity io_ctrl is
port (clk_i : in std_logic; -- System clock (100 MHZ)
reset_i : in std_logic; -- Asynchronous high active reset
cntr0_i : in std_logic_vector(3 downto 0); -- Digit 0 from internal logic
cntr1_i : in std_logic_vector(3 downto 0); -- Digit 1 from internal logic
cntr2_i : in std_logic_vector(3 downto 0); -- Digit 2 from internal logic
cntr3_i : in std_logic_vector(3 downto 0); -- Digit 3 from internal logic
sw_i : in std_logic_vector(15 downto 0); -- 16 switches (from FPGA board)
pb_i : in std_logic_vector(3 downto 0); -- 4 buttons (from FPGA board)
ss_o : out std_logic_vector(7 downto 0); -- to 7 segment displays of the FPGA board
ss_sel_o : out std_logic_vector(3 downto 0); -- Selection of a 7 segment digit
swclean_o: out std_logic_vector(15 downto 0); -- 16 switches (to internal logic)
pbclean_o : out std_logic_vector(3 downto 0)); -- 4 buttons
end io_ctrl;
cntr_rtl.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
architecture rtl of cntr is
constant COUNTVALUE : std_logic_vector(26 downto 0):= "000000000000000001111101000";
--constant COUNTVALUE : std_logic_vector(26 downto 0):= "101111101011110000100000000";
signal s_enctr : std_logic_vector(26 downto 0) := "000000000000000000000000000";
signal s_1hzen : std_logic :='0';
signal s_cntr0 : std_logic_vector(3 downto 0) :="0000"; -- All digits set to zero.
signal s_cntr1 : std_logic_vector(3 downto 0) :="0000";
signal s_cntr2 : std_logic_vector(3 downto 0) :="0000";
signal s_cntr3 : std_logic_vector(3 downto 0) :="0000";
type s_state is (reset, hold, up, down);
signal s_present_state : s_state;
signal s_next_state : s_state;
begin
p_cntr: process(clk_i, reset_i)
variable v_digit0 : std_logic_vector(3 downto 0):= "0000";
variable v_digit1 : std_logic_vector(3 downto 0):= "0000";
variable v_digit2 : std_logic_vector(3 downto 0):= "0000";
variable v_digit3 : std_logic_vector(3 downto 0):= "0000";
begin
if reset_i = '1' then
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := "0000";
v_digit3 := "0000";
s_enctr <= (others => '0');
elsif (clk_i'event and clk_i = '1') then
s_present_state <= s_next_state;
if s_enctr = COUNTVALUE then --When the number of terminals is reached, set the release flag and reset the counter
s_enctr <= (others => '0');
s_1hzen <= '1';
case s_present_state is
when up => --counting up.
if v_digit0 /= "1001" then
v_digit0 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit0 )) + 1, 4)); -- incrementing the bits.
elsif v_digit0 = "1001" and v_digit1 /= "1001" then
v_digit0 := "0000";
v_digit1 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit1 )) + 1, 4));
elsif v_digit0 = "1001" and v_digit1 = "1001" and v_digit2 /= "1001" then
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit2 )) + 1, 4));
elsif v_digit0 = "1001" and v_digit1 = "1001" and v_digit2 = "1001" and v_digit3 /= "1001"then
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := "0000";
v_digit3 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit3 )) + 1, 4));
else
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := "0000";
v_digit3 := "0000";
end if;
when down => --counting down.
if v_digit0 /= "0000" then
v_digit0 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit0 )) - 1, 4)); -- decrementing the bits.
elsif v_digit0 = "0000" and v_digit1 /= "0000" then
v_digit0 := "1001";
v_digit1 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit1 )) - 1, 4));
elsif v_digit0 = "0000" and v_digit1 = "0000" and v_digit2 /= "0000" then
v_digit0 := "1001";
v_digit1 := "1001";
v_digit2 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit2 )) - 1, 4));
elsif v_digit0 = "0000" and v_digit1 = "0000" and v_digit2 = "0000" and v_digit3 /= "0000"then
v_digit0 := "1001";
v_digit1 := "1001";
v_digit2 := "1001";
v_digit3 := std_logic_vector(to_unsigned(to_integer(unsigned( v_digit3 )) - 1, 4));
else
v_digit0 := "1001";
v_digit1 := "1001";
v_digit2 := "1001";
v_digit3 := "1001";
end if;
when hold => null; -- holding the counting.
when reset => -- reset all the values to zero.
v_digit0 := "0000";
v_digit1 := "0000";
v_digit2 := "0000";
v_digit3 := "0000";
end case;
else
s_enctr <=std_logic_vector(to_unsigned(to_integer(unsigned( s_enctr )) + 1, 27));
if s_1hzen = '1' then
s_1hzen <= '0';
end if;
end if;
s_cntr0 <= v_digit0;
s_cntr1 <= v_digit1;
s_cntr2 <= v_digit2;
s_cntr3 <= v_digit3;
end if;
end process p_cntr;
cntr0_o <= s_cntr0;
cntr1_o <= s_cntr1;
cntr2_o <= s_cntr2;
cntr3_o <= s_cntr3;
----------------------------------------------------------------------------------------------------------------
-- State machine
----------------------------------------------------------------------------------------------------------------
p_states: process(s_present_state, cntrup_i, cntrdown_i, cntrreset_i, cntrhold_i,reset_i)
begin
case s_present_state is
when reset => -- reset state conditions
if cntrreset_i = '1' then
s_next_state <= reset;
elsif cntrhold_i = '1' then
s_next_state <= hold;
elsif cntrup_i = '1' then
s_next_state <= up;
elsif cntrdown_i = '1' then
s_next_state <= down;
else s_next_state <= hold;
end if;
when hold => -- hold state conditions
if cntrreset_i = '1' then
s_next_state <= reset;
elsif cntrhold_i = '1' then
s_next_state <= hold;
elsif cntrup_i = '1' then
s_next_state <= up;
elsif cntrdown_i = '1' then
s_next_state <= down;
else s_next_state <= hold;
end if;
when up => -- up count state conditions
if cntrreset_i = '1' then
s_next_state <= reset;
elsif cntrhold_i = '1' then
s_next_state <= hold;
elsif cntrup_i = '1' then
s_next_state <= up;
elsif cntrdown_i = '1' then
s_next_state <= down;
else s_next_state <= hold;
end if;
when down => -- down count conditions
if cntrreset_i = '1' then
s_next_state <= reset;
elsif cntrhold_i = '1' then
s_next_state <= hold;
elsif cntrup_i = '1' then
s_next_state <= up;
elsif cntrdown_i = '1' then
s_next_state <= down;
else s_next_state <= hold;
end if;
when others => s_next_state <= reset;
end case;
end process p_states;
end rtl;
cntr.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity cntr is
port (clk_i : in std_logic; -- System clock (100 MHZ)
reset_i : in std_logic; -- Asysnchronous high active reset
cntrup_i : in std_logic; --counts up if signal is '1'
cntrdown_i : in std_logic; --counts down if signal is '1'
cntrreset_i : in std_logic; --sets counter to 0x0 if signal is '1'
cntrhold_i : in std_logic; --holds count value if signal is '1'
cntr0_o : out std_logic_vector(3 downto 0); -- Digit 0 (from internal logic)
cntr1_o : out std_logic_vector(3 downto 0); -- Digit 1 (from internal logic)
cntr2_o : out std_logic_vector(3 downto 0); -- Digit 2 (from internal logic)
cntr3_o : out std_logic_vector(3 downto 0)); -- Digit 3 (from internal logic)
end cntr;
Пожалуйста, ждите ваших предложений.
Любая помощь будет очень полезна, спасибо всем.
здесь ниже пример для debounce, но не смог найти способ реализации.
-----------------------------------------------------------------------------
--
-- Debounce buttons and switches
--
-----------------------------------------------------------------------------
p_debounce: process (clk_i, reset_i)
begin -- process debounce
if reset_i = '1' then -- asynchronous reset (active high)
elsif clk_i'event and clk_i = '1' then -- rising clock edge
end if;
end process p_debounce;
swsync_o <= swsync;
pbsync_o <= pbsync;
------------------------------------------------------------