2013-12-13 3 views
1

Моя fpga - спартанская 3E-100 Cp132. У меня есть четыре кнопки в качестве моих входов, и я хочу увеличить четыре цифры на 7-сегментном доске, используя их. Код VHDL ниже:Увеличение семи сегментов с помощью кнопок Push

entity main is 
    port(b1,b2,b3,b4 : in STD_LOGIC; 
      clk   : in STD_LOGIC; 
      sseg  : out STD_LOGIC_VECTOR(0 to 6); 
      anodes  : out STD_LOGIC_VECTOR(3 downto 0); 
      reset   : in STD_LOGIC 
     ); 
end main; 

architecture Behavioral of main is 
    signal bcd1, bcd2, bcd3, bcd4 : STD_LOGIC_VECTOR (3 downto 0); 
    signal clk2 : STD_LOGIC; 
    signal pushbuttons : STD_LOGIC_VECTOR(3 downto 0); 
    signal db_pushbuttons : STD_LOGIC_VECTOR(3 downto 0); 
    signal counter : STD_LOGIC_VECTOR(1 downto 0); 
    signal clk_divider : STD_LOGIC_VECTOR(20 downto 0); 
    component Debounce is 
     port(cclk : in STD_LOGIC; 
       inp : in STD_LOGIC_VECTOR(3 downto 0); 
       cclr : in STD_LOGIC; 
       db : out STD_LOGIC_VECTOR(3 downto 0) 
       ); 
    end component; 
begin 
    pushbuttons <= b4 & b3 & b2 & b1; 
    Db : Debounce port map 
      (cclk => clk2, 
       inp => pushbuttons, 
       cclr => reset, 
       db => db_pushbuttons); 

process (clk) 
begin 
    if rising_edge(clk) then 
     if clk_divider <= "1100001101010000" then 
      clk_divider <= clk_divider + 1; 
      clk2 <= '0'; 
     else 
      clk_divider <= (others => '0'); 
      clk2 <= '1'; 
     end if; 
    end if; 
end process; 

process (clk2, reset) 
begin 
    if reset = '1' then 
     -- do something here 
     bcd1 <= "0000"; 
     bcd2 <= "0000"; 
     bcd3 <= "0000"; 
     bcd4 <= "0000"; 
    elsif rising_edge(clk2) then 
     counter <= counter + 1; 
     if db_pushbuttons(0) = '1' then -- db_b1 
      if bcd1 <= "1000" then 
       bcd1 <= bcd1 + 1; 
      else 
       bcd1 <= "0000"; 
      end if; 
     elsif db_pushbuttons(1) = '1' then -- db_b2 
      if bcd2 <= "1000" then 
       bcd2 <= bcd2 + 1; 
      else 
       bcd2 <= "0000"; 
      end if; 
     elsif db_pushbuttons(2) = '1' then -- db_b3 
      if bcd3 <= "1000" then 
       bcd3 <= bcd3 + 1; 
      else 
       bcd3 <= "0000"; 
      end if; 
     elsif db_pushbuttons(3) = '1' then --db_b4 
      if bcd4 <= "1000" then 
       bcd4 <= bcd4 + 1; 
      else 
       bcd4 <= "0000"; 
      end if; 
     end if; 
    end if; 
end process; 

process (counter, bcd1, bcd2, bcd3, bcd4) 
    variable display : STD_LOGIC_VECTOR(3 downto 0); 
begin 
    case counter is 
     when "00" => anodes <= "1110"; display := bcd1; 
     when "01" => anodes <= "1101"; display := bcd2; 
     when "10" => anodes <= "1011"; display := bcd3; 
     when "11" => anodes <= "0111"; display := bcd4; 
     when others => null; 
    end case; 

    case display is 
     when "0000" => sseg <= "0000001"; --0 
     when "0001" => sseg <= "1001111"; --1 
     when "0010" => sseg <= "0010010"; --2 
     when "0011" => sseg <= "0000110"; --3 
     when "0100" => sseg <= "1001100"; --4 
     when "0101" => sseg <= "0100100"; --5 
     when "0110" => sseg <= "0100000"; --6 
     when "0111" => sseg <= "0001111"; --7 
     when "1000" => sseg <= "0000000"; --8 
     when "1001" => sseg <= "0000100"; --9 
     when others => sseg <= "0010000"; --e, represents error 
    end case; 
end process; 
end Behavioral; 

Каждого кнопочный выключатель должен увеличивать соответствующие 7-сегментные цифры (b1 -> правая цифра и b4 -> крайняя левая цифра) на единице. Проблема в том, что когда я нажимаю кнопку, она выполняет задание, но не увеличивает его на одно, а некоторое произвольное число. Причина в том, что он увеличивается на единицу при каждом нарастающем фронте часов 2, и это происходит слишком быстро из-за частоты этих часов. Как я могу избавиться от этой проблемы? Я попробовал несколько кнопок для отладки для кнопок, но они не были так полезны. Я полностью застрял здесь. Я имею в виду, что должен быть способ сделать это, но как? Кстати, код дребезга, что я использую с кодом выше

entity Debounce is 
    port(cclk  : in STD_LOGIC; 
      inp : in STD_LOGIC_VECTOR(3 downto 0); 
      cclr : in STD_LOGIC; 
      db  : out STD_LOGIC_VECTOR(3 downto 0) 
     ); 
end Debounce; 

architecture Behavioral of Debounce is 
    signal delay1, delay2, delay3 : STD_LOGIC_VECTOR(3 downto 0); 
begin 
    process (cclk, cclr) 
    begin 
     if cclr = '1' then 
      delay1 <= "0000"; 
      delay2 <= "0000"; 
      delay3 <= "0000"; 
     elsif rising_edge(cclk) then 
      delay1 <= inp; 
      delay2 <= delay1; 
      delay3 <= delay2; 
     end if; 
    end process; 
    db <= delay1 and delay2 and delay3; 
end Behavioral; 

Таким образом, любая помощь будет оценена, спасибо заранее!

+0

Какова частота clk? – Josh

+0

Должно быть, это 50 МГц. Это стандартные часы на FPGA. – user3100463

ответ

1

Если назначенная функция кнопки состоит в том, что вы будете увеличивать один раз один раз, независимо от того, как долго вы удерживаете ее, вам необходимо реализовать «обнаружение края» на выходе дебютационного переключателя. То есть, только разрешить счету bcd увеличивать/обновлять нарастающий фронт сигнала деблокированного переключателя. Например:

... 
elsif rising_edge(clk2) then 
    counter <= counter + 1; 
    db_pushbuttons_previous <= db_pushbuttons; 
    if db_pushbuttons(0) = '1' and db_pushbuttons_previous(0) = '0' then --rising edge detect 
     if bcd1 <= "1000" then 
      bcd1 <= bcd1 + 1; 
     else 
      bcd1 <= "0000"; 
     end if; 
... 

Таким образом, независимо от того, как долго db_pushbuttons(0) утверждается, значение BCD будет увеличиваться только один раз.

+0

Но если я это сделаю, я создаю FSM, верно? Я не уверен, где можно разместить назначение сигнала в коде? Нужно ли мне создать другой процесс или просто переместить его в существующие? – user3100463

+0

Вы, сэр, наконец, положили конец моему несчастью. Большое спасибо! – user3100463

0

Тестирование с помощью GHDL У меня есть следующий код. файл: sevensegns.vhdl

----------------------------------------- 
---- SevenSegNS.vhdl 
---- Seven segment driver with 4 input 
---- buttons 

---- Author: Derby Russell 
---- Date: 12-13-2013 
----------------------------------------- 
library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use ieee.numeric_std.ALL; 

entity main_7_seg is 
    port(b1,b2,b3,b4 : in std_logic; 
      clk   : in std_logic; 
      sseg  : out std_logic_vector(0 to 6); 
      anodes  : out std_logic_vector (3 downto 0); 
      reset  : in std_logic 
     ); 
end main_7_seg; 

architecture behavioral of main_7_seg is 
    signal bcd1, bcd2, bcd3, bcd4 : unsigned (3 downto 0) := "0000"; 
    signal clk2 : std_logic := '0'; 
    signal pushbuttons : std_logic_vector(3 downto 0) := "0000"; 
    signal db_pushbuttons : std_logic_vector(3 downto 0) := "0000"; 
    signal counter : unsigned (1 downto 0) := "00"; 
    component Debounce is 
     port(cclk : in std_logic; 
       inp : in std_logic_vector(3 downto 0); 
       cclr : in std_logic; 
       db : out std_logic_vector(3 downto 0) 
       ); 
    end component; 
begin 
    pushbuttons <= b4 & b3 & b2 & b1; 
    Db : Debounce port map 
      (cclk => clk2, 
       inp => pushbuttons, 
       cclr => reset, 
       db => db_pushbuttons); 
process (clk) 
begin 
    if rising_edge(clk) then 
     clk2 <= '1'; 
    else 
     clk2 <= '0'; 

    -- FOR RUNNING ON ACTUAL HARDWARE: 
    -- RESTORE NEXT 6 LINES AND COMMENT OUT ABOVE 4 LINES. 

    -- if clk_divider <= "1100001101010000" then 
    --  clk_divider <= clk_divider + 1; 
    --  clk2 <= '0'; 
    -- else 
    --  clk_divider <= (others => '0'); 
    --  clk2 <= '1'; 


    end if; 
end process; 

P2: process (clk2, reset) 
begin 
    if reset = '1' then 
     -- do something here 
     bcd1 <= "0000"; 
     bcd2 <= "0000"; 
     bcd3 <= "0000"; 
     bcd4 <= "0000"; 
    elsif rising_edge(clk2) then 
     counter <= counter + 1; 
     if db_pushbuttons(0) = '1' then -- db_b1 
      if bcd1 <= "0010" then 
       if bcd1 = "0000" then 
        bcd1 <= bcd1 + 1; 
       end if; 
      else 
       bcd1 <= "0000"; 
      end if; 
     elsif db_pushbuttons(1) = '1' then -- db_b2 
      if bcd2 <= "0010" then 
       if bcd2 = "0000" then 
        bcd2 <= bcd2 + 1; 
       end if; 
      else 
       bcd2 <= "0000"; 
      end if; 
     elsif db_pushbuttons(2) = '1' then -- db_b3 
      if bcd3 <= "0010" then 
       if bcd3 = "0000" then 
        bcd3 <= bcd3 + 1; 
       end if; 
      else 
       bcd3 <= "0000"; 
      end if; 
     elsif db_pushbuttons(3) = '1' then --db_b4 
      if bcd4 <= "0010" then 
       if bcd4 = "0000" then 
        bcd4 <= bcd4 + 1; 
       end if; 
      else 
       bcd4 <= "0000"; 
      end if; 
     end if; 
    end if; 
end process P2; 

P3: process (counter, bcd1, bcd2, bcd3, bcd4) 
    -- variable display : std_logic_vector(3 downto 0); 
    variable display : unsigned (3 downto 0); 
begin 
    case counter is 
     when "00" => anodes <= "1110"; display := bcd1; 
     when "01" => anodes <= "1101"; display := bcd2; 
     when "10" => anodes <= "1011"; display := bcd3; 
     when "11" => anodes <= "0111"; display := bcd4; 
     when others => null; 
    end case; 

    case display is 
     when "0000" => sseg <= "0000001"; --0 
     when "0001" => sseg <= "1001111"; --1 
     when "0010" => sseg <= "0010010"; --2 
     when "0011" => sseg <= "0000110"; --3 
     when "0100" => sseg <= "1001100"; --4 
     when "0101" => sseg <= "0100100"; --5 
     when "0110" => sseg <= "0100000"; --6 
     when "0111" => sseg <= "0001111"; --7 
     when "1000" => sseg <= "0000000"; --8 
     when "1001" => sseg <= "0000100"; --9 
     when others => sseg <= "0010000"; --e, represents error 
    end case; 
end process P3; 
end behavioral; 

файл: debounce.vhdl

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use ieee.numeric_std.ALL; 

entity Debounce is 
    port(cclk  : in std_logic; 
      inp : in std_logic_vector(3 downto 0); 
      cclr : in std_logic; 
      db  : out std_logic_vector(3 downto 0) 
     ); 
end Debounce; 

architecture behavioral_2 of Debounce is 
    signal delay1, delay2, delay3 : std_logic_vector(3 downto 0); 
begin 
    process (cclk, cclr) 
    begin 
     if cclr = '1' then 
      delay1 <= "0000"; 
      delay2 <= "0000"; 
      delay3 <= "0000"; 
     elsif rising_edge(cclk) then 
      delay1 <= inp; 
      delay2 <= delay1; 
      delay3 <= delay2; 
     end if; 
    end process; 
    db <= delay1 and delay2 and delay3; 
end behavioral_2; 

я обрабатывал эти два файла с файлом данных sevensegns_tb.vhdl Затем я побежал файлы и соблюдал данные с gtkwave вот выход: gtkwave output

и я отправил весь код и результаты в: Google Code sevenseg
Нажмите вкладку «Источник», чтобы просмотреть все созданные файлы.

+0

Спасибо за ответ! Возможно, я ошибаюсь, но, похоже, в симуляции bcd увеличиваются, когда соответствующая кнопка отпущена. И я не понимаю, почему вы не делите clk, чтобы получить clk2 с частотой 50 кГц (так как иначе вы не можете ничего не наблюдать на семи сегментах). Но вместо этого вы используете два одинаковых такта. Когда я попытался запустить ваш код, Xilinix дал ошибку, указывающую на то, что clk2 не синтезируется из-за плохого синхронного описания. Может быть, я делаю что-то неправильно, но если бы вы могли немного объяснить, я был бы очень рад. – user3100463

+0

О, я поменял часы так, чтобы моя тестовая кровать не была 20 страниц. Часы можно вернуть без вреда. – user2737761

+0

Восстановите часы до кода, который у вас был, я оставил этот код в моем коде. – user2737761

Смежные вопросы