Вы находитесь на странице: 1из 15

Writing Characters to FPGA board

Author: Aditya Joshi


aditya.joshi@mathworks.com

Overview:

The Spartan® 3A starter kit board comes with a 2-line by 16-character liquid
crystal display (LCD) [1], which offers a practical way to display
information. The FPGA can use both 8-bit and 4-bit data interface to control
the LCD. Both ASCII and custom characters can be used for displaying
information.

In this tutorial, we discuss a way to display the word “HOLA” on the LCD
using the eight bit data interface.

For complete details on how the LCD display configuration and commands,
please refer to the Spartan® 3A User Guide.

Design Overflow:

1. Design and simulate the top level model in Simulink® and


Stateflow®.
2. Use the Simulink® HDL Coder to produce VHDL code.
3. Synthesize and implement the VHDL code in Xilinx® ISE.
4. Deploy the .bit file produced using iMPACT® in Xilinx® ISE v9.2.

Background:

All the clock cycles are measured relative to the 50 MHz on board clock
(LOC E12).

The character codes to be displayed on the screen are stored in the Display
Data Ram (DD-RAM). There are special addresses to store these characters:
0x00 to 0x0F (upper line) and 0x40 to 0x4F (lower line).

We use the following commands to the DD RAM

1. Set DD RAM Address: To initialize the address counter before


reading/writing.
This command has the general form:

LCD_RS LCD_RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 1 A6 A5 A4 A3 A2 A1 A0

‘A’ in A6-A0 stands for address-bit. A6-A0 can be either ‘0’ or ‘1’ and refer
to one of the valid DD RAM addresses.

2. Write Data to DD RAM:

The general form of this command is:

LCD_RS LCD_RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
1 0 D7 D6 D5 D4 D3 D2 D1 D0

‘D’ in D7-D0 stands for the data-bit to be written to the DD RAM address.
This could correspond to one of the LCD character sets in the CG ROM.

The CG ROM contains certain pre-defined characters that can be displayed


on the LCD. Here is the chart for determining the ASII code addresses of the
stored characters (Please see the reference for details [1]):
Please note that the character sets are described in terms of “Upper Data
Nibble” and “Lower Data Nibble”. These are used to print to the LCD
screen using the 4-bit data interface, which has a totally different process.

Since we are using the 8-bit interface, we can combine both the upper and
lower nibbles. For example, the command ‘Write Data to DD RAM’ for the
character ‘I’ can be sent as:

1001001001 (2 control bits (LCD_RS + LCD_RW) + 8 data bits)

Before writing to the LCD display, a set of commands must be issued to


configure the LCD for the data write operation. These are:

1. Waiting: Wait for display to get ready after power-on.

Value: 0x00
Execution Time: 15 ms = 750000 cycles
2. Function Set: This is used to set the number of display lines, the
character font and the data length (in bits)

Value used*: 0x3C


Execution Time: 8.4 ms = 420000 cycles

* Please note that some of the value used can be changed by setting the
DB0 and DB1. Please refer to the user manual for details.

3. Set Display On: Turn the display on, cursor off and cursor position
off.

Value used: 0x0C


Execution Time: 4.2 ms = 210000 cycles

4. Clear Display:

Value used: 0x01


Execution Time: 4.2 ms = 210000 cycles

5. Entry Mode Set: This is a powerful command! It can be used to set the
direction in which the cursor moves and to specify whether to shift the
display or not.

Value used: 0x06


Execution Time: 4.2 ms = 210000 cycles

Once the LCD is configured for writing, the characters to be displayed


can be transferred:

1. Char_h:

Value: 0x48
Execution Time: 4.2 ms = 210000 cycles

2. Char_o:

Value: 0x4F
Execution Time: 4.2 ms = 210000 cycles
3. Char_l:

Value: 0x4C
Execution Time: 4.2 ms = 210000 cycles

4. Char_a:
Value: 0x41
Execution Time: 4.2 ms = 210000 cycles

After writing the characters, it is good to wait for additional 4.2 ms


(210000 cycles) before exiting the program.

It is also important to remember switching the values of the control


signals. Here is a description of the three LCD control signals:

Signal Name FPGA Pin Description


LCD_E AB4 Read/ Write enable
Values:
0: Disabled
1: Enabled for Read/
Write
LCD_RS Y14 Register Select
Values:
0: Instruction Register
during write operation
Busy flash during read
operation*
1. Data for Read/ Write

LCD_RW W13 Read/ Write Control


0: Write data to LCD
1: Read data from LCD

*Please refer to the user manual [1] for details.


Implementation:

The entire write process can be represented in terms of state diagrams:

Waiting
LCD_E=0 T > 15 ms Function_set
LCD_RS=0
Initialize1
T < 20 ns 20 ns<T<8.4 ms T=8.4 ms LCD_Data=0x3C
LCD_RW=0

LCD_E=1 LCD_E=0 LCD_E=1


LCD_RS=0 LCD_RS=0 LCD_RS=0
LCD_RW=0 LCD_RW=0 LCD_RW=0

Function_set

LCD_Data=0x3C

T > 8.4 ms

Initialize3 Function_set
T < 20 ns 20 ns<T<8.4 ms T=8.4 ms
LCD_Data=0x3C
LCD_E=1 LCD_E=0 LCD_E=1
LCD_RS=0 LCD_RS=0 LCD_RS=0
LCD_RW=0 LCD_RW=0 LCD_RW=0

T > 8.4 ms

Initialize4 Function_set
T < 20 ns 20 ns<T<4.2 ms T=4.2 ms LCD_Data=0x3C

LCD_E=1 LCD_E=0 LCD_E=1


LCD_RS=0 LCD_RS=0 LCD_RS=0
LCD_RW=0 LCD_RW=0 LCD_RW=0
T > 4.2 ms

Set_display LCD_Data=0x0C
T < 20 ns 20 ns<T<4.2 ms T=4.2 ms

LCD_E=1 LCD_E=0 LCD_E=1


LCD_RS=0 LCD_RS=0 LCD_RS=0
LCD_RW=0 LCD_RW=0 LCD_RW=0

T > 4.2 ms

Clear_display LCD_Data=0x01
T < 20 ns 20 ns<T<4.2 ms T=4.2 ms

LCD_E=1 LCD_E=0 LCD_E=1


LCD_RS=0 LCD_RS=0 LCD_RS=0
LCD_RW=0 LCD_RW=0 LCD_RW=0

T > 4.2 ms

Entry_set LCD_Data=0x06
T < 20 ns 20 ns<T<4.2 ms T=4.2 ms

LCD_E=1 LCD_E=0 LCD_E=1


LCD_RS=0 LCD_RS=0 LCD_RS=0
LCD_RW=0 LCD_RW=0 LCD_RW=0

T > 4.2 ms

Char_h LCD_Data=0x48
T < 20 ns 20 ns<T<4.2 ms T=4.2 ms

LCD_E=1 LCD_E=0 LCD_E=1


LCD_RS=1 LCD_RS=0 LCD_RS=1
LCD_RW=0 LCD_RW=0 LCD_RW=0
T > 4.2 ms

LCD_Data=0x4F
Char_o
T < 20 ns 20 ns<T<4.2 ms T=4.2 ms

LCD_E=1 LCD_E=0 LCD_E=1


LCD_RS=1 LCD_RS=0 LCD_RS=1
LCD_RW=0 LCD_RW=0 LCD_RW=0

T > 4.2 ms

LCD_Data=0x4C
Char_l
T < 20 ns 20 ns<T<4.2 ms T=4.2 ms

LCD_E=1 LCD_E=0 LCD_E=1


LCD_RS=1 LCD_RS=0 LCD_RS=1
LCD_RW=0 LCD_RW=0 LCD_RW=0

T > 4.2 ms

LCD_Data=0x41
Char_a
T<4.2 ms T=4.2 ms

LCD_E=0 LCD_E=1
LCD_RS=0 LCD_RS=1
LCD_RW=0 LCD_RW=0

T > 4.2 ms
LCD_Data=0x00
Done
T<4.2 ms

LCD_E=0
LCD_RS=1
LCD_RW=0
We use Stateflow® in Simulink® to model the states and the state
transitions. The attached zip file contains the model ‘lcd_hola_sim.mdl’
which is the most direct implementation of the above flow diagram. When
the model is run, the corresponding values of the LCD_E, LCD_RW,
LCD_RS and LCD_DATA can be visualized in the scope block.

The values of T1, T2, T3 and T4, which correspond to 15 ms, 20 ns, 4.2 ms
and 8.4 ms, have been scaled down to reduce simulation time.

Figure 1: Simulation in Simulink


A note on Data types:

The default data type in Simulink® is ‘double’ which is 64-bit precision


floating-point. Since Spartan® 3A will only work with fixed-point data
types, all ‘double’ and ‘single’ data-types should be converted to equivalent
fixed-point types.

To generate the HDL code, please follow these steps:

1. Remove the ‘clock’ and the ‘scope’ in ‘lcd_hola_sim.mdl’. Replace


the scope with output ports.
2. The output ‘LCD_DATA’ has to be converted to binary values to work
on the FPGA. We use an Embedded MATLAB Function for this
conversion.

Figure 2: HDL Code Generation in Simulink


The model ‘lcd_hola.mdl’ is obtained after applying the above
modifications. Click on Tools->HDL Coder->Generate HDL to generate the
VHDL code.

Before the code can be used for synthesis in Xilinx® ISE, some additional
changes need to be made to the generated VHDL file that corresponds to the
binary convertor embedded MATLAB function block ‘uint2bin’. This is
because this block produces a temporary variable of type ‘real’, which must
be changed to ‘integer’.

Here are the steps:

1. Remove the following function (Line # 39):


-- TMW_TO_UNSIGNED
FUNCTION tmw_to_unsigned(arg: real; width: integer) RETURN unsigned
IS
BEGIN
RETURN to_unsigned(integer(arg), width);
END FUNCTION;

2. Change the following (Line # 55) :


VARIABLE argin_t_0 : real;

to:
VARIABLE argin_t_0 : integer;

3. Change the following lines (Line #72 and 73):


argin_t_0 := real(to_integer(argin_t)) - real(to_integer(c(n - 1)));
argin_t := tmw_to_unsigned(argin_t_0, 8);

to:
argin_t_0 := to_integer(argin_t) - to_integer(c(n - 1));
argin_t := to_unsigned(argin_t_0, 8);

The generated code should now be ready to be synthesized on Xilinx®


ISE. The attached zip file contains the project built using Xilinx® ISE
v9.2.
Working in Xilinx® ISE:

This section is for those not familiar with Xilinx® ISE. Following are the
most straightforward way to synthesize, build and deploy the project to the
FPGA board (Please refer to the ISE in depth tutorial for complete details
[2]):

1. Open the project: “lcd_eight_hola_spartan.ise”. Double click on


“Synthesize-XST”
2. Implement Design:

3. Configure the device:


4. Program the board:

ISE should prompt this:

Right Click:
LCD display should print “HOLA”. Please ensure that the “Clock enable”
switch is “HIGH” as specified in the constraint file (constraints.ucf).

References:

1. Spartan 3A Starter Kit Board User Guide, Xilinx®.


2. ISE In-depth Tutorial, Xilinx®.

Вам также может понравиться