A、B、OUTの各レジスタとPCとをVHDLで書き換える

今度はA、B、OUTの各レジスタとPC (p.115-118)。『CPUの創りかた』のときと同じく、まず共通のカウンター兼レジスターを作っておく(このとき作った74161のようなものからリプルキャリーアウト機能を省いたもの)。それを4つまとめて実体化する。

共通のカウンター兼レジスター:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity counter_register is
    generic(
        NUM_BITS: natural := 4
    );
    port(
        clk   : in std_logic;
        aclr_n: in std_logic;
        sload : in std_logic;
        d     : in std_logic_vector(NUM_BITS-1 downto 0);
        
        ena_count: in std_logic;
        
        q: out std_logic_vector(NUM_BITS-1 downto 0)
    );
end entity;

architecture rtl of counter_register is
    signal count: natural range 0 to 2**NUM_BITS-1; -- この変数をカウンターとして使う。
    constant COUNT_MAX: natural := 2**NUM_BITS-1;   -- カウンターのトップ値。
begin
   -- カウント値をそのまま出力する。
    q <= std_logic_vector(to_unsigned(count, NUM_BITS));
    
    process(all)
    begin

       -- !非同期リセット
        if aclr_n = '0' then
            count <= 0;

        elsif rising_edge(clk) then

           -- 同期ロード
            if sload then
                count <= to_integer(unsigned(d));

           -- 同期カウント
            elsif ena_count then
                if count >= COUNT_MAX then
                    count <= 0;
                else
                    count <= count + 1;
                end if;
            end if;
        end if;
    end process;
    
end architecture;

それ4つ組み合わせる:

library ieee;
use ieee.std_logic_1164.all;

entity registers is
    generic(
        NUM_BITS: natural := 4
    );
    port(
        inp: in std_logic_vector(NUM_BITS-1 downto 0);

        a_reg_ld: in std_logic;
        b_reg_ld: in std_logic;
        out_ld  : in std_logic;
        pc_ld   : in std_logic;
        
        clk_inside: in std_logic;
        aclr_n    : in std_logic;
        
        pc_up: in std_logic;

        a_reg  : out std_logic_vector(NUM_BITS-1 downto 0);
        b_reg  : out std_logic_vector(NUM_BITS-1 downto 0);
        out_reg: out std_logic_vector(NUM_BITS-1 downto 0);
        pc     : out std_logic_vector(NUM_BITS-1 downto 0)
    );
end entity;

architecture rtl of registers is
begin
   -- A_REGを実体化
    a_register: entity work.counter_register
        generic map(
            NUM_BITS => NUM_BITS
        )
        port map(
            clk       => clk_inside,
            aclr_n    => aclr_n,
            sload     => a_reg_ld,
            d         => inp,
            ena_count => '0', -- カウンターを無効化
            q         => a_reg
        );

   -- B_REGを実体化
    b_register: entity work.counter_register
        generic map(
            NUM_BITS => NUM_BITS
        )
        port map(
            clk       => clk_inside,
            aclr_n    => aclr_n,
            sload     => b_reg_ld,
            d         => inp,
            ena_count => '0',  -- カウンターを無効化
            q         => b_reg
        );

   -- OUT_REGを実体化
    out_register: entity work.counter_register
        generic map(
            NUM_BITS => NUM_BITS
        )
        port map(
            clk       => clk_inside,
            aclr_n    => aclr_n,
            sload     => out_ld,
            d         => inp,
            ena_count => '0',  -- カウンターを無効化
            q         => out_reg
        );

   -- PCを実体化
    program_counter: entity work.counter_register
        generic map(
            NUM_BITS => NUM_BITS
        )
        port map(
            clk       => clk_inside,
            aclr_n    => aclr_n,
            sload     => pc_ld,
            d         => inp,
            ena_count => pc_up,  -- カウンターを有効化
            q         => pc
        );

end architecture;