Гвоздик 0 June 15, 2006 Posted June 15, 2006 (edited) · Report post Здравствуйте. Привожу исходный текст ЖКИ-контроллера для отладочной платы Altera MAX2 Development kit (ЖКИшник тамошний). По таймингу работает на 55 МГц, в железе гоняю на 66.66 МГц. Уверен, что код очень не оптимален - не стесняйтесь в выражениях, лишь бы на пользу дела было. Как улучшить код и повысить скорость работы при минимальных занимаемых ресурсах ПЛИС? library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; -- for conversions to std_logic_vector from natural entity lcd_controller is generic(LCD_DATA_SIZE : natural := 7; LCD_ROW_SIZE : natural := 2; LCD_COLUMN_SIZE : natural := 16); port(reset, clk : in std_logic; lcd_rs, lcd_rw, lcd_e : out std_logic; lcd_data : out std_logic_vector(LCD_DATA_SIZE downto 0)); end entity lcd_controller; architecture behavioural of lcd_controller is -- PCI_clk = 66 MHz => T_clk = 15 ns => T_count = 2 * T_clk = 30 ns constant delay_30ms : natural := 1000000; constant delay_6ms : natural := 200000; constant delay_2ms : natural := 60000; constant delay_2x2ms : natural := 120000; constant delay_3x2ms : natural := 180000; constant delay_4x2ms : natural := 240000; constant delay_5x2ms : natural := 300000; constant delay_6x2ms : natural := 360000; constant delay_7x2ms : natural := 420000; constant delay_8x2ms : natural := 480000; constant lcd_init_state_0 : natural := 0; constant lcd_init_state_1 : natural := delay_30ms; constant lcd_init_state_2 : natural := lcd_init_state_1 + delay_6ms; constant lcd_init_state_3 : natural := lcd_init_state_2 + delay_2ms; constant lcd_init_state_4 : natural := lcd_init_state_3 + delay_2ms; constant lcd_init_state_5 : natural := lcd_init_state_4 + delay_2ms; constant lcd_init_state_6 : natural := lcd_init_state_5 + delay_2ms; constant lcd_init_state_7 : natural := lcd_init_state_6 + delay_2ms; constant lcd_init_state_8 : natural := lcd_init_state_7 + delay_2ms; constant lcd_init_state_9 : natural := lcd_init_state_8 + delay_2ms; constant lcd_init_state_10 : natural := lcd_init_state_9 + delay_2ms; constant lcd_init_state_11 : natural := lcd_init_state_10 + delay_2ms; constant lcd_init_state_12 : natural := lcd_init_state_11 + delay_2ms; constant lcd_init_state_13 : natural := lcd_init_state_12 + delay_2ms; constant lcd_init_state_14 : natural := lcd_init_state_13 + delay_2ms; constant lcd_init_state_15 : natural := lcd_init_state_14 + delay_2ms; constant lcd_init_state_16 : natural := lcd_init_state_15 + delay_2ms; constant lcd_init_state_17 : natural := lcd_init_state_16 + delay_2ms; constant lcd_init_state_18 : natural := lcd_init_state_17 + delay_2ms; constant lcd_init_state_is_finished : natural := lcd_init_state_18 + delay_2ms; signal lcd_rs_sig, lcd_rw_sig, lcd_e_sig : std_logic; signal lcd_data_sig : std_logic_vector(LCD_DATA_SIZE downto 0) := X"00"; signal clk_counter : natural := 0; -- lcd row and column place of the symbol signal lcd_row : natural range 0 to LCD_ROW_SIZE := 1; signal lcd_column : natural range 0 to LCD_COLUMN_SIZE := 1; signal start_write_digit_state : natural := 0; signal pci_to_lcd_data_sig : natural := 0; signal lcd_is_initialized, write_digit_is_started : natural range 0 to 1 := 0; -- calculation of symbol absolute position pure function calculate_lcd_symbol_position(lcd_row_position : in natural; lcd_column_position : in natural) return natural is constant LCD_FIRST_ROW_ADDRESS_CORRECTION : natural := 127; constant LCD_SECOND_ROW_ADDRESS_CORRECTION : natural := 191; begin case lcd_row_position is when 1 => return lcd_column_position + LCD_FIRST_ROW_ADDRESS_CORRECTION; when 2 => return lcd_column_position + LCD_SECOND_ROW_ADDRESS_CORRECTION; when others => return lcd_column_position + LCD_FIRST_ROW_ADDRESS_CORRECTION; end case; end function calculate_lcd_symbol_position; -- ascii correction of the digit for correct lcd writing pure function do_lcd_ascii_correction(ascii_lcd_digit : in natural) return natural is constant ASCII_LCD_CORRECTION : natural := 48; begin return ascii_lcd_digit + ASCII_LCD_CORRECTION; end function do_lcd_ascii_correction; begin lcd_init_and_write: process(reset, clk, clk_counter) begin if (reset = '0') then clk_counter <= 0; lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"00"; lcd_is_initialized <= 0; start_write_digit_state <= 0; write_digit_is_started <= 0; else if ((clk'event) and (clk = '1')) then clk_counter <= clk_counter + 1; if (lcd_is_initialized = 0) then case clk_counter is when lcd_init_state_0 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"00"; when lcd_init_state_1 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"38"; when lcd_init_state_2 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '1'; lcd_data_sig <= X"38"; when lcd_init_state_3 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"38"; when lcd_init_state_4 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '1'; lcd_data_sig <= X"38"; when lcd_init_state_5 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"38"; when lcd_init_state_6 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '1'; lcd_data_sig <= X"38"; when lcd_init_state_7 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"38"; when lcd_init_state_8 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '1'; lcd_data_sig <= X"38"; when lcd_init_state_9 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"38"; when lcd_init_state_10 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"0C"; when lcd_init_state_11 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '1'; lcd_data_sig <= X"0C"; when lcd_init_state_12 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"0C"; when lcd_init_state_13 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"01"; when lcd_init_state_14 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '1'; lcd_data_sig <= X"01"; when lcd_init_state_15 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"01"; when lcd_init_state_16 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"06"; when lcd_init_state_17 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '1'; lcd_data_sig <= X"06"; when lcd_init_state_18 => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"06"; when lcd_init_state_is_finished => lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= X"06"; lcd_is_initialized <= 1; when others => end case; else -- lcd is ready for data display if (write_digit_is_started = 0) then start_write_digit_state <= clk_counter; write_digit_is_started <= 1; end if; if (clk_counter < (start_write_digit_state + delay_8x2ms)) then lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= conv_std_logic_vector(do_lcd_ascii_correction(pci_to_lcd_data_sig),LCD_DATA_SIZE + 1); if (clk_counter < (start_write_digit_state + delay_7x2ms)) then lcd_rs_sig <= '1'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= conv_std_logic_vector(do_lcd_ascii_correction(pci_to_lcd_data_sig),LCD_DATA_SIZE + 1); if (clk_counter < (start_write_digit_state + delay_6x2ms)) then lcd_rs_sig <= '1'; lcd_rw_sig <= '0'; lcd_e_sig <= '1'; lcd_data_sig <= conv_std_logic_vector(do_lcd_ascii_correction(pci_to_lcd_data_sig),LCD_DATA_SIZE + 1); if (clk_counter < (start_write_digit_state + delay_5x2ms)) then lcd_rs_sig <= '1'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= conv_std_logic_vector(do_lcd_ascii_correction(pci_to_lcd_data_sig),LCD_DATA_SIZE + 1); if (clk_counter < (start_write_digit_state + delay_4x2ms)) then lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= conv_std_logic_vector(do_lcd_ascii_correction(pci_to_lcd_data_sig),LCD_DATA_SIZE + 1); if (clk_counter < (start_write_digit_state + delay_3x2ms)) then lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= conv_std_logic_vector(calculate_lcd_symbol_position(lcd_row,lcd_column),LCD_DATA_SIZE + 1); if (clk_counter < (start_write_digit_state + delay_2x2ms)) then lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '1'; lcd_data_sig <= conv_std_logic_vector(calculate_lcd_symbol_position(lcd_row,lcd_column),LCD_DATA_SIZE + 1); if (clk_counter < (start_write_digit_state + delay_2ms)) then lcd_rs_sig <= '0'; lcd_rw_sig <= '0'; lcd_e_sig <= '0'; lcd_data_sig <= conv_std_logic_vector(calculate_lcd_symbol_position(lcd_row,lcd_column),LCD_DATA_SIZE + 1); end if; end if; end if; end if; end if; end if; end if; else write_digit_is_started <= 0; end if; end if; end if; end if; end process lcd_init_and_write; lcd_rs <= lcd_rs_sig; lcd_rw <= lcd_rw_sig; lcd_e <= lcd_e_sig; lcd_data(LCD_DATA_SIZE downto 0) <= lcd_data_sig(LCD_DATA_SIZE downto 0); end architecture behavioural; Edited June 15, 2006 by Гвоздик Quote Share this post Link to post Share on other sites More sharing options...