Guest User

Untitled

a guest
May 16th, 2011
557
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VHDL 7.91 KB | None | 0 0
  1. -- VHDL module for easily driving an HD44780-compatible LCD display (8-bit mode, 2 lines).
  2. -- Copyright (C) 2011  Philippe Proulx ([email protected])
  3. --                     École Polytechnique de Montréal, Montréal (QC)
  4. --
  5. -- This module is free software: you can redistribute it and/or modify
  6. -- it under the terms of the GNU Lesser General Public License as published by
  7. -- the Free Software Foundation, either version 3 of the License, or
  8. -- (at your option) any later version.
  9. --
  10. -- This module is distributed in the hope that it will be useful,
  11. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. -- GNU Lesser General Public License for more details.
  14. --
  15. -- You should have received a copy of the GNU Lesser General Public License
  16. -- along with this module.  If not, see <http://www.gnu.org/licenses/>.
  17. --
  18. -- This file is best viewed with tabs set at 8 columns.
  19.  
  20. library ieee;
  21. use ieee.std_logic_1164.all;
  22. use ieee.numeric_std.all;
  23.  
  24. entity hd44780_simple is
  25.     generic (
  26.         CLK_FREQ : positive := 100000000;           -- clock frequency (Hz)
  27.         CHARS_PER_LINE : integer range 0 to 63 := 16;       -- characters/line
  28.         LINE1_ADDR_OFFSET : integer range 0 to 127 := 0;    -- DDRAM address offset (line 1)
  29.         LINE2_ADDR_OFFSET : integer range 0 to 127 := 40    -- DDRAM address offset (line 2)
  30.     );
  31.     port (
  32.         chars_line1 : in std_logic_vector((CHARS_PER_LINE * 8) - 1 downto 0);   -- first line
  33.         chars_line2 : in std_logic_vector((CHARS_PER_LINE * 8) - 1 downto 0);   -- second line
  34.         clk : in std_logic;             -- clock
  35.         reset : in std_logic;               -- asynchronous reset
  36.        
  37.         hd44780_db : out std_logic_vector(7 downto 0) := (others => '0'); -- HD44780 data bus
  38.         hd44780_rw : out std_logic := '0';      -- HD44780 R/W signal
  39.         hd44780_rs : out std_logic := '0';      -- HD44780 RS signal
  40.         hd44780_en : out std_logic := '0'       -- HD44780 EN signal
  41.     );
  42. end hd44780_simple;
  43.  
  44. architecture arch of hd44780_simple is
  45.     -- states:
  46.     type state is (
  47.         S_RESET,
  48.         S_WAIT,
  49.         S_EN_AND_WAIT,
  50.         S_INIT_FS0,
  51.         S_INIT_FS1,
  52.         S_INIT_DISP,
  53.         S_INIT_DC,
  54.         S_INIT_EMS,
  55.         S_SET_DDRAM_ADDR,
  56.         S_WR
  57.     );
  58.    
  59.     -- constants:
  60.     constant CLK_US_MAX : positive := CLK_FREQ / 1000000;
  61.     constant TIMER_US_WIDTH : integer := 20;
  62.     constant EN_CLOCKS : integer := 30;
  63.    
  64.     -- signals:
  65.     signal led_sig : std_logic := '0';
  66.     signal clk_us : std_logic := '0';
  67.     signal initialized : std_logic := '0';
  68.     signal cur_state : state := S_RESET;
  69.     signal state2timer_go : std_logic := '0';
  70.     signal timer2state_done : std_logic := '0';
  71.     signal timer_us_start : std_logic := '0';
  72.     signal timer_us_value : integer range 0 to ((2 ** TIMER_US_WIDTH) - 1) := 0;
  73. begin
  74.     -- only write:
  75.     hd44780_rw <= '0';
  76.    
  77.     -- µs clock generator:
  78.     clk_us_gen : process (clk, reset)
  79.         variable count : integer range 0 to (CLK_US_MAX - 1) := 0;
  80.     begin
  81.         if (reset = '1') then
  82.             count := 0;
  83.             clk_us <= '0';
  84.         elsif (rising_edge(clk)) then
  85.             if (count = (CLK_US_MAX - 1)) then
  86.                 clk_us <= '1';
  87.                 count := 0;
  88.             else
  89.                 clk_us <= '0';
  90.                 count := count + 1;
  91.             end if;
  92.         end if;
  93.     end process;
  94.    
  95.     -- µs timer:
  96.     timer_us : process (clk, clk_us, reset)
  97.         variable valuez : integer range 0 to ((2 ** TIMER_US_WIDTH) - 1) := 0;
  98.         variable running : boolean := false;
  99.     begin
  100.         if (reset = '1') then
  101.             timer2state_done <= '0';
  102.             valuez := 0;
  103.             running := false;
  104.         elsif (rising_edge(clk)) then
  105.             if (state2timer_go = '1') then
  106.                 timer2state_done <= '0';
  107.                 valuez := timer_us_value;
  108.                 running := true;
  109.             elsif (clk_us = '1' and running = true) then
  110.                 if (valuez > 0) then
  111.                     valuez := valuez - 1;
  112.                 else
  113.                     timer2state_done <= '1';
  114.                     running := false;
  115.                 end if;
  116.             end if;
  117.         end if;
  118.     end process;
  119.    
  120.     -- state machine:
  121.     sm : process (clk, reset)
  122.         variable next_state : state;
  123.         variable timer_called_cnt : integer range 0 to 3 := 0;
  124.         variable en_started : boolean := false;
  125.         variable en_count : integer range 0 to EN_CLOCKS := EN_CLOCKS;
  126.         variable cur_ddram_addr : integer range 0 to (CHARS_PER_LINE - 1) := 0;
  127.         variable cur_line : integer range 0 to 1 := 0;
  128.         variable addr : integer range 0 to 255;
  129.         variable char : std_logic_vector(7 downto 0);
  130.     begin
  131.         if (reset = '1') then
  132.             cur_state <= S_RESET;
  133.         elsif (rising_edge(clk)) then
  134.             case cur_state is
  135.                 -- EN signal for a few clocks (minimum 80 ns)
  136.                 when S_EN_AND_WAIT =>
  137.                 if (en_started = false) then
  138.                     en_count := EN_CLOCKS;
  139.                     en_started := true;
  140.                     hd44780_en <= '1';
  141.                 else
  142.                     if (en_count > 0) then
  143.                         en_count := en_count - 1;
  144.                     else
  145.                         en_started := false;
  146.                         hd44780_en <= '0';
  147.                         cur_state <= S_WAIT;
  148.                     end if;
  149.                 end if;
  150.                
  151.                 -- programmable wait time (place value in timer_us_value (µs) and
  152.                 -- next state in next_state)
  153.                 when S_WAIT =>
  154.                 case timer_called_cnt is
  155.                     when 0 =>
  156.                     timer_called_cnt := 1;
  157.                     state2timer_go <= '1';
  158.                    
  159.                     when 1 =>
  160.                     timer_called_cnt := 2;
  161.                     state2timer_go <= '0';
  162.                    
  163.                     when 2 =>
  164.                     if (timer2state_done = '1') then
  165.                         cur_state <= next_state;
  166.                         timer_called_cnt := 0;
  167.                     end if;
  168.                    
  169.                     when others =>
  170.                 end case;
  171.                
  172.                 -- reset state (reset everything and wait 40 ms until Vcc rises)
  173.                 when S_RESET =>
  174.                 initialized <= '0';
  175.                 hd44780_db <= (others => '0');
  176.                 hd44780_rs <= '0';
  177.                 hd44780_en <= '0';
  178.                 cur_state <= S_WAIT;
  179.                 next_state := S_INIT_FS0;
  180.                 timer_us_value <= 40000;
  181.                 timer_called_cnt := 0;
  182.                 state2timer_go <= '0';
  183.                 en_started := false;
  184.                 en_count := EN_CLOCKS;
  185.                 cur_ddram_addr := 0;
  186.                 cur_line := 0;
  187.                
  188.                 -- Function Set state
  189.                 when S_INIT_FS0 =>
  190.                 hd44780_db <= "00111000";
  191.                 hd44780_rs <= '0';
  192.                 cur_state <= S_EN_AND_WAIT;
  193.                 next_state := S_INIT_FS1;
  194.                 timer_us_value <= 37;
  195.                
  196.                 -- another Function Set (just in case)
  197.                 when S_INIT_FS1 =>
  198.                 hd44780_db <= "00111000";
  199.                 hd44780_rs <= '0';
  200.                 cur_state <= S_EN_AND_WAIT;
  201.                 next_state := S_INIT_DISP;
  202.                 timer_us_value <= 37;
  203.                
  204.                 -- Display ON/OFF Control state
  205.                 when S_INIT_DISP =>
  206.                 hd44780_db <= "00001100";
  207.                 hd44780_rs <= '0';
  208.                 cur_state <= S_EN_AND_WAIT;
  209.                 next_state := S_INIT_DC;
  210.                 timer_us_value <= 37;
  211.                
  212.                 -- Display Clear state
  213.                 when S_INIT_DC =>
  214.                 hd44780_db <= "00000001";
  215.                 hd44780_rs <= '0';
  216.                 cur_state <= S_EN_AND_WAIT;
  217.                 next_state := S_INIT_EMS;
  218.                 timer_us_value <= 1520;
  219.                
  220.                 -- Entry Mode Set state
  221.                 when S_INIT_EMS =>
  222.                 hd44780_db <= "00000110";
  223.                 hd44780_rs <= '0';
  224.                 cur_state <= S_EN_AND_WAIT;
  225.                 next_state := S_SET_DDRAM_ADDR;
  226.                 timer_us_value <= 37;
  227.                
  228.                 -- Set DDRAM address state (from 0 to 7)
  229.                 when S_SET_DDRAM_ADDR =>
  230.                 case cur_line is
  231.                     when 0 =>
  232.                     addr := cur_ddram_addr + LINE1_ADDR_OFFSET;
  233.                    
  234.                     when 1 =>
  235.                     addr := cur_ddram_addr + LINE2_ADDR_OFFSET;
  236.                    
  237.                     when others =>
  238.                 end case;
  239.                 hd44780_db <= "1" & std_logic_vector(to_unsigned(addr, 7));
  240.                 hd44780_rs <= '0';
  241.                 timer_us_value <= 37;
  242.                 cur_state <= S_EN_AND_WAIT;
  243.                 next_state := S_WR;
  244.                
  245.                 -- write state (according to DDRAM address)
  246.                 when S_WR =>
  247.                 case cur_line is
  248.                     when 0 =>
  249.                     char := chars_line1((cur_ddram_addr * 8) + 7 downto (cur_ddram_addr * 8));
  250.                    
  251.                     when 1 =>
  252.                     char := chars_line2((cur_ddram_addr * 8) + 7 downto (cur_ddram_addr * 8));
  253.                    
  254.                     when others =>
  255.                 end case;
  256.                 hd44780_db <= char;
  257.                 hd44780_rs <= '1';
  258.                 timer_us_value <= 37;
  259.                 cur_state <= S_EN_AND_WAIT;
  260.                 next_state := S_SET_DDRAM_ADDR;
  261.                 if (cur_ddram_addr = (CHARS_PER_LINE - 1)) then
  262.                     cur_ddram_addr := 0;
  263.                     case cur_line is
  264.                         when 0 =>
  265.                         cur_line := 1;
  266.                        
  267.                         when 1 =>
  268.                         cur_line := 0;
  269.                        
  270.                         when others =>
  271.                     end case;
  272.                 else
  273.                     cur_ddram_addr := cur_ddram_addr + 1;
  274.                 end if;
  275.                
  276.                 when others =>
  277.             end case;
  278.         end if;
  279.     end process;
  280. end arch;
Advertisement
Add Comment
Please, Sign In to add comment