60進カウンタをつくってみます。
少し工夫が必要なのは、10の桁が 0 1 2 3 4 5 0 1 2... となることと、そのタイミングです。
単純に
if (DIV_CLK'event and DIV_CLK = '0') then
if (COUNT2 = "0101") then
COUNT2 <= (others => '0');
else
COUNT2 <= COUNT2 + 1;
end if;
end if;
ではダメで、
1.1桁目が9の時、つまり繰り上がりが発生したときにカウントアップし、
2.5の次を0にする
必要があります。
Enable信号(入力)を入れました。Enable信号が入っているときのみ、カウントします。
つまり、カウントしたり、止めたりできます。
また、拡張性の為、60カウントした時の繰り上がりも入れています。
似たようなコードを何回も書くのも、いい加減疲れて来ました。
そろそろ、階層設計*1で書いた方がいいですね。
-- 60 Counter with Sync RESET
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity COUNTER60 is
port(
CLK : in std_logic;
RESET : in std_logic;
ENABLE : in std_logic;
LED_7SEG1: out std_logic_vector(7 downto 0);
LED_7SEG2: out std_logic_vector(7 downto 0);
CARRYOUT : out std_logic
);
end COUNTER60;
architecture RTL of COUNTER60 is
signal DIV_COUNTER : std_logic_vector(24 downto 0);
signal DIV_CLK : std_logic;
signal COUNT1 : std_logic_vector(3 downto 0);
signal COUNT2 : std_logic_vector(3 downto 0);
signal CARRY : std_logic;
begin
-- CLK
process(CLK,RESET)
begin
if (RESET = '0') then
DIV_COUNTER <= (others => '0');
elsif (CLK'event and CLK = '0') then
DIV_COUNTER <= DIV_COUNTER + 1;
end if;
end process;
DIV_CLK <= not DIV_COUNTER(23); -- 2Hz:(23)
-- 1Hz:(24) 4Hz:(22) 8Hz:(21)...
-- 10Counter with AsyncReset
process(DIV_CLK,RESET)
begin
if (RESET = '0') then
COUNT1 <= (others => '0');
elsif (DIV_CLK'event and DIV_CLK='0') then
if (ENABLE = '1') then
if (COUNT1 = "1001") then
COUNT1 <= (others => '0');
else
COUNT1 <= COUNT1 + 1;
end if;
end if;
end if;
end process;
-- Carry from 1digit
process(COUNT1)
begin
if (COUNT1 = "1001" and ENABLE = '1') then
CARRY <= '1';
else
CARRY <= '0';
end if;
end process;
-- 6Counter with AsyncReset
process(DIV_CLK,RESET)
begin
if (RESET = '0') then
COUNT2 <= (others => '0');
elsif (DIV_CLK'event and DIV_CLK = '0') then
if (CARRY = '1' and ENABLE = '1') then
if (COUNT2 = "0101") then
COUNT2 <= (others => '0');
else
COUNT2 <= COUNT2 + 1;
end if;
end if;
end if;
end process;
-- Carry from 2digit
process(COUNT1,COUNT2)
begin
if (COUNT1 = "1001" and COUNT2 = "0101" and ENABLE = '1') then
CARRYOUT <= '1';
else
CARRYOUT <= '0';
end if;
end process;
-- 7seg LED Decoder
process(COUNT1)
begin
case COUNT1 is
when "0000" => LED_7SEG1 <= "00000011"; -- 0
when "0001" => LED_7SEG1 <= "10011111"; -- 1
when "0010" => LED_7SEG1 <= "00100101"; -- 2
when "0011" => LED_7SEG1 <= "00001101"; -- 3
when "0100" => LED_7SEG1 <= "10011001"; -- 4
when "0101" => LED_7SEG1 <= "01001001"; -- 5
when "0110" => LED_7SEG1 <= "01000001"; -- 6
when "0111" => LED_7SEG1 <= "00011111"; -- 7
when "1000" => LED_7SEG1 <= "00000001"; -- 8
when "1001" => LED_7SEG1 <= "00001001"; -- 9
when others => LED_7SEG1 <= "01100001"; -- E
end case;
end process;
process(COUNT2)
begin
case COUNT2 is
when "0000" => LED_7SEG2 <= "00000011"; -- 0
when "0001" => LED_7SEG2 <= "10011111"; -- 1
when "0010" => LED_7SEG2 <= "00100101"; -- 2
when "0011" => LED_7SEG2 <= "00001101"; -- 3
when "0100" => LED_7SEG2 <= "10011001"; -- 4
when "0101" => LED_7SEG2 <= "01001001"; -- 5
when "0110" => LED_7SEG2 <= "01000001"; -- 6
when "0111" => LED_7SEG2 <= "00011111"; -- 7
when "1000" => LED_7SEG2 <= "00000001"; -- 8
when "1001" => LED_7SEG2 <= "00001001"; -- 9
when others => LED_7SEG2 <= "01100001"; -- E
end case;
end process;
end RTL;
*1:なんの前触れもなく、階層設計で書くかもしれません(^_^;)