blob: 456c2d0400be471ea4c0318140708a23f58ff923 [file] [log] [blame]
Tim Edwardscd64af52020-08-07 11:11:58 -04001/*
2 * PicoSoC - A simple example SoC using PicoRV32
3 *
4 * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
shalanfd13eb52020-08-21 16:48:07 +020020module spimemio_wb (
21 input wb_clk_i,
22 input wb_rst_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040023
shalanfd13eb52020-08-21 16:48:07 +020024 input [31:0] wb_adr_i,
Tim Edwards04ba17f2020-10-02 22:27:50 -040025 input [31:0] wb_dat_i,
shalanfd13eb52020-08-21 16:48:07 +020026 input [3:0] wb_sel_i,
27 input wb_we_i,
28 input wb_cyc_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040029
shalanfd13eb52020-08-21 16:48:07 +020030 input wb_flash_stb_i,
31 input wb_cfg_stb_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040032
shalanfd13eb52020-08-21 16:48:07 +020033 output wb_flash_ack_o,
34 output wb_cfg_ack_o,
Tim Edwardscd64af52020-08-07 11:11:58 -040035
shalanfd13eb52020-08-21 16:48:07 +020036 output [31:0] wb_flash_dat_o,
37 output [31:0] wb_cfg_dat_o,
Tim Edwardscd64af52020-08-07 11:11:58 -040038
Tim Edwards04ba17f2020-10-02 22:27:50 -040039 input pass_thru,
40 input pass_thru_csb,
41 input pass_thru_sck,
42 input pass_thru_sdi,
43 output pass_thru_sdo,
44
shalanfd13eb52020-08-21 16:48:07 +020045 output flash_csb,
46 output flash_clk,
Tim Edwardscd64af52020-08-07 11:11:58 -040047
shalanfd13eb52020-08-21 16:48:07 +020048 output flash_csb_oeb,
49 output flash_clk_oeb,
Tim Edwardscd64af52020-08-07 11:11:58 -040050
shalanfd13eb52020-08-21 16:48:07 +020051 output flash_io0_oeb,
52 output flash_io1_oeb,
53 output flash_io2_oeb,
54 output flash_io3_oeb,
Tim Edwardscd64af52020-08-07 11:11:58 -040055
shalanfd13eb52020-08-21 16:48:07 +020056 output flash_csb_ieb,
57 output flash_clk_ieb,
Tim Edwardscd64af52020-08-07 11:11:58 -040058
shalanfd13eb52020-08-21 16:48:07 +020059 output flash_io0_ieb,
60 output flash_io1_ieb,
61 output flash_io2_ieb,
62 output flash_io3_ieb,
63
64 output flash_io0_do,
65 output flash_io1_do,
66 output flash_io2_do,
67 output flash_io3_do,
68
69 input flash_io0_di,
70 input flash_io1_di,
71 input flash_io2_di,
72 input flash_io3_di
73
Tim Edwardscd64af52020-08-07 11:11:58 -040074);
shalanfd13eb52020-08-21 16:48:07 +020075 wire spimem_ready;
76 wire [23:0] mem_addr;
77 wire [31:0] spimem_rdata;
78 wire [31:0] spimemio_cfgreg_do;
79 wire [3:0] cfgreg_we;
80 wire spimemio_cfgreg_sel;
81 wire valid;
82 wire resetn;
Tim Edwardscd64af52020-08-07 11:11:58 -040083
shalanfd13eb52020-08-21 16:48:07 +020084 assign resetn = ~wb_rst_i;
85 assign valid = wb_cyc_i && wb_flash_stb_i;
86 assign wb_flash_ack_o = spimem_ready;
87 assign wb_cfg_ack_o = spimemio_cfgreg_sel;
Tim Edwardscd64af52020-08-07 11:11:58 -040088
shalanfd13eb52020-08-21 16:48:07 +020089 assign mem_addr = wb_adr_i[23:0];
90 assign spimemio_cfgreg_sel = wb_cyc_i && wb_cfg_stb_i;
Tim Edwardscd64af52020-08-07 11:11:58 -040091
shalanfd13eb52020-08-21 16:48:07 +020092 assign cfgreg_we = spimemio_cfgreg_sel ? wb_sel_i & {4{wb_we_i}} : 4'b 0000;
93 assign wb_flash_dat_o = spimem_rdata;
94 assign wb_cfg_dat_o = spimemio_cfgreg_do;
Tim Edwardscd64af52020-08-07 11:11:58 -040095
shalanfd13eb52020-08-21 16:48:07 +020096 spimemio spimemio (
97 .clk (wb_clk_i),
98 .resetn (resetn),
99 .valid (valid),
100 .ready (spimem_ready),
101 .addr (mem_addr),
102 .rdata (spimem_rdata),
Tim Edwardscd64af52020-08-07 11:11:58 -0400103
shalanfd13eb52020-08-21 16:48:07 +0200104 .flash_csb (flash_csb),
105 .flash_clk (flash_clk),
Tim Edwardscd64af52020-08-07 11:11:58 -0400106
shalanfd13eb52020-08-21 16:48:07 +0200107 .flash_csb_oeb (flash_csb_oeb),
108 .flash_clk_oeb (flash_clk_oeb),
Tim Edwardscd64af52020-08-07 11:11:58 -0400109
shalanfd13eb52020-08-21 16:48:07 +0200110 .flash_io0_oeb (flash_io0_oeb),
111 .flash_io1_oeb (flash_io1_oeb),
112 .flash_io2_oeb (flash_io2_oeb),
113 .flash_io3_oeb (flash_io3_oeb),
Tim Edwardscd64af52020-08-07 11:11:58 -0400114
shalanfd13eb52020-08-21 16:48:07 +0200115 .flash_csb_ieb (flash_csb_ieb),
116 .flash_clk_ieb (flash_clk_ieb),
Tim Edwardscd64af52020-08-07 11:11:58 -0400117
shalanfd13eb52020-08-21 16:48:07 +0200118 .flash_io0_ieb (flash_io0_ieb),
119 .flash_io1_ieb (flash_io1_ieb),
120 .flash_io2_ieb (flash_io2_ieb),
121 .flash_io3_ieb (flash_io3_ieb),
Tim Edwardscd64af52020-08-07 11:11:58 -0400122
shalanfd13eb52020-08-21 16:48:07 +0200123 .flash_io0_do (flash_io0_do),
124 .flash_io1_do (flash_io1_do),
125 .flash_io2_do (flash_io2_do),
126 .flash_io3_do (flash_io3_do),
Tim Edwardscd64af52020-08-07 11:11:58 -0400127
shalanfd13eb52020-08-21 16:48:07 +0200128 .flash_io0_di (flash_io0_di),
129 .flash_io1_di (flash_io1_di),
130 .flash_io2_di (flash_io2_di),
131 .flash_io3_di (flash_io3_di),
Tim Edwardscd64af52020-08-07 11:11:58 -0400132
shalanfd13eb52020-08-21 16:48:07 +0200133 .cfgreg_we(cfgreg_we),
134 .cfgreg_di(wb_dat_i),
135 .cfgreg_do(spimemio_cfgreg_do)
136 );
Tim Edwardscd64af52020-08-07 11:11:58 -0400137
shalanfd13eb52020-08-21 16:48:07 +0200138endmodule
Tim Edwardscd64af52020-08-07 11:11:58 -0400139
shalanfd13eb52020-08-21 16:48:07 +0200140module spimemio (
141 input clk, resetn,
Tim Edwardscd64af52020-08-07 11:11:58 -0400142
shalanfd13eb52020-08-21 16:48:07 +0200143 input valid,
144 output ready,
145 input [23:0] addr,
146 output reg [31:0] rdata,
Tim Edwardscd64af52020-08-07 11:11:58 -0400147
shalanfd13eb52020-08-21 16:48:07 +0200148 output flash_csb,
149 output flash_clk,
Tim Edwardscd64af52020-08-07 11:11:58 -0400150
shalanfd13eb52020-08-21 16:48:07 +0200151 output flash_csb_oeb,
152 output flash_clk_oeb,
Tim Edwardscd64af52020-08-07 11:11:58 -0400153
shalanfd13eb52020-08-21 16:48:07 +0200154 output flash_io0_oeb,
155 output flash_io1_oeb,
156 output flash_io2_oeb,
157 output flash_io3_oeb,
Tim Edwardscd64af52020-08-07 11:11:58 -0400158
shalanfd13eb52020-08-21 16:48:07 +0200159 output flash_csb_ieb,
160 output flash_clk_ieb,
Tim Edwardscd64af52020-08-07 11:11:58 -0400161
shalanfd13eb52020-08-21 16:48:07 +0200162 output flash_io0_ieb,
163 output flash_io1_ieb,
164 output flash_io2_ieb,
165 output flash_io3_ieb,
Tim Edwardscd64af52020-08-07 11:11:58 -0400166
shalanfd13eb52020-08-21 16:48:07 +0200167 output flash_io0_do,
168 output flash_io1_do,
169 output flash_io2_do,
170 output flash_io3_do,
Tim Edwardscd64af52020-08-07 11:11:58 -0400171
shalanfd13eb52020-08-21 16:48:07 +0200172 input flash_io0_di,
173 input flash_io1_di,
174 input flash_io2_di,
175 input flash_io3_di,
Tim Edwardscd64af52020-08-07 11:11:58 -0400176
shalanfd13eb52020-08-21 16:48:07 +0200177 input [3:0] cfgreg_we,
178 input [31:0] cfgreg_di,
179 output [31:0] cfgreg_do
180);
181 reg xfer_resetn;
182 reg din_valid;
183 wire din_ready;
184 reg [7:0] din_data;
185 reg [3:0] din_tag;
186 reg din_cont;
187 reg din_qspi;
188 reg din_ddr;
189 reg din_rd;
Tim Edwardscd64af52020-08-07 11:11:58 -0400190
shalanfd13eb52020-08-21 16:48:07 +0200191 wire dout_valid;
192 wire [7:0] dout_data;
193 wire [3:0] dout_tag;
Tim Edwardscd64af52020-08-07 11:11:58 -0400194
shalanfd13eb52020-08-21 16:48:07 +0200195 reg [23:0] buffer;
Tim Edwardscd64af52020-08-07 11:11:58 -0400196
shalanfd13eb52020-08-21 16:48:07 +0200197 reg [23:0] rd_addr;
198 reg rd_valid;
199 reg rd_wait;
200 reg rd_inc;
201
202 assign ready = valid && (addr == rd_addr) && rd_valid;
203 wire jump = valid && !ready && (addr != rd_addr+4) && rd_valid;
204
205 reg softreset;
206
207 reg config_en; // cfgreg[31]
208 reg config_ddr; // cfgreg[22]
209 reg config_qspi; // cfgreg[21]
210 reg config_cont; // cfgreg[20]
211 reg [3:0] config_dummy; // cfgreg[19:16]
212 reg [3:0] config_oe; // cfgreg[11:8]
213 reg config_csb; // cfgreg[5]
214 reg config_clk; // cfgref[4]
215 reg [3:0] config_do; // cfgreg[3:0]
216
217 assign cfgreg_do[31] = config_en;
218 assign cfgreg_do[30:23] = 0;
219 assign cfgreg_do[22] = config_ddr;
220 assign cfgreg_do[21] = config_qspi;
221 assign cfgreg_do[20] = config_cont;
222 assign cfgreg_do[19:16] = config_dummy;
223 assign cfgreg_do[15:12] = 0;
224 assign cfgreg_do[11:8] = {~flash_io3_oeb, ~flash_io2_oeb, ~flash_io1_oeb, ~flash_io0_oeb};
225 assign cfgreg_do[7:6] = 0;
226 assign cfgreg_do[5] = flash_csb;
227 assign cfgreg_do[4] = flash_clk;
228 assign cfgreg_do[3:0] = {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
229
230 always @(posedge clk) begin
231 softreset <= !config_en || cfgreg_we;
232 if (!resetn) begin
233 softreset <= 1;
234 config_en <= 1;
235 config_csb <= 0;
236 config_clk <= 0;
237 config_oe <= 0;
238 config_do <= 0;
239 config_ddr <= 0;
240 config_qspi <= 0;
241 config_cont <= 0;
242 config_dummy <= 8;
243 end else begin
244 if (cfgreg_we[0]) begin
245 config_csb <= cfgreg_di[5];
246 config_clk <= cfgreg_di[4];
247 config_do <= cfgreg_di[3:0];
248 end
249 if (cfgreg_we[1]) begin
250 config_oe <= cfgreg_di[11:8];
251 end
252 if (cfgreg_we[2]) begin
253 config_ddr <= cfgreg_di[22];
254 config_qspi <= cfgreg_di[21];
255 config_cont <= cfgreg_di[20];
256 config_dummy <= cfgreg_di[19:16];
257 end
258 if (cfgreg_we[3]) begin
259 config_en <= cfgreg_di[31];
260 end
261 end
262 end
263
264 wire xfer_csb;
265 wire xfer_clk;
266
267 wire xfer_io0_oe;
268 wire xfer_io1_oe;
269 wire xfer_io2_oe;
270 wire xfer_io3_oe;
271
272 wire xfer_io0_do;
273 wire xfer_io1_do;
274 wire xfer_io2_do;
275 wire xfer_io3_do;
276
277 reg xfer_io0_90;
278 reg xfer_io1_90;
279 reg xfer_io2_90;
280 reg xfer_io3_90;
281
282 always @(negedge clk) begin
283 xfer_io0_90 <= xfer_io0_do;
284 xfer_io1_90 <= xfer_io1_do;
285 xfer_io2_90 <= xfer_io2_do;
286 xfer_io3_90 <= xfer_io3_do;
287 end
288
Tim Edwards04ba17f2020-10-02 22:27:50 -0400289 wire pass_thru;
290 wire pass_thru_csb;
291 wire pass_thru_sck;
292 wire pass_thru_sdi;
293 wire pass_thru_sdo;
shalanfd13eb52020-08-21 16:48:07 +0200294
Tim Edwards04ba17f2020-10-02 22:27:50 -0400295 assign flash_csb = (pass_thru) ? pass_thru_csb : (config_en ? xfer_csb : config_csb);
296 assign flash_clk = (pass_thru) ? pass_thru_sck : (config_en ? xfer_clk : config_clk);
shalanfd13eb52020-08-21 16:48:07 +0200297
Tim Edwards04ba17f2020-10-02 22:27:50 -0400298 assign flash_csb_oeb = (pass_thru) ? 1'b0 : (~resetn ? 1'b1 : 1'b0);
299 assign flash_clk_oeb = (pass_thru) ? 1'b0 : (~resetn ? 1'b1 : 1'b0);
300
301 assign flash_io0_oeb = pass_thru ? 1'b0 : ~resetn ? 1'b1 : (config_en ? ~xfer_io0_oe : ~config_oe[0]);
302 assign flash_io1_oeb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? ~xfer_io1_oe : ~config_oe[1]);
303 assign flash_io2_oeb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? ~xfer_io2_oe : ~config_oe[2]);
304 assign flash_io3_oeb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? ~xfer_io3_oe : ~config_oe[3]);
shalanfd13eb52020-08-21 16:48:07 +0200305 assign flash_csb_ieb = 1'b1; /* Always disabled */
306 assign flash_clk_ieb = 1'b1; /* Always disabled */
307
Tim Edwards04ba17f2020-10-02 22:27:50 -0400308 assign flash_io0_ieb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? xfer_io0_oe : config_oe[0]);
309 assign flash_io1_ieb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? xfer_io1_oe : config_oe[1]);
310 assign flash_io2_ieb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? xfer_io2_oe : config_oe[2]);
311 assign flash_io3_ieb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? xfer_io3_oe : config_oe[3]);
shalanfd13eb52020-08-21 16:48:07 +0200312
Tim Edwards04ba17f2020-10-02 22:27:50 -0400313 assign flash_io0_do = pass_thru ? pass_thru_sdi : (config_en ? (config_ddr ? xfer_io0_90 : xfer_io0_do) : config_do[0]);
shalanfd13eb52020-08-21 16:48:07 +0200314 assign flash_io1_do = config_en ? (config_ddr ? xfer_io1_90 : xfer_io1_do) : config_do[1];
315 assign flash_io2_do = config_en ? (config_ddr ? xfer_io2_90 : xfer_io2_do) : config_do[2];
316 assign flash_io3_do = config_en ? (config_ddr ? xfer_io3_90 : xfer_io3_do) : config_do[3];
Tim Edwards04ba17f2020-10-02 22:27:50 -0400317 assign pass_thru_sdo = pass_thru ? flash_io1_di : 1'b0;
shalanfd13eb52020-08-21 16:48:07 +0200318
319 wire xfer_dspi = din_ddr && !din_qspi;
320 wire xfer_ddr = din_ddr && din_qspi;
321
322 spimemio_xfer xfer (
323 .clk (clk ),
324 .resetn (resetn ),
325 .xfer_resetn (xfer_resetn ),
326 .din_valid (din_valid ),
327 .din_ready (din_ready ),
328 .din_data (din_data ),
329 .din_tag (din_tag ),
330 .din_cont (din_cont ),
331 .din_dspi (xfer_dspi ),
332 .din_qspi (din_qspi ),
333 .din_ddr (xfer_ddr ),
334 .din_rd (din_rd ),
335 .dout_valid (dout_valid ),
336 .dout_data (dout_data ),
337 .dout_tag (dout_tag ),
338 .flash_csb (xfer_csb ),
339 .flash_clk (xfer_clk ),
340 .flash_io0_oe (xfer_io0_oe ),
341 .flash_io1_oe (xfer_io1_oe ),
342 .flash_io2_oe (xfer_io2_oe ),
343 .flash_io3_oe (xfer_io3_oe ),
344 .flash_io0_do (xfer_io0_do ),
345 .flash_io1_do (xfer_io1_do ),
346 .flash_io2_do (xfer_io2_do ),
347 .flash_io3_do (xfer_io3_do ),
348 .flash_io0_di (flash_io0_di),
349 .flash_io1_di (flash_io1_di),
350 .flash_io2_di (flash_io2_di),
351 .flash_io3_di (flash_io3_di)
352 );
353
354 reg [3:0] state;
355
356 always @(posedge clk) begin
357 xfer_resetn <= 1;
358 din_valid <= 0;
359
360 if (!resetn || softreset) begin
361 state <= 0;
362 xfer_resetn <= 0;
363 rd_valid <= 0;
364 din_tag <= 0;
365 din_cont <= 0;
366 din_qspi <= 0;
367 din_ddr <= 0;
368 din_rd <= 0;
369 end else begin
370 if (dout_valid && dout_tag == 1) buffer[ 7: 0] <= dout_data;
371 if (dout_valid && dout_tag == 2) buffer[15: 8] <= dout_data;
372 if (dout_valid && dout_tag == 3) buffer[23:16] <= dout_data;
373 if (dout_valid && dout_tag == 4) begin
374 rdata <= {dout_data, buffer};
375 rd_addr <= rd_inc ? rd_addr + 4 : addr;
376 rd_valid <= 1;
377 rd_wait <= rd_inc;
378 rd_inc <= 1;
379 end
380
381 if (valid)
382 rd_wait <= 0;
383
384 case (state)
385 0: begin
386 din_valid <= 1;
387 din_data <= 8'h ff;
388 din_tag <= 0;
389 if (din_ready) begin
390 din_valid <= 0;
391 state <= 1;
392 end
393 end
394 1: begin
395 if (dout_valid) begin
396 xfer_resetn <= 0;
397 state <= 2;
398 end
399 end
400 2: begin
401 din_valid <= 1;
402 din_data <= 8'h ab;
403 din_tag <= 0;
404 if (din_ready) begin
405 din_valid <= 0;
406 state <= 3;
407 end
408 end
409 3: begin
410 if (dout_valid) begin
411 xfer_resetn <= 0;
412 state <= 4;
413 end
414 end
415 4: begin
416 rd_inc <= 0;
417 din_valid <= 1;
418 din_tag <= 0;
419 case ({config_ddr, config_qspi})
420 2'b11: din_data <= 8'h ED;
421 2'b01: din_data <= 8'h EB;
422 2'b10: din_data <= 8'h BB;
423 2'b00: din_data <= 8'h 03;
424 endcase
425 if (din_ready) begin
426 din_valid <= 0;
427 state <= 5;
428 end
429 end
430 5: begin
431 if (valid && !ready) begin
432 din_valid <= 1;
433 din_tag <= 0;
434 din_data <= addr[23:16];
435 din_qspi <= config_qspi;
436 din_ddr <= config_ddr;
437 if (din_ready) begin
438 din_valid <= 0;
439 state <= 6;
440 end
441 end
442 end
443 6: begin
444 din_valid <= 1;
445 din_tag <= 0;
446 din_data <= addr[15:8];
447 if (din_ready) begin
448 din_valid <= 0;
449 state <= 7;
450 end
451 end
452 7: begin
453 din_valid <= 1;
454 din_tag <= 0;
455 din_data <= addr[7:0];
456 if (din_ready) begin
457 din_valid <= 0;
458 din_data <= 0;
459 state <= config_qspi || config_ddr ? 8 : 9;
460 end
461 end
462 8: begin
463 din_valid <= 1;
464 din_tag <= 0;
465 din_data <= config_cont ? 8'h A5 : 8'h FF;
466 if (din_ready) begin
467 din_rd <= 1;
468 din_data <= config_dummy;
469 din_valid <= 0;
470 state <= 9;
471 end
472 end
473 9: begin
474 din_valid <= 1;
475 din_tag <= 1;
476 if (din_ready) begin
477 din_valid <= 0;
478 state <= 10;
479 end
480 end
481 10: begin
482 din_valid <= 1;
483 din_data <= 8'h 00;
484 din_tag <= 2;
485 if (din_ready) begin
486 din_valid <= 0;
487 state <= 11;
488 end
489 end
490 11: begin
491 din_valid <= 1;
492 din_tag <= 3;
493 if (din_ready) begin
494 din_valid <= 0;
495 state <= 12;
496 end
497 end
498 12: begin
499 if (!rd_wait || valid) begin
500 din_valid <= 1;
501 din_tag <= 4;
502 if (din_ready) begin
503 din_valid <= 0;
504 state <= 9;
505 end
506 end
507 end
508 endcase
509
510 if (jump) begin
511 rd_inc <= 0;
512 rd_valid <= 0;
513 xfer_resetn <= 0;
514 if (config_cont) begin
515 state <= 5;
516 end else begin
517 state <= 4;
518 din_qspi <= 0;
519 din_ddr <= 0;
520 end
521 din_rd <= 0;
522 end
523 end
524 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400525endmodule
526
527module spimemio_xfer (
shalanfd13eb52020-08-21 16:48:07 +0200528 input clk, resetn, xfer_resetn,
Tim Edwardscd64af52020-08-07 11:11:58 -0400529
shalanfd13eb52020-08-21 16:48:07 +0200530 input din_valid,
531 output din_ready,
532 input [7:0] din_data,
533 input [3:0] din_tag,
534 input din_cont,
535 input din_dspi,
536 input din_qspi,
537 input din_ddr,
538 input din_rd,
Tim Edwardscd64af52020-08-07 11:11:58 -0400539
shalanfd13eb52020-08-21 16:48:07 +0200540 output dout_valid,
541 output [7:0] dout_data,
542 output [3:0] dout_tag,
Tim Edwardscd64af52020-08-07 11:11:58 -0400543
shalanfd13eb52020-08-21 16:48:07 +0200544 output reg flash_csb,
545 output reg flash_clk,
Tim Edwardscd64af52020-08-07 11:11:58 -0400546
shalanfd13eb52020-08-21 16:48:07 +0200547 output reg flash_io0_oe,
548 output reg flash_io1_oe,
549 output reg flash_io2_oe,
550 output reg flash_io3_oe,
Tim Edwardscd64af52020-08-07 11:11:58 -0400551
shalanfd13eb52020-08-21 16:48:07 +0200552 output reg flash_io0_do,
553 output reg flash_io1_do,
554 output reg flash_io2_do,
555 output reg flash_io3_do,
Tim Edwardscd64af52020-08-07 11:11:58 -0400556
shalanfd13eb52020-08-21 16:48:07 +0200557 input flash_io0_di,
558 input flash_io1_di,
559 input flash_io2_di,
560 input flash_io3_di
Tim Edwardscd64af52020-08-07 11:11:58 -0400561);
shalanfd13eb52020-08-21 16:48:07 +0200562 reg [7:0] obuffer;
563 reg [7:0] ibuffer;
Tim Edwardscd64af52020-08-07 11:11:58 -0400564
shalanfd13eb52020-08-21 16:48:07 +0200565 reg [3:0] count;
566 reg [3:0] dummy_count;
Tim Edwardscd64af52020-08-07 11:11:58 -0400567
shalanfd13eb52020-08-21 16:48:07 +0200568 reg xfer_cont;
569 reg xfer_dspi;
570 reg xfer_qspi;
571 reg xfer_ddr;
572 reg xfer_ddr_q;
573 reg xfer_rd;
574 reg [3:0] xfer_tag;
575 reg [3:0] xfer_tag_q;
Tim Edwardscd64af52020-08-07 11:11:58 -0400576
shalanfd13eb52020-08-21 16:48:07 +0200577 reg [7:0] next_obuffer;
578 reg [7:0] next_ibuffer;
579 reg [3:0] next_count;
Tim Edwardscd64af52020-08-07 11:11:58 -0400580
shalanfd13eb52020-08-21 16:48:07 +0200581 reg fetch;
582 reg next_fetch;
583 reg last_fetch;
Tim Edwardscd64af52020-08-07 11:11:58 -0400584
shalanfd13eb52020-08-21 16:48:07 +0200585 always @(posedge clk) begin
586 xfer_ddr_q <= xfer_ddr;
587 xfer_tag_q <= xfer_tag;
588 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400589
shalanfd13eb52020-08-21 16:48:07 +0200590 assign din_ready = din_valid && xfer_resetn && next_fetch;
Tim Edwardscd64af52020-08-07 11:11:58 -0400591
shalanfd13eb52020-08-21 16:48:07 +0200592 assign dout_valid = (xfer_ddr_q ? fetch && !last_fetch : next_fetch && !fetch) && xfer_resetn;
593 assign dout_data = ibuffer;
594 assign dout_tag = xfer_tag_q;
Tim Edwardscd64af52020-08-07 11:11:58 -0400595
shalanfd13eb52020-08-21 16:48:07 +0200596 always @* begin
597 flash_io0_oe = 0;
598 flash_io1_oe = 0;
599 flash_io2_oe = 0;
600 flash_io3_oe = 0;
Tim Edwardscd64af52020-08-07 11:11:58 -0400601
shalanfd13eb52020-08-21 16:48:07 +0200602 flash_io0_do = 0;
603 flash_io1_do = 0;
604 flash_io2_do = 0;
605 flash_io3_do = 0;
Tim Edwardscd64af52020-08-07 11:11:58 -0400606
shalanfd13eb52020-08-21 16:48:07 +0200607 next_obuffer = obuffer;
608 next_ibuffer = ibuffer;
609 next_count = count;
610 next_fetch = 0;
Tim Edwardscd64af52020-08-07 11:11:58 -0400611
shalanfd13eb52020-08-21 16:48:07 +0200612 if (dummy_count == 0) begin
613 casez ({xfer_ddr, xfer_qspi, xfer_dspi})
614 3'b 000: begin
615 flash_io0_oe = 1;
616 flash_io0_do = obuffer[7];
Tim Edwardscd64af52020-08-07 11:11:58 -0400617
shalanfd13eb52020-08-21 16:48:07 +0200618 if (flash_clk) begin
619 next_obuffer = {obuffer[6:0], 1'b 0};
620 next_count = count - |count;
621 end else begin
622 next_ibuffer = {ibuffer[6:0], flash_io1_di};
623 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400624
shalanfd13eb52020-08-21 16:48:07 +0200625 next_fetch = (next_count == 0);
626 end
627 3'b 01?: begin
628 flash_io0_oe = !xfer_rd;
629 flash_io1_oe = !xfer_rd;
630 flash_io2_oe = !xfer_rd;
631 flash_io3_oe = !xfer_rd;
Tim Edwardscd64af52020-08-07 11:11:58 -0400632
shalanfd13eb52020-08-21 16:48:07 +0200633 flash_io0_do = obuffer[4];
634 flash_io1_do = obuffer[5];
635 flash_io2_do = obuffer[6];
636 flash_io3_do = obuffer[7];
Tim Edwardscd64af52020-08-07 11:11:58 -0400637
shalanfd13eb52020-08-21 16:48:07 +0200638 if (flash_clk) begin
639 next_obuffer = {obuffer[3:0], 4'b 0000};
640 next_count = count - {|count, 2'b00};
641 end else begin
642 next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
643 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400644
shalanfd13eb52020-08-21 16:48:07 +0200645 next_fetch = (next_count == 0);
646 end
647 3'b 11?: begin
648 flash_io0_oe = !xfer_rd;
649 flash_io1_oe = !xfer_rd;
650 flash_io2_oe = !xfer_rd;
651 flash_io3_oe = !xfer_rd;
Tim Edwardscd64af52020-08-07 11:11:58 -0400652
shalanfd13eb52020-08-21 16:48:07 +0200653 flash_io0_do = obuffer[4];
654 flash_io1_do = obuffer[5];
655 flash_io2_do = obuffer[6];
656 flash_io3_do = obuffer[7];
Tim Edwardscd64af52020-08-07 11:11:58 -0400657
shalanfd13eb52020-08-21 16:48:07 +0200658 next_obuffer = {obuffer[3:0], 4'b 0000};
659 next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
660 next_count = count - {|count, 2'b00};
Tim Edwardscd64af52020-08-07 11:11:58 -0400661
shalanfd13eb52020-08-21 16:48:07 +0200662 next_fetch = (next_count == 0);
663 end
664 3'b ??1: begin
665 flash_io0_oe = !xfer_rd;
666 flash_io1_oe = !xfer_rd;
Tim Edwardscd64af52020-08-07 11:11:58 -0400667
shalanfd13eb52020-08-21 16:48:07 +0200668 flash_io0_do = obuffer[6];
669 flash_io1_do = obuffer[7];
Tim Edwardscd64af52020-08-07 11:11:58 -0400670
shalanfd13eb52020-08-21 16:48:07 +0200671 if (flash_clk) begin
672 next_obuffer = {obuffer[5:0], 2'b 00};
673 next_count = count - {|count, 1'b0};
674 end else begin
675 next_ibuffer = {ibuffer[5:0], flash_io1_di, flash_io0_di};
676 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400677
shalanfd13eb52020-08-21 16:48:07 +0200678 next_fetch = (next_count == 0);
679 end
680 endcase
681 end
682 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400683
shalanfd13eb52020-08-21 16:48:07 +0200684 always @(posedge clk) begin
685 if (!resetn || !xfer_resetn) begin
686 fetch <= 1;
687 last_fetch <= 1;
688 flash_csb <= 1;
689 flash_clk <= 0;
690 count <= 0;
691 dummy_count <= 0;
692 xfer_tag <= 0;
693 xfer_cont <= 0;
694 xfer_dspi <= 0;
695 xfer_qspi <= 0;
696 xfer_ddr <= 0;
697 xfer_rd <= 0;
698 end else begin
699 fetch <= next_fetch;
700 last_fetch <= xfer_ddr ? fetch : 1;
701 if (dummy_count) begin
702 flash_clk <= !flash_clk && !flash_csb;
703 dummy_count <= dummy_count - flash_clk;
704 end else
705 if (count) begin
706 flash_clk <= !flash_clk && !flash_csb;
707 obuffer <= next_obuffer;
708 ibuffer <= next_ibuffer;
709 count <= next_count;
710 end
711 if (din_valid && din_ready) begin
712 flash_csb <= 0;
713 flash_clk <= 0;
Tim Edwardscd64af52020-08-07 11:11:58 -0400714
shalanfd13eb52020-08-21 16:48:07 +0200715 count <= 8;
716 dummy_count <= din_rd ? din_data : 0;
717 obuffer <= din_data;
Tim Edwardscd64af52020-08-07 11:11:58 -0400718
shalanfd13eb52020-08-21 16:48:07 +0200719 xfer_tag <= din_tag;
720 xfer_cont <= din_cont;
721 xfer_dspi <= din_dspi;
722 xfer_qspi <= din_qspi;
723 xfer_ddr <= din_ddr;
724 xfer_rd <= din_rd;
725 end
726 end
727 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400728endmodule
shalanfd13eb52020-08-21 16:48:07 +0200729