LCD Verilog
LCD Verilog
Close
Home
FPGA projects - Text LCD modules are cheap and easy to interface using a
Basic microcontroller or FPGA.
LED displays
Pong game
R/C servos
Debouncer
Crossing clock domains
FPGA projects -
To control an LCD module, you need 11 IO pins to drive an 8-bits data
Interfaces bus and 3 control signals. The 3 control signals are:
EPP Most of the LCD modules are based on the HD44780 chip or
compatible. One good information page is available here.
SPI
SD card 7 bits design
PCI
Let's drive the LCD module from an FPGA board.
PCI Express
Here's the block diagram of our design:
Ethernet
HDMI
SDRAM
FPGA j
http://www.fpga4fun.com/TextLCDmodule.html 1/6
12/1/2017 fpga4fun.com - Text LCD module
FPGA projects -
Pluto receives data from the PC serial port, de-serializes it, and send it
to the LCD module. The de-serializer is the same module from the
serial interface project, so it is just instantiated here.
wire RxD_data_ready;
wire [7:0] RxD_data;
async_receiver deserializer(.clk(clk), .RxD(RxD),
.RxD_data_ready(RxD_data_ready), .RxD_data(RxD_data));
Every time a byte becomes available from the serial port, then
"RxD_data_ready" is active for one clock period.
The PC sends us data through the serial port in 8-bits mode. Ideally,
we would need to receive 9 bits from the PC, so that we can drive the
8-bits data bus and the "RS" line of the LCD module. For now, let's use
the MSB (bit 7) of the data received to drive "RS", and send only 7
bits to the data bus.
assign LCD_RW = 0;
We never read from the LCD module, so the R/W line is tied to
ground.
The last complication is that the "E" signal needs to be active for a
long time, 220ns. That's long from the FPGA point of view, since I use
a 25MHz clock (40ns period). So "E" needs to be driven for at least
5.5 clocks. Here we drive it for 7 clocks, using a counter to count the
clocks.
<= count + 1;
reg LCD_E;
always @(posedge clk) LCD_E <= (count!=0);
The software
We initialize the LCD and send some data to be displayed.
Here's the C code to initialize the LCD module and display 'hello'.
void main()
{
OpenComm();
// display "hello"
WriteCommByte('h' + 0x80);
WriteCommByte('e' + 0x80);
WriteCommByte('l' + 0x80);
WriteCommByte('l' + 0x80);
WriteCommByte('o' + 0x80);
http://www.fpga4fun.com/TextLCDmodule.html 3/6
12/1/2017 fpga4fun.com - Text LCD module
CloseComm();
}
To get more info about the HD44780 instruction set, check here.
8 bits design
The major drawback is the earlier design is that we send only 7 bits to
the LCD data bus. That is a problem because the set DD RAM Address
command of the LCD module cannot be used anymore.
void main()
{
OpenComm();
WriteCommByte('h');
WriteCommByte('e');
WriteCommByte('l');
WriteCommByte('l');
WriteCommByte('o');
WriteCommByte(0x00); WriteCommByte(0xC0); // go on
second half of LCD
WriteCommByte('e');
WriteCommByte('v');
WriteCommByte('e');
WriteCommByte('r');
WriteCommByte('y');
http://www.fpga4fun.com/TextLCDmodule.html 4/6
12/1/2017 fpga4fun.com - Text LCD module
WriteCommByte('o');
WriteCommByte('n');
WriteCommByte('e');
CloseComm();
}
wire RxD_data_ready;
wire [7:0] RxD_data;
async_receiver deserialer(.clk(clk), .RxD(RxD),
.RxD_data_ready(RxD_data_ready), .RxD_data(RxD_data));
assign LCD_RW = 0;
assign LCD_DataBus = RxD_data;
reg LCD_instruction;
always @(posedge clk)
if(LCD_instruction==0)
LCD_instruction <= Received_Escape;
else
LCD_instruction <= (count!=7);
http://www.fpga4fun.com/TextLCDmodule.html 5/6
12/1/2017 fpga4fun.com - Text LCD module
endmodule
The HD44780 specification shows that "RS" needs to be valid for 10ns
after "E" goes low. So you'll note that here "E" is driven for 6 clocks
only, and the "LCD_instruction" flag is reset only after clock 7, to give
25ns room.
http://www.fpga4fun.com/TextLCDmodule.html 6/6