FPGA/CPLD 16x2 LCD Interface

Program Download:

Quartus II Project Files
LCD16X2.zip
LCD.vhd

The Software
           There are two main portions of VHDL that we are concerned with:
    -Sending Commands
    -Writing Characters



           After the module port has been described to link up to the newly connected 16x2 LCD (44780) it's time to tell the LCD that you want it to start up in 1 line mode with a cursor. The state machine I designed allows the FPGA/CPLD to move in moderately slow steps sending a command and enabling the HD44780 LCD module to accept the comand.

ASCII to Numbers/Letters

------------« Begin Code »------------
..
...
-------------------Function Set-------------------
			 when S0 =>
				current_state <= S1;				
				LCD_DATA	<= "00110000";			
				LCD_ENABLE	<= '0';
				LCD_RW 		<= '0';
				LCD_RS		<= '0';
			 when S1 =>
				current_state <= S2;
				LCD_DATA	<= "00110000";				
				LCD_ENABLE	<= '1';
				LCD_RW 		<= '0';
				LCD_RS		<= '0';				
			 when S2 =>
				current_state <= S3;
				LCD_DATA	<= "00110000";				
				LCD_ENABLE	<= '0';
				LCD_RW 		<= '0';
				LCD_RS		<= '0';
-------------------Reset Display-------------------				
			 when S3 =>
				current_state <= S4;
				LCD_DATA	<= "00000001";				
				LCD_ENABLE	<= '0';
				LCD_RW 		<= '0';
				LCD_RS		<= '0';				
			 when S4 =>
				current_state <= S5;
				LCD_DATA	<= "00000001";				
				LCD_ENABLE	<= '1';
				LCD_RW 		<= '0';
				LCD_RS		<= '0';					
			 when S5 =>
				current_state <= S6;
				LCD_DATA	<= "00000001";				
				LCD_ENABLE	<= '0';
				LCD_RW 		<= '0';
				LCD_RS		<= '0';

-------------------Display On-------------------
			 when S6 =>
				current_state <= S7;					
				LCD_DATA	<= "00001110";
				LCD_ENABLE	<= '0';
				LCD_RW 		<= '0';
				LCD_RS		<= '0';
			 when S7 =>
				current_state <= S8;
				LCD_DATA	<= "00001110";
				LCD_ENABLE	<= '1';
				LCD_RW 		<= '0';
				LCD_RS		<= '0';
			 when S8 =>
				current_state <= S9;	
				LCD_DATA	<= "00001110";
				LCD_ENABLE	<= '0';
				LCD_RW 		<= '0';
				LCD_RS		<= '1';
...
..
------------« End Code »------------

           Because of the parallel nature of the LCD's I/O it's very easy to send chunks of data to the LCD and we're loving sending 8-bit commands to it with a simple enable bit pulse.
           Since data is taken into the 16x2 LCD module on the falling edge of enable, I took a shortcut and made writing characters a 2-state event to save some time.

Diplaying Characters To The LCD via FPGA

------------« Begin Code »------------
..
...
-------------------Write 'P'-------------------				
			 when S9 =>
				current_state <= S10;		
				LCD_DATA	<= x"50";
				LCD_ENABLE	<= '1';
				LCD_RW 		<= '0';
				LCD_RS		<= '1';		
			 when S10 =>
				current_state <= S11;
				LCD_DATA	<= x"50";
				LCD_ENABLE	<= '0';
				LCD_RW 		<= '0';
				LCD_RS		<= '1';		
-------------------WRITE 'Y'-------------------						
			 when S11 =>
				current_state <= S12;				
				LCD_DATA	<= X"59";
				LCD_ENABLE	<= '1';
				LCD_RW 		<= '0';
				LCD_RS		<= '1';			
			 when S12 =>
				current_state <= S13;	
				LCD_DATA	<= X"59";
				LCD_ENABLE	<= '0';
				LCD_RW 		<= '0';
				LCD_RS		<= '1';						
-------------------WRITE 'R'-------------------						
			 when S13 =>
				current_state <= S14;				
				LCD_DATA	<= X"52";
				LCD_ENABLE	<= '1';
				LCD_RW 		<= '0';
				LCD_RS		<= '1';		
			 when S14 =>
				current_state <= S15;
				LCD_DATA	<= X"52";
				LCD_ENABLE	<= '0';
				LCD_RW 		<= '0';
				LCD_RS		<= '1';
...
..
------------« End Code »------------

           And there's a simple VHDL hardware module for telling a 16x2 LCD what to do in a sequence courtesy of a standard state machine. It's important to note that Alter's QSYS library has a premade 16x2 LCD interface that is definitely worth looking into as a premade full solution is always welcome in the world of FPGAs. They're modular! So new modules fit into existing designs very well!



;