📄 sdcard_spi.vhd
字号:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity sdcard_spi is
generic(
write_block_length:integer:=512;
max_block_length:integer:=512;
sd_card_size:integer:=4*1024
);
port(
res:in std_logic; --for test only
cs:in std_logic;
clk:in std_logic;
di:in std_logic;
-- test_is_cmd:out std_logic;
-- test_is_start_block:out std_logic;
-- test_din_8:out std_logic_vector(47 downto 0);
-- test_crc_result_cmd:out std_logic;
-- test_crc_result_data:out std_logic;
test_clk0:out std_logic;
test_ram_out:out std_logic_vector(7 downto 0);
test_current_state:out std_logic_vector(11 downto 0);
do:out std_logic
);
end entity;
architecture behave of sdcard_spi is
component CRC16Generator
port(
RST:in std_logic;
TestData:in std_logic;
Clock:in std_logic;
Hold:in std_logic;
CRC:out std_logic_vector(15 downto 0)
);
end component;
component CRC7Generator
port(
RST:in std_logic;
TestData:in std_logic;
Clock:in std_logic;
Hold:in std_logic;
CRC:out std_logic_vector(6 downto 0)
);
end component;
component CRC16Generator_D8
port(
RST:in std_logic;
TestData:in std_logic_vector(7 downto 0);
Clock:in std_logic;
Hold:in std_logic;
CRC:out std_logic_vector(15 downto 0)
);
end component;
component main_ram
port(
address:in std_logic_vector(12 downto 0);
clken:in std_logic;
clock:in std_logic;
data:in std_logic_vector(7 downto 0);
wren:in std_logic;
q:out std_logic_vector(7 downto 0)
);
end component;
component w_fifo
port(
aclr:in std_logic;
clock:in std_logic;
data:in std_logic_vector(7 downto 0);
rdreq:in std_logic;
wrreq:in std_logic;
empty:out std_logic;
full:out std_logic;
q:out std_logic_vector(7 downto 0);
usedw:out std_logic_vector(9 downto 0)
);
end component;
--globally used
constant idle_out:std_logic_vector(7 downto 0):="11111111";
constant dresponse_write_error:std_logic_vector(7 downto 0):="00001101";
constant dresponse_crc_error:std_logic_vector(7 downto 0):="00001011";
constant dresponse_accept:std_logic_vector(7 downto 0):="00000101";
constant buzy_response:std_logic_vector(7 downto 0):="00000000";
constant start_block_token:std_logic_vector(7 downto 0):="11111110";
constant inactive_state:std_logic_vector(11 downto 0):="000000000001";
constant standby_state:std_logic_vector(11 downto 0):="000000000010";
constant working_state:std_logic_vector(11 downto 0):="000000000100";
constant sendr2_state:std_logic_vector(11 downto 0):="000000001000";
constant sendr3_state:std_logic_vector(11 downto 0):="000000010000";
constant toread_state:std_logic_vector(11 downto 0):="000000100000";
constant reading_state:std_logic_vector(11 downto 0):="000001000000";
constant towrite_state:std_logic_vector(11 downto 0):="000010000000";
constant buffering_state:std_logic_vector(11 downto 0):="000100000000";
constant writing_state:std_logic_vector(11 downto 0):="001000000000";
constant erasing_state:std_logic_vector(11 downto 0):="010000000000";
constant swrited_block_state:std_logic_vector(11 downto 0):="100000000000";
constant empty_byte:std_logic_vector(7 downto 0):="00000000";
constant after_erase:std_logic_vector(7 downto 0):="00000000";
signal clk0:std_logic:='0'; --clock for byte process
signal r_clk0:std_logic:='0'; --the reverse of the clock
signal cnt_8:std_logic_vector(2 downto 0):=(others=>'0'); --cnt form 0 to 7
signal ram_out:std_logic_vector(7 downto 0); --the output of the main ram
signal current_state:std_logic_vector(11 downto 0):=inactive_state; --current state of the auto-machine
signal cnt_writed:std_logic_vector(31 downto 0):=(others=>'0'); -- correctly writed block amount
signal cur_address:std_logic_vector(31 downto 0):=(others=>'0'); -- the current start address
signal real_address:std_logic:='0'; --whether the address is represent a real data address or just a register place
signal end_address:std_logic_vector(31 downto 0):=(others=>'0'); -- the erase end address
signal num_toread:std_logic_vector(9 downto 0):=(others=>'0'); -- number of bytes being read in ram
signal cur_block_len:std_logic_vector(9 downto 0):="1000000000"; --the current size of block length
signal CRC_enable:std_logic:='0';
signal address_error:std_logic:='0';
--initial part
signal din_buf:std_logic_vector(47 downto 0):=(others=>'1'); --last 48 bits to the main process
signal d_in_cmd:std_logic:='0';
signal in_cmd:std_logic:='0'; --whether inside a cmd
signal go_start_cmd:std_logic:='0';
signal cnt_cmd:std_logic_vector(7 downto 0); --cnt_cmd form 0 to 48 maximal
signal cnt_data:std_logic_vector(13 downto 0);
signal crc7_res:std_logic:='0';
signal crc:std_logic_vector(6 downto 0);
signal crc_data:std_logic_vector(15 downto 0);
signal d_crc_result_cmd:std_logic:='0';
signal crc16_res:std_logic:='0';
signal go_start_data:std_logic:='0';
signal in_data:std_logic:='0'; --whether inside a data block
signal end_data:std_logic:='0';
signal is_cmd:std_logic:='0'; --whether the din_8 is representing a cmd
signal is_start_block:std_logic:='0'; --whether the din_8 is representing a start block token
signal is_stop_tran:std_logic:='0'; --whether the din_8 is representing a stop tran token
signal data_ended:std_logic:='0'; --whether a data block is about to end
signal crc_result_cmd:std_logic:='0'; --represent the condition of last cmd crc check
signal crc_result_data:std_logic:='0'; --represent the conditon of last data block crc check
signal din_8:std_logic_vector(47 downto 0):=(others=>'1'); --data given to main process
--main part
signal next_state:std_logic_vector(11 downto 0); --the next state in the auto-machine
signal cmd_id:integer; --current command id
signal callingcmd58_state:std_logic_vector(11 downto 0); --represent the where to return after the cmd58 done
signal last_is_cmd55:std_logic:='0'; --represent whether the last cmd is cmd55
signal read_terminated:std_logic:='0'; --whether it is about the time to end the read process
signal write_terminated:std_logic:='0'; --whether it is about the time to end the write process
signal is_multi_read:std_logic:='0'; --it is a multi read or not
signal is_multi_write:std_logic:='0'; --it is a multi write or not
signal valid_cmd:std_logic:='0'; --whether it is a valid cmd (is_cmd+crc ok+last cmd is not 55) (comb)
signal valid_cmd_a:std_logic:='0'; --whether it is a valid acmd (is_cmd+crc ok+last cmd is 55) (comb)
signal delayed_r1:std_logic:='0'; --whether it needs to response a r1 for early cmd12
signal delayed_response:std_logic_vector(7 downto 0); --the content of delayed response
signal in_idle_state:std_logic:='0'; --first bit of r1(comb)
signal parameter_error:std_logic:='0'; --parameter error (comb)
signal crc_error:std_logic:='0'; --the crc is correct or not (comb)
signal illegal_command:std_logic:='0'; --
constant erase_reset:std_logic:='0';
constant erase_seq_error:std_logic:='0';
signal norm_r1:std_logic_vector(7 downto 0);
constant norm_r2:std_logic_vector(7 downto 0):=(others=>'0');
constant data_error:std_logic_vector(7 downto 0):="00001000";
signal next_dout_8:std_logic_vector(7 downto 0);
--interface to lower block of the structure
signal reading_out:std_logic_vector(7 downto 0);
signal sendnum_out:std_logic_vector(7 downto 0);
signal sendr3_out:std_logic_vector(7 downto 0);
signal reading_finished:std_logic:='0';
signal writing_finished:std_logic:='0';
signal erasing_finished:std_logic:='0';
signal sendnum_finished:std_logic:='0';
signal sendr3_finished:std_logic:='0';
signal dout_8:std_logic_vector(7 downto 0):=(others=>'1');
--sendr3 functional block
signal cnt_r3:std_logic_vector(1 downto 0):=(others=>'0');
constant first_ocr_byte:std_logic_vector(7 downto 0):="01111111";
constant mid_ocr_byte:std_logic_vector(7 downto 0):="11111111";
constant last_ocr_byte:std_logic_vector(7 downto 0):="11111110";
--erasing functional block
signal cnt_erasing:std_logic_vector(31 downto 0):=(others=>'0');
signal now_address_erase:std_logic_vector(31 downto 0);
signal erasing_enable:std_logic:='0';
signal erasing_wren:std_logic:='0';
signal erasing_address:std_logic_vector(12 downto 0);
signal erasing_data:std_logic_vector(7 downto 0);
--send wrted num block
signal cnt_sw:std_logic_vector(2 downto 0):=(others=>'0');
signal s_crc_res:std_logic:='0';
signal s_crc_hold:std_logic:='0';
signal s_crc_out:std_logic_vector(15 downto 0);
signal s_crc_data:std_logic_vector(7 downto 0);
--reading functional block--
signal cnt_reading:std_logic_vector(10 downto 0):=(others=>'0');
signal info_buf:std_logic_vector(15 downto 0):=(others=>'1');
signal reading_enable:std_logic:='0';
signal reading_wren:std_logic:='0';
signal reading_address:std_logic_vector(12 downto 0);
signal r_crc_data:std_logic_vector(7 downto 0);
signal r_crc_hold:std_logic:='0';
signal r_crc_res:std_logic:='0';
signal r_crc_out:std_logic_vector(15 downto 0);
---buffering functional block--
signal cnt_buf:std_logic_vector(10 downto 0);
signal buf_ended:std_logic:='0';
signal b_fifo_aclr:std_logic:='0';
signal b_fifo_data:std_logic_vector(7 downto 0);
signal b_fifo_rdreq:std_logic:='0';
signal b_fifo_wrreq:std_logic:='0';
---writing functional block
signal cnt_write:std_logic_vector(10 downto 0);
signal write_tmp_buf:std_logic_vector(7 downto 0);
signal w_fifo_aclr:std_logic:='0';
signal w_fifo_data:std_logic_vector(7 downto 0);
signal w_fifo_rdreq:std_logic:='0';
signal w_fifo_wrreq:std_logic:='0';
signal w_fifo_out:std_logic_vector(7 downto 0);
signal writing_address:std_logic_vector(12 downto 0);
signal writing_enable:std_logic:='0';
signal writing_data:std_logic_vector(7 downto 0);
signal writing_wren:std_logic:='0';
---w_fifo controll---
signal w_f_aclr:std_logic:='0';
signal w_f_data:std_logic_vector(7 downto 0);
signal w_f_rdreq:std_logic:='0';
signal w_f_wrreq:std_logic:='0';
---main ram controll---
signal ram_address:std_logic_vector(12 downto 0);
signal ram_clken:std_logic:='0';
signal ram_data:std_logic_vector(7 downto 0);
signal ram_wren:std_logic:='0';
---output part---
signal do_buf:std_logic_vector(7 downto 0):=(others=>'1');
begin
----intialization part-----
process(clk, cs)
begin
if cs='1' then
din_buf<=(others=>'1');
elsif clk='1' and clk'event then
din_buf(47 downto 1)<=din_buf(46 downto 0);
din_buf(0)<=di;
end if;
end process;
process(clk, cs)
begin
if cs='1' then
cnt_8<=(others=>'0');
elsif clk='1' and clk'event then
cnt_8<=cnt_8+1;
end if;
end process;
process(cnt_8, in_cmd, din_buf, in_data)
begin
if cnt_8=2 and in_cmd='0' and in_data='0' and din_buf(0)='1' and din_buf(1)='0' then
go_start_cmd<='1';
else
go_start_cmd<='0';
end if;
end process;
process(in_cmd, clk, go_start_cmd)
begin
if go_start_cmd='1' then
cnt_cmd<=(others=>'0');
elsif clk='1' and clk'event then
if in_cmd='1' then
cnt_cmd<=cnt_cmd+1;
end if;
end if;
end process;
process(in_cmd, cnt_cmd, go_start_cmd)
begin
if go_start_cmd='1' then
d_in_cmd<='1';
elsif in_cmd='1' and cnt_cmd=45 then
d_in_cmd<='0';
else
d_in_cmd<=in_cmd;
end if;
end process;
process(cs, clk)
begin
if cs='1' then
in_cmd<='0';
elsif clk='1' and clk'event then
in_cmd<=d_in_cmd;
end if;
end process;
process(clk, cnt_8, in_cmd)
begin
if cnt_8=0 and clk='1' and in_cmd='0' then
crc7_res<='1';
else
crc7_res<='0';
end if;
end process;
CRC7checker:CRC7Generator port map(RST=>crc7_res,TestData=>di,Clock=>clk,Hold=>'0',CRC=>crc);
process(crc, in_cmd, cnt_cmd, crc_result_cmd)
begin
if cnt_cmd=44 and in_cmd='1' and crc/=0 then
d_crc_result_cmd<='1';
elsif in_cmd='1' and cnt_cmd=0 and crc_result_cmd='1' then
d_crc_result_cmd<='0';
else
d_crc_result_cmd<=crc_result_cmd;
end if;
end process;
process(clk, cs, crc_enable)
begin
if cs='1' or crc_enable='0' then
crc_result_cmd<='0';
elsif clk='1' and clk'event then
crc_result_cmd<=d_crc_result_cmd;
end if;
end process;
process(din_buf, in_cmd, in_data, cnt_8)
begin
if cnt_8=0 and (din_buf(7 downto 0)="11111110" or din_buf(7 downto 0)="11111100") and in_cmd='0' and in_data='0' then
go_start_data<='1';
else
go_start_data<='0';
end if;
end process;
process(in_data, cnt_data)
begin
if in_data='1' and cnt_data=(write_block_length+2)*8-1 then
end_data<='1';
else
end_data<='0';
end if;
end process;
process(clk, cs, go_start_data, end_data)
begin
if cs='1' then
in_data<='0';
elsif clk='1' and clk'event then
if go_start_data='1' then
in_data<='1';
elsif end_data='1' then
in_data<='0';
end if;
end if;
end process;
process(clk, go_start_data)
begin
if go_start_data='1' then
cnt_data<=(others=>'0');
elsif clk='1' and clk'event then
cnt_data<=cnt_data+1;
end if;
end process;
crc16_res<=go_start_data and clk;
CRC16checker:CRC16Generator port map(TestData=>di, Clock=>clk, Rst=>crc16_res, Hold=>'0', CRC=>crc_data);
process(cs, clk, crc_enable, end_data)
begin
if cs='1' or crc_enable='0' then
crc_result_data<='0';
elsif clk='1' and clk'event then
if end_data='1' then
if crc_data=0 then
crc_result_data<='0';
else
crc_result_data<='1';
end if;
end if;
end if;
end process;
process(cs, clk)
begin
if cs='1' then
din_8<=(others=>'0');
elsif clk='1' and clk'event then
if cnt_8=7 then
din_8(47 downto 1)<=din_buf(46 downto 0);
din_8(0)<=di;
end if;
end if;
end process;
process(cs, clk)
begin
if cs='1' then
is_cmd<='0';
elsif clk='1' and clk'event then
if cnt_8=7 then
if in_cmd='1' and cnt_cmd=44 then
is_cmd<='1';
else
is_cmd<='0';
end if;
end if;
end if;
end process;
process(cs, clk, in_cmd, in_data, din_buf, di)
begin
if cs='1' then
is_start_block<='0';
elsif clk='1' and clk'event then
if cnt_8=7 then
if in_cmd='0' and in_data='0' and din_buf(6 downto 1)="111111" and di='0' then
is_start_block<='1';
else
is_start_block<='0';
end if;
end if;
end if;
end process;
process(cs, clk, in_cmd, in_data, din_buf, di)
begin
if cs='1' then
is_stop_tran<='0';
elsif clk='1' and clk'event then
if cnt_8=7 then
if in_cmd='0' and in_data='0' and din_buf(6 downto 0)="1111110" and di='1' then
is_stop_tran<='1';
else
is_stop_tran<='0';
end if;
end if;
end if;
end process;
process(cs, clk, in_cmd, in_data, cnt_data)
begin
if cs='1' then
data_ended<='0';
elsif clk='1' and clk'event then
if cnt_8=7 then
if in_cmd='0' and in_data='1' and cnt_data=(write_block_length+2)*8-2 then
data_ended<='1';
else
data_ended<='0';
end if;
end if;
end if;
end process;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -