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 60

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

powered by: WebSVN 2.1.0

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