1 |
2 |
ayersg |
`timescale 1ns / 1ps
|
2 |
|
|
/*
|
3 |
|
|
* File : lcd_ctrl.v
|
4 |
|
|
* Project : University of Utah, XUM Project MIPS32 core
|
5 |
|
|
* Creator(s) : Grant Ayers (ayers@cs.utah.edu)
|
6 |
|
|
*
|
7 |
|
|
* Modification History:
|
8 |
|
|
* Rev Date Initials Description of Change
|
9 |
|
|
* 1.0 16-Jun-2011 GEA Initial design.
|
10 |
|
|
*
|
11 |
|
|
* Standards/Formatting:
|
12 |
|
|
* Verilog 2001, 4 soft tab, wide column.
|
13 |
|
|
*
|
14 |
|
|
* Description:
|
15 |
|
|
* A controller for the common 16x2-character LCD screen based on the
|
16 |
|
|
* Sitronix ST7066U, Samsung S6A0069X / KS0066U, Hitachi HD44780, SMOS SED1278,
|
17 |
|
|
* or other compatible device. This controller uses a 4-bit data bus, is write-only,
|
18 |
|
|
* and requires a total of 7 output pins to the LCD. The timing must be adjusted for
|
19 |
|
|
* different input clock frequencies where noted. The primary version is based on a
|
20 |
|
|
* 100 MHz clock.
|
21 |
|
|
*/
|
22 |
|
|
module lcd_ctrl(
|
23 |
|
|
input clock,
|
24 |
|
|
input reset,
|
25 |
|
|
input [8:0] command,
|
26 |
|
|
input write,
|
27 |
|
|
output reg ack,
|
28 |
|
|
//---------------------------------
|
29 |
|
|
output reg [3:0] LCD_D, // 4-bit LCD data bus
|
30 |
|
|
output reg LCD_E, // Enable
|
31 |
|
|
output LCD_RS, // Register Select (0->Register; 1->Data)
|
32 |
|
|
output LCD_RW // Read/Write (0->Write; 1->Read)
|
33 |
|
|
);
|
34 |
|
|
|
35 |
|
|
localparam [4:0] INIT_1=1, INIT_2=2, INIT_3=3, INIT_4=4, INIT_5=5, INIT_6=6, INIT_7=7, INIT_8=8,
|
36 |
|
|
CMD_WAIT=9, NOP=10, U_SETUP=11, U_ENAB=12, U_HOLD=13, UL_WAIT=14, L_SETUP=15,
|
37 |
|
|
L_ENAB=16, L_HOLD=17;
|
38 |
|
|
|
39 |
|
|
reg [18:0] count;
|
40 |
|
|
reg [18:0] compare;
|
41 |
|
|
reg [4:0] state;
|
42 |
|
|
wire bell;
|
43 |
|
|
wire long_instr;
|
44 |
|
|
|
45 |
|
|
assign LCD_RW = 0; // There is no reason to read from the LCD screen.
|
46 |
|
|
assign LCD_RS = command[8];
|
47 |
|
|
assign bell = (count == compare);
|
48 |
|
|
assign long_instr = ((command == 9'b0_0000_0001) || (command[8:1] == 8'b0_0000_001));
|
49 |
|
|
|
50 |
|
|
|
51 |
|
|
/* The count register increments until it equals 'compare' */
|
52 |
|
|
always @(posedge clock) begin
|
53 |
|
|
count <= (reset | bell) ? 19'b0 : count + 1;
|
54 |
|
|
end
|
55 |
|
|
|
56 |
|
|
/* Time delays for various states */
|
57 |
|
|
always @(*) begin
|
58 |
|
|
case (state)
|
59 |
|
|
INIT_1 : compare <= 19'd410000; // 15ms (4.1ms OK due to power-up delay)
|
60 |
|
|
INIT_2 : compare <= 19'd24; // 240 ns
|
61 |
|
|
INIT_3 : compare <= 19'd410000; // 4.1 ms
|
62 |
|
|
INIT_4 : compare <= 19'd24; // 240 ns
|
63 |
|
|
INIT_5 : compare <= 19'd10000; // 100 us or longer
|
64 |
|
|
INIT_6 : compare <= 19'd24; // 240 ns
|
65 |
|
|
INIT_7 : compare <= 19'd4000; // 40 us or longer
|
66 |
|
|
INIT_8 : compare <= 19'd24; // 240 ns
|
67 |
|
|
CMD_WAIT : compare <= (long_instr) ? 19'd164000 : 19'd4000; // 40 us or 1.64 ms
|
68 |
|
|
NOP : compare <= 19'hxxxxx;
|
69 |
|
|
U_SETUP : compare <= 19'd4; // 40 ns
|
70 |
|
|
U_ENAB : compare <= 19'd23; // 230 ns
|
71 |
|
|
U_HOLD : compare <= 19'd1; // 10 ns
|
72 |
|
|
UL_WAIT : compare <= 19'd100; // 1 us
|
73 |
|
|
L_SETUP : compare <= 19'd4; // 40 ns
|
74 |
|
|
L_ENAB : compare <= 19'd23; // 230 ns
|
75 |
|
|
L_HOLD : compare <= 19'd1; // 10 ns
|
76 |
|
|
default : compare <= 19'hxxxxx;
|
77 |
|
|
endcase
|
78 |
|
|
end
|
79 |
|
|
|
80 |
|
|
/* The main state machine */
|
81 |
|
|
always @(posedge clock) begin
|
82 |
|
|
if (reset) begin
|
83 |
|
|
state <= INIT_1;
|
84 |
|
|
end
|
85 |
|
|
else begin
|
86 |
|
|
case (state)
|
87 |
|
|
INIT_1 : state <= (bell) ? INIT_2 : INIT_1;
|
88 |
|
|
INIT_2 : state <= (bell) ? INIT_3 : INIT_2;
|
89 |
|
|
INIT_3 : state <= (bell) ? INIT_4 : INIT_3;
|
90 |
|
|
INIT_4 : state <= (bell) ? INIT_5 : INIT_4;
|
91 |
|
|
INIT_5 : state <= (bell) ? INIT_6 : INIT_5;
|
92 |
|
|
INIT_6 : state <= (bell) ? INIT_7 : INIT_6;
|
93 |
|
|
INIT_7 : state <= (bell) ? INIT_8 : INIT_7;
|
94 |
|
|
INIT_8 : state <= (bell) ? CMD_WAIT : INIT_8;
|
95 |
|
|
CMD_WAIT : state <= (bell) ? NOP : CMD_WAIT;
|
96 |
|
|
NOP : state <= (write & ~ack) ? U_SETUP : NOP;
|
97 |
|
|
U_SETUP : state <= (bell) ? U_ENAB : U_SETUP;
|
98 |
|
|
U_ENAB : state <= (bell) ? U_HOLD : U_ENAB;
|
99 |
|
|
U_HOLD : state <= (bell) ? UL_WAIT : U_HOLD;
|
100 |
|
|
UL_WAIT : state <= (bell) ? L_SETUP : UL_WAIT;
|
101 |
|
|
L_SETUP : state <= (bell) ? L_ENAB : L_SETUP;
|
102 |
|
|
L_ENAB : state <= (bell) ? L_HOLD : L_ENAB;
|
103 |
|
|
L_HOLD : state <= (bell) ? CMD_WAIT : L_HOLD;
|
104 |
|
|
default : state <= 5'bxxxxx;
|
105 |
|
|
endcase
|
106 |
|
|
end
|
107 |
|
|
end
|
108 |
|
|
|
109 |
|
|
/* Combinatorial enable and data assignments */
|
110 |
|
|
always @(*) begin
|
111 |
|
|
case (state)
|
112 |
|
|
INIT_1 : begin LCD_E <= 0; LCD_D <= 4'b0000; end
|
113 |
|
|
INIT_2 : begin LCD_E <= 0; LCD_D <= 4'b0011; end
|
114 |
|
|
INIT_3 : begin LCD_E <= 0; LCD_D <= 4'b0000; end
|
115 |
|
|
INIT_4 : begin LCD_E <= 1; LCD_D <= 4'b0011; end
|
116 |
|
|
INIT_5 : begin LCD_E <= 0; LCD_D <= 4'b0000; end
|
117 |
|
|
INIT_6 : begin LCD_E <= 1; LCD_D <= 4'b0011; end
|
118 |
|
|
INIT_7 : begin LCD_E <= 0; LCD_D <= 4'b0000; end
|
119 |
|
|
INIT_8 : begin LCD_E <= 1; LCD_D <= 4'b0010; end
|
120 |
|
|
CMD_WAIT : begin LCD_E <= 0; LCD_D <= 4'b0000; end
|
121 |
|
|
NOP : begin LCD_E <= 0; LCD_D <= 4'b0000; end
|
122 |
|
|
U_SETUP : begin LCD_E <= 0; LCD_D <= command[7:4]; end
|
123 |
|
|
U_ENAB : begin LCD_E <= 1; LCD_D <= command[7:4]; end
|
124 |
|
|
U_HOLD : begin LCD_E <= 0; LCD_D <= command[7:4]; end
|
125 |
|
|
UL_WAIT : begin LCD_E <= 0; LCD_D <= 4'b0000; end
|
126 |
|
|
L_SETUP : begin LCD_E <= 0; LCD_D <= command[3:0]; end
|
127 |
|
|
L_ENAB : begin LCD_E <= 1; LCD_D <= command[3:0]; end
|
128 |
|
|
L_HOLD : begin LCD_E <= 0; LCD_D <= command[3:0]; end
|
129 |
|
|
default : begin LCD_E <= 0; LCD_D <= 4'b0000; end
|
130 |
|
|
endcase
|
131 |
|
|
end
|
132 |
|
|
|
133 |
|
|
/* Full 4-way Handshake */
|
134 |
|
|
always @(posedge clock) begin
|
135 |
|
|
ack <= (reset | ~write) ? 0 : (((state == L_HOLD) && (bell == 1'b1)) ? 1 : ack);
|
136 |
|
|
end
|
137 |
|
|
|
138 |
|
|
endmodule
|