⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdcard_spi.vhd

📁 实现了SD的SPI模式,通过了所有的仿真及测试,支持数据的读和写.对SD卡的SPI模式的绝大多数命令都支持.
💻 VHD
📖 第 1 页 / 共 3 页
字号:
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 + -