テキストは8ビットモードで制御しているが今度は4ビットモードを試す。もっとスマートに書けると思うが今のところわからない。
library ieee; use ieee.std_logic_1164.all; entity digital_watch_with_LCD_display_4bit is generic( F_CLK: natural := 48_000_000 ); port( clk, rst : in std_logic; set_sec, set_min, set_hour: in std_logic; E, RS/*, RW, LCD_ON, BKLT_ON*/: out std_logic; DB: out std_logic_vector(7 downto 4) ); end entity; architecture rtl of digital_watch_with_LCD_display_4bit is function int_to_lcd(input: natural) return std_logic_vector is begin case input is when 0 => return "00110000"; when 1 => return "00110001"; when 2 => return "00110010"; when 3 => return "00110011"; when 4 => return "00110100"; when 5 => return "00110101"; when 6 => return "00110110"; when 7 => return "00110111"; when 8 => return "00111000"; when 9 => return "00111001"; when others => return "00111111"; -- '?'マーク end case; end function; type state_type is ( FunctionSet1, FunctionSet2, FunctionSet3, FunctionSet4, FunctionSet5, FunctionSet6, ClearDisplay_H, DisplayControl_H, EntryMode_H, ClearDisplay_L, DisplayControl_L, EntryMode_L, WriteHourT_H, WriteHourU_H, WriteColon1_H, WriteHourT_L, WriteHourU_L, WriteColon1_L, WriteMinT_H, WriteMinU_H, WriteColon2_H, WriteMinT_L, WriteMinU_L, WriteColon2_L, WriteSecT_H, WriteSecU_H, ReturnHome_H, WriteSecT_L, WriteSecU_L, ReturnHome_L ); signal pr_state, nx_state: state_type; signal secU, minU, hourU: natural range 0 to 9; -- 一秒の桁, 一分の桁, 一時の桁 signal secT, minT : natural range 0 to 5; -- 十秒の桁, 十分の桁 signal hourT : natural range 0 to 2; -- 十時の桁 signal limit : natural range 0 to F_CLK; signal E_temp: std_logic; begin limit <= F_CLK / 8192 when set_hour else -- set_hourがHiなら時計の進む速度を8192倍にする。 F_CLK / 256 when set_min else -- set_min がHiなら時計の進む速度を 256倍になる。 F_CLK / 8 when set_sec else -- set_sec をHiなら時計の進む速度を 8倍にする F_CLK; process(clk, rst) variable count0: natural range 0 to F_CLK; -- ソースクロックのカウンター variable count1: natural range 0 to 10; -- 一秒桁のカウンター variable count2: natural range 0 to 6; -- 十秒桁のカウンター variable count3: natural range 0 to 10; -- 一分桁のカウンター variable count4: natural range 0 to 6; -- 十分桁のカウンター variable count5: natural range 0 to 10; -- 一時桁のカウンター variable count6: natural range 0 to 3; -- 十時桁のカウンター begin if rst then count0 := 0; count1 := 0; count2 := 0; count3 := 0; count4 := 0; count5 := 0; count6 := 0; elsif rising_edge(clk) then count0 := count0 + 1; if count0=limit then count0 := 0; count1 := count1 + 1; if count1=10 then count1 := 0; count2 := count2 + 1; if count2= 6 then count2 := 0; count3 := count3 + 1; if count3=10 then count3 := 0; count4 := count4 + 1; if count4= 6 then count4 := 0; count5 := count5 + 1; if (count6/=2 and count5=10) or (count6 =2 and count5= 4) then count5 := 0; count6 := count6 + 1; if count6= 3 then count6 := 0; end if; end if; end if; end if; end if; end if; end if; end if; secU <= count1; secT <= count2; minU <= count3; minT <= count4; hourU <= count5; hourT <= count6; end process; /*LCD_ON <= '1'; BKLT_ON <= '1'; RW <= '0';*/ -- LCDの駆動パルス生成する。 -- ここではソースクロック48 MHzから500 Hz(周期2 msec)を生成する。 -- 48000クロックサイクルごとにトグルする。 process(clk) variable count: natural range 0 to F_CLK / 1000; begin if rising_edge(clk) then count := count + 1; if count = F_CLK / 1000 then count := 0; E <= not E; end if; end if; end process; -- ステートを保存しておくためのレジスタ process(E, rst) begin E_temp <= E; if rst then pr_state <= FunctionSet1; elsif rising_edge(E_temp) then pr_state <= nx_state; end if; E <= E_temp; end process; -- 次のステートを決めるための組み合わせ論理回路 process(all) variable hourT_temp: std_logic_vector(7 downto 0); variable hourU_temp: std_logic_vector(7 downto 0); variable minT_temp : std_logic_vector(7 downto 0); variable minU_temp : std_logic_vector(7 downto 0); variable secT_temp : std_logic_vector(7 downto 0); variable secU_temp : std_logic_vector(7 downto 0); begin RS <= '0'; DB <= "0011"; case pr_state is 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 <= WriteHourT_H; when WriteHourT_H => hourT_temp := int_to_lcd(hourT); RS <= '1'; DB <= hourT_temp(7 downto 4); nx_state <= WriteHourT_L; when WriteHourT_L => RS <= '1'; DB <= hourT_temp(3 downto 0); nx_state <= WriteHourU_H; when WriteHourU_H => hourU_temp := int_to_lcd(hourU); RS <= '1'; DB <= hourU_temp(7 downto 4); nx_state <= WriteHourU_L; when WriteHourU_L => RS <= '1'; DB <= hourU_temp(3 downto 0); nx_state <= WriteColon1_H; when WriteColon1_H => RS <= '1'; DB <= "0011"; nx_state <= WriteColon1_L; when WriteColon1_L => RS <= '1'; DB <= "1010"; nx_state <= WriteMinT_H; when WriteMinT_H => minT_temp := int_to_lcd(minT); RS <= '1'; DB <= minT_temp(7 downto 4); nx_state <= WriteMinT_L; when WriteMinT_L => RS <= '1'; DB <= minT_temp(3 downto 0); nx_state <= WriteMinU_H; when WriteMinU_H => minU_temp := int_to_lcd(minU); RS <= '1'; DB <= minU_temp(7 downto 4); nx_state <= WriteMinU_L; when WriteMinU_L => RS <= '1'; DB <= minU_temp(3 downto 0); nx_state <= WriteColon2_H; when WriteColon2_H => RS <= '1'; DB <= "0011"; nx_state <= WriteColon2_L; when WriteColon2_L => RS <= '1'; DB <= "1010"; nx_state <= WriteSecT_H; when WriteSecT_H => secT_temp := int_to_lcd(secT); RS <= '1'; DB <= secT_temp(7 downto 4); nx_state <= WriteSecT_L; when WriteSecT_L => RS <= '1'; DB <= secT_temp(3 downto 0); nx_state <= WriteSecU_H; when WriteSecU_H => secU_temp := int_to_lcd(secU); RS <= '1'; DB <= secU_temp(7 downto 4); nx_state <= WriteSecU_L; when WriteSecU_L => RS <= '1'; DB <= secU_temp(3 downto 0); nx_state <= ReturnHome_H; when ReturnHome_H => DB <= "1000"; nx_state <= ReturnHome_L; when ReturnHome_L => DB <= "0000"; nx_state <= WriteHourT_H; end case; end process; end architecture;