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

📄 sd_wr.vhd

📁 SD卡读卡器模块的VHDL及软件驱动代码
💻 VHD
📖 第 1 页 / 共 2 页
字号:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use WORK.sd_wr_state.all;

entity sd_wr is
	generic
	(
		BLOCK_LEN_LOG2:	integer := 9;
		FIFO_DEPTH_LOG2:integer := 11
	);
	port
	(
		clk:			in std_logic;	-- sd clk
		areset:			in std_logic;	-- async reset
		init:			in std_logic;	-- from sd_rd (async)
		read:			in std_logic;	-- from sd_rd (async)
		readm:			in std_logic;	-- from sd_rd (async)
		dataaddr:		in std_logic_vector( 31 downto 0 ); -- from sd_rd (async)
		autoreread:		in std_logic;	-- from sd_rd (async)
		sc_buzy:		in std_logic;	-- from sendcmd
		sc_q:			in std_logic;	-- from sendcmd
		rr_buzy:		in std_logic;	-- from recvresp
		rr_content:		in std_logic_vector( 126 downto 0 ); -- from recvresp
		rr_crcerr:		in std_logic;	-- from recvresp
		rd_buzy:		in std_logic;	-- from recvdata
		rd_crcerr:		in std_logic;	-- from recvdata
		wrusedw:		in std_logic_vector( 11 downto 0 ); -- from dcfifo
		sd_cmd:			inout std_logic; -- sd cmt
		sd_data:		inout std_logic_vector( 3 downto 0 ); -- sd data
		buzy:			out std_logic;	-- to sd_rd (async)
		cardready:		out std_logic;	-- to sd_rd (async)
		sc_send:		out std_logic;	-- to sendcmd
		sc_cmdno:		out std_logic_vector( 5 downto 0 ); -- to sendcmd
		sc_content:		out std_logic_vector( 31 downto 0 ); -- to sendcmd
		rr_recv:		out std_logic;	-- to recvresp
		rr_longresp:	out std_logic;	-- to recvresp
		rr_cmd:			out std_logic;	-- to recvresp
		rd_recv:		out std_logic;	-- to recvdata
		rd_data:		out std_logic_vector( 3 downto 0 ); -- to recvdata
--------------- for debug ---------------------
--		ostat:			out SD_WR_STAT;
-----------------------------------------------
		aclr:			out std_logic	-- to dcfifo
	);
end sd_wr;

architecture RTL of sd_wr is
	
	constant BLOCK_LEN:	integer := 2 ** BLOCK_LEN_LOG2;
	constant FIFO_DEPTH:integer := 2 ** FIFO_DEPTH_LOG2;
	constant WRITE_TH:	integer := FIFO_DEPTH - BLOCK_LEN;
	
	constant CARD_STATUS_ERROR_BIT:	integer := 19;
	
	signal init_r:		std_logic;
	signal read_r:		std_logic;
	signal readm_r:		std_logic;
	signal dataaddr_r:	std_logic_vector( 31 downto 0 );
	signal autoreread_r:std_logic;
	
	signal stat:		SD_WR_STAT;
	signal stat_next:	SD_WR_STAT;
	signal cnt_q:		integer range 0 to 127;
	signal cnt_d:		integer range 0 to 127;
	
	-- for streaming read
	signal traceaddr:	std_logic;	-- latch
	signal straddr:		std_logic_vector( 31 downto 0 ); -- latch
	
	signal RCA:			std_logic_vector( 15 downto 0 ); -- latch
	signal sc_buzy_reg:	std_logic; -- registered sc_buzy
	signal rr_buzy_reg:	std_logic; -- registered rr_buzy
	signal rd_buzy_reg:	std_logic; -- registered rd_buzy
	signal sc_buzy_dl:	std_logic; -- delayed sc_buzy
	signal rr_buzy_dl:	std_logic; -- delayed rr_buzy
	signal rd_buzy_dl:	std_logic; -- delayed rd_buzy
	signal buzy_r:		std_logic;
	signal cardready_r:	std_logic; -- latch
	
begin
	
	Reg_async: process( clk, init, read, readm, dataaddr, autoreread )
	begin
		if( rising_edge( clk ) ) then
			init_r <= init;
			read_r <= read;
			readm_r <= readm;
			dataaddr_r <= dataaddr;
			autoreread_r <= autoreread;
		end if;
	end process Reg_async;
	
	Reg_buzy: process( clk, sc_buzy, rr_buzy, rd_buzy,  sc_buzy_reg, rr_buzy_reg, rd_buzy_reg )
	begin
		if( rising_edge( clk ) ) then
			sc_buzy_dl <= sc_buzy_reg;
			rr_buzy_dl <= rr_buzy_reg;
			rd_buzy_dl <= rd_buzy_reg;
			sc_buzy_reg <= sc_buzy;
			rr_buzy_reg <= rr_buzy;
			rd_buzy_reg <= rd_buzy;
		end if;
	end process Reg_buzy;
	
	Stat_P: process( clk, areset, stat_next )
	begin
		if( rising_edge( clk ) ) then
			if( areset = '1' ) then
				stat <= SD_WR_INIT;
			else
				stat <= stat_next;
			end if;
		end if;
	end process Stat_P;
	
	Stat_next_P: process( stat, init_r, read_r, cnt_q, sc_buzy, rr_buzy, rd_buzy, sc_buzy_dl, rr_buzy_dl, rd_buzy_dl, rr_crcerr, rr_content, rd_crcerr, autoreread_r, readm_r, traceaddr, wrusedw )
	begin
		case stat is
			
			when SD_WR_INIT =>
				stat_next <= SD_WR_IDLE;
			
			when SD_WR_IDLE =>
				stat_next <= SD_WR_IDLE;
				if( init_r = '1' ) then
					stat_next <= SD_WR_PRE_WAIT_PWRUP;
				end if;
				if( read_r = '1' or readm_r = '1' ) then
					stat_next <= SD_WR_CLEAR_BUFFER;
				end if;
			
			-- reset the card
			when SD_WR_PRE_WAIT_PWRUP =>
				stat_next <= SD_WR_WAIT_PWRUP;
				
			when SD_WR_WAIT_PWRUP =>
				if( cnt_q = 0 ) then
					stat_next <= SD_WR_SEND_CMD0;
				else
					stat_next <= SD_WR_WAIT_PWRUP;
				end if;
			
			when SD_WR_SEND_CMD0 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_PRE_WAIT_READY;
				else
					stat_next <= SD_WR_SEND_CMD0;
				end if;
			
			-- wait for the card to be ready
			when SD_WR_PRE_WAIT_READY =>
				stat_next <= SD_WR_WAIT_READY;
				
			when SD_WR_WAIT_READY =>
				if( cnt_q = 0 ) then
					stat_next <= SD_WR_SEND_CMD55;
				else
					stat_next <= SD_WR_WAIT_READY;
				end if;
			
			when SD_WR_SEND_CMD55 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R1_TO_CMD55;
				else
					stat_next <= SD_WR_SEND_CMD55;
				end if;
			
			when SD_WR_RECV_R1_TO_CMD55 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					if( rr_crcerr = '1' or rr_content(CARD_STATUS_ERROR_BIT) = '1' ) then
						stat_next <= SD_WR_INIT_FAILED;
					else
						stat_next <= SD_WR_SEND_ACMD41;
					end if;
				else
					stat_next <= SD_WR_RECV_R1_TO_CMD55;
				end if;
			
			when SD_WR_SEND_ACMD41 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R3_TO_ACMD41;
				else
					stat_next <= SD_WR_SEND_ACMD41;
				end if;
			
			when SD_WR_RECV_R3_TO_ACMD41 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					if( rr_content(31) = '1' ) then
						stat_next <= SD_WR_SEND_CMD2;
					else
						stat_next <= SD_WR_PRE_WAIT_READY;
					end if;
				else
					stat_next <= SD_WR_RECV_R3_TO_ACMD41;
				end if;
			
			-- continue init the card
			when SD_WR_SEND_CMD2 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R2_TO_CMD2;
				else
					stat_next <= SD_WR_SEND_CMD2;
				end if;
			
			when SD_WR_RECV_R2_TO_CMD2 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					stat_next <= SD_WR_SEND_CMD3;
				else
					stat_next <= SD_WR_RECV_R2_TO_CMD2;
				end if;
			
			when SD_WR_SEND_CMD3 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R6_TO_CMD3;
				else
					stat_next <= SD_WR_SEND_CMD3;
				end if;
			
			when SD_WR_RECV_R6_TO_CMD3 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					if( rr_crcerr = '1' ) then
						stat_next <= SD_WR_INIT_FAILED;
					else
						stat_next <= SD_WR_RECORD_RCA;
					end if;
				else
					stat_next <= SD_WR_RECV_R6_TO_CMD3;
				end if;
			
			when SD_WR_RECORD_RCA =>
				stat_next <= SD_WR_SEND_CMD9;
			
			when SD_WR_SEND_CMD9 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R2_TO_CMD9;
				else
					stat_next <= SD_WR_SEND_CMD9;
				end if;
			
			when SD_WR_RECV_R2_TO_CMD9 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					stat_next <= SD_WR_SEND_CMD7;
				else
					stat_next <= SD_WR_RECV_R2_TO_CMD9;
				end if;
			
			when SD_WR_SEND_CMD7 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R1_TO_CMD7;
				else
					stat_next <= SD_WR_SEND_CMD7;
				end if;
			
			when SD_WR_RECV_R1_TO_CMD7 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					if( rr_crcerr = '1' or rr_content(CARD_STATUS_ERROR_BIT) = '1' ) then
						stat_next <= SD_WR_INIT_FAILED;
					else
						stat_next <= SD_WR_SEND_CMD55_2;
					end if;
				else
					stat_next <= SD_WR_RECV_R1_TO_CMD7;
				end if;
			
			-- set 4 line mode
			when SD_WR_SEND_CMD55_2 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R1_TO_CMD55_2;
				else
					stat_next <= SD_WR_SEND_CMD55_2;
				end if;
			
			when SD_WR_RECV_R1_TO_CMD55_2 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					if( rr_crcerr = '1' or rr_content(CARD_STATUS_ERROR_BIT) = '1' ) then
						stat_next <= SD_WR_INIT_FAILED;
					else
						stat_next <= SD_WR_SEND_ACMD6;
					end if;
				else
					stat_next <= SD_WR_RECV_R1_TO_CMD55_2;
				end if;
			
			when SD_WR_SEND_ACMD6 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R1_TO_ACMD6;
				else
					stat_next <= SD_WR_SEND_ACMD6;
				end if;
			
			when SD_WR_RECV_R1_TO_ACMD6 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					if( rr_crcerr = '1' or rr_content(CARD_STATUS_ERROR_BIT) = '1' ) then
						stat_next <= SD_WR_INIT_FAILED;
					else
						stat_next <= SD_WR_SEND_CMD16;
					end if;
				else
					stat_next <= SD_WR_RECV_R1_TO_ACMD6;
				end if;
			
			-- set block length
			when SD_WR_SEND_CMD16 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R1_TO_CMD16;
				else
					stat_next <= SD_WR_SEND_CMD16;
				end if;
			
			when SD_WR_RECV_R1_TO_CMD16 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					if( rr_crcerr = '1' or rr_content(CARD_STATUS_ERROR_BIT) = '1' ) then
						stat_next <= SD_WR_INIT_FAILED;
					else
						stat_next <= SD_WR_INIT_SUCCESS;
					end if;
				else
					stat_next <= SD_WR_RECV_R1_TO_CMD16;
				end if;
			
			-- init finished
			when SD_WR_INIT_FAILED =>
				stat_next <= SD_WR_IDLE;
			
			when SD_WR_INIT_SUCCESS =>
				stat_next <= SD_WR_IDLE;
			
			-- start read
			when SD_WR_CLEAR_BUFFER =>
				if( readm_r = '0' ) then
					stat_next <= SD_WR_SEND_CMD17;
				else
					stat_next <= SD_WR_REC_ADDR;
				end if;
			
			-- read single block
			when SD_WR_SEND_CMD17 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_DATA;
				else
					stat_next <= SD_WR_SEND_CMD17;
				end if;
			
			when SD_WR_RECV_DATA =>
				if( rd_buzy_dl = '1' and rd_buzy = '0' ) then
					if( rd_crcerr = '1' and autoreread_r = '1' ) then
						stat_next <= SD_WR_CLEAR_BUFFER;
					else
						stat_next <= SD_WR_IDLE;
					end if;
				else
					stat_next <= SD_WR_RECV_DATA;
				end if;
			
			-- streaming read
			when SD_WR_REC_ADDR =>
				stat_next <= SD_WR_SEND_CMD18;
			
			when SD_WR_SEND_CMD18 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_STRRECV_DATA;
				else
					stat_next <= SD_WR_SEND_CMD18;
				end if;
			
			when SD_WR_STRRECV_DATA =>
				if( rd_buzy_dl = '1' and rd_buzy = '0' ) then
					if( traceaddr = '0' ) then
						stat_next <= SD_WR_SEND_CMD12;
					else
						stat_next <= SD_WR_INC_ADDR;
					end if;
				else
					stat_next <= SD_WR_STRRECV_DATA;
				end if;
			
			when SD_WR_INC_ADDR =>
				if( wrusedw <= WRITE_TH ) then
					stat_next <= SD_WR_STRRECV_DATA;
				else
					stat_next <= SD_WR_SEND_CMD12;
				end if;
			
			when SD_WR_SEND_CMD12 =>
				if( sc_buzy_dl = '1' and sc_buzy = '0' ) then
					stat_next <= SD_WR_RECV_R1b_TO_CMD12;
				else
					stat_next <= SD_WR_SEND_CMD12;
				end if;
			
			when SD_WR_RECV_R1b_TO_CMD12 =>
				if( rr_buzy_dl = '1' and rr_buzy = '0' ) then
					if( traceaddr = '0' ) then
						stat_next <= SD_WR_IDLE;
					else
						stat_next <= SD_WR_STRRECV_PAUSE;
					end if;
				else

⌨️ 快捷键说明

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