Jump to content
    

Исходник ЖКИ-контроллера

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...