0% found this document useful (1 vote)
373 views19 pages

8.4 A Case Study: Using LCD Module On DE2 Board

The document describes using an LCD module on an Altera DE2 FPGA development board. It provides details on the interface between the FPGA chip and LCD module, the function of the LCD controller and its registers, and provides code examples to initialize and display text on the LCD. Key steps include initializing the LCD with function set, display off, clear, and entry mode set commands, then writing character data to the LCD data RAM to display text at specific addresses on the screen.

Uploaded by

Mas Shari
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (1 vote)
373 views19 pages

8.4 A Case Study: Using LCD Module On DE2 Board

The document describes using an LCD module on an Altera DE2 FPGA development board. It provides details on the interface between the FPGA chip and LCD module, the function of the LCD controller and its registers, and provides code examples to initialize and display text on the LCD. Key steps include initializing the LCD with function set, display off, clear, and entry mode set commands, then writing character data to the LCD data RAM to display text at specific addresses on the screen.

Uploaded by

Mas Shari
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

8.

4 A Case Study: using LCD Module on DE2 Board


8.4.1 LCD module on DE2 board
On the Altera DE2 FPGA development board, there is a Liquid Crystal Display (LCD) module that can be used to display text by sending appropriate commands from FPGA chip to the LCD module. There is a built-in controller HD44780 in the LCD module to drive the display. The interface between FPGA chip and the LCD module is shown in Fig.8.22.

LCD_ON LCD_BLON LCD_RW LCD_RS

FPGA

LCD_EN

LCD_DATA[0:7]

Fig.8.22 The interface between FPGA chip and LCD module

LCD_ON (high-active) turns on the power of LCD module. LCD_BLON controls the LCD back light. LCD_DATA [0:7] is an 8-bit data bus for their data communication. LCD_RW defines the direction of data bus (LCD_RW=1 for read: from LCD to FPGA; LCD_RW=0 for write: from FPGA to LCD). LCD_EN is a read/write enable signal, i.e., a falling edge on LCD_EN is required for a data read/write operation. LCD_RS is a Data/Command select signal, i.e., LCD_DATA [0:7] is data for display when LCD_RS is 1; LCD_DATA is a command (display clear, cursor shift and address information etc.) if LCD_RS is 0. The FPGA pin assignment of the interface is shown in Table.8.1

LCD display (controller HD44780 included)

Table 8.1 LCD related pin assignments on DE2

8.4.2 Function description of LCD module

1) Registers, DDRAM, and CGROM in LCD module The controller HD44780, built in LCD module, plays an important role in the LCD display task. The controller communicates with FPGA, and controls the LCD display. The block diagram of HD44780 is shown in Fig.8.23. The HD44780 has two 8-bit registers (IR, and DR) to store information sent from FPGA. The operation and selection of two registers are defined by Table 8.2. The IR (instruction register) stores instruction codes, such as display clear, cursor shift, and address information for display data RAM (DDRAM) and character generator RAM (CGRAM). The IR can only be written from FPGA. The DR (data register) temporarily stores data to be written into DDRAM or CGRAM and temporarily stores data read from DDRAM or CGRAM. Here we only consider the situation that data are written into DDRAM or CGRAM. So, in our following discussion, LCD_RW is always

set to 0 for writing only, unless otherwise stated. By LCD_RS, the data LCD_DATA [0:7] is interpreted either as instruction codes (when LCD_RS=0) or as display data (when LCD_RS=1).

Fig.8.23 HD44780 block diagram

Table 8.2 Register Selection

Fig.8.24 the relationship between DDRAM addresses and positions on LCD The address counter (AC) receives an initial address through IR based on a command/instruction code, and assigns and updates addresses to both DDRAM and CGRAM. The DDRAM is used to store the display data represented in 8-bit character codes and sent from FPGA. Each address of DDRAM corresponds to a position on the LCD. The relationship between DDRAM addresses and positions on LCD is shown in Fig. 8.24 (2-by-16 character display).

Character Generator ROM (CGROM): The CGROM generate 5x8 dot or 5x10 dot character patterns from 8-bit character codes. See Table 8.3. For example, in order to display 2 on the first line position 5, 8h32 should be written into the address (AC) 8h04 of DDRAM.

Table 8.3 CGROM pattern (5x8 dots)

2) Instruction table
Table 8.4 includes all available instructions to control LCD. The MPU/FPGA will send a sequence of instructions to LCD with appropriate timing constraints. The instructions are divided into two types: 1) command; 2) data transfer. The command instructions (RS=0) are used to initialize the LCD or set required address. The data transfer instructions are used to send the data (to be displayed on LCD) to LCD or read the data information from RAM in LCD built-in controller (HD44780).

Table 8.4 Instruction table

3) Timing requirements
The MPU/FPGA should meet the following timing requirements when it communicates with LCD. For write operation (R/W=0), a negative edge of E (i.e. LCD_EN) is required to send DB (i.e. LCD_DATA [0:7]) to LCD, as shown in Fig.8.25. For read operation, it is the same except that R/W needs to be 1.

Fig. 8.25 Writing operation

8.4.3 Initializing of LCD


FPGA chip needs to send a series of initialization commands to initialize the LCD. These commands include function set, display off, display clear, and entry mode set. The datasheet provides a typical initialization process shown in Fig.8.26. Thus an entire flowchart of LCD tasks is illustrated in Fig.8.27.

Fig. 8.26 Initialization steps

reset Function set Display off

Display char 1 Display other chars

Set DDRAM address for 2nd line display Display clear Display on Display chars in 2nd line

Mode set

Return home

Initialization Fig.8.27 Flowchart of LCD display

Text display

8.4.4 An example: digital clock on LCD


We will design a digital clock on Altera DE2 board, shown in Fig.8.28. The time will be displayed on both 7-segment displays HEX0 to HEX7 and LCD module. The digital_clock block delivers BCD of each digit of time (hour, minute, and second) to module fsm_lcd, which is an FSM that communicates with the LCD for display.

Fig.8.28 Diagram of a digital clock on DE2

State transition diagram for fsm_lcd


Based on the flow of LCD tasks and timing requirements, a state transition diagram is developed as follows. Each task in Fig.8.27 requires two states since a falling edge on LCD_EN is needed to write commands/data (LCD_DATA) to DDRAM

Reset1

{LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8h38 {LCD_EN, LCD_RS}=2b00 LCD_DATA_VALUE=8h38 {LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8h38 {LCD_EN, LCD_RS}=2b00 LCD_DATA_VALUE=8h38 {LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8h38 {LCD_EN, LCD_RS}=2b00 LCD_DATA_VALUE=8h38

Func_set

{LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8h38

Drop_e1

Drop_e4

{LCD_EN, LCD_RS}=2b00 LCD_DATA_VALUE=8h38 {LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8h08 {LCD_EN, LCD_RS}=2b00 LCD_DATA_VALUE=8h08

Reset2

Display_off

Drop_e2

Drop_e5

Reset3

Display_clr

{LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8h01 {LCD_EN, LCD_RS}=2b00 LCD_DATA_VALUE=8h08

Drop_e3

Drop_e6

(to be continued)

Display_on

{LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8h0c {LCD_EN, LCD_RS}=2b00 LCD_DATA_VALUE=8h0c

Drop_e12

{LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE=

Drop_e7

Write_m0 Mode_set
{LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8h06 {LCD_EN, LCD_RS}=2b00 LCD_DATA_VALUE=8h06 {LCD_EN, LCD_RS}=2b11 LCD_DATA_VALUE= {3b011,bcd_hrd1} {LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE= {3b011,bcd_hrd1}

{LCD_EN, LCD_RS}=2b11 LCD_DATA_VALUE=

Drop_e8

Drop_e13

{LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE=

Write_h1

Write_dot2

{LCD_EN, LCD_RS}=2b11 LCD_DATA_VALUE=

Drop_e9

Drop_e14

{LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE=

Write_h0

{LCD_EN, LCD_RS}= 2b11 LCD_DATA_VALUE=

Write_s1 Drop_e10
{LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE=

{LCD_EN, LCD_RS}=2b11 LCD_DATA_VALUE=

Drop_e15 Write_dot1
{LCD_EN, LCD_RS}=2b11 LCD_DATA_VALUE=

{LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE=

Write_s0

{LCD_EN, LCD_RS}=2b11 LCD_DATA_VALUE=

Drop_e11

{LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE=

Drop_e16

{LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE=

Write_m1

{LCD_EN, LCD_RS}=2b11 LCD_DATA_VALUE=

Set_add_line2

{LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8hc0;

Drop_e17

{LCD_EN, LCD_RS}=2b00 LCD_DATA_VALUE=8hc0; {LCD_EN, LCD_RS}=2b11 LCD_DATA_VALUE=

Write_J

Drop_e18

{LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE=

Continue for other letters of student name

Set_add_line1

{LCD_EN, LCD_RS}=2b10 LCD_DATA_VALUE=8h80;

Drop_en ``

{LCD_EN, LCD_RS}=2b01 LCD_DATA_VALUE=8h80

Go back to Write_h1

Notes: 1) Each task is followed by drop_e state. In drop_e sate, LCD_EN drops to zero while other output signals keep the same. 2) LCD_RS=0 for selecting instruction register (IR) (i.e. command), LCD_RS=1 for selecting data register (DR) (i.e. data display) 3) Set_add_line1: before going back to display digit bcd_hrd1, set the DDRAM address for the position of displaying bcd_hrd1.

Verilog code for fsm_lcd

// FSM to control LCD for display time h1h0:mim0:s1s0


module fsm_lcd(CLK_400Hz, resetn, bcd_hrd1, bcd_hrd0, bcd_mind1, bcd_mind0, bcd_secd1, bcd_secd0, LCD_ON, LCD_RS, LCD_EN, LCD_RW, LCD_DATA);

input CLK_400Hz, resetn; input [3:0] bcd_hrd1, bcd_hrd0, bcd_mind1, bcd_mind0, bcd_secd1, bcd_secd0; output LCD_ON, LCD_RS, LCD_EN, LCD_RW; output [7:0] LCD_DATA; reg [5:0] p_state, n_state; reg LCD_EN, LCD_RS; reg [7:0] LCD_DATA_VALUE;

parameter [5:0] reset1=1, reset2=2, reset3=3, FUNC_SET=4, display_off=5, display_clear=6, display_on=7, mode_set=8, write_char1=9, write_char2=10, write_char3=11, write_char4=12, write_char5=13, write_char6=14, write_char7=15, write_char8=16, write_char9=17, write_char10=18, return_home=19, toggle_e1=20,toggle_e2=21, toggle_e3=22, toggle_e4=23, toggle_e5=24,toggle_e6=25, toggle_e7=26, toggle_e8=27, toggle_e9=28,toggle_e10=29, toggle_e11=30, toggle_e12=31, toggle_e13=32,toggle_e14=33, toggle_e15=34, toggle_e16=35, toggle_e17=36,toggle_e18=37, toggle_e19=38, w_address=39, write_w=40; parameter [5:0] toggle_e20=41, toggle_e21=42, char1_address=43, write_e=44;

assign LCD_ON=1; assign LCD_RW=0; assign LCD_DATA = LCD_RW? 8'bzzzzzzzz: LCD_DATA_VALUE; always @ (p_state) begin case (p_state) reset1: begin n_state = toggle_e1; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE = 8'h38; end toggle_e1: begin n_state = reset2; {LCD_EN, LCD_RS}=2'b00;

LCD_DATA_VALUE = 8'h38; end reset2: begin n_state = toggle_e2; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE = 8'h38; end toggle_e2: begin n_state = reset3; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE = 8'h38; end reset3: begin n_state = toggle_e3; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE = 8'h38; end toggle_e3: begin n_state = FUNC_SET; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE = 8'h38; end FUNC_SET: begin n_state = toggle_e4; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE = 8'h38; end toggle_e4: begin n_state = display_off; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE = 8'h38; end display_off: begin n_state = toggle_e5; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE = 8'h08; end

toggle_e5: begin n_state = display_clear; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE = 8'h08; end display_clear: begin n_state = toggle_e6; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE = 8'h01; end toggle_e6: begin n_state = display_on; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE = 8'h01; end display_on: begin n_state = toggle_e7; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE = 8'h0c; end toggle_e7: begin n_state = mode_set; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE = 8'h0c; end mode_set: begin n_state = toggle_e8; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE = 8'h06; end toggle_e8: begin n_state = write_char1; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE = 8'h06; end

write_char1: begin n_state = toggle_e9; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE = {3'b011, bcd_hrd1}; end toggle_e9: begin n_state = write_char2; {LCD_EN, LCD_RS}=2'b01; LCD_DATA_VALUE = {3'b011, bcd_hrd1}; end write_char2: begin n_state = toggle_e10; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE = {3'b011, bcd_hrd0}; end toggle_e10: begin n_state = write_char3; {LCD_EN, LCD_RS}=2'b01; LCD_DATA_VALUE = {3'b011, bcd_hrd0}; end write_char3: begin n_state = toggle_e11; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE = 8'h3a; end toggle_e11: begin n_state = write_char4; {LCD_EN, LCD_RS}=2'b01; LCD_DATA_VALUE = 8'h3a; end write_char4: begin n_state = toggle_e12; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE = {3'b011, bcd_mind1}; end toggle_e12: begin n_state = write_char5; {LCD_EN, LCD_RS}=2'b01; LCD_DATA_VALUE = {3'b011, bcd_mind1}; end

write_char5: begin n_state = toggle_e13; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE = {3'b011, bcd_mind0}; end toggle_e13: begin n_state = write_char6; {LCD_EN, LCD_RS}=2'b01; LCD_DATA_VALUE = {3'b011, bcd_mind0}; end write_char6: begin n_state = toggle_e14; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE = 8'h3a; end toggle_e14: begin n_state = write_char7; {LCD_EN, LCD_RS}=2'b01; LCD_DATA_VALUE = 8'h3a; end write_char7: begin n_state = toggle_e15; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE ={3'b011, bcd_secd1}; end toggle_e15: begin n_state = write_char8; {LCD_EN, LCD_RS}=2'b01; LCD_DATA_VALUE ={3'b011, bcd_secd1}; end write_char8: begin n_state = toggle_e16; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE ={3'b011, bcd_secd0}; end toggle_e16: begin n_state = w_address; {LCD_EN, LCD_RS}=2'b01; LCD_DATA_VALUE ={3'b011, bcd_secd0}; end

// set DDRAM address for the second line w_address: begin n_state = toggle_e17; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE =8'hc0; end toggle_e17: begin n_state = write_w; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE =8'hc0; end write_w: begin n_state = toggle_e18; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE =8'h57; end toggle_e18: begin n_state = write_e; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE =8'h57; end write_e: begin n_state = toggle_e20; {LCD_EN, LCD_RS}=2'b11; LCD_DATA_VALUE =8'h65; end toggle_e20: begin n_state = return_home; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE =8'h65; end return_home: begin n_state = toggle_e21; {LCD_EN, LCD_RS}=2'b10; LCD_DATA_VALUE =8'h80; //8'h80; end toggle_e21: begin n_state = write_char1; {LCD_EN, LCD_RS}=2'b00; LCD_DATA_VALUE =8'h80;//8'h80; end endcase end

always @ (posedge CLK_400Hz, negedge resetn) begin if (resetn == 0) begin p_state <= reset1; end else p_state <= n_state; end endmodule

You might also like