This is an interesting project for a number of reasons. These little LCD displays are very common, and thanks to Arduino libraries (and perhaps I2C interfaces), they are super easy to interface with a microcontroller.
Getting one to work with a FPGA is a little more challenging, however. First of all, without an Arduino library, you have to interface with the Hitachi HD44780 LCD Controller common to all these displays. And the controller is designed to interface with a microcontroller, so we need to send it sequential instructions and characters to put anything on the display.
This means that our FPGA circuit needs to behave to a large extent like a microcontroller, capable of issuing long sequencies of commands. And we have to get familiar with the data sheet and instruction set of the HD44780 controller!
We are using the 20 x 4 version of LCD display, but you can actually use any of them, as they all use the HD44780 controller. In 2-line mode, the HD44780 has two lines of 40 characters each. For the 4 line LCD display, the first 40 character line starts on the display's line 1 and finishes on line 3. The second 40 character line starts on the display's line 2 and finishes on line 4. Normally, we just place the cursor at the beginning of a line, start adding characters, and don't much care about how the lines wrap around, But, later, when we start scrolling, this wrap around of lines becomes very apparent.
Hardware SetupThis project starts with my Beginner's Guide to FPGAs, where in Part 1, we set up both hardware and software for the Alchitry Au FPGA board. And then in Part 4, I showed you how to use the Br Prototype board to connect external hardware to the Au board. You will need to refer to those two earlier projects in order to get started on this new project.
Wiring and configuring the LCD display is just like it would be if we were hooking it up to an Arduino, except that the 6 data lines that control it are coming from output pins on our FPGA instead of a microcontroller. See the schematic for details.
The 6 data lines, as well as ground and +3.3 volts for the display all come from the Alchitry BR Prototype board.
This excerpt from the constraint file (shown below) tells you how the 6 data pins above are connected between the FPGA and the LCD display. We are using the display in 4 bit mode, which means we only use the 4 upper data lines, while the 4 lower ones are not connected.
This entire project and all associated files are contained in the attached zip file. There are actually three separate projects here, as we first just put some text on the screen, and then, in the second and third projects, we scroll text across the screen.
You can get a display working with the text of your choice by just copying what I have done here, but to really understand what's going on in detail, you probably need to refer to the HD44780 datasheet. It provides details on the instruction set.
The BasicsWe use a ROM module to store a table with our HD44780 instructions and character strings. By convention, table indexing in FPGA tables is backwards from normal arrays in C+. The 0 address gives you the last entry. I find this confusing, so I use a function called $reverse() to switch the order back to what I am used to, where address 0 yields the first entry in the table.
The first entries in this table are commands like turn on the display, select 2-line mode, clear the display, set the cursor at the beginning of line 1. We then enter characters that go onto the first line. Then place the cursor on line two and enter the characters for that line, etc.
The au_top module is where our FPGA connects to the outside world, in this case, our display. It doesn't really do anything other than connect the signals from our sequencer module to the BR prototype board pins.
The sequencer module is where the action is! It is where we time and send out signal data to the LCD controller. The Au board has a 100 MHz clock, which we first step down to a 1 kHz clock which is fast enough for our LCD display. We then use up to 1000 or more steps from this 1 kHz clock to program our display.
The first step in this procedure is to start up the HD44780 controller and put it in 4 bit mode. We do this directly in the sequencer module, and then we start reading instructions from the ROM module to continue programming the display.
Instructions and characters are both 8 bits wide, but in 4 bit mode they are input as 4 upper bits followed by 4 lower bits. Two other pins are RS (register select) and E (enable). RS is set to 0 for the instruction register and to 1 for the data/character register. E is pulsed high to latch in an input of 4 bits, whether an instruction or character input. (The R/W (read/write) pin is another input pin, but for our purposes, it is just tied to ground, as we are always writing to the display.)
Finally, when we reach the end of the table in our ROM and have read all instructions and text into the display, we send our sequencer into a hold mode, where our step counter enters an endless loop.
Stationary TextWhat we have discussed so far is our first project, "lcd_display", where we simply display stationary text. It's output is shown above!
Scrolling All TextThe HD44780 controller has shift right and shift left commands that in theory make scrolling easy. However, there are two problems. The first is that the LCD display itself is slow to respond. Whenever a new character is sent to the display, it takes several milliseconds for the display to respond and come to full brightness. Try scrolling too fast and the text almost totally disappears. Scrolling needs to be fairly slow as a result. The second issue is that the built in shifts are applied to the whole display. We might want three lines to be stationary and one line to scroll, but that is not an option. And as you scroll text on line one, it wraps around onto another line!
Our second project is "lcd_scroll". It uses shift left commands to scroll all the text on the display. It is a fairly easy modification of the sequencing module in our first project. But it wraps the first line onto line 3 and wraps the second line onto line 4. It is also very slow, and having the entire display scroll isn't necessarily what we want.
Scroll a Single LineThe alternative is to scroll the text "in software" or, in this case with FPGA, scroll the text "in hardware". This is project "lcd_scroll2". This approach adds some additional complexity to our sequencer module, but the approach is straight forward: Take the text on one line and wrap it around itself, separating the beginning and end with some spaces as a buffer. Add an "offset" register that sets how much we offset that one line of text. Now continuously rewrite that one line of text while incrementing the offset. To scroll our 20 characters completely across the screen and off the screen on the other side requires our offset go from 0 to 40 and start over. We continue to do that indefinitely!
Scrolling is still slow as this new approach doesn't fix the slow response time of the lcd screen itself, but it generally is a better effect than trying the scroll the entire display!
One thing I did try here to improve scroll speed and the response time of the display was to increase the clock speed. The idea is: the faster we can write our text to the screen, the more time we have for it to reach full brightness, before we have to rewrite it in its new position.
I was able to increase my clock speed to 3.3 kHz, which helped a little. Above that speed, I couldn't get the controller to respond. This was somewhat surprising. While the the HD44780 has some timing constraints during startup, the datasheet suggests it can handle input rates up to 2 MHz!
What's NextThis LCD display project involved a lot of sequencing. I am starting to move into the kind of things best done by CPUs, so I think my next project will be to design a simple CPU on a FPGA. There are a couple of very simple CPUs already built on the Alchitry Au board in the tutorials, so I think building one myself will be my next project!
Comments