diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..549d1b59 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..99b222d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +output_files/ +simulation/ +db/ +incremental_db/ diff --git a/peripherals/.DS_Store b/peripherals/.DS_Store new file mode 100644 index 00000000..1b5619e8 Binary files /dev/null and b/peripherals/.DS_Store differ diff --git a/peripherals/lcd_hd44780/.DS_Store b/peripherals/lcd_hd44780/.DS_Store new file mode 100644 index 00000000..57a07df3 Binary files /dev/null and b/peripherals/lcd_hd44780/.DS_Store differ diff --git a/peripherals/lcd_hd44780/lcd_hd44780.vhd b/peripherals/lcd_hd44780/lcd_hd44780.vhd index 561a6772..a7aa64fe 100644 --- a/peripherals/lcd_hd44780/lcd_hd44780.vhd +++ b/peripherals/lcd_hd44780/lcd_hd44780.vhd @@ -13,248 +13,273 @@ use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity lcd_hd44780 is - generic( - display_width : integer := 16; - display_heigth : integer := 2; - -- Countings - t0_startup_time : integer := 80000; --! 40ms [1] - t1_short_wait : integer := 200; --! 100us [1] - t2_long_wait : integer := 10000; --! 4.1ms [1] - t3_enable_pulse : integer := 500; --! 0,450us [1] - t4_clear_and_return : integer := 2000 --! 1,52ms [1] - ); - port( - --! @brief Internal signals (RISC-V Datapath) - clk : in std_logic; - rst : in std_logic; - -- TODO: 16x2 8-bit RAM peripheral memory shared with RISC-V + generic( + MY_CHIPSELECT : std_logic_vector(1 downto 0) := "11"; + MY_WORD_ADDRESS : unsigned(15 downto 0) := x"0020"; + DADDRESS_BUS_SIZE : integer := 32; + display_width : integer := 16; + display_heigth : integer := 2; + -- Countings + t0_startup_time : integer := 80000; --! 40ms [1] + t1_short_wait : integer := 200; --! 100us [1] + t2_long_wait : integer := 10000; --! 4.1ms [1] + t3_enable_pulse : integer := 500; --! 0,450us [1] + t4_clear_and_return : integer := 2000 --! 1,52ms [1] + ); + port( + --! @brief Internal signals (RISC-V Datapath) + clk : in std_logic; + rst : in std_logic; + -- Core data bus signals + daddress : in unsigned(DADDRESS_BUS_SIZE - 1 downto 0); + ddata_w : in std_logic_vector(31 downto 0); + ddata_r : out std_logic_vector(31 downto 0); + d_we : in std_logic; + d_rd : in std_logic; + dcsel : in std_logic_vector(1 downto 0); --! Chip select + -- ToDo: Module should mask bytes (Word, half word and byte access) + dmask : in std_logic_vector(3 downto 0); --! Byte enable mask - --! @brief LCD peripheral 32-bit register ("LCDREG0") - lcd_init : in std_logic; --! Bit 8 - Rising edge will start display initialization FSM - lcd_write_char : in std_logic; --! Bit 9 - '1' will write char in bits 0-7 - lcd_clear : in std_logic; --! Bit 10 - '1' will return cursor to home (Line1-0) and clear display - lcd_goto_l1 : in std_logic; --! Bit 11 - '1' will put cursor in first position of line 1 - lcd_goto_l2 : in std_logic; --! Bit 12 - '1' will put cursor in first position of line 2 + -- --! @brief LCD peripheral 32-bit register ("LCDREG0") + -- lcd_data_in : in std_logic; --! 0 to 7 + -- lcd_init : in std_logic; --! Bit 8 - Rising edge will start display initialization FSM + -- lcd_write_char : in std_logic; --! Bit 9 - '1' will write char in bits 0-7 + -- lcd_clear : in std_logic; --! Bit 10 - '1' will return cursor to home (Line1-0) and clear display + -- lcd_goto_l1 : in std_logic; --! Bit 11 - '1' will put cursor in first position of line 1 + -- lcd_goto_l2 : in std_logic; --! Bit 12 - '1' will put cursor in first position of line 2 + lcd_is_busy : out std_logic; --! Bit 13 - Status flag, during command send will be 1, else 0 - lcd_is_busy : out std_logic; --! Bit 13 - Status flag, during command send will be 1, else 0 - - --! @brief External signals (IOs to interface with LCD) - lcd_data : out std_logic_vector(7 downto 0); - lcd_rs : out std_logic; --! Controls if command or char data - lcd_e : out std_logic --! Pulse in every command/data - ); + --! @brief External signals (IOs to interface with LCD) + lcd_data : out std_logic_vector(7 downto 0); + lcd_rs : out std_logic; --! Controls if command or char data + lcd_e : out std_logic --! Pulse in every command/data + ); end lcd_hd44780; architecture controller of lcd_hd44780 is - type fsm_state is ( - LCD_OFF, LCD_STARTUP, LCD_ON - ); - type lcd_commands is ( - LCD_CMD_IDLE, LCD_CMD_INITIALIZE, LCD_CMD_WRITE_CHAR, LCD_CMD_CLEAR_RETURN_HOME, LCD_CMD_GOTO_LINE_1, LCD_CMD_GOTO_LINE_2 - ); - type lcd_initialize is ( - LCD_INIT_0, LCD_INIT_1, LCD_INIT_2, LCD_INIT_3, LCD_INIT_4, LCD_INIT_5, LCD_INIT_6 - ); + type fsm_state is ( + LCD_OFF, LCD_STARTUP, LCD_ON + ); + type lcd_commands is ( + LCD_CMD_IDLE, LCD_CMD_INITIALIZE, LCD_CMD_WRITE_CHAR, LCD_CMD_CLEAR_RETURN_HOME, LCD_CMD_GOTO_LINE_1, LCD_CMD_GOTO_LINE_2 + ); + type lcd_initialize is ( + LCD_INIT_0, LCD_INIT_1, LCD_INIT_2, LCD_INIT_3, LCD_INIT_4, LCD_INIT_5, LCD_INIT_6 + ); + + signal hd44780_register : std_logic_vector(31 downto 0); + + signal power_state : fsm_state := LCD_STARTUP; + signal command : lcd_commands := LCD_CMD_IDLE; + signal lcd_cmd_init_state : lcd_initialize := LCD_INIT_0; + signal startup_counter : integer range 0 to 1000000; --! 0 microseconds to 1s + signal time_counter : integer range 0 to 1000000; --! 0 microseconds to 1s + signal enable_counter : integer range 0 to 1000000; --! 0 microseconds to 1s + + constant LCD_INIT_BIT : integer := 8; + constant LCD_WRITE_CHAR_BIT : integer := 9; + constant LCD_CLEAR_BIT : integer := 10; + constant LCD_LINE1_BIT : integer := 11; + constant LCD_LINE2_BIT : integer := 12; - signal power_state : fsm_state := LCD_STARTUP; - signal command : lcd_commands := LCD_CMD_IDLE; - signal lcd_cmd_init_state : lcd_initialize := LCD_INIT_0; - signal startup_counter : integer range 0 to 1000000; --! 0 microseconds to 1s - signal time_counter : integer range 0 to 1000000; --! 0 microseconds to 1s - signal enable_counter : integer range 0 to 1000000; --! 0 microseconds to 1s begin - lcd_control : process(clk, rst, lcd_init) - begin - if (rst = '1') then - power_state <= LCD_OFF; - startup_counter <= 0; - time_counter <= 0; - enable_counter <= 0; - lcd_data <= "00000000"; - lcd_e <= '0'; - lcd_rs <= '0'; + lcd_control : process(clk, rst) + begin + if (rst = '1') then + hd44780_register <= (others => '0'); + power_state <= LCD_OFF; + startup_counter <= 0; + time_counter <= 0; + enable_counter <= 0; + lcd_data <= "00000000"; + lcd_e <= '0'; + lcd_rs <= '0'; + + elsif rising_edge(clk) then + if (d_we = '1') and (dcsel = MY_CHIPSELECT) then + startup_counter <= startup_counter + 1; + time_counter <= time_counter + 1; + enable_counter <= enable_counter + 1; - elsif rising_edge(clk) then - startup_counter <= startup_counter + 1; - time_counter <= time_counter + 1; - enable_counter <= enable_counter + 1; + case power_state is + when LCD_OFF => + lcd_is_busy <= '0'; + if (hd44780_register(LCD_INIT_BIT) = '1') then + power_state <= LCD_STARTUP; + end if; + when LCD_STARTUP => + lcd_is_busy <= '1'; + if (startup_counter >= t0_startup_time) then + startup_counter <= 0; + power_state <= LCD_ON; + end if; - case power_state is - when LCD_OFF => - lcd_is_busy <= '0'; - if (lcd_init = '1') then - power_state <= LCD_STARTUP; - end if; - when LCD_STARTUP => - lcd_is_busy <= '1'; - if (startup_counter >= t0_startup_time) then - startup_counter <= 0; - power_state <= LCD_ON; - end if; + when LCD_ON => + --! Busy flag control + if (command = LCD_CMD_IDLE) then + lcd_is_busy <= '0'; + else + lcd_is_busy <= '1'; + end if; + end case; + case command is + when LCD_CMD_IDLE => + --! Fetch bit instructions to internal "command" signal + if (hd44780_register(LCD_INIT_BIT) = '1') then + command <= LCD_CMD_INITIALIZE; + elsif (hd44780_register(LCD_WRITE_CHAR_BIT) = '1') then + command <= LCD_CMD_WRITE_CHAR; + elsif (hd44780_register(LCD_CLEAR_BIT) = '1') then + command <= LCD_CMD_CLEAR_RETURN_HOME; + elsif (hd44780_register(LCD_LINE1_BIT) = '1') then + command <= LCD_CMD_GOTO_LINE_1; + elsif (hd44780_register(LCD_LINE2_BIT) = '1') then + command <= LCD_CMD_GOTO_LINE_2; + else + command <= LCD_CMD_IDLE; + end if; + --! Initialization state machine + when LCD_CMD_INITIALIZE => + lcd_rs <= '0'; + case lcd_cmd_init_state is + when LCD_INIT_0 => + lcd_data <= "00110000"; --! Special function set 3x times + if (time_counter >= t2_long_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + lcd_cmd_init_state <= LCD_INIT_1; + end if; + when LCD_INIT_1 => + lcd_data <= "00110000"; + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + lcd_cmd_init_state <= LCD_INIT_2; + end if; + when LCD_INIT_2 => + lcd_data <= "00110000"; --! Function sets if Nlines = 1 or 2 + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + lcd_cmd_init_state <= LCD_INIT_3; + end if; + when LCD_INIT_3 => + lcd_data <= "00001000"; + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + lcd_cmd_init_state <= LCD_INIT_4; + end if; + when LCD_INIT_4 => + lcd_data <= "00000001"; + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + lcd_cmd_init_state <= LCD_INIT_5; + end if; + when LCD_INIT_5 => + lcd_data <= "00000101"; + lcd_e <= '0'; + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + lcd_cmd_init_state <= LCD_INIT_6; + end if; + when LCD_INIT_6 => + lcd_data <= "00001101"; + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + lcd_cmd_init_state <= LCD_INIT_0; + command <= LCD_CMD_IDLE; + end if; + end case; + --! Write char + when LCD_CMD_WRITE_CHAR => + lcd_rs <= '1'; + lcd_data <= "01000001"; --! 'A' 01000001 // 00000000 + -- db7 db0 - when LCD_ON => - --! Busy flag control - if (command = LCD_CMD_IDLE) then - lcd_is_busy <= '0'; - else - lcd_is_busy <= '1'; - end if; - end case; - case command is - when LCD_CMD_IDLE => - --! Fetch bit instructions to internal "command" signal - if (lcd_init = '1') then - command <= LCD_CMD_INITIALIZE; - elsif (lcd_write_char = '1') then - command <= LCD_CMD_WRITE_CHAR; - elsif (lcd_clear = '1') then - command <= LCD_CMD_CLEAR_RETURN_HOME; - elsif (lcd_goto_l1 = '1') then - command <= LCD_CMD_GOTO_LINE_1; - elsif (lcd_goto_l2 = '1') then - command <= LCD_CMD_GOTO_LINE_2; - else - command <= LCD_CMD_IDLE; - end if; - --! Initialization state machine - when LCD_CMD_INITIALIZE => - lcd_rs <= '0'; - case lcd_cmd_init_state is - when LCD_INIT_0 => - lcd_data <= "00110000"; --! Special function set 3x times - if (time_counter >= t2_long_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - lcd_cmd_init_state <= LCD_INIT_1; - end if; - when LCD_INIT_1 => - lcd_data <= "00110000"; - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - lcd_cmd_init_state <= LCD_INIT_2; - end if; - when LCD_INIT_2 => - lcd_data <= "00110000"; --! Function sets if Nlines = 1 or 2 - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - lcd_cmd_init_state <= LCD_INIT_3; - end if; - when LCD_INIT_3 => - lcd_data <= "00001000"; - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - lcd_cmd_init_state <= LCD_INIT_4; - end if; - when LCD_INIT_4 => - lcd_data <= "00000001"; - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - lcd_cmd_init_state <= LCD_INIT_5; - end if; - when LCD_INIT_5 => - lcd_data <= "00000101"; - lcd_e <= '0'; - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - lcd_cmd_init_state <= LCD_INIT_6; - end if; - when LCD_INIT_6 => - lcd_data <= "00001101"; - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - lcd_cmd_init_state <= LCD_INIT_0; - command <= LCD_CMD_IDLE; - end if; - end case; - --! Write char - when LCD_CMD_WRITE_CHAR => - lcd_rs <= '1'; - lcd_data <= "01000001"; --! 'A' - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - end if; - command <= LCD_CMD_IDLE; - --! Position cursor in 0x80 (L1) and clear DDRAM - when LCD_CMD_CLEAR_RETURN_HOME => - lcd_rs <= '0'; - lcd_data <= "00000001"; - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - end if; - command <= LCD_CMD_IDLE; - --! Position cursor in 0x40 -> 0x80 (L1) - when LCD_CMD_GOTO_LINE_1 => - lcd_rs <= '0'; - lcd_data <= "10000000"; - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - end if; - command <= LCD_CMD_IDLE; - --! Position cursor in 0x40 -> 0xC0 (L2) - when LCD_CMD_GOTO_LINE_2 => - lcd_rs <= '0'; - lcd_data <= "11000000"; - if (time_counter >= t1_short_wait) then - time_counter <= 0; - lcd_e <= '1'; - if (enable_counter >= t3_enable_pulse) then - enable_counter <= 0; - lcd_e <= '0'; - end if; - end if; - command <= LCD_CMD_IDLE; - end case; - end if; + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + end if; + command <= LCD_CMD_IDLE; + --! Position cursor in 0x80 (L1) and clear DDRAM + when LCD_CMD_CLEAR_RETURN_HOME => + lcd_rs <= '0'; + lcd_data <= "00000001"; + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + end if; + command <= LCD_CMD_IDLE; + --! Position cursor in 0x40 -> 0x80 (L1) + when LCD_CMD_GOTO_LINE_1 => + lcd_rs <= '0'; + lcd_data <= "10000000"; + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + end if; + command <= LCD_CMD_IDLE; + --! Position cursor in 0x40 -> 0xC0 (L2) + when LCD_CMD_GOTO_LINE_2 => + lcd_rs <= '0'; + lcd_data <= "11000000"; + if (time_counter >= t1_short_wait) then + time_counter <= 0; + lcd_e <= '1'; + if (enable_counter >= t3_enable_pulse) then + enable_counter <= 0; + lcd_e <= '0'; + end if; + end if; + command <= LCD_CMD_IDLE; + end case; + end if; + end if; - end process; + end process; end controller; diff --git a/peripherals/lcd_hd44780/sint2/de10_lite/de0_lite.vhd b/peripherals/lcd_hd44780/sint2/de10_lite/de0_lite.vhd index da76f68b..2e0a195e 100644 --- a/peripherals/lcd_hd44780/sint2/de10_lite/de0_lite.vhd +++ b/peripherals/lcd_hd44780/sint2/de10_lite/de0_lite.vhd @@ -120,6 +120,7 @@ architecture rtl of de0_lite is signal ddata_r_i2c : std_logic_vector(31 downto 0); signal ddata_r_dig_fil : std_logic_vector(31 downto 0); signal ddata_r_stepmot : std_logic_vector(31 downto 0); + signal ddata_r_hd44780 : std_logic_vector(31 downto 0); signal data_in_dig_fil : std_logic_vector(15 downto 0); @@ -297,6 +298,43 @@ begin hex6 => open, hex7 => open ); + + lcd : entity work.lcd_hd44780 + port map( + clk => clk_1k, + rst => SW(9), + -- + daddress => daddress, + ddata_w => ddata_w, + ddata_r => ddata_r_segments, + d_we => d_we, + d_rd => d_rd, + dcsel => dcsel, + dmask => dmask, + -- + lcd_data(7) => ARDUINO_IO(0), + lcd_data(6) => ARDUINO_IO(1), + lcd_data(5) => ARDUINO_IO(2), + lcd_data(4) => ARDUINO_IO(3), + lcd_data(3) => ARDUINO_IO(4), + lcd_data(2) => ARDUINO_IO(5), + lcd_data(1) => ARDUINO_IO(6), + lcd_data(0) => ARDUINO_IO(7), + lcd_rs => ARDUINO_IO(9), + lcd_e => ARDUINO_IO(8), + lcd_is_busy => LEDR(8) + ); + + -- daddress : in unsigned(DADDRESS_BUS_SIZE - 1 downto 0); + -- ddata_w : in std_logic_vector(31 downto 0); + -- ddata_r : out std_logic_vector(31 downto 0); + -- d_we : in std_logic; + -- d_rd : in std_logic; + -- dcsel : in std_logic_vector(1 downto 0); --! Chip select + -- -- ToDo: Module should mask bytes (Word, half word and byte access) + -- dmask : in std_logic_vector(3 downto 0); --! Byte enable mask + + -- Connect input hardware to gpio data gpio_input(3 downto 0) <= SW(3 downto 0); diff --git a/peripherals/lcd_hd44780/sint2/de10_lite/de10_lite.qsf b/peripherals/lcd_hd44780/sint2/de10_lite/de10_lite.qsf index 3a818ad4..afb36950 100644 --- a/peripherals/lcd_hd44780/sint2/de10_lite/de10_lite.qsf +++ b/peripherals/lcd_hd44780/sint2/de10_lite/de10_lite.qsf @@ -216,7 +216,6 @@ set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "2.5 V" set_global_assignment -name TIMING_ANALYZER_MULTICORNER_ANALYSIS ON set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL -set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top set_global_assignment -name VHDL_FILE ../../lcd_hd44780.vhd set_global_assignment -name VHDL_FILE ../../../gpio/gpio.vhd set_global_assignment -name VHDL_FILE ../../../gpio/led_displays.vhd @@ -242,4 +241,5 @@ set_global_assignment -name VHDL_FILE ../../../../alu/alu_types.vhd set_global_assignment -name VHDL_FILE ../../../../alu/alu.vhd set_global_assignment -name VHDL_FILE de0_lite.vhd set_global_assignment -name QIP_FILE pll.qip -set_global_assignment -name SOURCE_FILE db/de10_lite.cmp.rdb \ No newline at end of file +set_global_assignment -name SOURCE_FILE db/de10_lite.cmp.rdb +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file