周波数カウンターを作る5 / キャラクターLCDに表示する

CPLDでディジタル電子工作 (CQ文庫), pp.171ff.

テキストは8桁ぶん並べた7セグLEDに測定結果を表示しているが、ここではキャラクターLCDに表示する。SC1602BBWB-XA-LB-Gを使った。フォントが小さいので本当は測定器のディスプレイには適さない。4ビットモードで動かす。

f:id:ti-nspire:20210601124606p:plain
今FGから9.876 kHzの矩形波を入力している。
f:id:ti-nspire:20210601124931j:plain:w600

LCD_4bits.vhd

library ieee;
use ieee.std_logic_1164.all;

entity LCD_4bits is
    generic(
        F_CLK: natural:= 32_768
    );
    port(
        clk, rst: in std_logic;
        bcd_in  : in std_logic_vector(31 downto 0);
        E, RS   : out std_logic;
        DB      : out std_logic_vector(7 downto 4);
        is_ready: out std_logic
    );
end entity;

architecture rtl of LCD_4bits is

    type state_type is (
        power_on_reset1,
        power_on_reset2,
        power_on_reset3,
        power_on_reset4,
        power_on_reset5,
        power_on_reset6,
        power_on_reset7,
        power_on_reset8,
    
        FunctionSet1,
        FunctionSet2,
        FunctionSet3,
        FunctionSet4,
        FunctionSet5,
        FunctionSet6,

        ClearDisplay_H, DisplayControl_H, EntryMode_H,
        ClearDisplay_L, DisplayControl_L, EntryMode_L,

        W_10M_H, W_1M_H, W_100k_H, W_10k_H, W_1k_H, W_100_H, W_10_H, W_1_H,
        W_10M_L, W_1M_L, W_100k_L, W_10k_L, W_1k_L, W_100_L, W_10_L, W_1_L,
        
        ReturnHome_H,
        ReturnHome_L
    );
    signal pr_state, nx_state: state_type;
    signal E_temp: std_logic;

begin

   -- 周期2 ms以上のクロックを生成する。割に適当でよい。
    process(clk)
        variable count: natural range 0 to F_CLK / 900;
    begin
        if rising_edge(clk) then
            count := count + 1;
            if count = F_CLK / 900 then
                count := 0;
                E <= not E;
            end if;
        end if;
    end process;

   -- ステートを保存しておくためのレジスタ
    process(E, rst)
    begin
        E_temp <= E;
        if    rst                    then pr_state <= power_on_reset1;
        elsif rising_edge(E_temp) then pr_state <= nx_state;
        end if;
        E <= E_temp;
    end process;

   -- 次のステートを決めるための組み合わせ論理回路
    process(all)
    
    begin
        RS <= '0';
        DB <= "0011";
        is_ready <= '0';
        
        case pr_state is
            when power_on_reset1 => nx_state <= power_on_reset2;
            when power_on_reset2 => nx_state <= power_on_reset3;
            when power_on_reset3 => nx_state <= power_on_reset4;
            when power_on_reset4 => nx_state <= power_on_reset5;
            when power_on_reset5 => nx_state <= power_on_reset6;
            when power_on_reset6 => nx_state <= power_on_reset7;
            when power_on_reset7 => nx_state <= power_on_reset8;

            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 <= W_10M_H;
            

            when W_10M_H  => RS <= '1'; DB <= "0011"              ; nx_state <= W_10M_L;
            when W_10M_L  => RS <= '1'; DB <= bcd_in(31 downto 28); nx_state <= W_1M_H;

            when W_1M_H   => RS <= '1'; DB <= "0011"              ; nx_state <= W_1M_L;
            when W_1M_L   => RS <= '1'; DB <= bcd_in(27 downto 24); nx_state <= W_100k_H;

            when W_100k_H => RS <= '1'; DB <= "0011"              ; nx_state <= W_100k_L;
            when W_100k_L => RS <= '1'; DB <= bcd_in(23 downto 20); nx_state <= W_10k_H;

            when W_10k_H  => RS <= '1'; DB <= "0011"              ; nx_state <= W_10k_L;
            when W_10k_L  => RS <= '1'; DB <= bcd_in(19 downto 16); nx_state <= W_1k_H;

            when W_1k_H   => RS <= '1'; DB <= "0011"              ; nx_state <= W_1k_L;
            when W_1k_L   => RS <= '1'; DB <= bcd_in(15 downto 12); nx_state <= W_100_H;

            when W_100_H  => RS <= '1'; DB <= "0011"              ; nx_state <= W_100_L;
            when W_100_L  => RS <= '1'; DB <= bcd_in(11 downto  8); nx_state <= W_10_H;

            when W_10_H   => RS <= '1'; DB <= "0011"              ; nx_state <= W_10_L;
            when W_10_L   => RS <= '1'; DB <= bcd_in( 7 downto  4); nx_state <= W_1_H;
                
            when W_1_H    => RS <= '1'; DB <= "0011"              ; nx_state <= W_1_L;
            when W_1_L    => RS <= '1'; DB <= bcd_in( 3 downto  0); nx_state <= ReturnHome_H;

            when ReturnHome_H => DB <= "1000"; nx_state <= ReturnHome_L;
            when ReturnHome_L => DB <= "0000"; nx_state <= W_10M_H;
        end case;
    end process;

end architecture;