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

📄 sdcard_spi.vhd

📁 实现了SD的SPI模式,通过了所有的仿真及测试,支持数据的读和写.对SD卡的SPI模式的绝大多数命令都支持.
💻 VHD
📖 第 1 页 / 共 3 页
字号:
	
	process(cnt_8)
	begin
		if cnt_8>3 then
			clk0<='1';
		else
			clk0<='0';
		end if;
	end process;
	
--	test_is_cmd<=is_cmd;
--	test_is_start_block<=is_start_block;
--	test_din_8<=din_8;
--	test_crc_result_cmd<=crc_result_cmd;
--	test_crc_result_data<=crc_result_data;
--	do<=clk0;

------main part------

	r_clk0 <= not clk0;
	
	process(res, clk0, cs)
	begin
		if res='1' then
			current_state<=inactive_state;
		elsif clk0='1' and clk0'event and cs='0' then
			current_state<=next_state;
		end if;
	end process;
	
	cmd_id<=conv_integer(din_8(45 downto 40));
	
	--it is the process to calculate the next state of state machine
	process(current_state, valid_cmd, reading_finished, writing_finished, sendr3_finished, sendnum_finished, erasing_finished, din_8, is_cmd, is_start_block, crc_result_cmd, crc_result_data, last_is_cmd55, write_terminated, read_terminated, data_ended, callingcmd58_state, cmd_id, cur_address, real_address)
	begin
		if current_state(0)='1' then
			if is_cmd='1' and crc_result_cmd='0' and cmd_id=0 then
				next_state<=standby_state;
			else
				next_state<=current_state;
			end if;
		elsif current_state(1)='1' then
			if valid_cmd='1' and cmd_id=0 then
				next_state<=inactive_state;
			elsif is_cmd='1' and crc_result_cmd='0' and ((cmd_id=1 and last_is_cmd55='0') or (cmd_id=41 and last_is_cmd55='1')) then
				next_state<=working_state;
			elsif is_cmd='1' and crc_result_cmd='0' and cmd_id=58 and last_is_cmd55='0' then
				next_state<=sendr3_state;
			else
				next_state<=current_state;
			end if;
		elsif current_state(2)='1' then
			if is_cmd='1' and crc_result_cmd='0' then
				if (cmd_id=0 and last_is_cmd55='0') then
					next_state<=inactive_state;
				elsif (cmd_id=9 or cmd_id=10 or cmd_id=17 or cmd_id=18) and last_is_cmd55='0' then
					next_state<=toread_state;
				elsif cmd_id=13 and last_is_cmd55='0' then
					next_state<=sendr2_state;
				elsif cmd_id=58 and last_is_cmd55='0' then
					next_state<=sendr3_state;
				elsif (cmd_id=24 or cmd_id=25) and last_is_cmd55='0' then
					next_state<=towrite_state;
				elsif cmd_id=38 and last_is_cmd55='0' then
					next_state<=erasing_state;
				elsif cmd_id=22 and last_is_cmd55='1' then
					next_state<=swrited_block_state;
				else
					next_state<=current_state;
				end if;
			else
				next_state<=current_state;
			end if;
		elsif current_state(3)='1' then
			next_state<=working_state;
		elsif current_state(4)='1' then
			if sendr3_finished='1' then
				next_state<=callingcmd58_state;
			else
				next_state<=current_state;
			end if;
		elsif current_state(5)='1' then
			if read_terminated='1' then
				next_state<=working_state;
			else
				next_state<=reading_state;
			end if;
		elsif current_state(6)='1' then
			if reading_finished='1' then
				next_state<=toread_state;
			else
				next_state<=current_state;
			end if;
		elsif current_state(7)='1' then
			if write_terminated='1' then
				next_state<=working_state;
			elsif is_start_block='1' then
				next_state<=buffering_state;
			else
				next_state<=current_state;
			end if;
		elsif current_state(8)='1' then
			if data_ended='1' then
				if crc_result_data='1' or (cur_address>sd_card_size-write_block_length and real_address='1') then
					next_state<=towrite_state;
				else
					next_state<=writing_state;
				end if;
			else
				next_state<=current_state;
			end if;
		elsif current_state(9)='1' then
			if writing_finished='1' then
				next_state<=towrite_state;
			else
				next_state<=current_state;
			end if;
		elsif current_state(10)='1' then
			if erasing_finished='1' then
				next_state<=working_state;
			else
				next_state<=current_state;
			end if;
		else
			if sendnum_finished='1' then
				next_state<=working_state;
			else
				next_state<=current_state;
			end if;
		end if;
	end process;
	
	valid_cmd<=is_cmd and (not crc_result_cmd) and (not last_is_cmd55);
	valid_cmd_a<=is_cmd and (not crc_result_cmd) and last_is_cmd55;
	
	
	process(clk0, res, cs)
	begin
		if res='1' then
			last_is_cmd55<='0';
		elsif clk0='1' and clk0'event and cs='0' then
			if is_cmd='1' then
				if cmd_id=55 and current_state(0)/='1' and last_is_cmd55='0' then
					last_is_cmd55<='1';
				else
					last_is_cmd55<='0';
				end if;
			end if;
		end if;
	end process;
	
	process(clk0, res, cs)
	begin
		if res='1' then
			callingcmd58_state<=(others=>'0');
		elsif clk0='1' and clk0'event and cs='0' then
			if valid_cmd='1' and cmd_id=58 then
				if current_state(1)='1' or current_state(2)='1' then
					callingcmd58_state<=current_state;
				end if;
			end if;
		end if;
	end process;
	
	process(clk0, res, cmd_id, is_multi_read, reading_finished, valid_cmd, cs)
	begin
		if res='1' then
			read_terminated<='0';
		elsif clk0='1' and clk0'event and cs='0' then
			if (is_multi_read='0' and current_state(6)='1' and reading_finished='1') or 
			(valid_cmd='1' and cmd_id=12 and (current_state(5)='1' or current_state(6)='1')) then
				read_terminated<='1';
			elsif (current_state(2)='1' and next_state(5)='1') or (current_state(5)='1' and read_terminated='1') then 
				read_terminated<='0';
			end if;
		end if;
	end process;
	
	process(clk0, res, is_multi_write, writing_finished, cs)
	begin
		if res='1' then
			write_terminated<='0';
		elsif clk0='1' and clk0'event and cs='0' then
			if (is_multi_write='0' and current_state(9)='1' and writing_finished='1') or
				((current_state(7)='1' or current_state(8)='1' or current_state(9)='1') and is_stop_tran='1') then
				write_terminated<='1';
			elsif (current_state(7)='1' and write_terminated='1') or (current_state(2)='1' and next_state(7)='1') then
				write_terminated<='0';
			end if;
		end if;
	end process;
	
	process(clk0, res, cmd_id, valid_cmd, cs)
	begin
		if res='1' then
			is_multi_read<='0';
		elsif clk0='1' and clk0'event and cs='0' then
			if current_state(2)='1' and valid_cmd='1' then
				if cmd_id=18 then
					is_multi_read<='1';
				elsif cmd_id=17 then
					is_multi_read<='0';
				end if;
			end if;
		end if;
	end process;
	
	process(clk0, res, cmd_id, valid_cmd, cs)
	begin
		if res='1' then
			is_multi_write<='1';
		elsif clk0='1' and clk0'event and cs='0' then
			if valid_cmd='1' and current_state(2)='1' then
				if cmd_id=25 then
					is_multi_write<='1';
				elsif cmd_id=24 then
					is_multi_write<='0';
				end if;
			end if;
		end if;
	end process;
	
	process(res, clk0, current_state, valid_cmd, cmd_id, cs)
	begin
		if res='1' then
			delayed_r1<='0';
		elsif clk0='1' and clk0'event and cs='0' then
			if (current_state(5)='1' or current_state(6)='1') and valid_cmd='1' and cmd_id=12 then
				delayed_r1<='1';
			elsif current_state(2)='1' then
				delayed_r1<='0';
			end if;
		end if;
	end process;
	
	process(res, clk0, current_state, valid_cmd, cmd_id, norm_r1, cs)
	begin
		if res='1' then
			delayed_response<=(others=>'0');
		elsif clk0='1' and clk0'event and cs='0' then
			if (current_state(5)='1' or current_state(6)='1') and valid_cmd='1' and cmd_id=12 then
				delayed_response<=norm_r1;
			end if;
		end if;
	end process;
	
	process(clk0, res, current_state, next_state, valid_cmd, valid_cmd_a, cmd_id, din_8, cs, is_multi_read, is_multi_write, read_terminated, reading_finished, write_terminated, writing_finished)
	begin
		if res='1' then
			cur_address<=(others=>'0');
			real_address<='0';
		elsif clk0='1' and clk0'event and cs='0' then
			if current_state(2)='1' then
				if valid_cmd='1' then
					if cmd_id=17 or cmd_id=18 or cmd_id=24 or cmd_id=25 or cmd_id=32 then
						cur_address<=din_8(39 downto 8);
						real_address<='1';
					elsif cmd_id=9 then
						cur_address(31 downto 13)<=(others=>'0');
						cur_address(12)<='1';
						cur_address(11 downto 0)<=(others=>'0');
						real_address<='0';
					elsif cmd_id=10 then
						cur_address(31 downto 13)<=(others=>'0');
						cur_address(12)<='1';
						cur_address(11 downto 0)<="000000010000";
						real_address<='0';
					end if;
				elsif valid_cmd_a='1' then
					if cmd_id=13 then
						cur_address(31 downto 13)<=(others=>'0');
						cur_address(12)<='1';
						cur_address(11 downto 0)<="000000101000";
						real_address<='0';
					elsif cmd_id=51 then
						cur_address(31 downto 13)<=(others=>'0');
						cur_address(12)<='1';
						cur_address(11 downto 0)<="000000100000";
						real_address<='0';
					end if;
				end if;
			elsif current_state(2)='0' and next_state(2)='1' then
				cur_address<=(others=>'0');
				real_address<='0';
			elsif current_state(6)='1' and reading_finished='1' and read_terminated='0' and is_multi_read='1' then
				cur_address<=cur_address+cur_block_len;
			elsif current_state(9)='1' and writing_finished='1' and write_terminated='0' and is_multi_write='1' then
				cur_address<=cur_address+write_block_length;
			end if;
		end if;
	end process;
	
	process(res, clk0, current_state, next_state, valid_cmd, cmd_id, valid_cmd_a, din_8, cs)
	begin
		if res='1' then
			num_toread<=(others=>'0');
		elsif clk0='1' and clk0'event and cs='0' then
			if current_state(2)='1' then
				if valid_cmd='1' then
					if cmd_id=17 or cmd_id=18 or cmd_id=24 or cmd_id=25 or cmd_id=32 then
						num_toread<=cur_block_len;
					elsif cmd_id=9 or cmd_id=10 then
						num_toread<="0000010000";
					end if;
				elsif valid_cmd_a='1' then
					if cmd_id=13 then
						num_toread<="0001000000";
					elsif cmd_id=51 then
						num_toread<="0000001000";
					end if;
				end if;
			end if;
		end if;
	end process;
	
	process(res, clk0, current_state, valid_cmd, cmd_id, din_8, cs)
	begin
		if res='1' then
			crc_enable<='0';
		elsif clk0='1' and clk0'event then
			if cs='0' then
				if current_state(2)='1' and valid_cmd='1' and cmd_id=59 then
					crc_enable<=din_8(8);
				end if;
			end if;
		end if;
	end process;
	
	process(res, clk0, current_state, valid_cmd, cmd_id, din_8, cs)
	begin
		if res='1' then
			cur_block_len<="1000000000";
		elsif clk0='1' and clk0'event then
			if cs='0' then
				if current_state(2)='1' and valid_cmd='1' and cmd_id=16 then
					if din_8(39 downto 8)<=max_block_length then
						cur_block_len<=din_8(17 downto 8);
					end if;
				end if;
			end if;
		end if;
	end process;
	
	process(res, clk0, current_state, valid_cmd, cmd_id, din_8)
	begin
		if res='1' then
			end_address<=(others=>'0');
		elsif clk0='1' and clk0'event then
			if cs='0' then
				if current_state(2)='1' and valid_cmd='1' and cmd_id=33 then
					if din_8(39 downto 8)<sd_card_size then
						end_address<=din_8(39 downto 8);
					end if;
				end if;
			end if;
		end if;
	end process;
	
	process(res, clk0, current_state, next_state, cs)
	begin
		if res='1' then
			cnt_writed<=(others=>'0');
		elsif clk0='1' and clk0'event and cs='0' then
			if current_state(2)='1' and next_state(7)='1' then
				cnt_writed<=(others=>'0');
			elsif current_state(8)='1' and next_state(9)='1' then
				cnt_writed<=cnt_writed+1;
			end if;
		end if;
	end process;

--- send r3 response block ---
	process(res, clk0, cs, current_state, next_state)
	begin
		if res='1' then
			cnt_r3<=(others=>'0');
		elsif clk0='1' and clk0'event and cs='0' then
			if current_state(2)='1' and next_state(4)='1' then
				cnt_r3<=(others=>'0');
			elsif current_state(4)='1' and cnt_r3/=3 then
				cnt_r3<=cnt_r3+1;
			end if;
		end if;
	end process;
	
	process(cnt_r3)
	begin
		if cnt_r3=0 then
			sendr3_out<=first_ocr_byte;
		elsif cnt_r3=3 then
			sendr3_out<=last_ocr_byte;
		else
			sendr3_out<=mid_ocr_byte;
		end if;
	end process;
	
	sendr3_finished<=cnt_r3(1) and cnt_r3(0);

--- functional erasing block------
	erasing_data<=after_erase;
	erasing_enable<='1';
	now_address_erase<=cur_address+cnt_erasing;
	erasing_address<=now_address_erase(12 downto 0);
	erasing_wren<='1';
	
	process(res, clk0, current_state, next_state)
	begin
		if res='1' then
			cnt_erasing<=(others=>'0');
		elsif clk0='1' and clk0'event then
			if current_state(2)='1' and next_state(10)='1' then
				cnt_erasing<=(others=>'0');
			elsif erasing_finished='0' then
				cnt_erasing<=cnt_erasing+1;
			end if;
		end if;
	end process;
	
	process(now_address_erase, end_address)
	begin
		if now_address_erase=end_address then
			erasing_finished<='1';
		else
			erasing_finished<='0';
		end if;
	end process;
	
--- send writed block num --
	process(res, clk0, current_state, next_state, cs)
	begin
		if res='1' then
			cnt_sw<=(others=>'0');
		elsif clk0='1' and clk0'event and cs='0' then 
			if current_state(2)='1' and next_state(11)='1' then
				cnt_sw<=(others=>'0');
			elsif current_state(11)='1' and sendnum_finished='0' then
				cnt_sw<=cnt_sw+1;
			end if;
		end if;
	end process;

	sendnum_finished<=cnt_sw(0) and cnt_sw(1) and cnt_sw(2);
		
	s_crc_res<=(not cnt_sw(0)) and (not cnt_sw(1)) and (not cnt_sw(2)) and clk0;
	
	process(cnt_sw)
	begin
		if cnt_sw>5 then
			s_crc_hold<='1';
		else
			s_crc_hold<='0';
		end if;
	end process;
	
	process(cnt_sw, cnt_writed)
	begin
		if cnt_sw=0 then
			s_crc_data<=cnt_writed(31 downto 24);
		elsif cnt_sw=1 then
			s_crc_data<=cnt_writed(23 downto 16);
		elsif cnt_sw=2 then
			s_crc_data<=cnt_writed(15 downto 8);
		elsif cnt_sw=3 then
			s_crc_data<=cnt_writed(7 downto 0);
		else
			s_crc_data<=empty_byte;
		end if;
	end process;

	CRC16Generator_D8a:CRC16Generator_D8 port map(RST=>s_crc_res, Hold=>s_crc_hold, TestData=>s_crc_data, Clock=>clk0, CRC=>s_crc_out);
		
	process(cnt_sw, s_crc_out, cnt_writed)
	begin
		if cnt_sw=2 then
			sendnum_out<=cnt_writed(31 downto 24);
		elsif cnt_sw=3 then
			sendnum_out<=cnt_writed(23 downto 16);
		elsif cnt_sw=4 then
			sendnum_out<=cnt_writed(15 downto 8);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -