記事一覧

60進カウンタをつくる

2013年06月14日(金)11時59分

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:なんの前触れもなく、階層設計で書くかもしれません(^_^;)