24進カウンタをつくってみます。
厄介なのは1桁目の動作ですね。
すなわち、
2桁目が0,1の場合、9までカウントアップして繰り上がり
2桁目が2の場合、3までカウントアップして繰り上がり
です。
この見方を逆にして、
1桁目は、
1桁目の繰り上がりがある場合、0になり、
1桁目の繰り上がりがない場合、カウントアップする
1桁目の繰り上がりは、
1桁目が9の場合と、
2桁目の繰り上がりがある場合
です。
つまり、繰り上がりをうまく利用すれば、簡単になりそうです。
こんなことができるのは、同時処理*1だからです。
Aの定義の中にBがあり、
Bの定義の中にAがある。
こんな禅問答のような処理ができるのです。
-- 24 Counter with CARRYOUT, Async RESET, and Enable
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity COUNTER24 is
port(
CLK : in std_logic; -- 33MHz
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 COUNTER24;
architecture RTL of COUNTER24 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 CARRY1 : std_logic;
signal CARRY2 : 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)...
-- 24Counter
-- Count 1digit : COUNT1
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 (CARRY1 = '1') then
COUNT1 <= (others => '0');
else
COUNT1 <= COUNT1 + 1;
end if;
end if;
end if;
end process;
-- Count 2digit : COUNT2
process(DIV_CLK,RESET)
begin
if (RESET = '0') then
COUNT2 <= (others => '0');
elsif (DIV_CLK'event and DIV_CLK = '0') then
if (ENABLE = '1') then
if (CARRY1 = '1') then
if (COUNT2 = "0010") then
COUNT2 <= (others => '0');
else
COUNT2 <= COUNT2 + 1;
end if;
end if;
end if;
end if;
end process;
-- Carry from 1digit : CARRY1
process(COUNT1,CARRY2)
begin
if (COUNT1 = "1001" or CARRY2 = '1') then
CARRY1 <= '1';
else
CARRY1 <= '0';
end if;
end process;
-- Carry from 2digit : CARRY2
process(COUNT1, COUNT2)
begin
if (COUNT1 = "0011" and COUNT2 = "0010") then
CARRY2 <= '1';
else
CARRY2 <= '0';
end if;
end process;
CARRYOUT <= CARRY2;
-- End 24Counter
-- 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 7seg LED Decoder
end RTL;
*1:今まで何気にコードを書いてましたが、説明してないですね。(^_^;)そのうち、書きます。書こうかな。たぶん。いつか。そのうち