32ビット値を16進8桁としてキャラクターLCDに表示する その2

というわけで、列挙型はインデックスから列挙子名が取得できるとともに列挙子名からインデックスの取得できることが分かった。インデックスであって、各列挙子名に割り当てられた番号ではない。「32ビット値を16進8桁としてキャラクターLCDに表示する -」で作ったchar_LCD_8_digits.vhdをもう少しコンパクトにしてみる。

VHDL_for_Quartus_Prime/char_LCD_8_digits_ver2 at main · ti-nspire/VHDL_for_Quartus_Prime · GitHub
char_LCD_8_digits.vhd

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

entity char_LCD_8_digits is
    generic(
        F_CLK : natural := 32_768
    );
    port(
        clk   : in std_logic;
        rst_n : in std_logic;
        bin_in: in std_logic_vector(31 downto 0);
        
        E : buffer std_logic;
        RS: out    std_logic;
        DB: out    std_logic_vector(7 downto 4);
        
        is_ready: out std_logic -- Whether the power_on_reset completed(1) or not(0).
    );
end entity;

architecture rtl of char_LCD_8_digits is

    type state_type is (
       -- Arrange these 17 states in this order, starting from the top of the list.
        ReturnHome_H,
        W1H, W2H, W3H, W4H, W5H, W6H, W7H, W8H,
        W1L, W2L, W3L, W4L, W5L, W6L, W7L, W8L,
       ---------------------------------------
    
        power_on_reset1, power_on_reset8,

        FunctionSet1, FunctionSet2, FunctionSet3,
        FunctionSet4, FunctionSet5, FunctionSet6,

        ClearDisplay_H, DisplayControl_H, EntryMode_H,
        ClearDisplay_L, DisplayControl_L, EntryMode_L,
    
        ReturnHome_L
    );

    signal pr_state, nx_state: state_type;
    attribute syn_encoding: string;
    attribute syn_encoding of state_type: type is "compact";

    /*
   attribute keep: boolean;
   attribute keep of pr_state, nx_state: signal is true;
   */

    function upper_4(num: std_logic_vector(3 downto 0))
        return std_logic_vector is
    begin
        if   unsigned(num)<10 then return "0011"; -- when 0-9
        else                       return "0100"; -- when A-F
        end if;
    end function;

    function lower_4(num: std_logic_vector(3 downto 0))
        return std_logic_vector  is
    begin
        if   unsigned(num)<10 then return num;         -- when 0-9
        else return std_logic_vector(unsigned(num)-9); -- when A-F
        end if;
    end function;

begin

   -- generate a clock signal whose period is 2 ms or more.
    process(clk)
        constant count_max: natural := F_CLK / 900;
        variable count: natural range 0 to count_max;
    begin
        if rising_edge(clk) then
            count := count + 1;
            if count = count_max then
                count := 0;
                E <= not E;
            end if;
        end if;
    end process;

   -- a register for keeping a state.
    process(E, rst_n)
    begin
        if    rst_n = '0'    then pr_state <= power_on_reset1;
        elsif rising_edge(E) then pr_state <= nx_state;
        end if;
    end process;

   -- a combinational logic circuit for deciding a next state.
    process(all)
    begin
        RS       <= '0';
        DB       <= "0011";
        is_ready <= '0';
        
        case pr_state is
            when power_on_reset1 =>
                for i in 1 to 7 loop
                    if    i < 7 then nx_state <= power_on_reset1;
                    elsif i = 7 then nx_state <= power_on_reset8;
                    end if;
                end loop;

            when power_on_reset8 => is_ready <= '1'; nx_state <= FunctionSet1;
            
            when FunctionSet1 => nx_state <= FunctionSet2;
            when FunctionSet2 => nx_state <= FunctionSet3;
            when FunctionSet3 => nx_state <= FunctionSet4;
            
            when FunctionSet4 => DB <= "0010"; nx_state <= FunctionSet5;
            when FunctionSet5 => DB <= "0010"; nx_state <= FunctionSet6;
            when FunctionSet6 => DB <= "1000"; nx_state <= ClearDisplay_H;
            
            when ClearDisplay_H => DB <= "0000"; nx_state <= ClearDisplay_L;
            when ClearDisplay_L => DB <= "0001"; nx_state <= DisplayCOntrol_H;
            
            when DisplayControl_H => DB <= "0000"; nx_state <= DisplayControl_L;
            when DisplayControl_L => DB <= "1100"; nx_state <= EntryMode_H;
            
            when EntryMode_H => DB <= "0000"; nx_state <= EntryMode_L;
            when EntryMode_L => DB <= "0110"; nx_state <= W8H; -- first, display a highest-order digit.

           -- Type_Name'pos(Type_Value) provides its position number (integer).
           -- Type_Name'val(Position_Number) provides its type value.
            when W1H to W8H => -- states 1-8
                RS <= '1';
                DB <= upper_4(bin_in(state_type'pos(pr_state)*4-1 downto state_type'pos(pr_state)*4-4));
                nx_state <= state_type'val(state_type'pos(pr_state)+8);
            when W1L to W8L => -- states 9-16
                RS <= '1';
                DB <= lower_4(bin_in((state_type'pos(pr_state)-8)*4-1 downto (state_type'pos(pr_state)-8)*4-4));
                nx_state <= state_type'val(state_type'pos(pr_state)-9);
                
            when ReturnHome_H => DB <= "1000"; nx_state <= ReturnHome_L; -- state 0
            when ReturnHome_L => DB <= "0000"; nx_state <= W8H;
            
            when others => nx_state <= power_on_reset1;
        end case;
    end process;

end architecture;

example_for_displaying_a_constant.vhd

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

entity example_for_displaying_a_constant is
    port(
        clk   : in std_logic;
        rst_n : in std_logic;
       --bin_in: in std_logic_vector(31 downto 0);
        
        E : out std_logic;
        RS: out std_logic;
        DB: out std_logic_vector(7 downto 4)
    );
end entity;

architecture rtl of example_for_displaying_a_constant is
begin

    c1: entity work.char_LCD_8_digits
        generic map(
            F_CLK => 1_000_000
        )
        port map(
            clk    => clk,
            rst_n  => rst_n,
           --bin_in => bin_in,
            bin_in => x"90fa_81eb",
            E      => E,
            RS     => RS,
            DB     => DB
        );

end architecture;

f:id:ti-nspire:20210812160837j:plain:w500