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 40

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

powered by: WebSVN 2.1.0

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