我的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 - >最左边的数字)增加1。问题是当我按下按钮时,它完成了工作,但没有增加一个,而是一些任意数字。原因是它在时钟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 :(得分: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值只会增加一次。
答案 1 :(得分: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;
file: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观察数据 这是输出:
我已将所有代码和结果发布到:
Google Code sevenseg
单击“源”选项卡以查看创建的所有文件。