Здравствуйте. Привожу исходный текст ЖКИ-контроллера для отладочной платы 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;