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

📄 sdcard_spi.vhd

📁 实现了SD的SPI模式,通过了所有的仿真及测试,支持数据的读和写.对SD卡的SPI模式的绝大多数命令都支持.
💻 VHD
📖 第 1 页 / 共 3 页
字号:
		elsif cnt_sw=5 then
			sendnum_out<=cnt_writed(7 downto 0);
		elsif cnt_sw=6 then
			sendnum_out<=s_crc_out(15 downto 8);
		elsif cnt_sw=7 then
			sendnum_out<=s_crc_out(7 downto 0);
		else
			sendnum_out<=idle_out;
		end if;
	end process;

--- reading functional block ---
	
	process(res, clk0, cs, current_state, next_state)
	begin
		if res='1' then
			cnt_reading<=(others=>'0');
		elsif clk0='1' and clk0'event and cs='0' then
			if current_state(5)='1' and next_state(6)='1' then
				cnt_reading<=(others=>'0');
			elsif current_state(6)='1' and reading_finished='0' then
				cnt_reading<=cnt_reading+1;
			end if;
		end if;
	end process;
	
	process(cnt_reading,address_error,num_toread, valid_cmd, cmd_id, current_state)
	begin
		if address_error='1' then
			reading_finished<='1';
		elsif valid_cmd='1' and cmd_id=12 and current_state(6)='1' then
			reading_finished<='1';
		elsif cnt_reading=num_toread+3 then
			reading_finished<='1';
		else
			reading_finished<='0';
		end if;
	end process;
	
	process(cnt_reading,address_error,num_toread)
	begin
		if address_error='1' then
			reading_enable<='0';
		elsif cnt_reading<num_toread then
			reading_enable<='1';
		else
			reading_enable<='0';
		end if;
	end process;
	
	reading_wren<='0';
	
	process(cnt_reading, cur_address)
	variable temp:std_logic_vector(31 downto 0);
	begin
		temp:=cnt_reading+cur_address;
		reading_address<=temp(12 downto 0);
	end process;
	
	process(res, clk0, ram_out)
	begin
		if res='1' then
			info_buf<=(others=>'1');
		elsif clk0='1' and clk0'event then
			if current_state(6)='1' then
				info_buf(15 downto 8)<=info_buf(7 downto 0);
				info_buf(7 downto 0)<=ram_out;
			end if;
		end if;
	end process;
	
	process(cnt_reading, clk0)
	begin
		if cnt_reading=0 then
			r_crc_res<=clk0;
		else
			r_crc_res<='0';
		end if;
	end process;
		
	process(cnt_reading, num_toread, ram_out)
	begin
		if cnt_reading<num_toread then
			r_crc_data<=ram_out;
		else
			r_crc_data<=empty_byte;
		end if;
	end process;
	
	process(cnt_reading, num_toread)
	begin
		if cnt_reading<num_toread+2 then
			r_crc_hold<='0';
		else
			r_crc_hold<='1';
		end if;
	end process;
	
	CRC16Generator_D8b:CRC16Generator_D8 port map(TestData=>r_crc_data, Clock=>clk0, Hold=>r_crc_hold, RST=>r_crc_res, CRC=>r_crc_out);
	
	process(cnt_reading, num_toread, info_buf, r_crc_out, address_error)
	begin
		if address_error='1' then
			reading_out<=data_error;
		elsif cnt_reading=0 then
			reading_out<=idle_out;
		elsif cnt_reading=1 then
			reading_out<=start_block_token;
		elsif cnt_reading<num_toread+2 then
			reading_out<=info_buf(15 downto 8);
		elsif cnt_reading=num_toread+2 then
			reading_out<=r_crc_out(15 downto 8);
		else
			reading_out<=r_crc_out(7 downto 0);
		end if;
	end process;

--- buffering functional block--
	
	process(cnt_buf)
	begin
		if cnt_buf=write_block_length+1 then 
			buf_ended<='1';
		else
			buf_ended<='0';
		end if;
	end process;
	
	process(res, clk0, cs, current_state, next_state)
	begin
		if res='1' then
			cnt_buf<=(others=>'0');
		elsif clk0='1' and clk0'event and cs='0' then
			if current_state(7)='1' and next_state(8)='1' then
				cnt_buf<=(others=>'0');
			elsif current_state(8)='1' and buf_ended='0' then
				cnt_buf<=cnt_buf+1;
			end if;
		end if;
	end process;
	
	b_fifo_aclr<=current_state(7) and next_state(8);
	
	b_fifo_data<=din_8(7 downto 0);
	
	b_fifo_rdreq<='0';
	
	process(current_state, cs, cnt_buf)
	begin
		if current_state(8)='1' and cs='0' then
			if cnt_buf<write_block_length then
				b_fifo_wrreq<='1';
			else
				b_fifo_wrreq<='0';
			end if;
		else
			b_fifo_wrreq<='0';
		end if;
	end process;

--- writing functional block

	process(res, clk0, current_state, next_state)
	begin
		if res='1' then
			cnt_write<=(others=>'0');
		elsif clk0='1' and clk0'event then
			if current_state(8)='1' and next_state(9)='1' then
				cnt_write<=(others=>'0');
			elsif current_state(9)='1' and writing_finished='0' then
				cnt_write<=cnt_write+1;
			end if;
		end if;
	end process;
	
	process(cnt_write)
	begin
		if cnt_write=write_block_length then
			writing_finished<='1';
		else
			writing_finished<='0';
		end if;
	end process;
	
	w_fifo_data<=empty_byte;
	w_fifo_wrreq<='0';
	
	process(writing_finished, current_state)
	begin
		if current_state(9)='1' then
			w_fifo_rdreq<=not writing_finished;
		else
			w_fifo_rdreq<='0';
		end if;
	end process;
	
	process(res, clk0)
	begin
		if res='1' then
			write_tmp_buf<=(others=>'0');
		elsif clk0='1' and clk0'event then
			write_tmp_buf<=w_fifo_out;
		end if;
	end process;
	
	process(cur_address, cnt_write)
	variable temp:std_logic_vector(31 downto 0);
	begin
		temp:=cur_address+cnt_write-1;
		writing_address<=temp(12 downto 0);
	end process;
	
	process(cnt_write)
	begin
		if cnt_write/=0 then
			writing_enable<='1';
		else
			writing_enable<='0';
		end if;
	end process;
	
	writing_data<=write_tmp_buf;
	writing_wren<='1';

--- controll the w_fifo --
	
	w_f_aclr<=current_state(7) and b_fifo_aclr;
	
	process(current_state, b_fifo_data, w_fifo_data)
	begin
		if current_state(8)='1' then
			w_f_data<=b_fifo_data;
		elsif current_state(9)='1' then
			w_f_data<=w_fifo_data;
		else
			w_f_data<=empty_byte;
		end if;
	end process;
	
	w_f_rdreq<=(current_state(8) and b_fifo_rdreq) or (current_state(9) and w_fifo_rdreq);
	w_f_wrreq<=(current_state(8) and b_fifo_wrreq) or (current_state(9) and w_fifo_wrreq);
	
	w_fifo_a:w_fifo port map(aclr=>w_f_aclr, clock=>r_clk0, data=>w_f_data, rdreq=>w_f_rdreq, wrreq=>w_f_wrreq, q=>w_fifo_out);

--- main ram controll --
	
	process(current_state, erasing_address, reading_address, writing_address)
	begin
		if current_state(10)='1' then
			ram_address<=erasing_address;
		elsif current_state(6)='1' then
			ram_address<=reading_address;
		elsif current_state(9)='1' then
			ram_address<=writing_address;
		else
			ram_address<=(others=>'0');
		end if;
	end process;
	
	process(current_state, erasing_wren, reading_wren, writing_wren)
	begin
		if current_state(10)='1' then
			ram_wren<=erasing_wren;
		elsif current_state(6)='1' then
			ram_wren<=reading_wren;
		elsif current_state(9)='1' then
			ram_wren<=writing_wren;
		else
			ram_wren<='0';
		end if;
	end process;
	
	process(current_state, erasing_enable, reading_enable, writing_enable)
	begin
		if current_state(10)='1' then
			ram_clken<=erasing_enable;
		elsif current_state(6)='1' then
			ram_clken<=reading_enable;
		elsif current_state(9)='1' then
			ram_clken<=writing_enable;
		else
			ram_clken<='0';
		end if;
	end process;
	
	process(current_state, erasing_data, writing_data)
	begin
		if current_state(10)='1' then
			ram_data<=erasing_data;
		elsif current_state(9)='1' then
			ram_data<=writing_data;
		else
			ram_data<=empty_byte;
		end if;
	end process;
	
	main_ram_a:main_ram port map(address=>ram_address, clken=>ram_clken, clock=>r_clk0, data=>ram_data, wren=>ram_wren, q=>ram_out);

--- to handle the final output of main ---
	in_idle_state<=next_state(0) or next_state(1);
	
	process(res, clk0, valid_cmd, cur_address, cs)
	begin
		if res='1' then
			address_error<='0';
		elsif clk0='1' and clk0'event then
			if cs='0' then
				if cur_address>sd_card_size-write_block_length and real_address='1' then
					address_error<='1';
				elsif valid_cmd='1' or valid_cmd_a='1' then
					address_error<='0';
				end if;
			end if;
		end if;
	end process;
	
	process(cmd_id, valid_cmd, din_8)
	begin
		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 or cmd_id=33) 
			and (din_8(39 downto 8)>=sd_card_size) then
				parameter_error<='1';
			elsif (cmd_id=16) and (din_8(39 downto 8)>max_block_length) then
				parameter_error<='1';
			else
				parameter_error<='0';	
			end if;
		else
			parameter_error<='0';
		end if;
	end process;
	
	crc_error<=is_cmd and crc_result_cmd;
	
	process(current_state, valid_cmd, valid_cmd_a, cmd_id)
	begin
		if valid_cmd='1' then
			if current_state(0)='1' then
				if cmd_id/=0 then
					illegal_command<='1';
				else
					illegal_command<='0';
				end if;
			elsif current_state(1)='1' then
				if cmd_id/=0 and cmd_id/=1 and cmd_id/=55 then
					illegal_command<='1';
				else
					illegal_command<='0';
				end if;
			else
				if cmd_id=0 or cmd_id=9 or cmd_id=10 or cmd_id=13 or cmd_id=12 or cmd_id=16 or cmd_id=17 or cmd_id=18
					or cmd_id=24 or cmd_id=25 or cmd_id=32 or cmd_id=33 or cmd_id=38 or cmd_id=55 or cmd_id=56
					or cmd_id=58 or cmd_id=59 then
					illegal_command<='0';
				else
					illegal_command<='1';
				end if;
			end if;
		elsif valid_cmd_a='1' then
			if current_state(0)='1' then
				illegal_command<='1';
			elsif current_state(1)='1' then
				if cmd_id/=41 then
					illegal_command<='1';
				else
					illegal_command<='0';
				end if;
			else
				if cmd_id=13 and cmd_id=22 and cmd_id=23 and cmd_id=42 and cmd_id=51 then
					illegal_command<='0';
				else
					illegal_command<='1';
				end if;
			end if;
		else
			illegal_command<='0';
		end if;
	end process;
	
	norm_r1(7)<='0';
	norm_r1(0)<=in_idle_state;
	norm_r1(1)<=erase_reset;
	norm_r1(2)<=illegal_command;
	norm_r1(3)<=crc_error;
	norm_r1(4)<=erase_seq_error;
	norm_r1(5)<=address_error;
	norm_r1(6)<=parameter_error;
	
	process(clk0, res)
	begin
		if res='1' then
			dout_8<=(others=>'0');
		elsif clk0='1' and clk0'event then
			dout_8<=next_dout_8;
		end if;
	end process;
	
	process(current_state, valid_cmd, valid_cmd_a, cmd_id, norm_r1, reading_out, sendnum_out, sendr3_out, data_ended, delayed_response, delayed_r1, cur_address, crc_result_data, real_address)
	begin
		if current_state(0)='1' then
			if valid_cmd='1' or valid_cmd_a='1' then
				next_dout_8<=norm_r1;
			else
				next_dout_8<=idle_out;
			end if;
		elsif current_state(1)='1' then
			if valid_cmd='1' or valid_cmd_a='1' then
				next_dout_8<=norm_r1;
			else
				next_dout_8<=idle_out;
			end if;
		elsif current_state(2)='1' then
			if delayed_r1='1' then
				next_dout_8<=delayed_response;
			elsif valid_cmd='1' or valid_cmd_a='1' then
				next_dout_8<=norm_r1;
			else
				next_dout_8<=idle_out;
			end if;
		elsif current_state(3)='1' then
			next_dout_8<=norm_r2;
		elsif current_state(4)='1' then
			next_dout_8<=sendr3_out;
		elsif current_state(5)='1' then
			next_dout_8<=idle_out;
		elsif current_state(6)='1' then
			next_dout_8<=reading_out;
		elsif current_state(7)='1' then
			next_dout_8<=idle_out;
		elsif current_state(8)='1' then
			if data_ended='1' then
				if cur_address>sd_card_size-write_block_length and real_address='1' then
					next_dout_8<=dresponse_write_error;
				elsif crc_result_data='1' then
					next_dout_8<=dresponse_crc_error;
				else
					next_dout_8<=dresponse_accept;
				end if;
			else
				next_dout_8<=idle_out;
			end if;
		elsif current_state(9)='1' then
			next_dout_8<=buzy_response;
		elsif current_state(10)='1' then
			next_dout_8<=buzy_response;
		else
			next_dout_8<=sendnum_out;
		end if;
	end process;
---output part, change byte to bit
	
	process(res, clk)
	begin
		if res='1' then
			do_buf<=(others=>'1');
		elsif clk='0' and clk'event then
			if cnt_8=0 then
				do_buf<=dout_8;
			else
				do_buf(7 downto 1)<=do_buf(6 downto 0);
				do_buf(0)<='1';
			end if;
		end if;
	end process;
	
	process(cs, do_buf)
	begin
		if cs='0' then
			do<=do_buf(7);
		else
			do<='Z';
		end if;
	end process;
	
	test_clk0<=clk0;
	test_ram_out<=ram_out;
	test_current_state<=current_state;
	
end architecture;

⌨️ 快捷键说明

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