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

Subversion Repositories yifive

[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [spi_master/] [src/] [spim_ctrl.sv] - Blame information for rev 21

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 18 dinesha
 
2
//////////////////////////////////////////////////////////////////////
3
////                                                              ////
4
////  SPI CTRL I/F Module                                         ////
5
////                                                              ////
6
////  This file is part of the YIFive cores project               ////
7
////  http://www.opencores.org/cores/yifive/                      ////
8
////                                                              ////
9
////  Description                                                 ////
10
////                                                              ////
11
////  To Do:                                                      ////
12
////    nothing                                                   ////
13
////                                                              ////
14
////  Author(s):                                                  ////
15
////      - Dinesh Annayya, dinesha@opencores.org                 ////
16
////                                                              ////
17
////  Revision :                                                  ////
18
////     V.0  -  June 8, 2021                                     ////
19
////                                                              ////
20
//////////////////////////////////////////////////////////////////////
21
////                                                              ////
22
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
23
////                                                              ////
24
//// This source file may be used and distributed without         ////
25
//// restriction provided that this copyright statement is not    ////
26
//// removed from the file and that any derivative work contains  ////
27
//// the original copyright notice and the associated disclaimer. ////
28
////                                                              ////
29
//// This source file is free software; you can redistribute it   ////
30
//// and/or modify it under the terms of the GNU Lesser General   ////
31
//// Public License as published by the Free Software Foundation; ////
32
//// either version 2.1 of the License, or (at your option) any   ////
33
//// later version.                                               ////
34
////                                                              ////
35
//// This source is distributed in the hope that it will be       ////
36
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
37
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
38
//// PURPOSE.  See the GNU Lesser General Public License for more ////
39
//// details.                                                     ////
40
////                                                              ////
41
//// You should have received a copy of the GNU Lesser General    ////
42
//// Public License along with this source; if not, download it   ////
43
//// from http://www.opencores.org/lgpl.shtml                     ////
44
////                                                              ////
45
//////////////////////////////////////////////////////////////////////
46
module spim_ctrl
47
(
48
    input  logic                          clk,
49
    input  logic                          rstn,
50
    output logic                          eot,
51
 
52
    input  logic                    [7:0] spi_clk_div,
53
    input  logic                          spi_clk_div_valid,
54 21 dinesha
    output logic                    [8:0] spi_status,
55 18 dinesha
 
56
 
57
    input  logic                          spi_req,
58
    input  logic                   [31:0] spi_addr,
59
    input  logic                    [5:0] spi_addr_len,
60
    input  logic                   [7:0]  spi_cmd,
61
    input  logic                    [5:0] spi_cmd_len,
62
    input  logic                   [7:0]  spi_mode_cmd,
63
    input  logic                          spi_mode_cmd_enb,
64
    input  logic                    [3:0] spi_csreg,
65
    input  logic                   [15:0] spi_data_len,
66
    input  logic                   [15:0] spi_dummy_rd_len,
67
    input  logic                   [15:0] spi_dummy_wr_len,
68
    input  logic                          spi_swrst, //FIXME Not used at all
69
    input  logic                          spi_rd,
70
    input  logic                          spi_wr,
71
    input  logic                          spi_qrd,
72
    input  logic                          spi_qwr,
73
    input  logic                   [31:0] spi_wdata,
74
    output logic                   [31:0] spi_rdata,
75
    output logic                          spi_ack,
76
 
77
    output logic                          spi_clk,
78
    output logic                          spi_csn0,
79
    output logic                          spi_csn1,
80
    output logic                          spi_csn2,
81
    output logic                          spi_csn3,
82
    output logic                    [1:0] spi_mode,
83
    output logic                          spi_sdo0,
84
    output logic                          spi_sdo1,
85
    output logic                          spi_sdo2,
86
    output logic                          spi_sdo3,
87
    input  logic                          spi_sdi0,
88
    input  logic                          spi_sdi1,
89
    input  logic                          spi_sdi2,
90
    input  logic                          spi_sdi3,
91
    output logic                          spi_en_tx // Spi Direction control
92
);
93
 
94
 
95
parameter  SPI_STD     = 2'b00;
96
parameter  SPI_QUAD_TX = 2'b01;
97
parameter  SPI_QUAD_RX = 2'b10;
98
 
99
  logic spi_rise;
100
  logic spi_fall;
101
 
102
  logic spi_clock_en;
103
 
104
  logic spi_en_rx;
105
 
106
  logic [15:0] counter_tx;
107
  logic        counter_tx_valid;
108
  logic [15:0] counter_rx;
109
  logic        counter_rx_valid;
110
 
111
  logic [31:0] data_to_tx;
112
  logic        data_to_tx_valid;
113
  logic        data_to_tx_ready;
114
 
115
  logic en_quad;
116
  logic en_quad_int;
117
  logic do_tx; //FIXME NOT USED at all!!
118
  logic do_rx;
119
 
120
  logic tx_done;
121
  logic rx_done;
122
 
123
  logic [1:0] s_spi_mode;
124
 
125
  logic ctrl_data_valid;
126
 
127
  logic spi_cs;
128
 
129
  logic tx_clk_en;
130
  logic rx_clk_en;
131
  logic en_quad_in;
132
 
133
 
134
  enum logic [2:0] {DATA_NULL,DATA_EMPTY,DATA_CMD,DATA_ADDR,DATA_MODE,DATA_FIFO} ctrl_data_mux;
135
 
136 21 dinesha
  enum logic [4:0] {IDLE,CMD,ADDR,MODE,DUMMY_RX,DUMMY_TX,DATA_TX,DATA_RX,WAIT_EDGE} state,state_next;
137 18 dinesha
 
138
  assign en_quad = spi_qrd | spi_qwr | en_quad_int;
139
 
140
 
141
  assign en_quad_in = (s_spi_mode == SPI_STD) ? 1'b0 : 1'b1;
142
 
143
  spim_clkgen u_clkgen
144
  (
145
    .clk           ( clk               ),
146
    .rstn          ( rstn              ),
147
    .en            ( spi_clock_en      ),
148
    .cfg_sck_period( spi_clk_div       ),
149
    .spi_clk       ( spi_clk           ),
150
    .spi_fall      ( spi_fall          ),
151
    .spi_rise      ( spi_rise          )
152
  );
153
 
154
  spim_tx u_txreg
155
  (
156
    .clk            ( clk              ),
157
    .rstn           ( rstn             ),
158
    .en             ( spi_en_tx        ),
159
    .tx_edge        ( spi_fall         ),
160
    .tx_done        ( tx_done          ),
161
    .sdo0           ( spi_sdo0         ),
162
    .sdo1           ( spi_sdo1         ),
163
    .sdo2           ( spi_sdo2         ),
164
    .sdo3           ( spi_sdo3         ),
165
    .en_quad_in     ( en_quad_in       ),
166
    .counter_in     ( counter_tx       ),
167
    .txdata         ( data_to_tx       ),
168
    .data_valid     ( data_to_tx_valid ),
169
    .data_ready     (                  ),
170
    .clk_en_o       ( tx_clk_en        )
171
  );
172
  spim_rx u_rxreg
173
  (
174
    .clk            ( clk                    ),
175
    .rstn           ( rstn                   ),
176
    .en             ( spi_en_rx              ),
177
    .rx_edge        ( spi_rise               ),
178
    .rx_done        ( rx_done                ),
179
    .sdi0           ( spi_sdi0               ),
180
    .sdi1           ( spi_sdi1               ),
181
    .sdi2           ( spi_sdi2               ),
182
    .sdi3           ( spi_sdi3               ),
183
    .en_quad_in     ( en_quad_in             ),
184
    .counter_in     ( counter_rx             ),
185
    .counter_in_upd ( counter_rx_valid       ),
186
    .data           ( spi_rdata              ),
187
    .data_valid     (                        ),
188
    .data_ready     ( 1'b1                   ),
189
    .clk_en_o       ( rx_clk_en              )
190
  );
191
 
192
 
193
  always_comb
194
  begin
195
      data_to_tx       =  'h0;
196
      data_to_tx_valid = 1'b0;
197
 
198
      case(ctrl_data_mux)
199
          DATA_NULL:
200
          begin
201
              data_to_tx       =  '0;
202
              data_to_tx_valid = 1'b0;
203
          end
204
 
205
          DATA_EMPTY:
206
          begin
207
              data_to_tx       =  '0;
208
              data_to_tx_valid = 1'b1;
209
          end
210
 
211
          DATA_CMD:
212
          begin
213
              data_to_tx       = {spi_cmd,24'h0};
214
              data_to_tx_valid = ctrl_data_valid;
215
          end
216
          DATA_MODE:
217
          begin
218
              data_to_tx       = {spi_mode_cmd,24'h0};
219
              data_to_tx_valid = ctrl_data_valid;
220
          end
221
 
222
          DATA_ADDR:
223
          begin
224
              data_to_tx       = spi_addr;
225
              data_to_tx_valid = ctrl_data_valid;
226
          end
227
 
228
          DATA_FIFO:
229
          begin
230
             data_to_tx             = spi_wdata;
231
             data_to_tx_valid       = ctrl_data_valid;
232
          end
233
      endcase
234
  end
235
 
236
  always_comb
237
  begin
238
    spi_cs           = 1'b1;
239
    spi_clock_en     = 1'b0;
240
    counter_tx       =  '0;
241
    counter_tx_valid = 1'b0;
242
    counter_rx       =  '0;
243
    counter_rx_valid = 1'b0;
244
    state_next       = state;
245
    ctrl_data_mux    = DATA_NULL;
246
    ctrl_data_valid  = 1'b0;
247
    spi_en_rx        = 1'b0;
248
    spi_en_tx        = 1'b0;
249
    spi_status       =  '0;
250
    s_spi_mode       = SPI_QUAD_RX;
251
    eot              = 1'b0;
252
    case(state)
253
      IDLE:
254
      begin
255
        spi_status[0] = 1'b1;
256
        s_spi_mode = SPI_QUAD_RX;
257 21 dinesha
        if (spi_req && spi_fall)
258 18 dinesha
        begin
259
          spi_cs       = 1'b0;
260
          spi_clock_en = 1'b1;
261
 
262
          if (spi_cmd_len != 0)
263
          begin
264
//            s_spi_mode = (spi_qrd | spi_qwr) ? `SPI_QUAD_TX : `SPI_STD;
265
            s_spi_mode       = SPI_STD; // COMMAND is always Standard Mode ?
266
            counter_tx       = {8'h0,spi_cmd_len};
267
            counter_tx_valid = 1'b1;
268
            ctrl_data_mux    = DATA_CMD;
269
            ctrl_data_valid  = 1'b1;
270
            spi_en_tx        = 1'b1;
271
            state_next       = CMD;
272
          end
273
          else if (spi_addr_len != 0)
274
          begin
275
            s_spi_mode = (spi_qrd | spi_qwr) ? SPI_QUAD_TX : SPI_STD;
276
            counter_tx       = {8'h0,spi_addr_len};
277
            counter_tx_valid = 1'b1;
278
            ctrl_data_mux    = DATA_ADDR;
279
            ctrl_data_valid  = 1'b1;
280
            spi_en_tx        = 1'b1;
281
            state_next       = ADDR;
282
          end
283
          else if (spi_mode_cmd_enb != 0)
284
          begin
285
            s_spi_mode = (spi_qrd | spi_qwr) ? SPI_QUAD_TX : SPI_STD;
286
            counter_tx       = {8'h0,8'h8};
287
            counter_tx_valid = 1'b1;
288
            ctrl_data_mux    = DATA_MODE;
289
            ctrl_data_valid  = 1'b1;
290
            spi_en_tx        = 1'b1;
291
            state_next       = MODE;
292
          end
293
          else if (spi_data_len != 0)
294
          begin
295
             if (spi_rd || spi_qrd)
296
             begin
297
                s_spi_mode = (spi_qrd) ? SPI_QUAD_RX : SPI_STD;
298
                if(spi_dummy_rd_len != 0)
299
                begin
300 21 dinesha
                  counter_rx       = en_quad ? {2'b00,spi_dummy_rd_len[13:0]} : spi_dummy_rd_len;
301
                  counter_rx_valid = 1'b1;
302
                  spi_en_rx        = 1'b1;
303 18 dinesha
                  ctrl_data_mux    = DATA_EMPTY;
304 21 dinesha
                  spi_clock_en     = rx_clk_en;
305
                  state_next       = DUMMY_RX;
306 18 dinesha
                end
307
                else
308
                begin
309
                   counter_rx       = spi_data_len;
310
                   counter_rx_valid = 1'b1;
311
                   spi_en_rx        = 1'b1;
312 21 dinesha
                   spi_clock_en     = rx_clk_en;
313 18 dinesha
                   state_next       = DATA_RX;
314
                end
315
             end
316
             else
317
             begin
318
                s_spi_mode = (spi_qwr) ? SPI_QUAD_TX : SPI_STD;
319
                if(spi_dummy_wr_len != 0)
320
                begin
321
                   counter_tx       = en_quad ? {2'b00,spi_dummy_wr_len[13:0]} : spi_dummy_wr_len;
322
                   counter_tx_valid = 1'b1;
323
                   ctrl_data_mux    = DATA_EMPTY;
324
                   spi_en_tx        = 1'b1;
325 21 dinesha
                   spi_clock_en     = tx_clk_en;
326
                   state_next       = DUMMY_TX;
327 18 dinesha
                end
328
                else
329
                begin
330
                   counter_tx       = spi_data_len;
331
                   counter_tx_valid = 1'b1;
332
                   ctrl_data_mux    = DATA_FIFO;
333
                   ctrl_data_valid  = 1'b0;
334
                   spi_en_tx        = 1'b1;
335 21 dinesha
                   spi_clock_en     = tx_clk_en;
336 18 dinesha
                   state_next       = DATA_TX;
337
                end
338
             end
339
          end
340
        end
341
        else
342
        begin
343
          spi_cs = 1'b1;
344
          state_next = IDLE;
345
        end
346
      end
347
 
348
      CMD:
349
      begin
350
        spi_status[1] = 1'b1;
351
        spi_cs = 1'b0;
352
        spi_clock_en = 1'b1;
353
//      s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
354
        s_spi_mode = SPI_STD; // Command is always Standard Mode ?
355 21 dinesha
        if (tx_done && spi_fall)
356 18 dinesha
        begin
357
          if (spi_addr_len != 0)
358
          begin
359
            s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
360
            counter_tx       = {8'h0,spi_addr_len};
361
            counter_tx_valid = 1'b1;
362
            ctrl_data_mux    = DATA_ADDR;
363
            ctrl_data_valid  = 1'b1;
364
            spi_en_tx        = 1'b1;
365
            state_next       = ADDR;
366
          end
367
          else if (spi_mode_cmd_enb != 0)
368
          begin
369
            s_spi_mode = (spi_qrd | spi_qwr) ? SPI_QUAD_TX : SPI_STD;
370
            counter_tx       = {8'h0,8'h8};
371
            counter_tx_valid = 1'b1;
372
            ctrl_data_mux    = DATA_MODE;
373
            ctrl_data_valid  = 1'b1;
374
            spi_en_tx        = 1'b1;
375
            state_next       = MODE;
376
          end
377
          else if (spi_data_len != 0)
378
          begin
379
            if (do_rx)
380
            begin
381
              s_spi_mode = (en_quad) ? SPI_QUAD_RX : SPI_STD;
382
              if(spi_dummy_rd_len != 0)
383
              begin
384 21 dinesha
                counter_rx       = en_quad ? {2'b00,spi_dummy_rd_len[13:0]} : spi_dummy_rd_len;
385
                counter_rx_valid = 1'b1;
386
                spi_en_rx        = 1'b1;
387 18 dinesha
                ctrl_data_mux    = DATA_EMPTY;
388 21 dinesha
                spi_clock_en     = rx_clk_en;
389
                state_next       = DUMMY_RX;
390 18 dinesha
              end
391
              else
392
              begin
393
                counter_rx       = spi_data_len;
394
                counter_rx_valid = 1'b1;
395
                spi_en_rx        = 1'b1;
396 21 dinesha
                spi_clock_en     = rx_clk_en;
397 18 dinesha
                state_next       = DATA_RX;
398
              end
399
            end
400
            else
401
            begin
402
              s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
403
              if(spi_dummy_wr_len != 0)
404
              begin
405
                counter_tx       = en_quad ? {2'b00,spi_dummy_wr_len[13:0]} : spi_dummy_wr_len;
406
                counter_tx_valid = 1'b1;
407
                ctrl_data_mux    = DATA_EMPTY;
408
                spi_en_tx        = 1'b1;
409 21 dinesha
                spi_clock_en     = tx_clk_en;
410
                state_next       = DUMMY_TX;
411 18 dinesha
              end
412
              else
413
              begin
414
                counter_tx       = spi_data_len;
415
                counter_tx_valid = 1'b1;
416
                ctrl_data_mux    = DATA_FIFO;
417
                ctrl_data_valid  = 1'b1;
418
                spi_en_tx        = 1'b1;
419 21 dinesha
                spi_clock_en     = tx_clk_en;
420 18 dinesha
                state_next       = DATA_TX;
421
              end
422
            end
423
          end
424
          else
425
          begin
426
            spi_en_tx  = 1'b1;
427
            state_next = WAIT_EDGE;
428
          end
429
        end
430
        else
431
        begin
432
          spi_en_tx  = 1'b1;
433
          state_next = CMD;
434
        end
435
      end
436
 
437
      ADDR:
438
      begin
439
        spi_en_tx     = 1'b1;
440
        spi_status[2] = 1'b1;
441
        spi_cs        = 1'b0;
442
        spi_clock_en  = 1'b1;
443
        s_spi_mode    = (en_quad) ? SPI_QUAD_TX : SPI_STD;
444
 
445 21 dinesha
        if (tx_done && spi_fall)
446 18 dinesha
        begin
447
          if (spi_mode_cmd_enb != 0)
448
          begin
449
            s_spi_mode = (spi_qrd | spi_qwr) ? SPI_QUAD_TX : SPI_STD;
450
            counter_tx       = {8'h0,8'h8};
451
            counter_tx_valid = 1'b1;
452
            ctrl_data_mux    = DATA_MODE;
453
            ctrl_data_valid  = 1'b1;
454
            spi_en_tx        = 1'b1;
455
            state_next       = MODE;
456
          end
457
          else if (spi_data_len != 0)
458
          begin
459
            if (do_rx)
460
            begin
461
              s_spi_mode = (en_quad) ? SPI_QUAD_RX : SPI_STD;
462
              if(spi_dummy_rd_len != 0)
463
              begin
464 21 dinesha
                counter_rx       = en_quad ? {2'b00,spi_dummy_rd_len[13:0]} : spi_dummy_rd_len;
465
                counter_rx_valid = 1'b1;
466
                spi_en_rx        = 1'b1;
467 18 dinesha
                ctrl_data_mux    = DATA_EMPTY;
468 21 dinesha
                spi_clock_en     = rx_clk_en;
469
                state_next       = DUMMY_RX;
470 18 dinesha
              end
471
              else
472
              begin
473
                counter_rx       = spi_data_len;
474
                counter_rx_valid = 1'b1;
475
                spi_en_rx        = 1'b1;
476 21 dinesha
                spi_clock_en     = rx_clk_en;
477 18 dinesha
                state_next       = DATA_RX;
478
              end
479
            end
480
            else
481
            begin
482
              s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
483
              spi_en_tx  = 1'b1;
484
 
485
              if(spi_dummy_wr_len != 0) begin
486
                counter_tx       = en_quad ? {2'b00,spi_dummy_wr_len[13:0]} : spi_dummy_wr_len;
487
                counter_tx_valid = 1'b1;
488
                ctrl_data_mux    = DATA_EMPTY;
489 21 dinesha
                spi_clock_en     = tx_clk_en;
490
                state_next       = DUMMY_TX;
491 18 dinesha
              end else begin
492
                counter_tx       = spi_data_len;
493
                counter_tx_valid = 1'b1;
494
                ctrl_data_mux    = DATA_FIFO;
495
                ctrl_data_valid  = 1'b1;
496 21 dinesha
                spi_clock_en     = tx_clk_en;
497 18 dinesha
                state_next       = DATA_TX;
498
              end
499
            end
500
          end
501
          else
502
          begin
503
            state_next = WAIT_EDGE;
504
          end
505
        end
506
      end
507
 
508
      MODE:
509
      begin
510
        spi_en_tx     = 1'b1;
511
        spi_status[3] = 1'b1;
512
        spi_cs        = 1'b0;
513
        spi_clock_en  = 1'b1;
514
        s_spi_mode    = (en_quad) ? SPI_QUAD_TX : SPI_STD;
515 21 dinesha
        if (tx_done && spi_fall)
516 18 dinesha
        begin
517
          if (spi_data_len != 0)
518
          begin
519
            if (do_rx)
520
            begin
521
              s_spi_mode = (en_quad) ? SPI_QUAD_RX : SPI_STD;
522
              if(spi_dummy_rd_len != 0)
523
              begin
524 21 dinesha
                counter_rx       = en_quad ? {2'b00,spi_dummy_rd_len[13:0]} : spi_dummy_rd_len;
525
                counter_rx_valid = 1'b1;
526
                spi_en_rx        = 1'b1;
527 18 dinesha
                ctrl_data_mux    = DATA_EMPTY;
528 21 dinesha
                spi_clock_en     = rx_clk_en;
529
                state_next       = DUMMY_RX;
530 18 dinesha
              end
531
              else
532
              begin
533
                counter_rx       = spi_data_len;
534
                counter_rx_valid = 1'b1;
535
                spi_en_rx        = 1'b1;
536 21 dinesha
                spi_clock_en     = rx_clk_en;
537 18 dinesha
                state_next       = DATA_RX;
538
              end
539
            end
540
            else
541
            begin
542
              s_spi_mode = (en_quad) ? SPI_QUAD_TX : SPI_STD;
543
              spi_en_tx  = 1'b1;
544
 
545
              if(spi_dummy_wr_len != 0) begin
546
                counter_tx       = en_quad ? {2'b00,spi_dummy_wr_len[13:0]} : spi_dummy_wr_len;
547
                counter_tx_valid = 1'b1;
548
                ctrl_data_mux    = DATA_EMPTY;
549 21 dinesha
                spi_clock_en     = tx_clk_en;
550
                state_next       = DUMMY_TX;
551 18 dinesha
              end else begin
552
                counter_tx       = spi_data_len;
553
                counter_tx_valid = 1'b1;
554
                ctrl_data_mux    = DATA_FIFO;
555
                ctrl_data_valid  = 1'b1;
556 21 dinesha
                spi_clock_en     = tx_clk_en;
557 18 dinesha
                state_next       = DATA_TX;
558
              end
559
            end
560
          end
561
          else
562
          begin
563
            state_next = WAIT_EDGE;
564
          end
565
        end
566
      end
567
 
568 21 dinesha
      DUMMY_TX:
569 18 dinesha
      begin
570
        spi_en_tx     = 1'b1;
571
        spi_status[4] = 1'b1;
572
        spi_cs        = 1'b0;
573
        spi_clock_en  = 1'b1;
574
        s_spi_mode    = (en_quad) ? SPI_QUAD_RX : SPI_STD;
575
 
576 21 dinesha
        if (tx_done && spi_fall) begin
577 18 dinesha
          if (spi_data_len != 0) begin
578
            if (do_rx) begin
579
              counter_rx       = spi_data_len;
580
              counter_rx_valid = 1'b1;
581
              spi_en_rx        = 1'b1;
582 21 dinesha
              spi_clock_en     = rx_clk_en;
583 18 dinesha
              state_next       = DATA_RX;
584
            end else begin
585
              counter_tx       = spi_data_len;
586
              counter_tx_valid = 1'b1;
587
              s_spi_mode       = (en_quad) ? SPI_QUAD_TX : SPI_STD;
588
 
589
              spi_clock_en     = tx_clk_en;
590
              spi_en_tx        = 1'b1;
591
              state_next       = DATA_TX;
592
            end
593
          end
594
          else
595
          begin
596
            eot        = 1'b1;
597
            state_next = WAIT_EDGE;
598
          end
599
        end
600
        else
601
        begin
602
          ctrl_data_mux = DATA_EMPTY;
603
          spi_en_tx     = 1'b1;
604 21 dinesha
          state_next    = DUMMY_TX;
605 18 dinesha
        end
606
      end
607
 
608 21 dinesha
      DUMMY_RX:
609
      begin
610
        spi_en_rx     = 1'b1;
611
        spi_status[5] = 1'b1;
612
        spi_cs        = 1'b0;
613
        spi_clock_en  = 1'b1;
614
        s_spi_mode    = (en_quad) ? SPI_QUAD_RX : SPI_STD;
615
 
616
        if (rx_done && spi_rise) begin
617
          if (spi_data_len != 0) begin
618
            if (do_rx) begin
619
              counter_rx       = spi_data_len;
620
              counter_rx_valid = 1'b1;
621
              spi_en_rx        = 1'b1;
622
              spi_clock_en     = rx_clk_en;
623
              state_next       = DATA_RX;
624
            end else begin
625
              counter_tx       = spi_data_len;
626
              counter_tx_valid = 1'b1;
627
              s_spi_mode       = (en_quad) ? SPI_QUAD_TX : SPI_STD;
628
 
629
              spi_clock_en     = tx_clk_en;
630
              spi_en_tx        = 1'b1;
631
              state_next       = DATA_TX;
632
            end
633
          end
634
          else
635
          begin
636
            eot        = 1'b1;
637
            state_next = WAIT_EDGE;
638
          end
639
        end
640
        else
641
        begin
642
          ctrl_data_mux = DATA_EMPTY;
643
          spi_en_tx     = 1'b1;
644
          spi_clock_en  = rx_clk_en;
645
          state_next    = DUMMY_RX;
646
        end
647
      end
648 18 dinesha
      DATA_TX:
649
      begin
650 21 dinesha
        spi_status[6]    = 1'b1;
651 18 dinesha
        spi_cs           = 1'b0;
652
        spi_clock_en     = tx_clk_en;
653
        ctrl_data_mux    = DATA_FIFO;
654
        spi_en_tx        = 1'b1;
655
        s_spi_mode       = (en_quad) ? SPI_QUAD_TX : SPI_STD;
656
 
657 21 dinesha
        if (tx_done && spi_fall) begin
658 18 dinesha
          eot          = 1'b1;
659
          state_next   = WAIT_EDGE;
660
          spi_clock_en = 1'b0;
661
        end else begin
662
          state_next = DATA_TX;
663
        end
664
      end
665
 
666
      DATA_RX:
667
      begin
668 21 dinesha
        spi_status[7] = 1'b1;
669 18 dinesha
        spi_cs        = 1'b0;
670
        spi_clock_en  = rx_clk_en;
671
        s_spi_mode    = (en_quad) ? SPI_QUAD_RX : SPI_STD;
672
 
673 21 dinesha
        if (rx_done && spi_rise) begin
674 18 dinesha
          state_next = WAIT_EDGE;
675
        end else begin
676
          spi_en_rx  = 1'b1;
677
          state_next = DATA_RX;
678
        end
679
      end
680
      WAIT_EDGE:
681
      begin
682 21 dinesha
        spi_status[8] = 1'b1;
683 18 dinesha
        spi_cs        = 1'b0;
684
        spi_clock_en  = 1'b0;
685
        s_spi_mode    = (en_quad) ? SPI_QUAD_RX : SPI_STD;
686
        eot           = 1'b1;
687
        state_next    = IDLE;
688
      end
689
    endcase
690
  end
691
 
692 21 dinesha
assign  spi_ack = ((spi_req ==1) && (state == WAIT_EDGE)) ? 1'b1 : 1'b0;
693 18 dinesha
 
694
 
695
  always_ff @(posedge clk, negedge rstn)
696
  begin
697
    if (rstn == 1'b0)
698
    begin
699
      state       <= IDLE;
700
      en_quad_int <= 1'b0;
701
      do_rx       <= 1'b0;
702
      do_tx       <= 1'b0;
703
      spi_mode    <= SPI_QUAD_RX;
704
    end
705
    else
706
    begin
707
       state <= state_next;
708
       spi_mode <= s_spi_mode;
709
      if (spi_qrd || spi_qwr)
710
        en_quad_int <= 1'b1;
711
      else if (state_next == IDLE)
712
        en_quad_int <= 1'b0;
713
 
714
      if (spi_rd || spi_qrd)
715
      begin
716
        do_rx <= 1'b1;
717
        do_tx <= 1'b0;
718
      end
719
      else if (spi_wr || spi_qwr)
720
      begin
721
        do_rx <= 1'b0;
722
        do_tx <= 1'b1;
723
      end
724
      else if (state_next == IDLE)
725
      begin
726
        do_rx <= 1'b0;
727
        do_tx <= 1'b0;
728
      end
729
    end
730
  end
731
 
732
  assign spi_csn0 = ~spi_csreg[0] | spi_cs;
733
  assign spi_csn1 = ~spi_csreg[1] | spi_cs;
734
  assign spi_csn2 = ~spi_csreg[2] | spi_cs;
735
  assign spi_csn3 = ~spi_csreg[3] | spi_cs;
736
 
737
endmodule
738
 

powered by: WebSVN 2.1.0

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