2013-12-13 33 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