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 17

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

powered by: WebSVN 2.1.0

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