我正在使用状态机创建一个倒数计时器,在启动时显示 00:00,当按下 Key1 时,您可以通过将分钟递增/递减 1 来输入时间,并且如果按住向上/向下按钮 5 个周期它将上升/下降 5。感谢一些很棒的帮助(@DavidKoontz),我已经完成了代码。无需对代码 b/c 中的按钮进行去抖动处理,我的 altera 板似乎可以很好地接收低信号。由于我只使用一个时钟,因此按钮反应缓慢 b/c,时钟设置为 1Hz。
Library ieee;
USE ieee.std_logic_1164.ALL;
ENTITY CountDownTimer IS
PORT(
CLK,RESET: IN STD_LOGIC;
a1, b1, c1, d1, e1, f1, g1 : OUT STD_LOGIC;
a2, b2, c2, d2, e2, f2, g2 : OUT STD_LOGIC;
a3, b3, c3, d3, e3, f3, g3 : OUT STD_LOGIC;
a4, b4, c4, d4, e4, f4, g4 : OUT STD_LOGIC;
--All 4 buttons for timer
BUTTON0, BUTTON1, BUTTON2, BUTTON3: IN STD_LOGIC;
--LEDR9
ON_OFF_LED: OUT BIT;
--LEDR9-R6
INPUT_LED1, INPUT_LED2, INPUT_LED3, INPUT_LED4: OUT BIT;
--LEDR0
DONE_LED: OUT BIT);
END CountdownTimer;
ARCHITECTURE Counter OF CountDownTimer IS
--Define state machine
TYPE STATE_TYPE IS (A_ON_OFF, B_INPUT, C_COUNTDOWN, D_DONE);
SIGNAL State : STATE_TYPE;
--Buttons produce 0 when pressed, signal for 1 when pressed
SIGNAL B3D0, B3D1, B3D2, B3D3: STD_LOGIC := '0';
SIGNAL B2D0, B2D1, B2D2, B2D3: STD_LOGIC := '0';
SIGNAL CLOCK: STD_LOGIC := '0';
SIGNAL Count: INTEGER:= 1;
--SIGNAL for range of integer values
SIGNAL Minute1 : INTEGER RANGE 0 TO 6;
SIGNAL Minute2 : INTEGER RANGE 0 TO 9;
SIGNAL Second1 : INTEGER RANGE 0 TO 5;
SIGNAL Second2 : INTEGER RANGE 0 TO 9;
--Output for the seven segment displays
SIGNAL OUTPUT_HEX0 : STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL OUTPUT_HEX1 : STD_LOGIC_VECTOR (6 DOWNTO 0);
SIGNAL OUTPUT_HEX2 : STD_LOGIC_VECTOR (6 DOWNTO 0);
SIGNAL OUTPUT_HEX3 : STD_LOGIC_VECTOR (6 DOWNTO 0);
SIGNAL B3_HOLD: STD_LOGIC := '0'; --Gets 1 if button3 was held
SIGNAL B2_HOLD: STD_LOGIC := '0'; --Gets 1 is button2 was held
BEGIN
--Segment 1 display pins
a1 <= OUTPUT_HEX0(6);
b1 <= OUTPUT_HEX0(5);
c1 <= OUTPUT_HEX0(4);
d1 <= OUTPUT_HEX0(3);
e1 <= OUTPUT_HEX0(2);
f1 <= OUTPUT_HEX0(1);
g1 <= OUTPUT_HEX0(0);
--Segment 2 display pins
a2 <= OUTPUT_HEX1(6);
b2 <= OUTPUT_HEX1(5);
c2 <= OUTPUT_HEX1(4);
d2 <= OUTPUT_HEX1(3);
e2 <= OUTPUT_HEX1(2);
f2 <= OUTPUT_HEX1(1);
g2 <= OUTPUT_HEX1(0);
--Segment 3 display pins
a3 <= OUTPUT_HEX2(6);
b3 <= OUTPUT_HEX2(5);
c3 <= OUTPUT_HEX2(4);
d3 <= OUTPUT_HEX2(3);
e3 <= OUTPUT_HEX2(2);
f3 <= OUTPUT_HEX2(1);
g3 <= OUTPUT_HEX2(0);
--Segment 4 display pins
a4 <= OUTPUT_HEX3(6);
b4 <= OUTPUT_HEX3(5);
c4 <= OUTPUT_HEX3(4);
d4 <= OUTPUT_HEX3(3);
e4 <= OUTPUT_HEX3(2);
f4 <= OUTPUT_HEX3(1);
g4 <= OUTPUT_HEX3(0);
WITH Second2 SELECT
--One's second place, 0 to 9
OUTPUT_HEX0 <= "0000001" WHEN 0,
"1001111" WHEN 1,
"0010010" WHEN 2,
"0000110" WHEN 3,
"1001100" WHEN 4,
"0100100" WHEN 5,
"0100000" WHEN 6,
"0001101" WHEN 7,
"0000000" WHEN 8,
"0001100" WHEN 9,
"0000001" WHEN OTHERS;
WITH Second1 SELECT
--Tens second place, 0 to 5
OUTPUT_HEX1 <= "0000001" WHEN 0,
"1001111" WHEN 1,
"0010010" WHEN 2,
"0000110" WHEN 3,
"1001100" WHEN 4,
"0100100" WHEN 5,
"0000001" WHEN OTHERS;
WITH Minute2 SELECT
--Ones minute place, 0 to 9
OUTPUT_HEX2 <= "0000001" WHEN 0,
"1001111" WHEN 1,
"0010010" WHEN 2,
"0000110" WHEN 3,
"1001100" WHEN 4,
"0100100" WHEN 5,
"0100000" WHEN 6,
"0001101" WHEN 7,
"0000000" WHEN 8,
"0001100" WHEN 9,
"0000001" WHEN OTHERS;
WITH Minute1 SELECT
--Tens minute place, 0 to 6
OUTPUT_HEX3 <= "0000001" WHEN 0,
"1001111" WHEN 1,
"0010010" WHEN 2,
"0000110" WHEN 3,
"1001100" WHEN 4,
"0100100" WHEN 5,
"0100000" WHEN 6,
"0000001" WHEN OTHERS;
PROCESS(CLK)
BEGIN
IF RISING_EDGE(CLK) THEN
Count <= Count + 1;
IF (Count = 30000000) THEN
CLOCK <= NOT(CLOCK);
Count <= 1;
END IF;
END IF;
END PROCESS;
PROCESS(CLOCK)
BEGIN
IF RISING_EDGE(CLOCK) THEN
B3D0 <= BUTTON3;
B3D1 <= NOT B3D0;
B3D2 <= B3D1;
B3D3 <= B3D2;
B2D0 <= BUTTON2;
B2D1 <= NOT B2D0;
B2D2 <= B2D1;
B2D3 <= B2D2;
B3_HOLD <= B3D1 AND B3D2 AND B3D3;
B2_HOLD <= B2D1 AND B2D2 AND B2D3;
END IF;
END PROCESS;
PROCESS(CLOCK)
BEGIN
IF RESET = '1' THEN --Async Reset
State <= A_ON_OFF;
ELSIF RISING_EDGE(CLOCK) THEN
CASE State IS
---------------------------------A_ON_OFF---------------------------------
WHEN A_ON_OFF =>
--Red LED9
ON_OFF_LED <= '1';
Minute1 <= 0;
Minute2 <= 0;
Second1 <= 0;
Second2 <= 0;
IF (BUTTON0 = '0') THEN
ON_OFF_LED <= '0';
State <= B_INPUT;
END IF;
---------------------------------B_INPUT/PAUSE---------------------------------
WHEN B_INPUT =>
--Light up LEDs
INPUT_LED1 <= '1';
INPUT_LED2 <= '1';
INPUT_LED3 <= '1';
INPUT_LED4 <= '1';
IF (Minute1 = 6) THEN
Minute2 <= 0;
Second1 <= 0;
Second2<= 0;
State <= B_INPUT;
END IF;
--Count up button
IF (BUTTON3 = '0' AND B3_HOLD = '0') THEN
IF (Minute1 = 6 AND Minute2 >= 0) THEN
Minute1 <= 0;
Minute2 <= 1;
Second1 <= 0;
Second2 <= 0;
State <= B_INPUT;
ELSIF (Minute2 < 9) THEN
Minute2 <= (Minute2 + 1);
State <= B_INPUT;
ELSIF (Minute2 = 9) THEN
Minute1 <= (Minute1 + 1);
Minute2 <= 0;
State <= B_INPUT;
END IF;
END IF;
IF (BUTTON3 = '0' AND B3_HOLD = '1') THEN
IF (Minute1 = 6 AND Minute2 >= 0) THEN
Minute1 <= 0;
Minute2 <= 5;
Second1 <= 0;
Second2 <= 0;
State <= B_INPUT;
ELSIF (Minute2 < 5) THEN
IF (Minute2 = 0) THEN
Minute2 <= (Minute2 + 5);
State <= B_INPUT;
ELSE
Minute2 <= (Minute2 + 1);
State <= B_INPUT;
END IF;
ELSIF (Minute2 = 5) THEN
Minute2 <= 0;
Minute1 <= (Minute1 + 1);
State <= B_INPUT;
ELSIF (Minute2 > 5) THEN
IF (Minute2 = 9) THEN
Minute2 <= 0;
Minute1 <= (Minute1 + 1);
State <= B_INPUT;
ELSE
Minute2 <= (Minute2 + 1);
State <= B_INPUT;
END IF;
END IF;
END IF;
--Count down button
IF (BUTTON2 = '0' AND B2_HOLD = '0') THEN
IF ((Minute1 = 0) AND (Minute2 = 0)) THEN
Minute1 <= 6;
Minute2 <= 0;
Second1 <= 0;
Second2 <= 0;
ELSIF (Minute2 = 0) THEN
Minute2 <= 9;
Minute1 <= (Minute1 - 1);
ELSE
Minute2 <= (Minute2 - 1);
END IF;
State <= B_INPUT;
END IF;
IF (BUTTON2 = '0' AND B2_HOLD = '1') THEN
IF (Minute1 = 0 AND Minute2 = 0) THEN
Minute1 <= 6;
Minute2 <= 0;
Second1 <= 0;
Second2 <= 0;
State <= B_INPUT;
ELSIF (Minute2 = 0 AND Minute1 > 0) THEN
Minute1 <= (Minute1 - 1);
Minute2 <= 5;
State <= B_INPUT;
ELSIF (Minute2 < 5) THEN
IF (Minute2 = 0) THEN
Minute1 <= (Minute1 - 1);
Minute2 <= 5;
State <= B_INPUT;
ELSE
Minute2 <= (Minute2 - 1);
State <= B_INPUT;
END IF;
ELSIF (Minute2 = 5) THEN
Minute2 <= (Minute2 - 5);
State <= B_INPUT;
ELSIF (Minute2 > 5) THEN
Minute2 <= (Minute2 - 1);
State <= B_INPUT;
END IF;
END IF;
--Clear button
IF (BUTTON1 = '0') THEN
Minute1 <= 0;
Minute2 <= 0;
Second1 <= 0;
Second2 <= 0;
State <= B_INPUT;
END IF;
--Start Button
IF (BUTTON0 = '0') THEN
--Turn off LEDs
INPUT_LED1 <= '0';
INPUT_LED2 <= '0';
INPUT_LED3 <= '0';
INPUT_LED4 <= '0';
State <= C_COUNTDOWN;
END IF;
---------------------------------C_COUNTDOWN---------------------------------
WHEN C_COUNTDOWN =>
IF (Second2 > 0) THEN
Second2 <= (Second2 - 1);
ELSIF (Second2 = 0) THEN
IF (Second1 > 0) THEN
Second2 <= 9;
Second1 <= (Second1 - 1);
ELSIF (Second1 = 0) THEN
IF (Minute2 > 0) THEN
Second1 <= 5;
Minute2 <= (Minute2 - 1);
IF (Second2 = 0) THEN
Second2 <= 9;
END IF;
ELSIF (Minute2 = 0) THEN
IF (Minute1 > 0) THEN
IF (Second1 = 0) THEN
Second1 <= 5;
Minute2 <= (Minute2 - 1);
IF (Second2 = 0) THEN
Second2 <= 9;
END IF;
END IF;
Minute2 <= 9;
Minute1 <= (Minute1 - 1);
ELSIF (Minute1 <= 0) THEN
State <= D_DONE;
END IF;
END IF;
END IF;
END IF;
--Reset Button
IF (BUTTON1 = '0') THEN
STATE <= A_ON_OFF;
--Input button
ELSIF (BUTTON0 = '0') THEN
STATE <= B_INPUT;
END IF;
---------------------------------D_DONE---------------------------------
WHEN D_DONE =>
--LEDR0
DONE_LED <= '1';
--Reset button
IF (BUTTON1 = '0') THEN
DONE_LED <= '0';
STATE <= A_ON_OFF;
--Input button
ELSIF (BUTTON0 = '0') THEN
DONE_LED <= '0';
STATE <= B_INPUT;
END IF;
END CASE;
END IF;
END PROCESS;
END Counter;