OpenCores
URL https://opencores.org/ocsvn/mips32r1/mips32r1/trunk

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Hardware/] [XUPV5-LX110T_SoC/] [MIPS32-Pipelined-Hw/] [src/] [LCD/] [lcd_ctrl.v] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.