1 | module oled_ctrl (
|
2 | input wire rst_n,
|
3 | input wire miso,
|
4 | output wire [9:0]gnd,
|
5 | output wire mosi,
|
6 | output wire sck,
|
7 | output wire oled_dc,
|
8 | output wire oled_cs,
|
9 | output wire oled_rst,
|
10 | output led_d2,
|
11 | output led_d3,
|
12 | output led_d4
|
13 | );
|
14 |
|
15 | localparam RESET_HOLD_COUNT = 16'h1000;
|
16 | localparam STATE_RESET = 8'h01;
|
17 | localparam STATE_SET_PINS = 8'h02;
|
18 | localparam STATE_START_SPI = 8'h04;
|
19 | localparam STATE_WAIT_SPI = 8'h08;
|
20 | localparam STATE_SPI_DONE = 8'h10;
|
21 | localparam STATE_HOLD = 8'h20;
|
22 |
|
23 | wire clk;
|
24 | wire oled_busy;
|
25 |
|
26 | reg [7:0] LUT_INDEX = 8'd0;
|
27 | reg [15:0] LUT_DATA;
|
28 |
|
29 | reg spim_start;
|
30 | reg [7:0] oled_data;
|
31 | reg [5:0] machine_state = STATE_RESET;
|
32 | reg [15:0] loop_counter = 16'd0;
|
33 |
|
34 | reg o_rst = 1'b1;
|
35 | reg o_cs = 1'b1;
|
36 | reg o_dc = 1'b1;
|
37 |
|
38 | assign gnd = 10'd0;
|
39 | assign oled_rst = o_rst;
|
40 | assign oled_cs = o_cs;
|
41 | assign oled_dc = oled_busy;
|
42 |
|
43 | // Tell-tale LEDS
|
44 | assign led_d2 = rst_n;
|
45 | assign led_d3 = ~sck;
|
46 | assign led_d4 = ~mosi;
|
47 |
|
48 |
|
49 | always @(posedge clk) begin
|
50 | if(!rst_n) begin
|
51 | oled_data <= 8'h00;
|
52 | spim_start <= 1'b0;
|
53 | machine_state <= STATE_RESET;
|
54 | loop_counter <= 16'h00;
|
55 | LUT_INDEX <= 0;
|
56 | end
|
57 | else begin
|
58 | // state machine
|
59 | case (machine_state)
|
60 | STATE_RESET: begin
|
61 | if(loop_counter==16'd0) begin
|
62 | o_rst <= 1'b0; // assert oled reset
|
63 | o_cs <= 1'b1;
|
64 | o_dc <= 1'b1;
|
65 | loop_counter <= loop_counter + 16'd1;
|
66 | end
|
67 | else if(loop_counter == RESET_HOLD_COUNT) begin
|
68 | o_rst <= 1'b1; // release oled reset
|
69 | machine_state <= STATE_SET_PINS;
|
70 | end else begin
|
71 | loop_counter <= loop_counter + 16'd1;
|
72 | end
|
73 | end
|
74 |
|
75 | STATE_SET_PINS: begin
|
76 | o_cs <= 1'b0; // assert oled chip select
|
77 | o_dc <= LUT_DATA[8]; // command or data pin (0:CMD, 1:DATA)
|
78 | oled_data <= LUT_DATA[7:0];
|
79 | machine_state <= STATE_START_SPI;
|
80 | end
|
81 |
|
82 | STATE_START_SPI: begin
|
83 | spim_start <= 1'b1;
|
84 | o_cs <= 1'b0;
|
85 | machine_state <= STATE_WAIT_SPI;
|
86 | end
|
87 |
|
88 | STATE_WAIT_SPI: begin
|
89 | spim_start <= 0; // release spim start
|
90 | o_cs <= 1'b0;
|
91 | if(!oled_busy) begin
|
92 | LUT_INDEX <= LUT_INDEX + 1'd1;
|
93 | machine_state <= STATE_SPI_DONE;
|
94 | end
|
95 | end
|
96 |
|
97 | STATE_SPI_DONE: begin
|
98 | o_cs <= 1'b1;
|
99 | spim_start <= 0;
|
100 | if(LUT_INDEX <= 8'd42) begin
|
101 | machine_state <= STATE_SET_PINS;
|
102 | end else begin
|
103 | machine_state <= STATE_HOLD;
|
104 | end
|
105 | end
|
106 |
|
107 | STATE_HOLD:
|
108 | o_cs <= 1'b1;
|
109 | default:
|
110 | o_cs <= 1'b1;
|
111 |
|
112 | endcase
|
113 | end
|
114 | end
|
115 |
|
116 |
|
117 | always @(posedge clk) begin
|
118 | case(LUT_INDEX)
|
119 | // Initialisation sequence for 128x128 OLED module
|
120 | 0: LUT_DATA <= 16'h00fd; // CMD lock =|
|
121 | 1: LUT_DATA <= 16'h0112; // Lock |
|
122 | 2: LUT_DATA <= 16'h00fd; // CMD lock |
|
123 | 3: LUT_DATA <= 16'h01b1; // Unlock =| Unlock sequence
|
124 |
|
125 | 4: LUT_DATA <= 16'h00AE; // Display off, sleep on
|
126 |
|
127 | 5: LUT_DATA <= 16'h00B3; // CMD DCLK Divide Ratio
|
128 | 6: LUT_DATA <= 16'h01f1; // clock = diviser+1
|
129 |
|
130 | 7: LUT_DATA <= 16'h00CA; // CMD Set MUX ratio
|
131 | 8: LUT_DATA <= 16'h017f; // OLED_END + 1
|
132 |
|
133 | 9: LUT_DATA <= 16'h00a2; // CMD Display offset
|
134 | 10: LUT_DATA <= 16'h0100; // 00
|
135 |
|
136 | 11: LUT_DATA <= 16'h00a1; // Display start line
|
137 | 12: LUT_DATA <= 16'h0100;
|
138 |
|
139 | 13: LUT_DATA <= 16'h00A0; // Set re-map, colour depth
|
140 | 14: LUT_DATA <= 16'h0162; // 8-Bit, 256 colours
|
141 |
|
142 | 15: LUT_DATA <= 16'h00B5; // setGPIO
|
143 | 16: LUT_DATA <= 16'h0100; // Disabled
|
144 |
|
145 | 17: LUT_DATA <= 16'h00AB; // Function set
|
146 | 18: LUT_DATA <= 16'h0101; // 8-Bit interface, internal VDD regulator
|
147 |
|
148 | 19: LUT_DATA <= 16'h00b4; // Set VSL (voltage-segment-low)
|
149 | 20: LUT_DATA <= 16'h01A0; // External VSL
|
150 | 21: LUT_DATA <= 16'h01B5;
|
151 | 22: LUT_DATA <= 16'h0155;
|
152 |
|
153 | 23: LUT_DATA <= 16'h00C1; // Set Contrast current for A,B,C
|
154 | 24: LUT_DATA <= 16'h018A; // A
|
155 | 25: LUT_DATA <= 16'h018a; // B
|
156 | 26: LUT_DATA <= 16'h018A; // C
|
157 |
|
158 | 27: LUT_DATA <= 16'h00c7; // Set mster Contrast
|
159 | 28: LUT_DATA <= 16'h010f;
|
160 |
|
161 | 29: LUT_DATA <= 16'h00B9; // reset to default LUT
|
162 |
|
163 | 30: LUT_DATA <= 16'h00B1; // Set pre and discharge phase length
|
164 | 31: LUT_DATA <= 16'h0132; //
|
165 |
|
166 | 32: LUT_DATA <= 16'h00BB; // Set pre-charge voltage of colour A,B,C
|
167 | 33: LUT_DATA <= 16'h0107;
|
168 |
|
169 | 34: LUT_DATA <= 16'h00B2; // Set enhanced driving scheme
|
170 | 35: LUT_DATA <= 16'h01a4; //
|
171 | 36: LUT_DATA <= 16'h0100;
|
172 | 37: LUT_DATA <= 16'h0100;
|
173 |
|
174 | 38: LUT_DATA <= 16'h00B6; // second precharge period
|
175 | 39: LUT_DATA <= 16'h0101;
|
176 |
|
177 | 40: LUT_DATA <= 16'h00BE; // Set VCOMH Voltage
|
178 | 41: LUT_DATA <= 16'h0107;
|
179 |
|
180 | 42: LUT_DATA <= 16'h00a6; // Normal display mode.
|
181 |
|
182 | default: LUT_DATA <= 16'h0100;
|
183 | endcase
|
184 | end
|
185 |
|
186 |
|
187 | /*************************/
|
188 | /* Instances of modules. */
|
189 | /*************************/
|
190 | // Lattice OSCH Clock Module
|
191 | defparam OSCH_inst.NOM_FREQ = "2.08";
|
192 | OSCH OSCH_inst (.STDBY(1'b0), .OSC(clk), .SEDSTDBY() );
|
193 | spi_master spim(.clk(clk), .rst_n(rst_n), .miso(miso), .mosi(mosi), .sck(sck), .start(spim_start), .data_in(oled_data), .data_out(), .busy(oled_busy), .new_data()) ;
|
194 | endmodule
|