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 38

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

powered by: WebSVN 2.1.0

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