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

Subversion Repositories spi_boot

[/] [spi_boot/] [trunk/] [rtl/] [vhdl/] [spi_boot.vhd] - Blame information for rev 8

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

Line No. Rev Author Line
1 3 arniml
-------------------------------------------------------------------------------
2
--
3
-- SD/MMC Bootloader
4
--
5 8 arniml
-- $Id: spi_boot.vhd,v 1.2 2005-02-13 17:25:51 arniml Exp $
6 3 arniml
--
7
-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org)
8
--
9
-- All rights reserved, see COPYING.
10
--
11
-- Redistribution and use in source and synthezised forms, with or without
12
-- modification, are permitted provided that the following conditions are met:
13
--
14
-- Redistributions of source code must retain the above copyright notice,
15
-- this list of conditions and the following disclaimer.
16
--
17
-- Redistributions in synthesized form must reproduce the above copyright
18
-- notice, this list of conditions and the following disclaimer in the
19
-- documentation and/or other materials provided with the distribution.
20
--
21
-- Neither the name of the author nor the names of other contributors may
22
-- be used to endorse or promote products derived from this software without
23
-- specific prior written permission.
24
--
25
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
29
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
-- POSSIBILITY OF SUCH DAMAGE.
36
--
37
-- Please report bugs to the author, but before you do so, please
38
-- make sure that this is not a derivative work and that
39
-- you have the latest version of this file.
40
--
41
-- The latest version of this file can be found at:
42
--      http://www.opencores.org/projects.cgi/web/spi_boot/overview
43
--
44
-------------------------------------------------------------------------------
45
 
46
library ieee;
47
use ieee.std_logic_1164.all;
48
 
49
 
50
entity spi_boot is
51
 
52
  generic (
53
    -- width of bit counter: minimum 6, maximum 12
54
    width_bit_cnt_g      : integer := 6;
55
    -- width of set counter: minimum 0, maximum n
56
    width_set_cnt_g      : integer := 2;
57
    -- number of bits required to address one set
58
    num_bits_per_set_g   : integer := 18;
59
    -- SD specific initialization
60
    sd_init_g            : integer := 0;
61
    -- clock divider to reach 400 kHz for MMC compatibility
62
    mmc_compat_clk_div_g : integer := 0;
63
    width_mmc_clk_div_g  : integer := 0;
64
    -- active level of reset_i
65
    reset_level_g        : integer := 0
66
  );
67
 
68
  port (
69
    -- System Interface -------------------------------------------------------
70
    clk_i          : in  std_logic;
71
    reset_i        : in  std_logic;
72
    -- Card Interface ---------------------------------------------------------
73
    spi_clk_o      : out std_logic;
74
    spi_cs_n_o     : out std_logic;
75
    spi_data_in_i  : in  std_logic;
76
    spi_data_out_o : out std_logic;
77
    -- FPGA Configuration Interface -------------------------------------------
78
    start_i        : in  std_logic;
79
    mode_i         : in  std_logic;
80
    config_n_o     : out std_logic;
81
    cfg_init_n_i   : in  std_logic;
82
    cfg_done_i     : in  std_logic;
83
    dat_done_i     : in  std_logic;
84
    cfg_clk_o      : out std_logic;
85
    cfg_dat_o      : out std_logic
86
  );
87
 
88
end spi_boot;
89
 
90
 
91
library ieee;
92
use ieee.numeric_std.all;
93
use work.spi_boot_pack.all;
94
 
95
architecture rtl of spi_boot is
96
 
97
  component spi_counter
98
    generic (
99
      cnt_width_g   : integer := 4;
100
      cnt_max_g     : integer := 15;
101
      reset_level_g : integer := 0
102
    );
103
    port (
104
      clk_i      : in  std_logic;
105
      reset_i    : in  std_logic;
106
      cnt_en_i   : in  boolean;
107
      cnt_o      : out std_logic_vector(cnt_width_g-1 downto 0);
108
      cnt_ovfl_o : out boolean
109
    );
110
  end component;
111
 
112
 
113
  -----------------------------------------------------------------------------
114
  -- States of the controller FSM
115
  --
116
  type ctrl_states_t is (POWER_UP1, POWER_UP2,
117
                         CMD0,
118
                         CMD1,
119
                         CMD55, ACMD41,
120
                         CMD16,
121
                         WAIT_START,
122
                         WAIT_INIT_LOW, WAIT_INIT_HIGH,
123
                         CMD18, CMD18_DATA,
124
                         CMD12,
125
                         INC_SET_CNT);
126
  --
127
  signal ctrl_fsm_q,
128
         ctrl_fsm_s  : ctrl_states_t;
129
  --
130
  -----------------------------------------------------------------------------
131
 
132
  -----------------------------------------------------------------------------
133
  -- States of the command FSM
134
  --
135
  type cmd_states_t is (CMD, START, R1, PAUSE);
136
  --
137
  signal cmd_fsm_q,
138
         cmd_fsm_s  : cmd_states_t;
139
  --
140
  -----------------------------------------------------------------------------
141
 
142
  subtype op_r     is integer range 5 downto 0;
143
  type    res_bc_t is (NONE, RES_MAX, RES_47, RES_15, RES_7);
144
  signal  bit_cnt_q  : unsigned(width_bit_cnt_g-1 downto 0);
145
  signal  res_bc_s   : res_bc_t;
146
  signal  upper_bitcnt_zero_s : boolean;
147
 
148
  signal cfg_dat_q : std_logic;
149
 
150
  signal spi_clk_q         : std_logic;
151
  signal spi_clk_rising_q  : boolean;
152
  signal spi_clk_falling_q : boolean;
153
  signal spi_dat_q,
154
         spi_dat_s         : std_logic;
155
  signal spi_cs_n_q,
156
         spi_cs_n_s        : std_logic;
157
 
158
  signal cfg_clk_q      : std_logic;
159
 
160
  signal start_q        : std_logic;
161
 
162
  signal set_cnt_s      : std_logic_vector(width_set_cnt_g downto 0);
163
  signal cnt_en_set_s   : boolean;
164
  signal mmc_cnt_ovfl_s : boolean;
165
  signal mmc_compat_s   : boolean;
166
 
167
  signal cmd_finished_s : boolean;
168
 
169
  signal r1_result_q    : std_logic;
170
  signal done_q,
171
         send_cmd12_q   : boolean;
172
 
173
  signal true_s         : boolean;
174
 
175
begin
176
 
177
  true_s <= true;
178
 
179
  -----------------------------------------------------------------------------
180
  -- Process seq
181
  --
182
  -- Purpose:
183
  --   Implements several sequential elements.
184
  --
185
  seq: process (clk_i, reset_i)
186
 
187
    variable bit_cnt_v : unsigned(1 downto 0);
188
 
189
  begin
190
    if reset_i = reset_level_g then
191
      -- reset bit counter to 63 for power up
192
      bit_cnt_q       <= (others => '0');
193
      bit_cnt_q(op_r) <= "111111";
194
      spi_dat_q    <= '1';
195
      spi_cs_n_q   <= '1';
196
      cfg_dat_q    <= '1';
197
      start_q      <= '0';
198
      done_q       <= false;
199
      send_cmd12_q <= false;
200
      ctrl_fsm_q   <= POWER_UP1;
201
      cmd_fsm_q    <= CMD;
202
      r1_result_q  <= '0';
203
 
204
    elsif clk_i'event and clk_i = '1' then
205
      -- bit counter control
206
      if spi_clk_rising_q then
207
        case res_bc_s is
208
          when NONE =>
209
            bit_cnt_q       <= bit_cnt_q - 1;
210
          when RES_MAX =>
211
            bit_cnt_q       <= (others => '1');
212
          when RES_47 =>
213
            bit_cnt_q       <= (others => '0');
214
            bit_cnt_q(op_r) <= "101111";
215
          when RES_15 =>
216
            bit_cnt_q       <= (others => '0');
217
            bit_cnt_q(op_r) <= "001111";
218
          when RES_7 =>
219
            bit_cnt_q       <= (others => '0');
220
            bit_cnt_q(op_r) <= "000111";
221
          when others =>
222
            bit_cnt_q       <= (others => '0');
223
        end case;
224
      end if;
225
 
226
      -- Card data output register
227
      -- spi_clk_falling_q acts as enable during MMC clock compatibility mode.
228
      -- As soon as this mode is left, the register must start latching.
229
      -- There is no explicit relation to spi_clk_q anymore in normal mode.
230
      -- Instead, spi_dat_s is operated by bit_cnt_q above which changes its
231
      -- value after the rising edge of spi_clk_q.
232
      --   -> spi_dat_q changes upon falling edge of spi_clk_q
233
      if spi_clk_falling_q or not mmc_compat_s then
234
        spi_dat_q <= spi_dat_s;
235
      end if;
236
 
237
      -- config data output register
238
      -- a new value is loaded when config clock is high,
239
      -- i.e. input data is sampled with rising spi_clk
240
      -- while output value changes on falling edge of cfg_clk
241
      if cfg_clk_q = '1' and spi_clk_rising_q then
242
        cfg_dat_q <= spi_data_in_i;
243
      end if;
244
 
245
      -- Controller FSM state
246
      ctrl_fsm_q <= ctrl_fsm_s;
247
 
248
      -- Command FSM state
249
      cmd_fsm_q <= cmd_fsm_s;
250
 
251
      -- CS signal for SPI card
252
      if spi_clk_q = '1' then
253
        spi_cs_n_q <= spi_cs_n_s;
254
      end if;
255
 
256
      -- Extract flags from R1 response
257
      if cmd_fsm_q = R1 then
258
        bit_cnt_v := bit_cnt_q(1 downto 0);
259
        case bit_cnt_v(1 downto 0) is
260
          when "10" =>
261
            -- always save "Illegal Command" flag
262
            r1_result_q <= to_X01(spi_data_in_i);
263
          when "00" =>
264
            -- overwrite with "Idle State" flag when not in CMD55
265
            if ctrl_fsm_q /= CMD55 then
266
              r1_result_q <= to_X01(spi_data_in_i);
267
            end if;
268
          when others =>
269
            null;
270
        end case;
271
      end if;
272
 
273
      -- Start trigger register for rising edge detection
274
      -- the reset value is '0' thus a rising edge will always be detected
275
      -- after reset even though start_i is tied to '1'
276
      if start_i = '0' then
277
        start_q <= '0';
278 8 arniml
      elsif ctrl_fsm_q = WAIT_START and cmd_finished_s then
279 3 arniml
        start_q <= start_i;
280
      end if;
281
 
282
      -- Marker for cfg_done and dat_done
283
      if ctrl_fsm_q = CMD18_DATA then
284 8 arniml
        if cfg_done_i = '1' and dat_done_i = '1' then
285 3 arniml
          done_q       <= true;
286
        end if;
287
 
288
        if done_q and
289
           (not upper_bitcnt_zero_s or cmd_fsm_q = START) then
290
          -- activate sending of CMD12 when it is safe:
291
          -- * upper bits of bit counter are not zero
292
          --   -> transmission of CMD12 is not running
293
          -- * cmd FSM is in START state
294
          --   -> also no transmission running
295
          send_cmd12_q <= true;
296
        end if;
297
      elsif ctrl_fsm_q = WAIT_START then
298
        -- reset done_q when WAIT_START has been reached
299
        -- this is necessary to let the stop transmission process come to
300
        -- an end without interruption or generation of unwanted cfg_clk_q
301
        done_q         <= false;
302
        send_cmd12_q   <= false;
303
      end if;
304
 
305
    end if;
306
 
307
  end process seq;
308
  --
309
  -----------------------------------------------------------------------------
310
 
311
 
312
  -----------------------------------------------------------------------------
313
  -- Process upper_bits
314
  --
315
  -- Purpose:
316
  --   Detects that the upper bits of the bit counter are zero.
317
  --   Upper bits = n downto 6, i.e. the optional part that is not required for
318
  --   commands but for extension of data blocks.
319
  --
320
  upper_bits: process (bit_cnt_q)
321
    variable zero_v : boolean;
322
  begin
323
 
324
    zero_v     := true;
325
    for i in bit_cnt_q'high downto 6 loop
326
      if bit_cnt_q(i) = '1' then
327
        zero_v := false;
328
      end if;
329
    end loop;
330
 
331
    upper_bitcnt_zero_s <= zero_v;
332
 
333
  end process upper_bits;
334
  --
335
  -----------------------------------------------------------------------------
336
 
337
 
338
  -----------------------------------------------------------------------------
339
  -- Process clk_gen
340
  --
341
  -- Purpose:
342
  --   Generates clocks for card and FPGA configuration.
343
  --   The card clock is free running with a divide by two of clk_i.
344
  --   The clock for FPGA config has an enable and is stopped on high level.
345
  --   There is a phase shift of half a period between spi_clk and cfg_clk.
346
  --
347
  clk_gen: process (clk_i, reset_i)
348
  begin
349
    if reset_i = reset_level_g then
350
      spi_clk_q        <= '0';
351
      cfg_clk_q        <= '1';
352
 
353
    elsif clk_i'event and clk_i = '1' then
354
 
355
      -- spi_clk_q rises according to the flag
356
      -- it falls with overflow indication
357
      -- the resulting duty cycle is not exactly 50:50,
358
      -- high time is a bit longer
359
      if mmc_compat_s then
360
        -- MMC clock compatibility mode:
361
        -- spi_clk_q rises when flagged by spi_clk_rising_q
362
        if spi_clk_rising_q then
363
          spi_clk_q <= '1';
364
        elsif mmc_cnt_ovfl_s then
365
          -- upon counter overflow spi_clk_q falls in case it does not rise
366
          spi_clk_q <= '0';
367
        end if;
368
      else
369
        -- normal mode
370
        -- spi_clk_q follows spi_clk_rising_q
371
        if spi_clk_rising_q then
372
          spi_clk_q <= '1';
373
        else
374
          spi_clk_q <= '0';
375
        end if;
376
      end if;
377
 
378
      -- clock for FPGA config must be enabled and follows spi_clk
379
      if ctrl_fsm_q = CMD18_DATA and cmd_fsm_q = CMD and
380
         not done_q then
381
        cfg_clk_q <= spi_clk_q;
382
      else
383
        cfg_clk_q <= '1';
384
      end if;
385
 
386
    end if;
387
 
388
  end process clk_gen;
389
  --
390
  -----------------------------------------------------------------------------
391
 
392
 
393
  -----------------------------------------------------------------------------
394
  -- Indication flags for rising and falling spi_clk_q.
395
  -- Essential for MMC clock compatibility mode.
396
  -----------------------------------------------------------------------------
397
  mmc_comap: if mmc_compat_clk_div_g > 0 generate
398
    mmc_compat_sig: process (clk_i, reset_i)
399
    begin
400
      if reset_i = reset_level_g then
401
        spi_clk_rising_q  <= false;
402
        spi_clk_falling_q <= false;
403
 
404
      elsif clk_i'event and clk_i = '1' then
405
        if mmc_compat_s then
406
          -- MMC clock compatibility mode:
407
          -- spi_clk_rising_q is an impulse right before rising edge of spi_clk_q
408
          -- spi_clk_falling_q is an impulse right before falling edge of spi_clk_q
409
          if mmc_cnt_ovfl_s then
410
            spi_clk_rising_q  <= spi_clk_q = '0';
411
            spi_clk_falling_q <= spi_clk_q = '1';
412
          else
413
            spi_clk_rising_q  <= false;
414
            spi_clk_falling_q <= false;
415
          end if;
416
        else
417
          -- normal mode
418
          spi_clk_rising_q  <= not spi_clk_rising_q;
419
          spi_clk_falling_q <= true;
420
        end if;
421
 
422
      end if;
423
    end process mmc_compat_sig;
424
  end generate;
425
 
426
  no_mmc_compat: if mmc_compat_clk_div_g = 0 generate
427
    -- SPI clock rising whenever spi_clk_q is '0'
428
    spi_clk_rising_q  <= spi_clk_q = '0';
429
    -- SPI clock falling whenever spi_clk_q is '1'
430
    spi_clk_falling_q <= spi_clk_q = '1';
431
  end generate;
432
 
433
 
434
  -----------------------------------------------------------------------------
435
  -- Process ctrl_fsm
436
  --
437
  -- Purpose:
438
  --   Implements the controller FSM.
439
  --
440
  ctrl_fsm: process (ctrl_fsm_q,
441
                     cmd_finished_s, r1_result_q,
442
                     start_i, start_q, mode_i,
443
                     cfg_init_n_i)
444
 
445
    variable mmc_compat_v : boolean;
446
 
447
  begin
448
    -- default assignments
449
    ctrl_fsm_s   <= POWER_UP1;
450
    config_n_o   <= '1';
451
    cnt_en_set_s <= false;
452
    spi_cs_n_s   <= '0';
453
    mmc_compat_v := false;
454
 
455
    case ctrl_fsm_q is
456
      -- Let card finish power up, step 1 -------------------------------------
457
      when POWER_UP1 =>
458
        mmc_compat_v := true;
459
        spi_cs_n_s   <= '1';
460
        if cmd_finished_s then
461
          ctrl_fsm_s <= POWER_UP2;
462
        else
463
          ctrl_fsm_s <= POWER_UP1;
464
        end if;
465
 
466
 
467
      -- Let card finish power up, step 2 -------------------------------------
468
      when POWER_UP2 =>
469
        mmc_compat_v := true;
470
        if cmd_finished_s then
471
          ctrl_fsm_s <= CMD0;
472
        else
473
          spi_cs_n_s <= '1';
474
          ctrl_fsm_s <= POWER_UP2;
475
        end if;
476
 
477
 
478
      -- Issue CMD0: GO_IDLE_STATE --------------------------------------------
479
      when CMD0 =>
480
        mmc_compat_v   := true;
481
        if cmd_finished_s then
482
          if sd_init_g = 1 then
483
            ctrl_fsm_s <= CMD55;
484
          else
485
            ctrl_fsm_s <= CMD1;
486
          end if;
487
        else
488
          ctrl_fsm_s   <= CMD0;
489
        end if;
490
 
491
 
492
      -- Issue CMD55: APP_CMD -------------------------------------------------
493
      when CMD55 =>
494
        if sd_init_g = 1 then
495
 
496
          mmc_compat_v   := true;
497
          if cmd_finished_s then
498
            if r1_result_q = '0' then
499
              -- command accepted, it's an SD card
500
              ctrl_fsm_s <= ACMD41;
501
            else
502
              -- command rejected, it's an MMC card
503
              ctrl_fsm_s <= CMD1;
504
            end if;
505
          else
506
            ctrl_fsm_s   <= CMD55;
507
          end if;
508
 
509
        end if;
510
 
511
 
512
      -- Issue ACMD41: SEND_OP_COND -------------------------------------------
513
      when ACMD41 =>
514
        if sd_init_g = 1 then
515
 
516
          mmc_compat_v   := true;
517
          if cmd_finished_s then
518
            if r1_result_q = '0' then
519
              ctrl_fsm_s <= CMD16;
520
            else
521
              ctrl_fsm_s <= CMD55;
522
            end if;
523
          else
524
            ctrl_fsm_s   <= ACMD41;
525
          end if;
526
 
527
        end if;
528
 
529
 
530
      -- Issue CMD1: SEND_OP_COND ---------------------------------------------
531
      when CMD1 =>
532
        mmc_compat_v   := true;
533
        if cmd_finished_s then
534
          if r1_result_q = '0' then
535
            ctrl_fsm_s <= CMD16;
536
          else
537
            ctrl_fsm_s <= CMD1;
538
          end if;
539
        else
540
          ctrl_fsm_s   <= CMD1;
541
        end if;
542
 
543
 
544
      -- Issue CMD16: SET_BLOCKLEN --------------------------------------------
545
      when CMD16 =>
546
        if cmd_finished_s then
547
          ctrl_fsm_s <= WAIT_START;
548
        else
549
          ctrl_fsm_s <= CMD16;
550
        end if;
551
 
552
 
553
      -- Wait for configuration start request ---------------------------------
554
      when WAIT_START =>
555
        spi_cs_n_s     <= '1';
556
 
557
        -- detect rising edge of start_i
558
        if start_i = '1' and start_q = '0' then
559
          -- decide which mode is requested
560
          if cmd_finished_s then
561
            if mode_i = '0' then
562
              ctrl_fsm_s <= CMD18;
563
            else
564
              ctrl_fsm_s <= WAIT_INIT_LOW;
565
            end if;
566
          else
567
            ctrl_fsm_s   <= WAIT_START;
568
          end if;
569
        else
570
          ctrl_fsm_s     <= WAIT_START;
571
        end if;
572
 
573
 
574
      -- Wait for INIT to become low ------------------------------------------
575
      when WAIT_INIT_LOW =>
576
        spi_cs_n_s   <= '1';
577
        -- activate FPGA configuration
578
        config_n_o   <= '0';
579
 
580
        if cfg_init_n_i = '0' then
581
          ctrl_fsm_s <= WAIT_INIT_HIGH;
582
        else
583
          ctrl_fsm_s <= WAIT_INIT_LOW;
584
        end if;
585
 
586
 
587
      -- Wait for INIT to become high -----------------------------------------
588
      when WAIT_INIT_HIGH =>
589
        spi_cs_n_s   <= '1';
590
 
591
        if cfg_init_n_i = '1' and cmd_finished_s then
592
          ctrl_fsm_s <= CMD18;
593
        else
594
          ctrl_fsm_s <= WAIT_INIT_HIGH;
595
        end if;
596
 
597
 
598
      -- Issue CMD18: READ_MULTIPLE_BLOCKS ------------------------------------
599
      when CMD18 =>
600
        if cmd_finished_s then
601
          ctrl_fsm_s <= CMD18_DATA;
602
        else
603
          ctrl_fsm_s <= CMD18;
604
        end if;
605
      --
606
      -- receive a data block
607
      when CMD18_DATA =>
608 8 arniml
        if cmd_finished_s then
609
          ctrl_fsm_s   <= CMD12;
610
        else
611
          ctrl_fsm_s   <= CMD18_DATA;
612
        end if;
613
 
614
 
615
       -- Issued CMD12: STOP_TRANSMISSION --------------------------------------
616
       when CMD12 =>
617 3 arniml
         if cmd_finished_s then
618 8 arniml
           ctrl_fsm_s <= INC_SET_CNT;
619 3 arniml
         else
620 8 arniml
           ctrl_fsm_s <= CMD12;
621 3 arniml
         end if;
622
 
623
 
624
      -- Increment Set Counter ------------------------------------------------
625
      when INC_SET_CNT =>
626
        spi_cs_n_s   <= '1';
627
        ctrl_fsm_s   <= WAIT_START;
628
        cnt_en_set_s <= true;
629
 
630
 
631
 
632
      when others =>
633
        null;
634
 
635
    end case;
636
 
637
    -- mmc_compat_s is suppressed if MMC clock compatibility is not required
638
    if mmc_compat_clk_div_g > 0 then
639
      mmc_compat_s <= mmc_compat_v;
640
    else
641
      mmc_compat_s <= false;
642
    end if;
643
 
644
  end process ctrl_fsm;
645
  --
646
  -----------------------------------------------------------------------------
647
 
648
 
649
  -----------------------------------------------------------------------------
650
  -- Process cmd_fsm
651
  --
652
  -- Purpose:
653
  --   Implements the command FSM.
654
  --
655
  cmd_fsm: process (spi_clk_rising_q,
656
                    spi_data_in_i,
657
                    bit_cnt_q,
658
                    ctrl_fsm_q,
659
                    cmd_fsm_q,
660
                    send_cmd12_q)
661
 
662
    variable cnt_zero_v     : boolean;
663
    variable spi_data_low_v : boolean;
664
    variable no_startbit_v  : boolean;
665
 
666
  begin
667
    -- default assignments
668
    cmd_finished_s <= false;
669
    cmd_fsm_s      <= CMD;
670
    res_bc_s       <= NONE;
671
 
672
    cnt_zero_v     := spi_clk_rising_q and bit_cnt_q = 0;
673
    spi_data_low_v := spi_clk_rising_q and spi_data_in_i = '0';
674
 
675
    -- these are no real commands thus there will be no startbit
676
    case ctrl_fsm_q is
677
      when POWER_UP1  | POWER_UP2 |
678
           WAIT_START | WAIT_INIT_HIGH | WAIT_INIT_LOW =>
679
        no_startbit_v := true;
680
      when others =>
681
        no_startbit_v := false;
682
    end case;
683
 
684
 
685
    case cmd_fsm_q is
686
      -- Send the command -----------------------------------------------------
687
      when CMD =>
688
        if cnt_zero_v then
689
          if ctrl_fsm_q /= CMD18_DATA then
690 8 arniml
            -- normal commands including CMD12 require startbit of R1 response
691 3 arniml
            cmd_fsm_s <= START;
692
          else
693 8 arniml
            if not send_cmd12_q then
694
              -- CMD18_DATA needs to read CRC
695
              cmd_fsm_s <= R1;
696
              res_bc_s <= RES_15;
697
            else
698
              -- CMD18_DATA finished, scan for startbit of response
699
              cmd_finished_s <= true;
700
              cmd_fsm_s      <= START;
701
            end if;
702 3 arniml
          end if;
703
        else
704
          cmd_fsm_s <= CMD;
705
        end if;
706
 
707
      -- Wait for startbit of response ----------------------------------------
708
      when START =>
709
        -- startbit detection or skip of this check
710
        if no_startbit_v and spi_clk_rising_q then
711
          cmd_fsm_s   <= R1;
712
          res_bc_s    <= RES_7;
713
        elsif spi_data_low_v then
714
          if ctrl_fsm_q /= CMD18_DATA then
715
            cmd_fsm_s <= R1;
716
          else
717
            -- CMD18_DATA startbit detected, read payload
718
            cmd_fsm_s <= CMD;
719
            res_bc_s  <= RES_MAX;
720
          end if;
721
        else
722
          cmd_fsm_s   <= START;
723
          res_bc_s    <= RES_7;
724
        end if;
725
 
726
      -- Read R1 response -----------------------------------------------------
727
      when R1 =>
728
        if cnt_zero_v then
729
          res_bc_s  <= RES_7;
730
 
731
          if not (ctrl_fsm_q = CMD18 or ctrl_fsm_q = CMD18_DATA) then
732
            cmd_fsm_s        <= PAUSE;
733
          else
734
            -- CMD18 needs another startbit detection for the data token.
735
            -- CMD18_DATA needs a startbit after having received the CRC, either
736
            --   * next data token
737
            --   * R1 response of CMD12
738
            cmd_fsm_s        <= START;
739
 
740 8 arniml
            if ctrl_fsm_q = CMD18 then
741
              -- CMD18 response received -> advance to CMD18_DATA
742 3 arniml
              cmd_finished_s <= true;
743
            end if;
744
          end if;
745
        else
746
          cmd_fsm_s <= R1;
747
        end if;
748
 
749
      -- PAUSE state -> required for Nrc, card response to host command -------
750
      when PAUSE =>
751
        if cnt_zero_v then
752
          cmd_fsm_s <= CMD;
753
          res_bc_s  <= RES_47;
754
          cmd_finished_s <= true;
755
        else
756
          cmd_fsm_s <= PAUSE;
757
        end if;
758
 
759
      when others =>
760
        null;
761
 
762
    end case;
763
 
764
  end process cmd_fsm;
765
  --
766
  -----------------------------------------------------------------------------
767
 
768
 
769
  -----------------------------------------------------------------------------
770
  -- Process transmit
771
  --
772
  -- Purpose:
773
  --   Generates the serial data output values based on the current FSM state
774
  --
775
  --   The local variable cmd_v is 64 bits wide in contrast to an SPI command
776
  --   with 48 bits. There are two reasons for this:
777
  --   * During "overlaid" sending of CMD12 in FSM state CMD18_DATA, the bit
778
  --     counter will start from 3F on its lowest 6 bits. Therefore, it is
779
  --     necessary to provide all 64 positions in cmd_v.
780
  --   * Reduces logic.
781
  --
782
  transmit: process (ctrl_fsm_q,
783
                     cmd_fsm_q,
784
                     bit_cnt_q,
785
                     set_cnt_s,
786
                     send_cmd12_q,
787
                     upper_bitcnt_zero_s)
788
 
789
    subtype cmd_r is natural range 47 downto 0;
790
    subtype cmd_t is std_logic_vector(cmd_r);
791
    subtype ext_cmd_t is std_logic_vector(63 downto 0);
792
    --                            STCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcccccccS
793
    constant cmd0_c   : cmd_t := "010000000000000000000000000000000000000010010101";
794 8 arniml
    constant cmd1_c   : cmd_t := "0100000100000000000000000000000000000000-------1";
795
    constant cmd12_c  : cmd_t := "0100110000000000000000000000000000000000-------1";
796 3 arniml
    constant cmd16_c  : cmd_t := "0101000000000000000000000000000000000000-------1";
797
    constant cmd18_c  : cmd_t := "0101001000000000000000000000000000000000-------1";
798 8 arniml
    constant cmd55_c  : cmd_t := "0111011100000000000000000000000000000000-------1";
799
    constant acmd41_c : cmd_t := "0110100100000000000000000000000000000000-------1";
800 3 arniml
 
801
    variable cmd_v      : ext_cmd_t;
802
    variable tx_v       : boolean;
803
 
804
  begin
805
    -- default assignments
806
    spi_dat_s    <= '1';
807
    cmd_v        := (others => '1');
808
    tx_v         := false;
809
 
810
    if cmd_fsm_q = CMD then
811
      case ctrl_fsm_q is
812
        when CMD0 =>
813
          cmd_v(cmd_r) := cmd0_c;
814
          tx_v := true;
815
        when CMD1 =>
816
          cmd_v(cmd_r) := cmd1_c;
817
          tx_v := true;
818
        when CMD16 =>
819
          cmd_v(cmd_r) := cmd16_c;
820
          cmd_v(8 + width_bit_cnt_g-3) := '1';
821
          tx_v := true;
822
        when CMD18 =>
823
          cmd_v(cmd_r) := cmd18_c;
824
          cmd_v(8 + num_bits_per_set_g + width_set_cnt_g downto 8 + num_bits_per_set_g)
825
            := set_cnt_s;
826
          tx_v := true;
827
        when CMD18_DATA =>
828
          cmd_v(cmd_r) := cmd12_c;
829
 
830
          if send_cmd12_q and upper_bitcnt_zero_s then
831
            tx_v := true;
832
          end if;
833
        when CMD55 =>
834
          cmd_v(cmd_r) := cmd55_c;
835
          tx_v := true;
836
        when ACMD41 =>
837
          cmd_v(cmd_r) := acmd41_c;
838
          tx_v := true;
839
 
840
        when others =>
841
          null;
842
      end case;
843
    end if;
844
 
845
    if tx_v then
846
      spi_dat_s <= cmd_v(to_integer(bit_cnt_q(5 downto 0)));
847
    end if;
848
 
849
  end process transmit;
850
  --
851
  -----------------------------------------------------------------------------
852
 
853
 
854
  -----------------------------------------------------------------------------
855
  -- Optional Set Counter
856
  -----------------------------------------------------------------------------
857
  set_cnt: if width_set_cnt_g > 0 generate
858
    set_cnt_b : spi_counter
859
      generic map (
860
        cnt_width_g   => width_set_cnt_g,
861
        cnt_max_g     => 2**width_set_cnt_g - 1,
862
        reset_level_g => reset_level_g
863
      )
864
      port map (
865
        clk_i         => clk_i,
866
        reset_i       => reset_i,
867
        cnt_en_i      => cnt_en_set_s,
868
        cnt_o         => set_cnt_s(width_set_cnt_g-1 downto 0),
869
        cnt_ovfl_o    => open
870
      );
871
    set_cnt_s(width_set_cnt_g) <= '0';
872
  end generate;
873
 
874
  no_set_cnt: if width_set_cnt_g = 0 generate
875
    set_cnt_s <= (others => '0');
876
  end generate;
877
 
878
 
879
  -----------------------------------------------------------------------------
880
  -- Optional MMC compatibility counter
881
  -----------------------------------------------------------------------------
882
  mmc_cnt: if mmc_compat_clk_div_g > 0 generate
883
    mmc_cnt_b : spi_counter
884
      generic map (
885
        cnt_width_g   => width_mmc_clk_div_g,
886
        cnt_max_g     => mmc_compat_clk_div_g,
887
        reset_level_g => reset_level_g
888
      )
889
      port map (
890
        clk_i         => clk_i,
891
        reset_i       => reset_i,
892
        cnt_en_i      => true_s,
893
        cnt_o         => open,
894
        cnt_ovfl_o    => mmc_cnt_ovfl_s
895
      );
896
  end generate;
897
 
898
  no_mmc_cnt: if mmc_compat_clk_div_g = 0 generate
899
    mmc_cnt_ovfl_s <= true;
900
  end generate;
901
 
902
 
903
  -----------------------------------------------------------------------------
904
  -- Output Mapping
905
  -----------------------------------------------------------------------------
906
  spi_clk_o      <= spi_clk_q;
907
  spi_cs_n_o     <= spi_cs_n_q;
908
  spi_data_out_o <= spi_dat_q;
909
  cfg_clk_o      <= cfg_clk_q;
910
  cfg_dat_o      <= cfg_dat_q;
911
 
912
end rtl;
913
 
914
 
915
-------------------------------------------------------------------------------
916
-- File History:
917
--
918
-- $Log: not supported by cvs2svn $
919 8 arniml
-- Revision 1.1  2005/02/08 20:41:33  arniml
920
-- initial check-in
921
--
922 3 arniml
-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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