URL
https://opencores.org/ocsvn/spi_boot/spi_boot/trunk
Subversion Repositories spi_boot
Compare Revisions
- This comparison shows the changes necessary to convert path
/spi_boot/trunk/bench/vhdl
- from Rev 42 to Rev 74
- ↔ Reverse comparison
Rev 42 → Rev 74
/tb_rl-c.vhd
0,0 → 1,27
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- |
-- $Id: tb_rl-c.vhd,v 1.1 2005-04-10 18:07:26 arniml Exp $ |
-- |
------------------------------------------------------------------------------- |
|
configuration tb_rl_behav_c0 of tb_rl is |
|
for behav |
|
for dut_b : chip |
use configuration work.chip_full_c0; |
end for; |
|
for card_b : card |
use configuration work.card_behav_c0; |
end for; |
|
for rl_b : ram_loader |
use configuration work.ram_loader_rtl_c0; |
end for; |
|
end for; |
|
end tb_rl_behav_c0; |
/tb_rl.vhd
0,0 → 1,256
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- Testbench for ram_loader |
-- |
-- $Id: tb_rl.vhd,v 1.1 2005-04-10 18:07:25 arniml Exp $ |
-- |
-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved, see COPYING. |
-- |
-- Redistribution and use in source and synthezised forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- |
-- Redistributions of source code must retain the above copyright notice, |
-- this list of conditions and the following disclaimer. |
-- |
-- Redistributions in synthesized form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution. |
-- |
-- Neither the name of the author nor the names of other contributors may |
-- be used to endorse or promote products derived from this software without |
-- specific prior written permission. |
-- |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
-- POSSIBILITY OF SUCH DAMAGE. |
-- |
-- Please report bugs to the author, but before you do so, please |
-- make sure that this is not a derivative work and that |
-- you have the latest version of this file. |
-- |
-- The latest version of this file can be found at: |
-- http://www.opencores.org/projects.cgi/web/spi_boot/overview |
-- |
------------------------------------------------------------------------------- |
|
entity tb_rl is |
|
end tb_rl; |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
|
architecture behav of tb_rl is |
|
component chip |
port ( |
clk_i : in std_logic; |
reset_i : in std_logic; |
set_sel_n_i : in std_logic_vector(3 downto 0); |
spi_clk_o : out std_logic; |
spi_cs_n_o : out std_logic; |
spi_data_in_i : in std_logic; |
spi_data_out_o : out std_logic; |
start_i : in std_logic; |
mode_i : in std_logic; |
config_n_o : out std_logic; |
detached_o : out std_logic; |
cfg_init_n_i : in std_logic; |
cfg_done_i : in std_logic; |
dat_done_i : in std_logic; |
cfg_clk_o : out std_logic; |
cfg_dat_o : out std_logic |
); |
end component; |
|
component card |
generic ( |
card_type_g : string := "none"; |
is_sd_card_g : integer := 1 |
); |
port ( |
spi_clk_i : in std_logic; |
spi_cs_n_i : in std_logic; |
spi_data_i : in std_logic; |
spi_data_o : out std_logic |
); |
end component; |
|
component ram_loader |
port ( |
clk_i : in std_logic; |
reset_i : in std_logic; |
lamp_o : out std_logic; |
cfg_clk_i : in std_logic; |
cfg_data_i : in std_logic; |
start_o : out std_logic; |
mode_o : out std_logic; |
done_o : out std_logic; |
detached_i : in std_logic; |
ram_addr_o : out std_logic_vector(15 downto 0); |
ram_data_b : out std_logic_vector( 7 downto 0); |
ram_ce_no : out std_logic_vector( 3 downto 0); |
ram_oe_no : out std_logic; |
ram_we_no : out std_logic |
); |
end component; |
|
constant period_c : time := 100 ns; |
constant rl_period_c : time := 20 ns; |
constant reset_level_c : integer := 0; |
|
signal clk_s : std_logic; |
signal rl_clk_s: std_logic; |
signal reset_s : std_logic; |
|
-- SPI interface signals |
signal spi_clk_s : std_logic; |
signal spi_data_to_card_s : std_logic; |
signal spi_data_from_card_s : std_logic; |
signal spi_cs_n_s : std_logic; |
|
-- config related signals |
signal start_s : std_logic; |
signal mode_s : std_logic; |
signal config_n_s : std_logic; |
signal cfg_init_n_s : std_logic; |
signal cfg_done_s : std_logic; |
signal dat_done_s : std_logic; |
signal cfg_clk_s : std_logic; |
signal cfg_dat_s : std_logic; |
signal detached_s : std_logic; |
|
signal set_sel_n_s : std_logic_vector(3 downto 0); |
|
begin |
|
set_sel_n_s <= (others => '1'); |
cfg_init_n_s <= '1'; |
cfg_done_s <= '1'; |
|
----------------------------------------------------------------------------- |
-- DUT |
----------------------------------------------------------------------------- |
dut_b : chip |
port map ( |
clk_i => clk_s, |
reset_i => reset_s, |
set_sel_n_i => set_sel_n_s, |
spi_clk_o => spi_clk_s, |
spi_cs_n_o => spi_cs_n_s, |
spi_data_in_i => spi_data_from_card_s, |
spi_data_out_o => spi_data_to_card_s, |
start_i => start_s, |
mode_i => mode_s, |
config_n_o => config_n_s, |
detached_o => detached_s, |
cfg_init_n_i => cfg_init_n_s, |
cfg_done_i => cfg_done_s, |
dat_done_i => dat_done_s, |
cfg_clk_o => cfg_clk_s, |
cfg_dat_o => cfg_dat_s |
); |
|
card_b : card |
generic map ( |
card_type_g => "Full Chip", |
is_sd_card_g => 1 |
) |
port map ( |
spi_clk_i => spi_clk_s, |
spi_cs_n_i => spi_cs_n_s, |
spi_data_i => spi_data_to_card_s, |
spi_data_o => spi_data_from_card_s |
); |
|
rl_b : ram_loader |
port map ( |
clk_i => rl_clk_s, |
reset_i => reset_s, |
lamp_o => open, |
cfg_clk_i => cfg_clk_s, |
cfg_data_i => cfg_dat_s, |
start_o => start_s, |
mode_o => mode_s, |
done_o => dat_done_s, |
detached_i => detached_s, |
ram_addr_o => open, |
ram_data_b => open, |
ram_ce_no => open, |
ram_oe_no => open, |
ram_we_no => open |
); |
|
----------------------------------------------------------------------------- |
-- Clock Generator |
----------------------------------------------------------------------------- |
clk: process |
begin |
clk_s <= '0'; |
wait for period_c / 2; |
clk_s <= '1'; |
wait for period_c / 2; |
end process clk; |
|
rl_clk: process |
begin |
rl_clk_s <= '0'; |
wait for rl_period_c / 2; |
rl_clk_s <= '1'; |
wait for rl_period_c / 2; |
end process rl_clk; |
|
|
----------------------------------------------------------------------------- |
-- Reset Generator |
----------------------------------------------------------------------------- |
reset: process |
begin |
if reset_level_c = 0 then |
reset_s <= '0'; |
else |
reset_s <= '1'; |
end if; |
|
wait for period_c * 4 + 10 ns; |
|
reset_s <= not reset_s; |
|
wait; |
end process reset; |
|
|
----------------------------------------------------------------------------- |
-- End of Simulation |
----------------------------------------------------------------------------- |
eos: process |
begin |
wait for 4 ms; |
assert false |
report "No checks have been performed. Investigate waveforms." |
severity note; |
assert false |
report "End of simulation." |
severity failure; |
end process eos; |
|
end behav; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
------------------------------------------------------------------------------- |
/tb_elem.vhd
0,0 → 1,373
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- Generic testbench element for a specific feature set |
-- |
-- $Id: tb_elem.vhd,v 1.7 2005-04-07 20:43:36 arniml Exp $ |
-- |
-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved, see COPYING. |
-- |
-- Redistribution and use in source and synthezised forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- |
-- Redistributions of source code must retain the above copyright notice, |
-- this list of conditions and the following disclaimer. |
-- |
-- Redistributions in synthesized form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution. |
-- |
-- Neither the name of the author nor the names of other contributors may |
-- be used to endorse or promote products derived from this software without |
-- specific prior written permission. |
-- |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
-- POSSIBILITY OF SUCH DAMAGE. |
-- |
-- Please report bugs to the author, but before you do so, please |
-- make sure that this is not a derivative work and that |
-- you have the latest version of this file. |
-- |
-- The latest version of this file can be found at: |
-- http://www.opencores.org/projects.cgi/web/spi_boot/overview |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
|
entity tb_elem is |
|
generic ( |
chip_type_g : string := "none"; |
has_sd_card_g : integer := 1 |
); |
port ( |
clk_i : in std_logic; |
reset_i : in std_logic; |
eos_o : out boolean |
); |
|
end tb_elem; |
|
|
library ieee; |
use ieee.numeric_std.all; |
library std; |
use std.textio.all; |
|
use work.spi_boot_pack.all; |
use work.tb_pack.all; |
|
architecture behav of tb_elem is |
|
component chip |
port ( |
clk_i : in std_logic; |
reset_i : in std_logic; |
set_sel_n_i : in std_logic_vector(3 downto 0); |
spi_clk_o : out std_logic; |
spi_cs_n_o : out std_logic; |
spi_data_in_i : in std_logic; |
spi_data_out_o : out std_logic; |
start_i : in std_logic; |
mode_i : in std_logic; |
config_n_o : out std_logic; |
detached_o : out std_logic; |
cfg_init_n_i : in std_logic; |
cfg_done_i : in std_logic; |
dat_done_i : in std_logic; |
cfg_clk_o : out std_logic; |
cfg_dat_o : out std_logic |
); |
end component; |
|
component card |
generic ( |
card_type_g : string := "none"; |
is_sd_card_g : integer := 1 |
); |
port ( |
spi_clk_i : in std_logic; |
spi_cs_n_i : in std_logic; |
spi_data_i : in std_logic; |
spi_data_o : out std_logic |
); |
end component; |
|
signal reset_s : std_logic; |
|
-- SPI interface signals |
signal spi_clk_s : std_logic; |
signal spi_data_to_card_s : std_logic; |
signal spi_data_from_card_s : std_logic; |
signal spi_cs_n_s : std_logic; |
|
-- config related signals |
signal start_s : std_logic; |
signal mode_s : std_logic; |
signal config_n_s : std_logic; |
signal cfg_init_n_s : std_logic; |
signal cfg_done_s : std_logic; |
signal dat_done_s : std_logic; |
signal cfg_clk_s : std_logic; |
signal cfg_dat_s : std_logic; |
signal data_s : unsigned(7 downto 0); |
|
signal set_sel_n_s : std_logic_vector(3 downto 0); |
|
constant verbose_c : boolean := false; |
|
begin |
|
-- weak pull-ups |
spi_clk_s <= 'H'; |
spi_cs_n_s <= 'H'; |
spi_data_to_card_s <= 'H'; |
|
----------------------------------------------------------------------------- |
-- DUT |
----------------------------------------------------------------------------- |
dut_b : chip |
port map ( |
clk_i => clk_i, |
reset_i => reset_s, |
set_sel_n_i => set_sel_n_s, |
spi_clk_o => spi_clk_s, |
spi_cs_n_o => spi_cs_n_s, |
spi_data_in_i => spi_data_from_card_s, |
spi_data_out_o => spi_data_to_card_s, |
start_i => start_s, |
mode_i => mode_s, |
config_n_o => config_n_s, |
detached_o => open, |
cfg_init_n_i => cfg_init_n_s, |
cfg_done_i => cfg_done_s, |
dat_done_i => dat_done_s, |
cfg_clk_o => cfg_clk_s, |
cfg_dat_o => cfg_dat_s |
); |
|
card_b : card |
generic map ( |
card_type_g => chip_type_g, |
is_sd_card_g => has_sd_card_g |
) |
port map ( |
spi_clk_i => spi_clk_s, |
spi_cs_n_i => spi_cs_n_s, |
spi_data_i => spi_data_to_card_s, |
spi_data_o => spi_data_from_card_s |
); |
|
|
----------------------------------------------------------------------------- |
-- DUT Stimuli |
-- |
stim: process |
|
procedure rise_cfg_clk(num : integer) is |
begin |
for i in 1 to num loop |
wait until cfg_clk_s'event and cfg_clk_s = '1'; |
end loop; |
end rise_cfg_clk; |
|
-- procedure fall_cfg_clk(num : integer) is |
-- begin |
-- for i in 1 to num loop |
-- wait until cfg_clk_s'event and cfg_clk_s = '0'; |
-- end loop; |
-- end fall_cfg_clk; |
|
procedure rise_clk(num : integer) is |
begin |
for i in 1 to num loop |
wait until clk_i'event and clk_i = '1'; |
end loop; |
end rise_clk; |
|
procedure read_check_byte(ref : unsigned(7 downto 0)) is |
variable byte_v : unsigned(7 downto 0); |
variable dump_line : line; |
begin |
for bit in 7 downto 0 loop |
rise_cfg_clk(1); |
byte_v(bit) := cfg_dat_s; |
end loop; |
data_s <= byte_v; |
|
if byte_v /= ref then |
write(dump_line, chip_type_g); |
write(dump_line, string'(" at ")); |
write(dump_line, now); |
write(dump_line, string'(": read_check_byte failed ")); |
write(dump_line, to_integer(byte_v)); |
write(dump_line, string'(" ")); |
write(dump_line, to_integer(ref)); |
writeline(output, dump_line); |
end if; |
end read_check_byte; |
|
variable dump_line : line; |
variable addr_v : unsigned(31 downto 0); |
variable temp_v : unsigned( 7 downto 0); |
variable set_sel_v : unsigned(3 downto 0); |
|
begin |
-- default assignments |
-- these defaults show the required pull resistors |
-- except start_i as this must be pulled high for automatic start |
start_s <= '0'; |
mode_s <= '1'; |
cfg_init_n_s <= '1'; |
cfg_done_s <= '0'; |
dat_done_s <= '1'; |
data_s <= (others => '1'); |
addr_v := (others => '0'); |
eos_o <= false; |
set_sel_n_s <= (others => '1'); |
reset_s <= '0'; |
|
-- loop through some sets |
for set in 0 to 3 loop |
set_sel_v := to_unsigned(set, 4); |
addr_v(23 downto 20) := set_sel_v; -- must match num_bits_per_img_g |
-- plus width_img_cnt_g |
set_sel_n_s <= not std_logic_vector(set_sel_v); |
|
assert not verbose_c |
report chip_type_g & ": Processing set " & to_string(set) |
severity note; |
|
wait for 100 us; |
reset_s <= '1'; |
|
assert not verbose_c |
report chip_type_g & ": Requesting image 0" |
severity note; |
|
-- signal start |
start_s <= '1'; |
mode_s <= '1'; |
cfg_done_s <= '0'; |
addr_v(19 downto 0) := (others => '0'); |
wait until config_n_s = '0'; |
-- run through configuration sequence |
rise_clk(1); |
cfg_init_n_s <= '0'; |
rise_clk(3); |
cfg_init_n_s <= '1'; |
|
-- and receive 32 bytes from image 0 |
for i in 1 to 32 loop |
temp_v := addr_v(0) & calc_crc(addr_v); |
read_check_byte(temp_v); |
addr_v := addr_v + 1; |
end loop; |
start_s <= '0'; |
cfg_done_s <= '1'; |
|
rise_clk(10); |
|
assert not verbose_c |
report chip_type_g & ": Requesting image 1" |
severity note; |
|
-- request next image |
mode_s <= '0'; |
start_s <= '1'; |
addr_v(17 downto 0) := (others => '0'); |
addr_v(19 downto 18) := "01"; -- must match num_bits_per_img_g in chip-*-a.vhd |
dat_done_s <= '0'; |
|
-- receive another 32 bytes from image 1 |
for i in 1 to 32 loop |
temp_v := addr_v(0) & calc_crc(addr_v); |
read_check_byte(temp_v); |
addr_v := addr_v + 1; |
end loop; |
start_s <= '0'; |
dat_done_s <= '1'; |
|
|
rise_clk(10); |
|
assert not verbose_c |
report chip_type_g & ": Requesting image 2" |
severity note; |
|
-- request next image |
mode_s <= '1'; |
start_s <= '1'; |
addr_v(17 downto 0) := (others => '0'); |
addr_v(19 downto 18) := "10"; -- must match num_bits_per_img_g in chip-*-a.vhd |
|
wait until config_n_s = '0'; |
-- run through configuration sequence |
rise_clk(1); |
cfg_done_s <= '0'; |
cfg_init_n_s <= '0'; |
rise_clk(3); |
cfg_init_n_s <= '1'; |
|
-- receive another 32 bytes from image 2 |
for i in 1 to 32 loop |
temp_v := addr_v(0) & calc_crc(addr_v); |
read_check_byte(temp_v); |
addr_v := addr_v + 1; |
end loop; |
start_s <= '0'; |
cfg_done_s <= '1'; |
|
-- give dut a chance to stop current transfer |
wait until spi_cs_n_s = '1'; |
rise_clk(10); |
|
reset_s <= '0'; |
end loop; |
|
eos_o <= true; |
wait; |
end process stim; |
-- |
----------------------------------------------------------------------------- |
|
end behav; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.6 2005/03/09 19:48:04 arniml |
-- make verbosity level switchable |
-- |
-- Revision 1.5 2005/03/08 22:06:21 arniml |
-- added set selection |
-- |
-- Revision 1.4 2005/02/17 18:59:23 arniml |
-- clarify wording for images |
-- |
-- Revision 1.3 2005/02/16 19:34:56 arniml |
-- add weak pull-ups for SPI lines |
-- |
-- Revision 1.2 2005/02/13 17:14:03 arniml |
-- change dat_done handling |
-- |
-- Revision 1.1 2005/02/08 21:09:20 arniml |
-- initial check-in |
-- |
------------------------------------------------------------------------------- |
/tb_pack-p.vhd
0,0 → 1,90
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- |
-- $Id: tb_pack-p.vhd,v 1.2 2005-03-08 22:06:39 arniml Exp $ |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
package tb_pack is |
|
function calc_crc(payload : in std_logic_vector) return std_logic_vector; |
function calc_crc(payload : in unsigned) return unsigned; |
|
function to_string(value : in integer) return string; |
|
end tb_pack; |
|
|
package body tb_pack is |
|
function calc_crc(payload : in std_logic_vector) return std_logic_vector is |
|
variable crc_v : std_logic_vector(6 downto 0); |
variable temp_v : std_logic; |
|
begin |
|
crc_v := (others => '0'); |
|
for i in payload'high downto payload'low loop |
temp_v := payload(i) xor crc_v(6); |
|
crc_v(6 downto 4) := crc_v(5 downto 3); |
crc_v(3) := crc_v(2) xor temp_v; |
crc_v(2 downto 1) := crc_v(1 downto 0); |
crc_v(0) := temp_v; |
end loop; |
|
return crc_v; |
end calc_crc; |
|
function calc_crc(payload : in unsigned) return unsigned is |
begin |
return unsigned(calc_crc(std_logic_vector(payload))); |
end calc_crc; |
|
function to_string(value : in integer) return string is |
variable str: string (11 downto 1); |
variable val: integer := value; |
variable digit: natural; |
variable index: natural := 0; |
begin |
-- Taken from: |
-- textio package body. This file is part of GHDL. |
-- Copyright (C) 2002 Tristan Gingold. |
-- Note: the absolute value of VAL cannot be directly taken, since |
-- it may be greather that the maximum value of an INTEGER. |
loop |
-- LRM93 7.2.6 |
-- (A rem B) has the sign of A and an absolute value less then |
-- the absoulte value of B. |
digit := abs (val rem 10); |
val := val / 10; |
index := index + 1; |
str (index) := character'val(48 + digit); |
exit when val = 0; |
end loop; |
if value < 0 then |
index := index + 1; |
str(index) := '-'; |
end if; |
|
return str; |
end to_string; |
|
end tb_pack; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.1 2005/02/08 21:09:20 arniml |
-- initial check-in |
-- |
------------------------------------------------------------------------------- |
/card.vhd
0,0 → 1,443
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- Simple SD and MMC model |
-- |
-- $Id: card.vhd,v 1.2 2005-02-13 17:06:22 arniml Exp $ |
-- |
-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved, see COPYING. |
-- |
-- Redistribution and use in source and synthezised forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- |
-- Redistributions of source code must retain the above copyright notice, |
-- this list of conditions and the following disclaimer. |
-- |
-- Redistributions in synthesized form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution. |
-- |
-- Neither the name of the author nor the names of other contributors may |
-- be used to endorse or promote products derived from this software without |
-- specific prior written permission. |
-- |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
-- POSSIBILITY OF SUCH DAMAGE. |
-- |
-- Please report bugs to the author, but before you do so, please |
-- make sure that this is not a derivative work and that |
-- you have the latest version of this file. |
-- |
-- The latest version of this file can be found at: |
-- http://www.opencores.org/projects.cgi/web/spi_boot/overview |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
|
entity card is |
|
generic ( |
card_type_g : string := "none"; |
is_sd_card_g : integer := 1 |
); |
|
port ( |
spi_clk_i : in std_logic; |
spi_cs_n_i : in std_logic; |
spi_data_i : in std_logic; |
spi_data_o : out std_logic |
); |
|
end card; |
|
|
library ieee; |
use ieee.numeric_std.all; |
library std; |
use std.textio.all; |
|
use work.tb_pack.all; |
|
architecture behav of card is |
|
signal power_on_n_s : std_logic; |
signal soft_res_n_s : std_logic; |
signal res_n_s : std_logic; |
|
signal rx_s : std_logic_vector(47 downto 0); |
|
signal set_spi_mode_s, |
spi_mode_q : boolean; |
signal set_idle_mode_s, |
poll_idle_mode_s : boolean; |
signal idle_mode_q : natural; |
|
signal block_len_q, |
block_len_s : unsigned(31 downto 0); |
signal set_block_len_s : boolean; |
|
signal new_read_addr_s, |
read_addr_q : unsigned(31 downto 0); |
signal set_read_addr_s, |
inc_read_addr_s : boolean; |
|
signal cmd_spi_data_s, |
read_spi_data_s : std_logic; |
signal start_read_s : boolean; |
signal reading_s : boolean; |
|
procedure rise_clk is |
begin |
wait until spi_clk_i'event and to_X01(spi_clk_i) = '1'; |
end rise_clk; |
|
-- procedure rise_clk(num : natural) is |
-- begin |
-- for i in 1 to num loop |
-- rise_clk; |
-- end loop; |
-- end rise_clk; |
|
procedure fall_clk is |
begin |
wait until spi_clk_i'event and to_X01(spi_clk_i) = '0'; |
end fall_clk; |
|
procedure fall_clk(num : natural) is |
begin |
for i in 1 to num loop |
fall_clk; |
end loop; |
end fall_clk; |
|
begin |
|
res_n_s <= power_on_n_s and soft_res_n_s; |
|
----------------------------------------------------------------------------- |
-- Power on reset |
----------------------------------------------------------------------------- |
por: process |
begin |
power_on_n_s <= '0'; |
wait for 200 ns; |
power_on_n_s <= '1'; |
wait; |
end process por; |
|
|
----------------------------------------------------------------------------- |
-- |
ctrl: process |
|
function check_crc(payload : in std_logic_vector(47 downto 0)) |
return boolean is |
|
begin |
|
return calc_crc(payload(47 downto 8)) = payload(7 downto 1); |
end check_crc; |
|
variable rx_v : std_logic_vector(47 downto 0); |
variable cmd_v : std_logic_vector( 5 downto 0); |
variable arg_v : std_logic_vector(31 downto 0); |
variable crc_v : std_logic_vector( 6 downto 0); |
variable wrong_v : std_logic; |
variable read_data_v : boolean; |
|
begin |
rx_s <= (others => '0'); |
set_spi_mode_s <= false; |
set_idle_mode_s <= false; |
poll_idle_mode_s <= false; |
cmd_spi_data_s <= '1'; |
soft_res_n_s <= '1'; |
set_block_len_s <= false; |
block_len_s <= (others => '0'); |
new_read_addr_s <= (others => '0'); |
set_read_addr_s <= false; |
start_read_s <= false; |
read_data_v := false; |
|
loop |
|
rise_clk; |
-- wait for startbit of command |
while to_X01(spi_data_i) = '1' loop |
rise_clk; |
end loop; |
rx_v(47) := '0'; |
|
-- read remaining 47 bits of command |
for i in 46 downto 0 loop |
rise_clk; |
rx_v(i) := to_X01(spi_data_i); |
end loop; |
rx_s <= rx_v; |
|
-- dissect received data |
cmd_v := rx_v(45 downto 40); |
arg_v := rx_v(39 downto 8); |
crc_v := rx_v( 7 downto 1); |
|
assert spi_mode_q or check_crc(payload => rx_v) |
report "CRC mismatch" |
severity error; |
|
wrong_v := '0'; |
case cmd_v is |
-- CMD0: GO_IDLE_STATE ------------------------------------------------ |
when "000000" => |
set_spi_mode_s <= true; |
set_idle_mode_s <= true; |
-- CMD1: SEND_OP_COND ------------------------------------------------- |
when "000001" => |
poll_idle_mode_s <= true; |
-- CMD12: STOP_TRANSMISSION ------------------------------------------- |
when "001100" => |
start_read_s <= false; |
read_data_v := false; |
-- CMD16: SET_BLOCKLEN ------------------------------------------------ |
when "010000" => |
block_len_s <= unsigned(arg_v); |
set_block_len_s <= true; |
-- CMD18: READ_MULTIPLE_BLOCK ----------------------------------------- |
when "010010" => |
new_read_addr_s <= unsigned(arg_v); |
set_read_addr_s <= true; |
read_data_v := true; |
-- CMD55: APPL_CMD ---------------------------------------------------- |
when "110111" => |
-- command only available for SD card |
if is_sd_card_g /= 1 then |
wrong_v := '1'; |
end if; |
-- ACMD41: SEND_OP_COND ----------------------------------------------- |
when "101001" => |
-- command only available for SD card |
if is_sd_card_g /= 1 then |
wrong_v := '1'; |
else |
poll_idle_mode_s <= true; |
end if; |
|
when others => |
wrong_v := '1'; |
null; |
end case; |
|
|
-- spend some time before removing control signals |
fall_clk(2); |
poll_idle_mode_s <= false; |
set_idle_mode_s <= false; |
fall_clk(6); |
set_spi_mode_s <= false; |
set_block_len_s <= false; |
set_read_addr_s <= false; |
|
if reading_s then |
wait until not reading_s; |
end if; |
|
|
-- wait for a total two "bytes" before sending out response |
for i in 1 to 8 loop |
fall_clk; |
end loop; |
|
for i in 7 downto 0 loop |
fall_clk; |
case i is |
when 2 => |
cmd_spi_data_s <= wrong_v; |
when 0 => |
if idle_mode_q = 0 then |
cmd_spi_data_s <= '0'; |
else |
cmd_spi_data_s <= '1'; |
end if; |
when others => |
cmd_spi_data_s <= '0'; |
end case; |
end loop; |
fall_clk; |
cmd_spi_data_s <= '1'; |
|
-- transmit data if requested |
start_read_s <= read_data_v; |
|
end loop; |
end process ctrl; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- |
seq: process (res_n_s, |
spi_clk_i, |
set_spi_mode_s, |
set_idle_mode_s, |
poll_idle_mode_s, |
set_block_len_s, |
block_len_s) |
|
begin |
if res_n_s = '0' then |
spi_mode_q <= false; |
idle_mode_q <= 5; |
block_len_q <= (others => '0'); |
read_addr_q <= (others => '0'); |
|
elsif spi_clk_i'event and spi_clk_i = '1' then |
if set_spi_mode_s then |
spi_mode_q <= true; |
end if; |
|
if set_idle_mode_s then |
idle_mode_q <= 5; |
elsif poll_idle_mode_s then |
if idle_mode_q > 0 then |
idle_mode_q <= idle_mode_q - 1; |
end if; |
end if; |
|
if set_block_len_s then |
block_len_q <= block_len_s; |
end if; |
|
if set_read_addr_s then |
read_addr_q <= new_read_addr_s; |
elsif inc_read_addr_s then |
read_addr_q <= read_addr_q + 1; |
end if; |
|
end if; |
end process seq; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- |
read_block: process |
|
variable t_v : unsigned(7 downto 0); |
|
begin |
-- default assignments |
inc_read_addr_s <= false; |
reading_s <= false; |
read_spi_data_s <= '1'; |
|
loop |
if not start_read_s then |
wait until start_read_s; |
end if; |
|
reading_s <= true; |
|
fall_clk(8); -- delay for one "byte" |
|
-- send data token |
fall_clk(7); -- 7 ones in a data token |
read_spi_data_s <= '0'; |
|
-- send payload |
payload: for i in 0 to to_integer(block_len_q)-1 loop |
t_v := read_addr_q(0) & calc_crc(read_addr_q); |
for bit in 7 downto 0 loop |
fall_clk; |
read_spi_data_s <= t_v(bit); |
|
exit payload when not start_read_s; |
end loop; |
inc_read_addr_s <= true; |
rise_clk; |
inc_read_addr_s <= false; |
wait for 10 ns; |
end loop; |
|
if start_read_s then |
-- send crc |
for i in 0 to 15 loop |
fall_clk; |
t_v := to_unsigned(i, 8); |
read_spi_data_s <= t_v(0); |
end loop; |
fall_clk; |
end if; |
|
read_spi_data_s <= '1'; |
reading_s <= false; |
-- loop for one "byte" |
fall_clk(8); |
|
end loop; |
end process read_block; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- |
clk_check: process (spi_clk_i) |
|
variable last_rising_v : time := 0 ns; |
variable dump_line : line; |
|
begin |
if spi_clk_i'event and spi_clk_i = '1' then |
if is_sd_card_g = 0 and card_type_g /= "Minimal Chip" and |
idle_mode_q > 0 then |
if now - last_rising_v < 2.5 us and last_rising_v > 0 ns then |
write(dump_line, card_type_g); |
write(dump_line, string'(" @ ")); |
write(dump_line, now); |
write(dump_line, string'(": Last rising edge of SPI clock ")); |
write(dump_line, now - last_rising_v); |
write(dump_line, string'(" ago.")); |
writeline(output, dump_line); |
end if; |
|
last_rising_v := now; |
end if; |
end if; |
end process clk_check; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Output Mapping |
----------------------------------------------------------------------------- |
spi_data_o <= cmd_spi_data_s and read_spi_data_s |
when spi_cs_n_i = '0' else |
'Z'; |
|
end behav; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.1 2005/02/08 21:09:20 arniml |
-- initial check-in |
-- |
------------------------------------------------------------------------------- |
/tb_elem-mmc-c.vhd
0,0 → 1,23
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- |
-- $Id: tb_elem-mmc-c.vhd,v 1.1 2005-02-08 21:09:20 arniml Exp $ |
-- |
------------------------------------------------------------------------------- |
|
configuration tb_elem_behav_mmc of tb_elem is |
|
for behav |
|
for dut_b : chip |
use configuration work.chip_mmc_c0; |
end for; |
|
for card_b : card |
use configuration work.card_behav_c0; |
end for; |
|
end for; |
|
end tb_elem_behav_mmc; |
/tb-c.vhd
0,0 → 1,31
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- |
-- $Id: tb-c.vhd,v 1.1 2005-02-08 21:09:20 arniml Exp $ |
-- |
------------------------------------------------------------------------------- |
|
configuration tb_behav_c0 of tb is |
|
for behav |
|
for tb_elem_full_b : tb_elem |
use configuration work.tb_elem_behav_full; |
end for; |
|
for tb_elem_mmc_b : tb_elem |
use configuration work.tb_elem_behav_mmc; |
end for; |
|
for tb_elem_sd_b : tb_elem |
use configuration work.tb_elem_behav_sd; |
end for; |
|
for tb_elem_minimal_b : tb_elem |
use configuration work.tb_elem_behav_minimal; |
end for; |
|
end for; |
|
end tb_behav_c0; |
/tb.vhd
0,0 → 1,198
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- Testbench |
-- |
-- $Id: tb.vhd,v 1.1 2005-02-08 21:09:20 arniml Exp $ |
-- |
-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved, see COPYING. |
-- |
-- Redistribution and use in source and synthezised forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- |
-- Redistributions of source code must retain the above copyright notice, |
-- this list of conditions and the following disclaimer. |
-- |
-- Redistributions in synthesized form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution. |
-- |
-- Neither the name of the author nor the names of other contributors may |
-- be used to endorse or promote products derived from this software without |
-- specific prior written permission. |
-- |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
-- POSSIBILITY OF SUCH DAMAGE. |
-- |
-- Please report bugs to the author, but before you do so, please |
-- make sure that this is not a derivative work and that |
-- you have the latest version of this file. |
-- |
-- The latest version of this file can be found at: |
-- http://www.opencores.org/projects.cgi/web/spi_boot/overview |
-- |
------------------------------------------------------------------------------- |
|
entity tb is |
|
end tb; |
|
|
library ieee; |
use ieee.std_logic_1164.all; |
|
architecture behav of tb is |
|
component tb_elem |
generic ( |
chip_type_g : string := "none"; |
has_sd_card_g : integer := 1 |
); |
port ( |
clk_i : in std_logic; |
reset_i : in std_logic; |
eos_o : out boolean |
); |
end component; |
|
constant period_c : time := 100 ns; |
constant reset_level_c : integer := 0; |
|
signal clk_s : std_logic; |
signal reset_s : std_logic; |
|
signal eos_full_s, |
eos_mmc_s, |
eos_sd_s, |
eos_minimal_s : boolean; |
|
begin |
|
|
----------------------------------------------------------------------------- |
-- Testbench element including full featured chip |
----------------------------------------------------------------------------- |
tb_elem_full_b : tb_elem |
generic map ( |
chip_type_g => "Full Chip", |
has_sd_card_g => 1 |
) |
port map ( |
clk_i => clk_s, |
reset_i => reset_s, |
eos_o => eos_full_s |
); |
|
|
----------------------------------------------------------------------------- |
-- Testbench element including MMC chip |
----------------------------------------------------------------------------- |
tb_elem_mmc_b : tb_elem |
generic map ( |
chip_type_g => "MMC Chip", |
has_sd_card_g => 0 |
) |
port map ( |
clk_i => clk_s, |
reset_i => reset_s, |
eos_o => eos_mmc_s |
); |
|
|
----------------------------------------------------------------------------- |
-- Testbench element including SD chip |
----------------------------------------------------------------------------- |
tb_elem_sd_b : tb_elem |
generic map ( |
chip_type_g => "SD Chip", |
has_sd_card_g => 1 |
) |
port map ( |
clk_i => clk_s, |
reset_i => reset_s, |
eos_o => eos_sd_s |
); |
|
|
----------------------------------------------------------------------------- |
-- Testbench element including cip with minimal features |
----------------------------------------------------------------------------- |
tb_elem_minimal_b : tb_elem |
generic map ( |
chip_type_g => "Minimal Chip", |
has_sd_card_g => 0 |
) |
port map ( |
clk_i => clk_s, |
reset_i => reset_s, |
eos_o => eos_minimal_s |
); |
|
|
----------------------------------------------------------------------------- |
-- Clock Generator |
----------------------------------------------------------------------------- |
clk: process |
begin |
clk_s <= '0'; |
wait for period_c / 2; |
clk_s <= '1'; |
wait for period_c / 2; |
end process clk; |
|
|
----------------------------------------------------------------------------- |
-- Reset Generator |
----------------------------------------------------------------------------- |
reset: process |
begin |
if reset_level_c = 0 then |
reset_s <= '0'; |
else |
reset_s <= '1'; |
end if; |
|
wait for period_c * 4 + 10 ns; |
|
reset_s <= not reset_s; |
|
wait; |
end process reset; |
|
|
----------------------------------------------------------------------------- |
-- End Of Simulation Detection |
----------------------------------------------------------------------------- |
eos: process (eos_full_s, |
eos_mmc_s, |
eos_sd_s, |
eos_minimal_s) |
begin |
|
if eos_full_s and eos_mmc_s and eos_sd_s and eos_minimal_s then |
assert false |
report "End of Simulation." |
severity failure; |
end if; |
|
end process eos; |
|
end behav; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
------------------------------------------------------------------------------- |
/tb_elem-full-c.vhd
0,0 → 1,23
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- |
-- $Id: tb_elem-full-c.vhd,v 1.1 2005-02-08 21:09:20 arniml Exp $ |
-- |
------------------------------------------------------------------------------- |
|
configuration tb_elem_behav_full of tb_elem is |
|
for behav |
|
for dut_b : chip |
use configuration work.chip_full_c0; |
end for; |
|
for card_b : card |
use configuration work.card_behav_c0; |
end for; |
|
end for; |
|
end tb_elem_behav_full; |
/card-c.vhd
0,0 → 1,14
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- |
-- $Id: card-c.vhd,v 1.1 2005-02-08 21:09:18 arniml Exp $ |
-- |
------------------------------------------------------------------------------- |
|
configuration card_behav_c0 of card is |
|
for behav |
end for; |
|
end card_behav_c0; |
/tb_elem-minimal-c.vhd
0,0 → 1,23
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- |
-- $Id: tb_elem-minimal-c.vhd,v 1.1 2005-02-08 21:09:20 arniml Exp $ |
-- |
------------------------------------------------------------------------------- |
|
configuration tb_elem_behav_minimal of tb_elem is |
|
for behav |
|
for dut_b : chip |
use configuration work.chip_minimal_c0; |
end for; |
|
for card_b : card |
use configuration work.card_behav_c0; |
end for; |
|
end for; |
|
end tb_elem_behav_minimal; |
/tb_elem-sd-c.vhd
0,0 → 1,23
------------------------------------------------------------------------------- |
-- |
-- SD/MMC Bootloader |
-- |
-- $Id: tb_elem-sd-c.vhd,v 1.1 2005-02-08 21:09:20 arniml Exp $ |
-- |
------------------------------------------------------------------------------- |
|
configuration tb_elem_behav_sd of tb_elem is |
|
for behav |
|
for dut_b : chip |
use configuration work.chip_sd_c0; |
end for; |
|
for card_b : card |
use configuration work.card_behav_c0; |
end for; |
|
end for; |
|
end tb_elem_behav_sd; |