CSE370 Laboratory Assignment 9

Final Project : Magnetic Stripe Reader
Part 1 - LCD Interface

Distributed: Monday, November 28, 2006
Due: By the beginning of the next lab session (December 5/6)


The final lab project will be designing an interface between a magnetic card stripe reader and an LCD (liquid crystal display).  You will work with a partner for the final project, which is separated into two parts.  In this first part, you will design a simple LCD controller using three 22V10 PALs and behavioral Verilog. In the second part (next week) you will add the interface to magnetic card stripe reader.  You will complete the first part by the end of next week’s lab, and complete the entire project by 5 PM on the last day of class. (December 8th)


You are now familiar with two very powerful tools: ActiveHDL and behavioral Verilog, and you will employ them both extensively in order to complete this assignment. You are also familiar with the design process where you fully design and simulate a circuit before you try to construct it. This lab assignment is definitely more challenging than the previous ones, and you may not be able to finish within the first lab session. However, this time you will have an extra week to complete the assignment.


Before You Begin

In these last two labs, you’ll be using the FPGA on your board to generate a variable-rate clock signal (to ensure proper initialization of the LCD and reading of the magnetic stripes) and to debug your circuit. To do this, you need to configure the FPGA to run in a special mode for these final two labs.


To configure the FPGA for use with the final labs:


  1. Locate the black jumper connecting the G and B pins just above the top-right corner of your breadboard.
  2. Remove the jumper.
  3. Place the jumper on the R and G pins.
  4. Power up the board and verify that the 7-segment LED display says, “CSE 370 LABS 9-10.”


If you need any assistance with configuring the FPGA for these last two labs, please ask!



Your goal is to design a circuit which can write an arbitrary ASCII character code entered on your prototyping switches to an LCD display. (In the next lab, characters will be come from the magnetic card stripe reader.) Three PALs will be required to implement this interface: a data buffer, an LCD command "table" and a main control PAL that directs them.


As you can see in the figure below, both commands and data are sent to the display.  The commands are used to initialize the display and tell it what to do, and the data is the character to be displayed.  The control PAL is the brains behind this outfit.  It must first send commands to the display to initialize it, and then send data to the display when it becomes available.  Note that the multiplexer that chooses between data from the data buffer and commands from the command table is missing.  Instead we will use tri-state buffers in the PALs to implement the multiplexer function.


Only the main controller is sequential.  The data buffer and command table are very simple and are implemented with merely combinational logic.




The LCD which you will be using has many advanced functions (see the datasheet for a complete explanation—also look at the timing diagrams), but you will only be concerned with the following two:


  1. Reset and clear the display.
  2. Write a character to the display.


The pin layout of the LCD follows:







0 V



5 V



1 V



High: Data input

Low: Instruction input



High: Read from LCD

Low: Write to LCD



Enable the LCD



Data bus
















Pins 1-3 are power supply connections and will be explained later. Pins 4-14 are signals that you must supply.  R/W specifies whether you are reading or writing the display: Since you will only be writing to the display, the R/W signal will always be 0 (You may connect it to GND). RS is used to determine whether you are sending a command or ASCII data to the display. E (enable) is used to provide a strobe that causes the operation to be executed.  The enable, E, for the LCD is a signal that you must generate: the LCD commits a new character or command on the negative edge of E (something to think about: how do you give E a negative edge?). Note that the timing diagrams in the datasheet indicate that RS and E cannot change at the same time. The data pins contain either an ASCII character code or a command code depending upon the value of RS. You will need to multiplex this data bus between an instruction source and a data source using tri-state drivers in the PAL.


The following is a table with the codes for the 5 commands that you need to execute for this assignment. The first four should be executed in sequence once after reset has been pushed. The last command is used to write a character to the display. You can look at the documentation if you would like to try out other commands.





Clear Display


0000 0001

Function Set


0011 0011

Display On


0000 1100

Entry Mode Set


0000 0110

Write Character




Your "main controller" PAL will contain a finite state machine that (a) sends the four command sequence to the LCD on reset, and (b) writes characters to the LCD when the input "write" is asserted indicating that a new character is available. This controller FSM will sequence through the commands, asserting the appropriate command or data on the data bus and generating the enable E and RS signals. It will be immediately apparent that one PAL is too small for this.  The data bus and control signals E and RS are 10 outputs just by themselves.  Thus you will need partition the state machine so that the 8-bit command value is generated by a 2nd PAL that is controlled by the FSM.  This "command table" PAL will expand a tightly encoded command code from your main controller into the 8-bit wide command code that the LCD expects. The controller PAL must also control the multiplexing of the command and data onto the databus. We will do this using tri-state drivers: either the command PAL will drive the databus, or the 3rd "data" PAL will drive the databus.


Finally, you will need to set the contrast for the LCD screen. For this, we have to apply a specific voltage at the Vo pin.  We can do so with the voltage divider circuit shown in the figure below. It will generate a voltage Vo of approximately 1/(1+4) of Vdd or 20% of 5V (1V).  In your kit should be a 3.9K ohm resistor and a 1K ohm resistor (If there aren't any in your kit, they are also on the conference table or available from the TAs). You can determine the resistance value of a resistor by the color coded bands on the resistor (see explanation of how the color coded system works).


8-bit Tri-State Driver for the Data Buffer

The following Verilog implements an 8-bit tri-state driver which will serve your purposes for this assignment.  You are encouraged to use an intuitive pin assignment.  The provided file tri_driver.ctl will do just fine.  Note how "turning off" the output of a pin is expressed in Verilog: rather than assigning 0 or 1 to the output, we assign a z, which stands for high impedance (“not driven”). This distinction between no voltage and some voltage is key to understanding this concept. Make sure you understand what each of the three possible states of the output means before moving on with the lab (your output is either (a) off, no voltage, (b) on and a voltage representing a 0, and (c) on and a voltage representing a 1).

module tri_driver (en, from, to);

      input en;

      input [7:0] from;

      output [7:0] to;


      assign to = (en) ? from : 8'bzzzzzzzz;


Command Table

The following is a do-nothing stub which you will need to complete for the command table.  Again, a sane pin assignment is highly recommended (use lcd_cmd.ctl).  Remember that, since you will wire the outputs of the 8-bit tri-state driver together with the outputs of this PAL, you will need to be able to also "turn off" this chip's output when data is being driven to the databus (think z's).

module lcd_cmd (RS, cmdIndex, lcdCMD);

   input RS;                  // Used to tristate the LCD CMD

   input [1:0] cmdIndex;      // Index of the command

   output [7:0] lcdCMD;       // LCD command





LCD Controller

Here is another module which you will need to complete.  Note: Before you start writing this module, draw a complete, correct state diagram for its finite state machine.  You will be asked to turn in the state diagram, and it definitely pays to carefully think about the exact timing of your finite state machine in this traditional manner before beginning to write the code for it. We strongly advise you to draw a detailed timing diagram so that you understand how to generate the different signals. Pay particular attention to the timing of the RS and EN signals and use the LCD test fixture to make sure you've got it right. Read the tips section below for some ideas that may help in implementing the LCD controller.


You will need to write your own pin assignment file for this chip.


module lcd_control (clk, reset, write, EN, RS, CMD);

   input clk, reset;

   input write;       // Write a character to the LCD

   output EN, RS;     // Enable, RS signals of LCD

   output [1:0] CMD;  // Index for current LCD command


   /* reg [??:??] state; */




   always @(posedge clk) begin






You must verify your final circuit design before actually programming your PALs and wiring it. As mentioned above, we use a variable-rate clock signal in these labs, which can be simulated with the fpga_clock_sim.v module and will provide you with the clock and reset signals to use. Use the LCD test fixture lcd_tf.v to simulate the behavior of the LCD entirely within ActiveHDL.  Now that you are beginning to understand behavioral Verilog, you might want to read and understand the behavior of the test fixture if the behavior of the LCD itself is not clear to you.  Note that this test fixture is not like some of those that you've worked with in the past.  It does not exhaustively test your design for all possible (or any) inputs.  It merely simulates an LCD and writes characters to the ActiveHDL console when properly used, so you will be responsible for anticipating, handling, and verifying all of the interesting "boundary conditions" for your design.


Note: Since the clock signal provided by fpga_clock_sim.v matches that of the real FPGA, you need to run the simulation for at least 9.4 ms in order for you to see if the LCD correctly initializes.


After successful simulation of your design, program your PALs, and wire up the full circuit.  Be prepared to reprogram a chip for a bug fix, and wire accordingly.  In other words, try to wire as neatly as possible, and try to do so such that your chips may be extracted from the circuit without significant rewiring.  Consider ways in which you might be able to use fewer wires for the LCD's data bus.  Also remember that careful construction of your CTL files can help in this area.  Here is the CTL tutorial and the Cypress WARP Synthesis tool's datasheet. You are encouraged to use the wire packages in your kits, but you may cut and strip your own wire from scratch if you wish. There is also a TA solution which you may look at as an example of how to lay your board out.


Hints and Tips

  • Use output-oriented state encodings for your finite state machines. (See pages 372-374 in your textbook for more information on output-oriented state encodings)
  • Before writing code for your modules, look at the diagram of how the PALs work internally, and convince yourself that your Verilog code can be implemented on the chip. Especially note how many registers you have available, how they’re clocked, and how outputs can be enabled and tri-stated.
  • Put all sequential code inside an “always @(posedge CLK)” block! If you look at the PAL diagram, you’ll see that every register shares a single clock signal coming from pin 1. That means that all registers must be updated on the positive edge of the signal on pin 1, and only then.
  • Outputs can only be tri-stated in sequential code under very limited conditions. Again, look at the PAL diagram and see if the way you’re tri-stating outputs will work. Remember, registers cannot hold Zs!
  • Unused pins on the PAL can have any truth value going to them without affecting the circuit. You can utilize this fact to reduce the number of wires you’ll need.



Full credit completion of this assignment will include all of the following by the given due date:


  1. Correct, working circuit checked off by a TA.
  2. Correct, complete state diagram for your LCD controller's finite state machine.
  3. Correct Verilog for the command table and LCD controller modules shown to your TA.