ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • VHDL 디지털시계 소스코드
    공부 2025. 1. 5. 05:25

     

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    
    entity watch is
    	port(
    		clk			: in std_logic;
    		reset			: in std_logic;
    		T0, T1, T2		: in std_logic;
    		fgo			: in std_logic;
    		reg			: in std_logic;
    		step			: in std_logic;
    		sw0			: in std_logic;
    		led_alarm		: out std_logic;
    		FND_out1		: out std_logic_vector(7 downto 0);
    		FND_out2		: out std_logic_vector(7 downto 0);
    		FND_out3		: out std_logic_vector(7 downto 0);
    		FND_sel1		: out std_logic_vector(1 downto 0);
    		FND_sel2		: out std_logic_vector(1 downto 0);
    		FND_sel3		: out std_logic_vector(1 downto 0)
    	);
    	function num_FND(num : integer) return std_logic_vector is
    	begin
    		case num is
    			when 0 => return "11111100";
    			when 1 => return "01100000";
    			when 2 => return "11011010";
    			when 3 => return "11110010";
    			when 4 => return "01100110";
    			when 5 => return "10110110";
    			when 6 => return "10111110";
    			when 7 => return "11100000";
    			when 8 => return "11111110";
    			when 9 => return "11110110";
    			when others => return "00000000";
    		end case;
    	end function num_FND;
    
    	function change_num(num : integer; change_mode : integer; time_plus_minus : std_logic) return integer is
    	begin
    		if time_plus_minus = '0' then
    			case change_mode is
    				when 0 => return num - 1;
    				when 1 => return num - 60;
    				when 2 => return num - 3600;
    				when others => return num;
    			end case;
    		else
    			case change_mode is
    				when 0 => return num + 1;
    				when 1 => return num + 60;
    				when 2 => return num + 3600;
    				when others => return num;
    			end case;
    		end if;
    	end function change_num;
    end watch;
    
    architecture Behavioral of watch is
    	signal clk_time, clk_fnd, clk_debouncing, clk_2hz	: std_logic;
    	signal watch_mode				: integer range 0 to 2 := 0;
    	signal change_mode				: integer range 0 to 2 := 0;
    	signal time_cnt, alarm_cnt			: integer range 0 to 86400 := 0;
    	signal alarm_out				: std_logic;	
    	signal h0, h1, m0, m1, s0, s1			: integer range 0 to 9;
    begin
    
    	process(clk_fnd, clk_time, clk_debouncing, clk_2hz)
    		variable cnt 		: integer range 0 to 999999 := 0;
    		variable cnt2hz 	: integer range 0 to 249999:= 0;
    		variable cnt5hz 	: integer range 0 to 199999 := 0;
    		variable cnt50hz 	: integer range 0 to 9999 := 0;
    	begin
    		if rising_edge(clk) then		
    			if cnt > 999999 then
    				cnt := 0;
    				clk_time <= '1';
    			else
    				clk_time <= '0';
    				cnt := cnt + 1;
    			end if;
    			
    			if cnt2hz > 249999 then
    				cnt2hz := 0;
    				clk_2hz <= not clk_2hz;
    			else
    				cnt2hz := cnt2hz + 1;
    			end if;
    			
    			if cnt5hz > 199999 then
    				cnt5hz := 0;
    				clk_debouncing <= '1';
    			else
    				clk_debouncing <= '0';
    				cnt5hz := cnt5hz + 1;
    			end if;
    			
    			if cnt50hz >= 9999 then
    				cnt50hz := 0;
    				clk_fnd <= not clk_fnd;
    			else
    				cnt50hz := cnt50hz + 1;
    			end if;
    		end if;
    	end process;
    	
    	process(watch_mode, change_mode)
    	begin
    		if rising_edge(clk) then
    			if T0 = '1' then
    				watch_mode <= 0;
    				change_mode <= 0;
    			end if;
    			if T1 = '1' then
    				watch_mode <= 1;
    				change_mode <= 0;
    			end if;
    			if T2 = '1' then
    				watch_mode <= 2;
    				change_mode <= 0;
    			end if;
    			
    			if clk_time = '1' then
    				if fgo = '0' then
    					case change_mode is
    						when 0 => change_mode <= 1;
    						when 1 => change_mode <= 2;
    						when 2 => change_mode <= 0;
    					end case;
    				end if;
    			end if;
    		end if;
    	end process;
    	
    	process(clk_time, clk_debouncing, time_cnt, alarm_cnt)
    	begin
    		if rising_edge(clk) then
    			if not (watch_mode = 1) then
    				if clk_time = '1' then
    					time_cnt <= time_cnt + 1;
    				end if;
    			end if;
    			
    			if watch_mode = 1 then
    				if clk_debouncing = '1' then
    					if reg = '0' or step = '0' then 
    						time_cnt <= change_num(time_cnt, change_mode, reg);
    					end if;
    				end if;
    			elsif watch_mode = 2 then
    				if clk_debouncing = '1' then
    					if reg = '0' or step = '0' then 
    						alarm_cnt <= change_num(alarm_cnt, change_mode, reg);
    					end if;
    				end if;
    			end if;
    			if time_cnt >= 86400 or (watch_mode = 0 and reset = '0') then
    				time_cnt <= 0;
    			end if;
    			if alarm_cnt >= 86400 or (watch_mode = 2 and reset = '0') then
    				alarm_cnt <= 0;
    			end if;
    		end if;
    	end process;
    	
    	process(alarm_out)
    	begin
    		if sw0 = '1' and watch_mode = 0 and time_cnt = alarm_cnt then
    			alarm_out <= '1';
    		end if;
    		
    		if sw0 = '0' then
    			alarm_out <= '0';
    		end if;
    	end process;
    	
    	process(alarm_out, clk_2hz)
    	begin
    		if alarm_out = '1' then
    			led_alarm <= clk_2hz;
    		else
    			led_alarm <= '0';
    		end if;
    	end process;
    	
    	process(time_cnt, s0, s1, m0, m1, h0, h1)
    	begin
    		if rising_edge(clk) then
    			if watch_mode = 0 or watch_mode = 1 then
    				s0 <= (time_cnt mod 60) mod 10;
    				s1 <= (time_cnt mod 60) / 10;
    				m0 <= ((time_cnt mod 3600) / 60) mod 10;
    				m1 <= ((time_cnt mod 3600) / 60) / 10;
    				h0 <= (time_cnt / 3600) mod 10;
    				h1 <= (time_cnt / 3600) / 10;
    			else
    				s0 <= (alarm_cnt mod 60) mod 10;
    				s1 <= (alarm_cnt mod 60) / 10;
    				m0 <= ((alarm_cnt mod 3600) / 60) mod 10;
    				m1 <= ((alarm_cnt mod 3600) / 60) / 10;
    				h0 <= (alarm_cnt / 3600) mod 10;
    				h1 <= (alarm_cnt / 3600) / 10;
    			end if;
    		end if;	
    	end process;
    	
    	process(clk_fnd, h0, h1, m0, m1, s0, s1, change_mode)
    	begin
    		if rising_edge(clk) then
    			if clk_fnd = '1' then
    				FND_sel1 <= "10";
    				FND_sel2 <= "10";
    				FND_sel3 <= "10";
    				FND_out1 <= num_FND(h1);
    				FND_out2 <= num_FND(m1);
    				FND_out3 <= num_FND(s1);
    			else
    				FND_sel1 <= "01";
    				FND_sel2 <= "01";
    				FND_sel3 <= "01";
    				FND_out1 <= num_FND(h0);
    				FND_out2 <= num_FND(m0);
    				FND_out3 <= num_FND(s0);
    			end if;
    			if (not (watch_mode = 0)) and clk_2hz = '0' then
    				case change_mode is
    					when 0 => 
    						FND_sel3 <= "11";
    					when 1 => 
    						FND_sel2 <= "11";
    					when 2 => 
    						FND_sel1 <= "11";
    					when others => null;
    				end case;
    			end if;
    		end if;
    	end process;
    
    end Behavioral;​

    댓글

Designed by Tistory.