FPGAでデジタル時計を作った話
学校の課題でFPGAを使ってデジタル時計を作りました。成績が出たので記事にします。
機能と動作している様子は以下の動画を見てください
www.youtube.com
以下ソースコードです。
回路図もコメントも無くて大変不親切なのですが、回路図を起こすのが面倒という身勝手な理由でソースコードだけ貼って終わりにします。
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity Clock is Port ( A : out STD_LOGIC_VECTOR (15 downto 0); B : out STD_LOGIC_VECTOR (15 downto 0); C : inout STD_LOGIC_VECTOR (15 downto 0); clk : in STD_LOGIC); end Clock; architecture Behavioral of Clock is signal counter : STD_LOGIC_VECTOR(24 downto 0) := (others => '0'); signal counter2 : STD_LOGIC_VECTOR(14 downto 0) := (others => '0'); signal dot : STD_LOGIC := '0'; signal clk_blink : STD_LOGIC := '0'; signal isSetmode : STD_LOGIC := '0'; signal set_sw : STD_LOGIC := '0'; signal set_sw_before : STD_LOGIC := '0'; signal up_sw : STD_LOGIC := '0'; signal up_sw_before : STD_LOGIC := '0'; signal down_sw : STD_LOGIC := '0'; signal down_sw_before : STD_LOGIC := '0'; signal sec : STD_LOGIC_VECTOR(5 downto 0) := "000000"; signal digit : STD_LOGIC_VECTOR(1 downto 0) := "00"; signal config_digit : STD_LOGIC_VECTOR(1 downto 0) := "00"; signal number : STD_LOGIC_VECTOR(3 downto 0) := "0000"; signal min01 : STD_LOGIC_VECTOR(3 downto 0) := "0000"; signal min10 : STD_LOGIC_VECTOR(3 downto 0) := "0000"; signal hour01 : STD_LOGIC_VECTOR(3 downto 0) := "0000"; signal hour10 : STD_LOGIC_VECTOR(3 downto 0) := "0000"; begin A <= "0000000000000000"; B <= "0000000000000000"; C(1) <= '1'; set_sw <= (not C(0)) and set_sw_before; up_sw <= (not C(14)) and up_sw_before; down_sw <= (not C(15)) and down_sw_before; process(clk) begin if rising_edge(clk) then if counter /= "1111010000100100000000000" then counter <= counter+1; else counter <= "0000000000000000000000000"; dot <= not dot; if isSetmode='0' then if sec /= "111011" then sec <= sec + 1; else sec <= "000000"; if min01 /= "1001" then min01 <= min01 + 1; else min01 <= "0000"; if min10 /= "0101" then min10 <= min10 + 1; else min10 <= "0000"; if hour10="0010" and hour01="0011" then hour01 <= "0000"; hour10 <= "0000"; else if hour01 /= "0101" then hour01 <= hour01 + 1; else hour01 <= "0000"; hour10 <= hour10 + 1; end if; end if; end if; end if; end if; end if; end if; if counter(23 downto 0) = "111010000100100000000000" then clk_blink <= not clk_blink; end if; counter2 <= counter2 + 1; if counter2 = "111110100000000" then counter2 <= "000000000000000"; set_sw_before <= C(0); if set_sw = '1' then if isSetmode = '0' then isSetmode <= '1'; config_digit <= "00"; else case config_digit is when "00" => config_digit <= "10"; if hour10 = "0010" and hour01 >= "0100" then hour01 <= "0000"; end if; when "10" => config_digit <= "11"; when "11" => config_digit <= "01"; when "01" => isSetmode <= '0'; sec <= "000000"; counter <= "0000000000000000000000000"; when others => null; end case; end if; end if; up_sw_before <= C(14); if up_sw = '1' and isSetmode='1' then case config_digit is when "01" => if min01 = "1001" then min01 <= "0000"; else min01 <= min01 + 1; end if; when "11" => if min10 = "0101" then min10 <= "0000"; else min10 <= min10 + 1; end if; when "10" => if hour10 = "0010" then if hour01 = "0011" then hour01 <= "0000"; else hour01 <= hour01 + 1; end if; else if hour01 = "1001" then hour01 <= "0000"; else hour01 <= hour01 + 1; end if; end if; when "00" => if hour10 = "0010" then hour10 <= "0000"; else hour10 <= hour10 + 1; end if; when others => null; end case; end if; down_sw_before <= C(15); if down_sw = '1' and isSetmode = '1' then case config_digit is when "01" => if min01 = "0000" then min01 <= "1001"; else min01 <= min01 - 1; end if; when "11" => if min10 = "0000" then min10 <= "0101"; else min10 <= min10 - 1; end if; when "10" => if hour10 = "0010" then if hour01 = "0000" then hour01 <= "0011"; else hour01 <= hour01 - 1; end if; else if hour01 = "0000" then hour01 <= "1001"; else hour01 <= hour01 - 1; end if; end if; when "00" => if hour10 = "0000" then hour10 <= "0010"; else hour10 <= hour10 - 1; end if; when others => null; end case; end if; case digit is when "00" => number <= hour10; digit <= "10"; if (isSetmode='0' and hour10="0000") or (isSetmode='1' and clk_blink='0' and config_digit="00") then C(2)<='0'; else C(2)<='1'; end if; C(11)<='0'; C(12)<='0'; C(10)<='0'; C(7) <= '1'; when "10" => number <= hour01; digit <= "11"; if isSetmode='1' and clk_blink='0' and config_digit="10" then C(11) <= '0'; else C(11) <= '1'; end if; C(2)<='0'; C(12)<='0'; C(10)<='0'; C(7) <= '1'; when "11" => number <= min10; digit <= "01"; if (isSetmode='0' and min10="0000") or (isSetmode='1' and clk_blink='0' and config_digit="11") then C(12)<='0'; else C(12)<='1'; end if; C(2)<='0'; C(11)<='0'; C(10)<='0'; C(7) <= '1'; when "01" => number <= min01; digit <= "00"; if isSetmode='1' and clk_blink='0' and config_digit="01" then C(10) <= '0'; else C(10) <= '1'; end if; C(2)<='0'; C(11)<='0'; C(12)<='0'; C(7) <= dot; when others => null; end case; end if; case number is when "0000" => C(3)<='0'; C(13)<= '0'; C(8)<='0'; C(6)<='0'; C(5)<='0'; C(4)<='0'; C(9)<='1'; when "0001" => C(3)<='1'; C(13)<= '0'; C(8)<='0'; C(6)<='1'; C(5)<='1'; C(4)<='1'; C(9)<='1'; when "0010" => C(3)<='0'; C(13)<= '0'; C(8)<='1'; C(6)<='0'; C(5)<='0'; C(4)<='1'; C(9)<='0'; when "0011" => C(3)<='0'; C(13)<= '0'; C(8)<='0'; C(6)<='0'; C(5)<='1'; C(4)<='1'; C(9)<='0'; when "0100" => C(3)<='1'; C(13)<= '0'; C(8)<='0'; C(6)<='1'; C(5)<='1'; C(4)<='0'; C(9)<='0'; when "0101" => C(3)<='0'; C(13)<= '1'; C(8)<='0'; C(6)<='0'; C(5)<='1'; C(4)<='0'; C(9)<='0'; when "0110" => C(3)<='0'; C(13)<= '1'; C(8)<='0'; C(6)<='0'; C(5)<='0'; C(4)<='0'; C(9)<='0'; when "0111" => C(3)<='0'; C(13)<= '0'; C(8)<='0'; C(6)<='1'; C(5)<='1'; C(4)<='0'; C(9)<='1'; when "1000" => C(3)<='0'; C(13)<= '0'; C(8)<='0'; C(6)<='0'; C(5)<='0'; C(4)<='0'; C(9)<='0'; when "1001" => C(3)<='0'; C(13)<= '0'; C(8)<='0'; C(6)<='0'; C(5)<='1'; C(4)<='0'; C(9)<='0'; when others => C(3)<='1'; C(13)<= '1'; C(8)<='1'; C(6)<='1'; C(5)<='1'; C(4)<='1'; C(9)<='1'; end case; end if; end process; end Behavioral;