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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [lloled.v] - Blame information for rev 3

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

Line No. Rev Author Line
1 3 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    lloled.v
4
//
5
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
6
//
7
// Purpose:     
8
//
9
// Creator:     Dan Gisselquist, Ph.D.
10
//              Gisselquist Technology, LLC
11
//
12
////////////////////////////////////////////////////////////////////////////////
13
//
14
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
15
//
16
// This program is free software (firmware): you can redistribute it and/or
17
// modify it under the terms of  the GNU General Public License as published
18
// by the Free Software Foundation, either version 3 of the License, or (at
19
// your option) any later version.
20
//
21
// This program is distributed in the hope that it will be useful, but WITHOUT
22
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
23
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
// for more details.
25
//
26
// You should have received a copy of the GNU General Public License along
27
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
28
// target there if the PDF file isn't present.)  If not, see
29
// <http://www.gnu.org/licenses/> for a copy.
30
//
31
// License:     GPL, v3, as defined and found on www.gnu.org,
32
//              http://www.gnu.org/licenses/gpl.html
33
//
34
//
35
////////////////////////////////////////////////////////////////////////////////
36
`define OLED_IDLE       3'h0
37
`define OLED_START      3'h1
38
`define OLED_BITS       3'h2
39
`define OLED_READY      3'h3
40
`define OLED_STOP       3'h4
41
`define OLED_STOP_B     3'h5
42
 
43
// Modes
44
`define OLED_MOD_SPI    2'b00
45
`define OLED_MOD_QOUT   2'b10
46
`define OLED_MOD_QIN    2'b11
47
 
48
module  lloled(i_clk,
49
                // Module interface
50
                i_wr, i_dbit, i_word, i_len, o_busy,
51
                // OLED interface
52
                o_sck, o_cs_n, o_mosi, o_dbit);
53
        parameter       CTRBITS = 8;
54
        input                   i_clk;
55
        // Chip interface
56
        //      Can send info
57
        //              i_wr = 1,
58
        //                      i_word = { 1'b0, 32'info to send },
59
        //                      i_len = # of bytes in word-1
60
        input                   i_wr, i_dbit;
61
        input           [31:0]   i_word;
62
        input           [1:0]    i_len;  // 0=>8bits, 1=>16 bits, 2=>24 bits, 3=>32 bits
63
        output  reg             o_busy;
64
        // Interface with the OLED lines
65
        output  reg             o_sck, o_cs_n, o_mosi, o_dbit;
66
 
67
        // Timing:
68
        //
69
        //      Tick    Clk     BSY/WR  CS_n    BIT/MO  STATE
70
        //       0      1       0/0     1        -      
71
        //       1      1       0/1     1        -
72
        //       2      1       1/0     0         -      OLED_START
73
        //       3      0        1/0     0         -      OLED_START
74
        //       4      0        1/0     0         0      OLED_BITS
75
        //       5      1       1/0     0         0      OLED_BITS
76
        //       6      0        1/0     0         1      OLED_BITS
77
        //       7      1       1/0     0         1      OLED_BITS
78
        //       8      0        1/0     0         2      OLED_BITS
79
        //       9      1       1/0     0         2      OLED_BITS
80
        //      10      0        1/0     0         3      OLED_BITS
81
        //      11      1       1/0     0         3      OLED_BITS
82
        //      12      0        1/0     0         4      OLED_BITS
83
        //      13      1       1/0     0         4      OLED_BITS
84
        //      14      0        1/0     0         5      OLED_BITS
85
        //      15      1       1/0     0         5      OLED_BITS
86
        //      16      0        1/0     0         6      OLED_BITS
87
        //      17      1       1/1     0         6      OLED_BITS
88
        //      18      0        1/1     0         7      OLED_READY
89
        //      19      1       0/1     0         7      OLED_READY
90
        //      20      0        1/0/V   0         8      OLED_BITS
91
        //      21      1       1/0     0         8      OLED_BITS
92
        //      22      0        1/0     0         9      OLED_BITS
93
        //      23      1       1/0     0         9      OLED_BITS
94
        //      24      0        1/0     0        10      OLED_BITS
95
        //      25      1       1/0     0        10      OLED_BITS
96
        //      26      0        1/0     0        11      OLED_BITS
97
        //      27      1       1/0     0        11      OLED_BITS
98
        //      28      0        1/0     0        12      OLED_BITS
99
        //      29      1       1/0     0        12      OLED_BITS
100
        //      30      0        1/0     0        13      OLED_BITS
101
        //      31      1       1/0     0        13      OLED_BITS
102
        //      32      0        1/0     0        14      OLED_BITS
103
        //      33      1       1/0     0        14      OLED_BITS
104
        //      34      0        1/0     0        15      OLED_READY
105
        //      35      1       1/0     0        15      OLED_READY
106
        //      36      1       1/0/V   0         -      OLED_STOP
107
        //      37      1       1/0     0         -      OLED_STOPB
108
        //      38      1       1/0     1        -      OLED_IDLE
109
        //      39      1       0/0     1        -
110
 
111
        reg     [5:0]    spi_len;
112
        reg     [31:0]   r_word;
113
        reg     [2:0]    state;
114
        initial state = `OLED_IDLE;
115
        initial o_sck   = 1'b1;
116
        initial o_cs_n  = 1'b1;
117
        initial o_mosi  = 1'b0;
118
        initial o_busy  = 1'b0;
119
 
120
        reg     [(CTRBITS-1):0]  counter;
121
        reg     last_counter, pre_last_counter;
122
        always @(posedge i_clk) // Clock cycle time > 150 ns > 300 ticks
123
                last_counter <= (counter == {{(CTRBITS-1){1'b0}},1'b1});
124
        always @(posedge i_clk)
125
                pre_last_counter <= (counter == {{(CTRBITS-2){1'b0}},2'b10});
126
        always @(posedge i_clk)
127
                if (state == `OLED_IDLE)
128
                        counter <= {(CTRBITS){1'b1}};
129
                else
130
                        counter <= counter + {(CTRBITS){1'b1}};
131
        always @(posedge i_clk)
132
                if ((state == `OLED_IDLE)&&(o_sck))
133
                begin
134
                        o_cs_n <= 1'b1;
135
                        o_busy  <= 1'b0;
136
                        r_word <= i_word;
137
                        spi_len<= { 1'b0, i_len, 3'b000 } + 6'h8;
138
                        o_sck <= 1'b1;
139
                        o_dbit <= i_dbit;
140
                        if (i_wr)
141
                        begin
142
                                state <= `OLED_START;
143
                                o_cs_n <= 1'b0;
144
                                o_busy <= 1'b1;
145
                        end
146
                end else if (state == `OLED_START)
147
                begin // We come in here with sck high, stay here 'til sck is low
148
                        o_sck <= 1'b0;
149
                        if (o_sck == 1'b0)
150
                        begin
151
                                state <= `OLED_BITS;
152
                                spi_len<= spi_len - 6'h1;
153
                                r_word <= { r_word[30:0], 1'b0 };
154
                        end
155
                        o_cs_n <= 1'b0;
156
                        o_busy <= 1'b1;
157
                        o_mosi <= r_word[31];
158
                end else if (~last_counter)
159
                begin
160
                        o_busy <= (pre_last_counter)&&(o_sck)
161
                                &&((state != `OLED_READY)||(~i_wr));
162
                end else if (~o_sck)
163
                begin
164
                        o_sck <= 1'b1;
165
                        o_busy <= 1'b1;
166
                end else if (state == `OLED_BITS)
167
                begin
168
                        // Should enter into here with at least a spi_len
169
                        // of one, perhaps more
170
                        o_sck <= 1'b0;
171
                        o_busy <= 1'b1;
172
                        o_mosi <= r_word[31];
173
                        r_word <= { r_word[30:0], 1'b0 };
174
                        spi_len <= spi_len - 6'h1;
175
                        if (spi_len == 6'h1)
176
                                state <= `OLED_READY;
177
                end else if (state == `OLED_READY)
178
                begin
179
                        o_cs_n <= 1'b0;
180
                        o_busy <= 1'b1;
181
                        // This is the state on the last clock (both low and
182
                        // high clocks) of the data.  Data is valid during
183
                        // this state.  Here we chose to either STOP or
184
                        // continue and transmit more.
185
                        o_sck <= 1'b0;
186
                        if((~o_busy)&&(i_wr))// Acknowledge a new request
187
                        begin
188
                                state <= `OLED_BITS;
189
                                o_busy <= 1'b1;
190
                                o_sck <= 1'b0;
191
 
192
                                // Set up the first bits on the bus
193
                                o_mosi <= i_word[31];
194
                                r_word <= { i_word[30:0], 1'b0 };
195
                                spi_len<= { 1'b0, i_len, 3'b111 };
196
 
197
                                // Read a bit upon any transition
198
                        end else begin
199
                                o_sck <= 1'b1;
200
                                state <= `OLED_STOP;
201
                                o_busy <= 1'b1;
202
                        end
203
                end else if (state == `OLED_STOP)
204
                begin
205
                        o_sck   <= 1'b1; // Stop the clock
206
                        o_busy  <= 1'b1; // Still busy till port is clear
207
                        state <= `OLED_STOP_B;
208
                end else // if (state == `OLED_STOP_B)
209
                begin
210
                        o_cs_n <= 1'b1; // Deselect CS
211
                        o_sck <= 1'b1;
212
                        // Do I need this????
213
                        // spi_len <= 3; // Minimum CS high time before next cmd
214
                        state <= `OLED_IDLE;
215
                        o_mosi <= 1'b1;
216
                        o_busy <= 1'b1;
217
                end
218
                /*
219
                */
220
 
221
endmodule
222
 

powered by: WebSVN 2.1.0

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