2013-12-13 132 views
1

我的fpga是斯巴達3E-100 Cp132。我有四個按鈕作爲我的輸入,我想通過使用它們來增加電路板7段上的四位數字。 VHDL代碼低於:使用按鈕遞增七段

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的每個上升沿增加1,並且由於此時鐘的頻率而發生得太快。我怎樣才能擺脫這個問題?我嘗試了幾次針對按鈕的debouncing代碼,但他們沒有那麼多幫助。我完全陷在這裏。我的意思是應該有辦法做到這一點,但怎麼做?順便說一句,我一直在使用的代碼去抖動碼以上

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

我猜應該是50MHz。它是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會增加。我不明白你爲什麼不把clk2分頻到50KHz的頻率(因爲否則你不能在七段上觀察到什麼)。相反,你使用兩個相同的時鐘。當我試圖運行你的代碼時,Xilinix給出了一個錯誤,表明由於錯誤的同步描述,clk2不可合成。也許我做錯了什麼,但如果你能解釋一點,我會很高興。 – user3100463

+0

哦,我改變了時鐘,以便我的測試牀不會長達20頁。時鐘可以放回,沒有傷害。 – user2737761

+0

將時鐘恢復到您的代碼,我將代碼留在了我的代碼中。 – user2737761