Čeština / English
Login

SVN Repository / Prohlížení

Aktuální adresář: FITkit / trunk / fpga / ctrls / lcd /

lcd_ctrl_high.vhd

   1  -- keyboard.vhd: Keyboard simulation file
   2  -- Author(s): Tomas Martinek <martinto at fit.vutbr.cz>
   3  --
   4  library ieee;
   5  use ieee.std_logic_1164.all;
   6  use ieee.std_logic_arith.all;
   7  use ieee.std_logic_unsigned.all;
   8  use ieee.numeric_std.all;
   9  
  10  -- ----------------------------------------------------------------------------
  11  --                        Entity declaration
  12  -- ----------------------------------------------------------------------------
  13  entity lcd_ctrl_high is
  14  port(
  15     CLK         : in  std_logic;
  16     RESET       : in  std_logic;
  17  
  18     -- user interface
  19     DATA        : in  std_logic_vector(7 downto 0);
  20     WRITE       : in  std_logic;
  21     CLEAR       : in  std_logic;
  22  
  23     -- lcd interface
  24     LRS         : out std_logic;
  25     LRW         : out std_logic;
  26     LE          : out std_logic;
  27     LD          : inout std_logic_vector(7 downto 0)
  28  );
  29  end entity lcd_ctrl_high;
  30  
  31  -- ----------------------------------------------------------------------------
  32  --                      Architecture declaration
  33  -- ----------------------------------------------------------------------------
  34  architecture behavioral of lcd_ctrl_high is
  35  
  36     constant ITEMS          : integer := 32;
  37     type   t_fifo is array(9 downto 0) of std_logic_vector(ITEMS-1 downto 0);
  38     type   t_state is (INIT, CLEAR_DISPLAY, CLEAR_CURSOR, SET_FUNCTION,
  39                        CURSOR_OFF, SET_CURSOR_DIR, WAIT_FOR_REQ, WRITE_ADDR,
  40                        WRITE_DATA);
  41  
  42     signal cnt_addr         : std_logic_vector(3 downto 0);
  43     signal cnt_addr_ce      : std_logic;
  44     signal cnt_addr_ld      : std_logic;
  45     signal lcd_busy         : std_logic;
  46     signal change_addr      : std_logic;
  47     signal write_req        : std_logic;
  48     signal clear_req        : std_logic;
  49  
  50     signal present_state, next_state : t_state;
  51     signal fsm_cnt_ce       : std_logic;
  52     signal fsm_cnt_clr      : std_logic;
  53     signal fsm_lcd_rs       : std_logic;
  54     signal fsm_fifo_rd      : std_logic;
  55     signal fsm_lcd_write    : std_logic;
  56     signal fsm_lcd_data     : std_logic_vector(7 downto 0);
  57     signal mx_lcd_addr      : std_logic_vector(7 downto 0);
  58     signal lcd_data         : std_logic_vector(7 downto 0);
  59     signal busy             : std_logic;
  60  
  61     signal fifo             : t_fifo;
  62     signal fifo_din         : std_logic_vector(9 downto 0);
  63     signal fifo_dout        : std_logic_vector(9 downto 0);
  64     signal fifo_rd          : std_logic;
  65     signal fifo_wr          : std_logic;
  66     signal fifo_empty       : std_logic;
  67     signal fifo_full        : std_logic;
  68     signal cnt_fifo_addr    : std_logic_vector(4 downto 0);
  69     signal cnt_fifo_count   : std_logic_vector(5 downto 0);
  70     signal cnt_fifo_addr_ce : std_logic;
  71     signal cnt_fifo_addr_updw : std_logic;
  72  
  73  begin
  74  
  75  -- cnt_addr counter
  76  cnt_addr_ld <= fsm_cnt_clr;
  77  cnt_addr_ce <= fsm_cnt_ce or fsm_cnt_clr;
  78  process(RESET, CLK)
  79  begin
  80     if (RESET = '1') then
  81        cnt_addr <= (others => '0');
  82     elsif (CLK'event AND CLK = '1') then
  83        if (cnt_addr_ce = '1') then
  84           if (cnt_addr_ld = '1') then
  85              cnt_addr <= (others => '0');
  86           else
  87              cnt_addr <= cnt_addr + 1;
  88           end if;
  89        end if;
  90     end if;
  91  end process;
  92  
  93  change_addr <= '1' when (cnt_addr(2 downto 0)="000") else '0';
  94  mx_lcd_addr <= X"80"  when (cnt_addr(3) = '0') else X"C0";
  95  
  96  -- ------------------------------------------------------------------
  97  --                         FIFO Block
  98  -- ------------------------------------------------------------------
  99  fifo_din    <= CLEAR & WRITE & DATA;
 100  fifo_wr     <= WRITE or CLEAR;
 101  fifo_rd     <= fsm_fifo_rd;
 102  
 103  cnt_fifo_addr_ce <= (fifo_wr and (not fifo_rd)) or (fifo_rd and (not fifo_wr));
 104  cnt_fifo_addr_updw <= fifo_rd;
 105  
 106  -- cnt_fifo_addr counter
 107  process(RESET, CLK)
 108  begin
 109     if (RESET = '1') then
 110        cnt_fifo_addr <= (others => '1');
 111        cnt_fifo_count <= (others => '0');
 112     elsif (CLK'event AND CLK = '1') then
 113        if (cnt_fifo_addr_ce = '1') then
 114           if (cnt_fifo_addr_updw = '1') then
 115              cnt_fifo_addr <= cnt_fifo_addr - 1;
 116              cnt_fifo_count <= cnt_fifo_count - 1;
 117           else
 118              cnt_fifo_addr <= cnt_fifo_addr + 1;
 119              cnt_fifo_count <= cnt_fifo_count + 1;
 120           end if;
 121        end if;
 122     end if;
 123  end process;
 124  
 125  -- full/empty flag setting
 126  fifo_full <= '1' when (cnt_fifo_count = conv_std_logic_vector(ITEMS,
 127                         cnt_fifo_count'length)) else '0';
 128  fifo_empty <= '1' when (cnt_fifo_count = conv_std_logic_vector(0,
 129                          cnt_fifo_count'length)) else '0';
 130  
 131  -- fifo memory
 132  FIFO_U : for i in 0 to 9 generate
 133     process(CLK)
 134     begin
 135        if (CLK'event and CLK='1') then
 136           if (fifo_wr='1') then
 137              fifo(i) <= fifo(i)(ITEMS-2 downto 0) & fifo_din(i);
 138           end if;
 139        end if;
 140     end process;
 141     fifo_dout(i) <= fifo(i)(conv_integer(cnt_fifo_addr));
 142  end generate;
 143  
 144  lcd_data  <= fifo_dout(7 downto 0);
 145  write_req <= fifo_dout(8);
 146  clear_req <= fifo_dout(9);
 147  
 148  -- ------------------------------------------------------------------
 149  --                        LCD controller
 150  -- ------------------------------------------------------------------
 151  lcd_u : entity work.lcd_ctrl_rw
 152  port map (
 153     RESET    => RESET,
 154     CLK      => CLK,
 155  
 156     -- interni rozhrani
 157     READ     => '0',
 158     WRITE    => fsm_lcd_write,
 159     RS       => fsm_lcd_rs,
 160     DIN      => fsm_lcd_data,
 161     DOUT     => open,
 162     DV       => open,
 163     BUSY     => busy,
 164  
 165     --- rozhrani LCD displeje
 166     LRS      => LRS,
 167     LRW      => LRW,
 168     LE       => LE,
 169     LD       => LD
 170  );
 171  
 172  lcd_busy <= busy;
 173  -- ------------------------------------------------------------------
 174  --                       Finite State Machine
 175  -- ------------------------------------------------------------------
 176  
 177  -- -------------------------------------------------------
 178  sync_logic : process(RESET, CLK)
 179  begin
 180     if (RESET = '1') then
 181        present_state <= INIT;
 182     elsif (CLK'event AND CLK = '1') then
 183        present_state <= next_state;
 184     end if;
 185  end process sync_logic;
 186  
 187  -- -------------------------------------------------------
 188  next_state_logic : process(present_state, lcd_busy, change_addr, write_req,
 189                             clear_req, fifo_empty)
 190  begin
 191     case (present_state) is
 192     -- - - - - - - - - - - - - - - - - - - - - - -
 193     when INIT =>
 194        next_state <= CLEAR_CURSOR;
 195     -- - - - - - - - - - - - - - - - - - - - - - -
 196     when CLEAR_CURSOR =>
 197        next_state <= CLEAR_CURSOR;
 198        if (lcd_busy = '0') then
 199           next_state <= SET_FUNCTION;
 200        end if;
 201     -- - - - - - - - - - - - - - - - - - - - - - -
 202     when SET_FUNCTION =>
 203        next_state <= SET_FUNCTION;
 204        if (lcd_busy = '0') then
 205           next_state <= CURSOR_OFF;
 206        end if;
 207     -- - - - - - - - - - - - - - - - - - - - - - -
 208     when CURSOR_OFF =>
 209        next_state <= CURSOR_OFF;
 210        if (lcd_busy = '0') then
 211           next_state <= SET_CURSOR_DIR;
 212        end if;
 213     -- - - - - - - - - - - - - - - - - - - - - - -
 214     when SET_CURSOR_DIR =>
 215        next_state <= SET_CURSOR_DIR;
 216        if (lcd_busy = '0') then
 217           next_state <= CLEAR_DISPLAY;
 218        end if;
 219     -- - - - - - - - - - - - - - - - - - - - - - -
 220     when CLEAR_DISPLAY =>
 221        next_state <= CLEAR_DISPLAY;
 222        if (lcd_busy = '0') then
 223           next_state <= WAIT_FOR_REQ;
 224        end if;
 225     -- - - - - - - - - - - - - - - - - - - - - - -
 226     when WAIT_FOR_REQ =>
 227        next_state <= WAIT_FOR_REQ;
 228        if (fifo_empty = '0') then
 229           if (write_req = '1') then
 230              if (change_addr = '1') then
 231                 next_state <= WRITE_ADDR;
 232              else
 233                 next_state <= WRITE_DATA;
 234              end if;
 235           elsif (clear_req = '1') then
 236              next_state <= CLEAR_DISPLAY;
 237           end if;
 238        end if;
 239     -- - - - - - - - - - - - - - - - - - - - - - -
 240     when WRITE_ADDR =>
 241        next_state <= WRITE_ADDR;
 242        if (lcd_busy = '0') then
 243           next_state <= WRITE_DATA;
 244        end if;
 245     -- - - - - - - - - - - - - - - - - - - - - - -
 246     when WRITE_DATA  =>
 247        next_state <= WRITE_DATA;
 248        if (lcd_busy = '0') then
 249           next_state <= WAIT_FOR_REQ;
 250        end if;
 251     -- - - - - - - - - - - - - - - - - - - - - - -
 252     when others =>
 253     end case;
 254  end process next_state_logic;
 255  
 256  -- -------------------------------------------------------
 257  output_logic : process(present_state, lcd_busy, lcd_data,
 258                         mx_lcd_addr, fifo_empty, clear_req)
 259  begin
 260     fsm_cnt_ce        <= '0';
 261     fsm_cnt_clr       <= '0';
 262     fsm_lcd_rs        <= '0';
 263     fsm_lcd_write     <= '0';
 264     fsm_fifo_rd       <= '0';
 265     fsm_lcd_data      <= (others => '0');
 266  
 267     case (present_state) is
 268     -- - - - - - - - - - - - - - - - - - - - - - -
 269     when INIT =>
 270     -- - - - - - - - - - - - - - - - - - - - - - -
 271     when CLEAR_CURSOR =>
 272        if (lcd_busy = '0') then
 273           fsm_lcd_write <= '1';
 274           fsm_lcd_data  <= X"02";
 275        end if;
 276     -- - - - - - - - - - - - - - - - - - - - - - -
 277     when SET_FUNCTION =>
 278        if (lcd_busy = '0') then
 279           fsm_lcd_write <= '1';
 280           fsm_lcd_data  <= X"38";
 281        end if;
 282     -- - - - - - - - - - - - - - - - - - - - - - -
 283     when CURSOR_OFF =>
 284        if (lcd_busy = '0') then
 285           fsm_lcd_write <= '1';
 286           fsm_lcd_data  <= X"0C";
 287        end if;
 288     -- - - - - - - - - - - - - - - - - - - - - - -
 289     when SET_CURSOR_DIR =>
 290        if (lcd_busy = '0') then
 291           fsm_lcd_write <= '1';
 292           fsm_lcd_data  <= X"06";
 293        end if;
 294     -- - - - - - - - - - - - - - - - - - - - - - -
 295     when CLEAR_DISPLAY =>
 296        if (lcd_busy = '0') then
 297           fsm_lcd_write <= '1';
 298           fsm_lcd_data  <= X"01";
 299           fsm_cnt_clr   <= '1';
 300        end if;
 301     -- - - - - - - - - - - - - - - - - - - - - - -
 302     when WAIT_FOR_REQ =>
 303        if (fifo_empty = '0' and clear_req = '1') then
 304           fsm_fifo_rd <= '1';
 305        end if;
 306     -- - - - - - - - - - - - - - - - - - - - - - -
 307     when WRITE_ADDR =>
 308        if (lcd_busy = '0') then
 309           fsm_lcd_write <= '1';
 310           fsm_lcd_data <= mx_lcd_addr;
 311        end if;
 312     -- - - - - - - - - - - - - - - - - - - - - - -
 313     when WRITE_DATA =>
 314        if (lcd_busy = '0') then
 315           fsm_lcd_write <= '1';
 316           fsm_cnt_ce    <= '1';
 317           fsm_lcd_rs    <= '1';
 318           fsm_fifo_rd   <= '1';
 319           fsm_lcd_data  <= lcd_data;
 320        end if;
 321     -- - - - - - - - - - - - - - - - - - - - - - -
 322     when others =>
 323     end case;
 324  end process output_logic;
 325  
 326  end architecture behavioral;
 327  
 328  
Zobrazeno: 679470x Naposledy: 25.6.2022 21:45:27