24進カウンタをつくる
を階層設計で書き直してみます。
機能を分割して、部品に分けていきます。
その上で部品を組み合わせていけば、他のプログラムにも利用でき、メンテナンスしやすくなり、見通しもよくなります。
同じようなコードを何度も書くなんて嫌ですよね。
で、24進カウンタをつくる
を見ると、
1.クロックの分周
2.カウンタ
3.7セグに表示(デコード)
の3つの機能があります。
また、分けたものをつなぎ合わせる必要がありますが、
4.つなぎ合わせるものが親、階層の上、トップエンティティとなります。
1.クロックの分周 Divider.vhd
-- Divider
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity DIVIDER is
port(
CLK : in std_logic;
RESET : in std_logic;
DIV_CLK_2HZ : out std_logic;
DIV_CLK_32HZ: out std_logic
);
end DIVIDER;
architecture RTL of DIVIDER is
constant CLK_BIT : integer := 25; --Osc 33MHz: 25bit
signal DIV_COUNTER : std_logic_vector(CLK_BIT-1 downto 0);
begin
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_2HZ <= not DIV_COUNTER(CLK_BIT-2);
DIV_CLK_32HZ <= not DIV_COUNTER(CLK_BIT-5);
end RTL;
constant文で定数を定義しています。
上の階層、トップエンティティで定義する場合はgeneric文で定義します。*1
2.カウンタ Counter24.vhd
-- 24 Counter with CARRYOUT, Async RESET, and Enable
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity COUNTER24 is
port(
DIV_CLK : in std_logic;
RESET : in std_logic;
ENABLE : in std_logic;
COUNT_1DIGIT: out std_logic_vector(3 downto 0);
COUNT_2DIGIT: out std_logic_vector(3 downto 0);
CARRYOUT : out std_logic
);
end COUNTER24;
architecture RTL of COUNTER24 is
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
-- 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_1DIGIT <= COUNT1;
-- 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;
COUNT_2DIGIT <= COUNT2;
-- 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
end RTL;
3.7セグに表示(デコード) Dec_7SegLED.vhd
-- 7Seg Decoder without dp
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity DEC_7SegLED is
port(
ENABLE : in std_logic;
RESET : in std_logic;
COUNTER : in std_logic_vector(3 downto 0);
LED_7SEG: out std_logic_vector(7 downto 1)
);
end DEC_7SegLED;
architecture RTL of DEC_7SegLED is
begin
process (RESET, ENABLE, COUNTER)
begin
if (RESET = '0') then
LED_7SEG <= "1111111";
elsif (ENABLE = '1') then
case COUNTER is
when "0000" => LED_7SEG <= "0000001"; -- 0
when "0001" => LED_7SEG <= "1001111"; -- 1
when "0010" => LED_7SEG <= "0010010"; -- 2
when "0011" => LED_7SEG <= "0000110"; -- 3
when "0100" => LED_7SEG <= "1001100"; -- 4
when "0101" => LED_7SEG <= "0100100"; -- 5
when "0110" => LED_7SEG <= "0100000"; -- 6
when "0111" => LED_7SEG <= "0001101"; -- 7
when "1000" => LED_7SEG <= "0000000"; -- 8
when "1001" => LED_7SEG <= "0000100"; -- 9
when "1010" => LED_7SEG <= "0001000"; -- A
when "1011" => LED_7SEG <= "1100000"; -- b
when "1100" => LED_7SEG <= "0110001"; -- C
when "1101" => LED_7SEG <= "1000010"; -- d
when "1110" => LED_7SEG <= "0110000"; -- E
when "1111" => LED_7SEG <= "0111000"; -- F
when others => LED_7SEG <= "1111110"; -- '-'
end case;
else
LED_7SEG <= "1111111";
end if;
end process;
end RTL;
7Segのbit数がstd_logic_vector(7 downto 1)になっているのは、最下位ビットのdb(小数点)を除いているためです。
4.トップエンティティ Counter24TOP.vhd
-- TOP VHDL of 24 Counter with CARRYOUT, Async RESET, and Enable
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity COUNTER24TOP is
port(
CLK : in std_logic;
RESET : in std_logic;
ENABLE : in std_logic;
LED_7SEG1: out std_logic_vector(7 downto 1);
LED_7SEG2: out std_logic_vector(7 downto 1);
CARRYOUT : out std_logic
);
end COUNTER24TOP;
architecture RTL of COUNTER24TOP is
component DIVIDER
port(
CLK : in std_logic;
RESET : in std_logic;
DIV_CLK_2HZ : out std_logic;
DIV_CLK_32HZ: out std_logic
);
end component;
component COUNTER24
port(
DIV_CLK : in std_logic;
RESET : in std_logic;
ENABLE : in std_logic;
COUNT_1DIGIT: out std_logic_vector(3 downto 0);
COUNT_2DIGIT: out std_logic_vector(3 downto 0);
CARRYOUT : out std_logic
);
end component;
component DEC_7SegLED
port(
ENABLE : in std_logic;
RESET : in std_logic;
COUNTER : in std_logic_vector(3 downto 0);
LED_7SEG: out std_logic_vector(7 downto 1)
);
end component;
signal CLK_2Hz : std_logic;
signal CLK_32Hz : std_logic;
signal COUNT_TMP1: std_logic_vector(3 downto 0);
signal COUNT_TMP2: std_logic_vector(3 downto 0);
begin
U1 :DIVIDER port map (CLK, RESET, CLK_2Hz, open);
U2 :COUNTER24 port map (CLK_2Hz, RESET, ENABLE, COUNT_TMP1, COUNT_TMP2, CARRYOUT);
U3 :DEC_7SegLED port map (ENABLE, RESET, COUNT_TMP1,LED_7SEG1);
U4 :DEC_7SegLED port map (ENABLE, RESET, COUNT_TMP2,LED_7SEG2);
end RTL;
信号をつないでいるだけです。
もちろんこのトップエンティティに処理内容を記載してもOKです。
port map の使用していないoutはopenにしています。
使用していない signal文につなげてもかまいません。
port map の in は、不定にできません。*2
port signal '0' '1' などにつなげます。
*1:またのちほど(^_^;)
*2:というか、コンパイルできないはずです。