名称:基于VHDL的倒计时控制器设计Basys3开发板验证
软件:VIVADO
语言:VHDL
代码功能:
倒计时控制器器
1、可以通过按键切换倒计时状态、设置状态
2、在设置状态下设计倒计时的时间,通过上下两个按键控制时间加减
3、时间设置好后,通过按键切换到倒计时状态,从设置的时间开始倒计时
FPGA代码Verilog/VHDL代码资源下载:www.hdlcode.com
本代码已在Basys3开发板验证,开发板如下,其他开发板可以修改管脚适配:
1. 工程文件
2. 程序文件
3. 程序编译
4. 仿真图
4.1 main1_one_digit模块仿真
Testbench
仿真图
4.2 main2_four_digits模块仿真
Testbench
仿真图
4.3 整体仿真
Testbench
仿真图
部分代码展示:
LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; --计时模块 ENTITY downcnt_time IS PORT ( clk : IN STD_LOGIC;--100MHz clk_5KHz : OUT STD_LOGIC;--输出5KHz,用于控制数码管切换 btnU : IN STD_LOGIC;--按键 btnD : IN STD_LOGIC;--按键 btnC : IN STD_LOGIC;--按键 d3 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--分钟十位 d2 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--分钟个位 d1 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--秒钟十位 d0 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)--秒钟十位 ); END downcnt_time; ARCHITECTURE Behavioral OF downcnt_time IS --定义信号 TYPE State_type IS (s_timing, s_set, s_setting, s_time); -- 定义状态 SIGNAL state : State_Type; -- 创建信号 SIGNAL clk_1Hz : STD_LOGIC;--1hz,用于计时 SIGNAL clk_5K : STD_LOGIC := '0'; SIGNAL count_1Hz : integer := 0; SIGNAL count_5KHz : integer := 0; SIGNAL btnU_dff1 : STD_LOGIC; SIGNAL btnU_dff2 : STD_LOGIC; SIGNAL btnD_dff1 : STD_LOGIC; SIGNAL btnD_dff2 : STD_LOGIC; SIGNAL btnU_push : STD_LOGIC; SIGNAL btnD_push : STD_LOGIC; SIGNAL Min_10 : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";--分钟十位 SIGNAL Min_1 : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";--分钟个位 SIGNAL Sec_10 : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";--秒钟十位 SIGNAL Sec_1 : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";--秒钟十位 BEGIN PROCESS (clk) BEGIN IF (clk'EVENT AND clk = '1') THEN IF (count_5KHz >= 100) THEN--100MHz计数10000后翻转得到5KHz的信号,仿真时将10000改小为100 count_5KHz <= 0; clk_5K <= NOT(clk_5K);--翻转,得到5Khz ELSE count_5KHz <= count_5KHz + 1;--计数 END IF; END IF; END PROCESS; clk_5KHz <= clk_5K;--输出5KHz PROCESS (clk) BEGIN IF (clk'EVENT AND clk = '1') THEN IF (count_1Hz >= 1000) THEN--100MHz分频到1Hz,计数100000000,仿真时减小为1000 count_1Hz <= 0; clk_1Hz <= '1';--得到1Hz信号脉冲 ELSE count_1Hz <= count_1Hz + 1;--计数 clk_1Hz <= '0'; END IF; END IF; END PROCESS; --状态控制 PROCESS (clk) BEGIN IF (clk'EVENT AND clk = '1') THEN CASE state IS WHEN s_timing =>--计时状态 IF (btnC = '1') THEN--btnC按下 state <= s_set; ELSE state <= s_timing; END IF; WHEN s_set =>--btnC按键按下 IF (btnC = '0') THEN--btnC按键松开 state <= s_setting;--进入设置状态 ELSE state <= s_set; END IF; WHEN s_setting =>--设置状态 IF (btnC = '1') THEN--btnC按下 state <= s_time; ELSE state <= s_setting; END IF; WHEN s_time =>--btnC按下 IF (btnC = '0') THEN--btnC按键松开 state <= s_timing;--进入计时状态 ELSE state <= s_time; END IF; WHEN OTHERS => END CASE; END IF; END PROCESS; --使用D触发器将btnU和btnD缓存 PROCESS (clk) BEGIN IF (clk'EVENT AND clk = '1') THEN btnU_dff1 <= btnU; btnU_dff2 <= btnU_dff1; btnD_dff1 <= btnD; btnD_dff2 <= btnD_dff1; END IF; END PROCESS; --得到btnU和btnD的按键上升沿,只保持一个时钟周期的高电平 btnU_push <= btnU_dff1 AND NOT(btnU_dff2); btnD_push <= btnD_dff1 AND NOT(btnD_dff2); PROCESS (clk) BEGIN IF (clk'EVENT AND clk = '1') THEN IF (state = s_setting) THEN--设置时间状态 IF (btnU_push = '1') THEN--btnU按键按下,控制分钟时间加 IF (Min_10 = "1001" AND Min_1 = "1001") THEN--分钟为99时,不再增加 Min_10 <= "1001"; Min_1 <= "1001"; ELSIF (Min_1 = "1001") THEN--分钟个位是9 Min_10 <= Min_10 + "0001";--十位加1 Min_1 <= "0000"; ELSE Min_10 <= Min_10; Min_1 <= Min_1 + "0001";--个位加1 END IF; ELSIF (btnD_push = '1') THEN--btnU按键按下,控制分钟时间减 IF (Min_10 = "0000" AND Min_1 = "0000") THEN--时间减到0,不再减 Min_10 <= "0000"; Min_1 <= "0000"; ELSIF (Min_1 = "0000") THEN--个位为0 Min_10 <= Min_10 - "0001";--十位减1 Min_1 <= "1001"; ELSE Min_10 <= Min_10; Min_1 <= Min_1 - "0001";--个位减1 END IF; END IF; ELSIF (state = s_timing) THEN--倒计时状态 IF (clk_1Hz = '1') THEN IF (Min_10 = "0000" AND Min_1 = "0000" AND Sec_10 = "0000" AND Sec_1 = "0000") THEN--减到0,倒计时结束 Min_10 <= "0000"; Min_1 <= "0000"; ELSIF (Min_1 = "0000" AND Sec_10 = "0000" AND Sec_1 = "0000") THEN-- Min_10 <= Min_10 - "0001";--分钟十位减1 Min_1 <= "1001"; ELSIF (Sec_10 = "0000" AND Sec_1 = "0000") THEN Min_10 <= Min_10; Min_1 <= Min_1 - "0001";--分钟个位减1 ELSE Min_10 <= Min_10; Min_1 <= Min_1; END IF; END IF; END IF; END IF; END PROCESS;