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

Subversion Repositories spi_boot

[/] [spi_boot/] [trunk/] [bench/] [vhdl/] [card.vhd] - Blame information for rev 77

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 arniml
-------------------------------------------------------------------------------
2
--
3
-- SD/MMC Bootloader
4
-- Simple SD and MMC model
5
--
6 77 arniml
-- $Id: card.vhd 77 2009-04-01 19:53:14Z arniml $
7 4 arniml
--
8
-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org)
9
--
10
-- All rights reserved, see COPYING.
11
--
12
-- Redistribution and use in source and synthezised forms, with or without
13
-- modification, are permitted provided that the following conditions are met:
14
--
15
-- Redistributions of source code must retain the above copyright notice,
16
-- this list of conditions and the following disclaimer.
17
--
18
-- Redistributions in synthesized form must reproduce the above copyright
19
-- notice, this list of conditions and the following disclaimer in the
20
-- documentation and/or other materials provided with the distribution.
21
--
22
-- Neither the name of the author nor the names of other contributors may
23
-- be used to endorse or promote products derived from this software without
24
-- specific prior written permission.
25
--
26
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
28
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
30
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
-- POSSIBILITY OF SUCH DAMAGE.
37
--
38
-- Please report bugs to the author, but before you do so, please
39
-- make sure that this is not a derivative work and that
40
-- you have the latest version of this file.
41
--
42
-- The latest version of this file can be found at:
43
--      http://www.opencores.org/projects.cgi/web/spi_boot/overview
44
--
45
-------------------------------------------------------------------------------
46
 
47
library ieee;
48
use ieee.std_logic_1164.all;
49
 
50
 
51
entity card is
52
 
53
  generic (
54
    card_type_g  : string := "none";
55
    is_sd_card_g : integer := 1
56
  );
57
 
58
  port (
59
    spi_clk_i  : in  std_logic;
60
    spi_cs_n_i : in  std_logic;
61
    spi_data_i : in  std_logic;
62
    spi_data_o : out std_logic
63
  );
64
 
65
end card;
66
 
67
 
68
library ieee;
69
use ieee.numeric_std.all;
70
library std;
71
use std.textio.all;
72
 
73
use work.tb_pack.all;
74
 
75
architecture behav of card is
76
 
77
  signal power_on_n_s : std_logic;
78
  signal soft_res_n_s : std_logic;
79
  signal res_n_s      : std_logic;
80
 
81
  signal rx_s : std_logic_vector(47 downto 0);
82
 
83
  signal set_spi_mode_s,
84
         spi_mode_q       : boolean;
85
  signal set_idle_mode_s,
86
         poll_idle_mode_s : boolean;
87
  signal idle_mode_q      : natural;
88
 
89
  signal block_len_q,
90
         block_len_s     : unsigned(31 downto 0);
91
  signal set_block_len_s : boolean;
92
 
93
  signal new_read_addr_s,
94
         read_addr_q     : unsigned(31 downto 0);
95
  signal set_read_addr_s,
96
         inc_read_addr_s : boolean;
97
 
98
  signal cmd_spi_data_s,
99
         read_spi_data_s : std_logic;
100
  signal start_read_s    : boolean;
101
  signal reading_s       : boolean;
102
 
103
  procedure rise_clk is
104
  begin
105
    wait until spi_clk_i'event and to_X01(spi_clk_i) = '1';
106
  end rise_clk;
107
 
108
--  procedure rise_clk(num : natural) is
109
--  begin
110
--    for i in 1 to num loop
111
--      rise_clk;
112
--    end loop;
113
--  end rise_clk;
114
 
115
  procedure fall_clk is
116
  begin
117
    wait until spi_clk_i'event and to_X01(spi_clk_i) = '0';
118
  end fall_clk;
119
 
120
  procedure fall_clk(num : natural) is
121
  begin
122
    for i in 1 to num loop
123
      fall_clk;
124
    end loop;
125
  end fall_clk;
126
 
127
begin
128
 
129
  res_n_s <= power_on_n_s and soft_res_n_s;
130
 
131
  -----------------------------------------------------------------------------
132
  -- Power on reset
133
  -----------------------------------------------------------------------------
134
  por: process
135
  begin
136
    power_on_n_s <= '0';
137
    wait for 200 ns;
138
    power_on_n_s <= '1';
139
    wait;
140
  end process por;
141
 
142
 
143
  -----------------------------------------------------------------------------
144
  --
145
  ctrl: process
146
 
147
    function check_crc(payload : in std_logic_vector(47 downto 0))
148
      return boolean is
149
 
150
    begin
151
 
152
      return calc_crc(payload(47 downto 8)) = payload(7 downto 1);
153
    end check_crc;
154
 
155
    variable rx_v        : std_logic_vector(47 downto 0);
156
    variable cmd_v       : std_logic_vector( 5 downto 0);
157
    variable arg_v       : std_logic_vector(31 downto 0);
158
    variable crc_v       : std_logic_vector( 6 downto 0);
159
    variable wrong_v     : std_logic;
160
    variable read_data_v : boolean;
161
 
162
  begin
163
    rx_s <= (others => '0');
164
    set_spi_mode_s   <= false;
165
    set_idle_mode_s  <= false;
166
    poll_idle_mode_s <= false;
167
    cmd_spi_data_s   <= '1';
168
    soft_res_n_s     <= '1';
169
    set_block_len_s  <= false;
170
    block_len_s      <= (others => '0');
171
    new_read_addr_s  <= (others => '0');
172
    set_read_addr_s  <= false;
173
    start_read_s     <= false;
174
    read_data_v      := false;
175
 
176
    loop
177
 
178
      rise_clk;
179
      -- wait for startbit of command
180
      while to_X01(spi_data_i) = '1' loop
181
        rise_clk;
182
      end loop;
183
      rx_v(47) := '0';
184
 
185
      -- read remaining 47 bits of command
186
      for i in 46 downto 0 loop
187
        rise_clk;
188
        rx_v(i) := to_X01(spi_data_i);
189
      end loop;
190
      rx_s <= rx_v;
191
 
192
      -- dissect received data
193
      cmd_v := rx_v(45 downto 40);
194
      arg_v := rx_v(39 downto  8);
195
      crc_v := rx_v( 7 downto  1);
196
 
197
      assert spi_mode_q or check_crc(payload => rx_v)
198
        report "CRC mismatch"
199
        severity error;
200
 
201
      wrong_v     := '0';
202
      case cmd_v is
203
        -- CMD0: GO_IDLE_STATE ------------------------------------------------
204
        when "000000" =>
205
          set_spi_mode_s  <= true;
206
          set_idle_mode_s <= true;
207
        -- CMD1: SEND_OP_COND -------------------------------------------------
208
        when "000001" =>
209
          poll_idle_mode_s <= true;
210
        -- CMD12: STOP_TRANSMISSION -------------------------------------------
211
        when "001100" =>
212
          start_read_s <= false;
213
          read_data_v  := false;
214
        -- CMD16: SET_BLOCKLEN ------------------------------------------------
215
        when "010000" =>
216
          block_len_s     <= unsigned(arg_v);
217
          set_block_len_s <= true;
218
        -- CMD18: READ_MULTIPLE_BLOCK -----------------------------------------
219
        when "010010" =>
220
          new_read_addr_s <= unsigned(arg_v);
221
          set_read_addr_s <= true;
222
          read_data_v     := true;
223
        -- CMD55: APPL_CMD ----------------------------------------------------
224
        when "110111" =>
225
          -- command only available for SD card
226
          if is_sd_card_g /= 1 then
227
            wrong_v := '1';
228
          end if;
229
        -- ACMD41: SEND_OP_COND -----------------------------------------------
230
        when "101001" =>
231
          -- command only available for SD card
232
          if is_sd_card_g /= 1 then
233
            wrong_v := '1';
234
          else
235
            poll_idle_mode_s <= true;
236
          end if;
237
 
238
        when others =>
239
          wrong_v := '1';
240
          null;
241
      end case;
242
 
243
 
244
      -- spend some time before removing control signals
245
      fall_clk(2);
246
      poll_idle_mode_s <= false;
247
      set_idle_mode_s <= false;
248
      fall_clk(6);
249
      set_spi_mode_s  <= false;
250
      set_block_len_s <= false;
251
      set_read_addr_s <= false;
252
 
253
      if reading_s then
254
        wait until not reading_s;
255
      end if;
256
 
257
 
258
      -- wait for a total two "bytes" before sending out response
259
      for i in 1 to 8 loop
260
        fall_clk;
261
      end loop;
262
 
263
      for i in 7 downto 0 loop
264
        fall_clk;
265
        case i is
266
          when 2 =>
267
            cmd_spi_data_s <= wrong_v;
268
          when 0 =>
269
            if idle_mode_q = 0 then
270
              cmd_spi_data_s <= '0';
271
            else
272
              cmd_spi_data_s <= '1';
273
            end if;
274
          when others =>
275
            cmd_spi_data_s <= '0';
276
        end case;
277
      end loop;
278
      fall_clk;
279
      cmd_spi_data_s <= '1';
280
 
281
      -- transmit data if requested
282
      start_read_s <= read_data_v;
283
 
284
    end loop;
285
  end process ctrl;
286
  --
287
  -----------------------------------------------------------------------------
288
 
289
 
290
  -----------------------------------------------------------------------------
291
  --
292
  seq: process (res_n_s,
293
                spi_clk_i,
294
                set_spi_mode_s,
295
                set_idle_mode_s,
296
                poll_idle_mode_s,
297
                set_block_len_s,
298
                block_len_s)
299
 
300
  begin
301
    if res_n_s = '0' then
302
      spi_mode_q  <= false;
303
      idle_mode_q <= 5;
304
      block_len_q <= (others => '0');
305
      read_addr_q <= (others => '0');
306
 
307
    elsif spi_clk_i'event and spi_clk_i = '1' then
308
      if set_spi_mode_s then
309
        spi_mode_q  <= true;
310
      end if;
311
 
312
      if set_idle_mode_s then
313
        idle_mode_q  <= 5;
314
      elsif poll_idle_mode_s then
315
        if idle_mode_q > 0 then
316
          idle_mode_q <= idle_mode_q - 1;
317
        end if;
318
      end if;
319
 
320
      if set_block_len_s then
321
        block_len_q <= block_len_s;
322
      end if;
323
 
324
      if set_read_addr_s then
325
        read_addr_q <= new_read_addr_s;
326
      elsif inc_read_addr_s then
327
        read_addr_q <= read_addr_q + 1;
328
      end if;
329
 
330
    end if;
331
  end process seq;
332
  --
333
  -----------------------------------------------------------------------------
334
 
335
 
336
  -----------------------------------------------------------------------------
337
  --
338
  read_block: process
339
 
340
    variable t_v : unsigned(7 downto 0);
341
 
342
  begin
343
    -- default assignments
344
    inc_read_addr_s <= false;
345
    reading_s       <= false;
346
    read_spi_data_s <= '1';
347
 
348
    loop
349
      if not start_read_s then
350
        wait until start_read_s;
351
      end if;
352
 
353
      reading_s <= true;
354
 
355
      fall_clk(8);                    -- delay for one "byte"
356
 
357
      -- send data token
358
      fall_clk(7);                    -- 7 ones in a data token
359
      read_spi_data_s <= '0';
360
 
361
      -- send payload
362 6 arniml
      payload: for i in 0 to to_integer(block_len_q)-1 loop
363 4 arniml
        t_v := read_addr_q(0) & calc_crc(read_addr_q);
364
        for bit in 7 downto 0 loop
365
          fall_clk;
366
          read_spi_data_s <= t_v(bit);
367 6 arniml
 
368
          exit payload when not start_read_s;
369 4 arniml
        end loop;
370
        inc_read_addr_s <= true;
371
        rise_clk;
372
        inc_read_addr_s <= false;
373
        wait for 10 ns;
374
      end loop;
375
 
376 6 arniml
      if start_read_s then
377
        -- send crc
378
        for i in 0 to 15 loop
379
          fall_clk;
380
          t_v := to_unsigned(i, 8);
381
          read_spi_data_s <= t_v(0);
382
        end loop;
383 4 arniml
        fall_clk;
384 6 arniml
      end if;
385
 
386 4 arniml
      read_spi_data_s <= '1';
387
      reading_s <= false;
388
      -- loop for one "byte"
389
      fall_clk(8);
390
 
391
    end loop;
392
  end process read_block;
393
  --
394
  -----------------------------------------------------------------------------
395
 
396
 
397
  -----------------------------------------------------------------------------
398
  --
399
  clk_check: process (spi_clk_i)
400
 
401
    variable last_rising_v : time := 0 ns;
402
    variable dump_line     : line;
403
 
404
  begin
405
    if spi_clk_i'event and spi_clk_i = '1' then
406
      if is_sd_card_g = 0 and card_type_g /= "Minimal Chip" and
407
         idle_mode_q > 0 then
408
        if now - last_rising_v < 2.5 us and last_rising_v > 0 ns then
409
          write(dump_line, card_type_g);
410
          write(dump_line, string'(" @ "));
411
          write(dump_line, now);
412
          write(dump_line, string'(": Last rising edge of SPI clock "));
413
          write(dump_line, now - last_rising_v);
414
          write(dump_line, string'(" ago."));
415
          writeline(output, dump_line);
416
        end if;
417
 
418
        last_rising_v := now;
419
      end if;
420
    end if;
421
  end process clk_check;
422
  --
423
  -----------------------------------------------------------------------------
424
 
425
 
426
  -----------------------------------------------------------------------------
427
  -- Output Mapping
428
  -----------------------------------------------------------------------------
429
  spi_data_o <=   cmd_spi_data_s and read_spi_data_s
430
                when spi_cs_n_i = '0' else
431
                  'Z';
432
 
433
end behav;

powered by: WebSVN 2.1.0

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