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

📄 recvdata.vhd

📁 SD卡读卡器模块的VHDL及软件驱动代码
💻 VHD
字号:
library IEEE;
use IEEE.std_logic_1164.all;
use WORK.pck_CRC16.all;

entity recvdata is
	generic
	(
		BLOCK_LEN_LOG2:	integer := 9
	);
	port
	(
		clk:		in std_logic;
		areset:		in std_logic;	-- async reset
		recv:		in std_logic;	-- from sd_wr
		data:		in std_logic_vector( 3 downto 0 ); -- sd_data
		buzy:		out std_logic;	-- buzy receiving
		crcerr:		out std_logic;	-- data crc error (async)
		wrreq:		out std_logic;	-- to dcfifo
------------- for debug -------------------
--		obitcnt:	out integer range 0 to 7;
--		ocnt:		out integer range 0 to 4095;
--		ocrc:		out std_logic_vector( 15 downto 0 );
-------------------------------------------
		q:			out std_logic_vector( 7 downto 0 ) -- to dcfifo
	);
end recvdata;

architecture RTL of recvdata is
	
	type RD_STAT is
	(
		RD_INIT,
		RD_IDLE,		-- load counter and init crc calculator
		RD_WAITRECV,	-- wait for '0'
		RD_PRERECVDATA,	-- recv first bit
		RD_RECVDATA,	-- recv data
		RD_PRECHECKCRC,	-- pre-check crc( load counter and check first bit )
		RD_CHECKCRC,	-- check crc
		RD_CRCPASS,	-- crc check passed
		RD_CRCFAIL,	-- crc check failed
		RD_WAITFINISH,	-- wait for receiving data finished
		RD_WAITRECVEND	-- wait for "recv" become low
	);

	constant LINE_NUM:		integer := 4;
	
	constant BLOCK_LEN:		integer := 2 ** BLOCK_LEN_LOG2;
	constant BLOCK_BITS:	integer := BLOCK_LEN * 8 / LINE_NUM;
	constant BITCNT_UPPER:	integer := (8 / LINE_NUM) - 1;
	
	signal stat:		RD_STAT;
	signal stat_next:	RD_STAT;
	signal cnt_q:		integer range 0 to BLOCK_BITS - 1;
	signal cnt_d:		integer range 0 to BLOCK_BITS - 1;
	signal bitcnt_q:	integer range 0 to BITCNT_UPPER;
	signal bitcnt_d:	integer range 0 to BITCNT_UPPER;
	signal crc0:		std_logic_vector( 15 downto 0 );
	signal crc1:		std_logic_vector( 15 downto 0 );
	signal crc2:		std_logic_vector( 15 downto 0 );
	signal crc3:		std_logic_vector( 15 downto 0 );
	signal crc0_next:	std_logic_vector( 15 downto 0 );
	signal crc1_next:	std_logic_vector( 15 downto 0 );
	signal crc2_next:	std_logic_vector( 15 downto 0 );
	signal crc3_next:	std_logic_vector( 15 downto 0 );
	
	signal crcerr_r:	std_logic;
	
	signal shiftreg:	std_logic_vector( 7 downto 0 ); -- latch
	
begin
	
	Stat_P: process( clk, areset, stat_next )
	begin
		if( areset = '1' ) then
			stat <= RD_INIT;
		elsif( rising_edge( clk ) ) then
			stat <= stat_next;
		end if;
	end process Stat_P;
	
	Stat_next_P: process( stat, recv, data, cnt_q, crc0, crc1, crc2, crc3 )
	begin
		case stat is
			
			when RD_INIT =>
				stat_next <= RD_IDLE;
			
			when RD_IDLE =>
				if( recv = '1' ) then
					stat_next <= RD_WAITRECV;
				else
					stat_next <= RD_IDLE;
				end if;
			
			when RD_WAITRECV =>
				if( data(0) = '0' ) then
					stat_next <= RD_PRERECVDATA;
				else
					stat_next <= RD_WAITRECV;
				end if;
			
			when RD_PRERECVDATA =>
				stat_next <= RD_RECVDATA;
			
			when RD_RECVDATA =>
				if( cnt_q = 0 ) then
					stat_next <= RD_PRECHECKCRC;
				else
					stat_next <= RD_RECVDATA;
				end if;
			
			when RD_PRECHECKCRC =>
				if( crc0(15) = data(0) and crc1(15) = data(1) and crc2(15) = data(2) and crc3(15) = data(3) ) then
					stat_next <= RD_CHECKCRC;
				else
					stat_next <= RD_CRCFAIL;
				end if;
			
			when RD_CHECKCRC =>
				if( crc0(cnt_q) = data(0) and crc1(cnt_q) = data(1) and crc2(cnt_q) = data(2) and crc3(cnt_q) = data(3) ) then
					if( cnt_q = 0 ) then
						stat_next <= RD_CRCPASS;
					else
						stat_next <= RD_CHECKCRC;
					end if;
				else
					stat_next <= RD_CRCFAIL;
				end if;
			
			when RD_CRCPASS =>
				if( recv = '1' ) then
					stat_next <= RD_WAITRECVEND;
				else
					stat_next <= RD_IDLE;
				end if;
			
			when RD_CRCFAIL =>
				if( cnt_q = 0 ) then
					if( recv = '1' ) then
						stat_next <= RD_WAITRECVEND;
					else
						stat_next <= RD_IDLE;
					end if;
				else
					stat_next <= RD_WAITFINISH;
				end if;
			
			when RD_WAITFINISH =>
				if( cnt_q = 0 ) then
					if( recv = '1' ) then
						stat_next <= RD_WAITRECVEND;
					else
						stat_next <= RD_IDLE;
					end if;
				else
					stat_next <= RD_WAITFINISH;
				end if;
				
			when RD_WAITRECVEND =>
				if( recv = '1' ) then
					stat_next <= RD_WAITRECVEND;
				else
					stat_next <= RD_IDLE;
				end if;
			
			when others =>
				stat_next <= RD_INIT;
			
		end case;
	end process Stat_next_P;
	
	Cnt_q_P: process( clk, stat, cnt_d )
	begin
		if( rising_edge( clk ) ) then
			case stat is
				
				when RD_IDLE =>
					cnt_q <= BLOCK_BITS - 1;
					
				when RD_WAITRECV =>
					cnt_q <= BLOCK_BITS - 1;
				
				when RD_PRECHECKCRC =>
					cnt_q <= 15 - 1;
				
				when others =>
					cnt_q <= cnt_d;
				
			end case;
		end if;
	end process Cnt_q_P;
	
	Cnt_d_P: process( cnt_q )
	begin
		if( cnt_q > 0 ) then
			cnt_d <= cnt_q - 1;
		else
			cnt_d <= 0;
		end if;
	end process Cnt_d_P;
	
	Bitcnt_q_P: process( clk, stat, bitcnt_d )
	begin
		if( rising_edge( clk ) ) then
			case stat is
				
				when RD_WAITRECV =>
					bitcnt_q <= 0;
				
				when others =>
					bitcnt_q <= bitcnt_d;
				
			end case;
		end if;
	end process Bitcnt_q_P;
	
	Bitcnt_d_P: process( bitcnt_q )
	begin
		bitcnt_d <= bitcnt_q + 1;
	end process Bitcnt_d_P;
	
	Crc_P: process( clk, crc0, crc1, crc2, crc3, crc0_next, crc1_next, crc2_next, crc3_next )
	begin
		if( rising_edge( clk ) ) then
			case stat is
				
				when RD_INIT =>
					crc0 <= ( others => '0' );
					crc1 <= ( others => '0' );
					crc2 <= ( others => '0' );
					crc3 <= ( others => '0' );
				
				when RD_IDLE =>
					crc0 <= ( others => '0' );
					crc1 <= ( others => '0' );
					crc2 <= ( others => '0' );
					crc3 <= ( others => '0' );
				
				when RD_PRERECVDATA =>
					crc0 <= crc0_next;
					crc1 <= crc1_next;
					crc2 <= crc2_next;
					crc3 <= crc3_next;
				
				when RD_RECVDATA =>
					crc0 <= crc0_next;
					crc1 <= crc1_next;
					crc2 <= crc2_next;
					crc3 <= crc3_next;
				
				when others =>
					crc0 <= crc0;
					crc1 <= crc1;
					crc2 <= crc2;
					crc3 <= crc3;
				
			end case;
		end if;
	end process Crc_P;
	
	Crc_next_P: process( crc0, crc1, crc2, crc3, data )
	begin
		crc0_next <= nextCRC16( data(0), crc0 );
		crc1_next <= nextCRC16( data(1), crc1 );
		crc2_next <= nextCRC16( data(2), crc2 );
		crc3_next <= nextCRC16( data(3), crc3 );
	end process Crc_next_P;
	
	Buzy_P: process( stat )
	begin
		case stat is
			
			when RD_IDLE =>
				buzy <= '0';
			
			when RD_WAITRECVEND =>
				buzy <= '0';
			
			when others =>
				buzy <= '1';
			
		end case;
	end process;
	
	Shiftreg_P: process( clk, stat, data, shiftreg )
	begin
		if( rising_edge( clk ) ) then
			
			shiftreg <= shiftreg;
			
			case stat is
				
				when RD_PRERECVDATA =>
					shiftreg( 7 downto 4 ) <= shiftreg( 3 downto 0 );
					shiftreg( 3 downto 0 ) <= data;
				
				when RD_RECVDATA =>
					shiftreg( 7 downto 4 ) <= shiftreg( 3 downto 0 );
					shiftreg( 3 downto 0 ) <= data;
				
				when others =>
				
			end case;
		end if;
	end process Shiftreg_P;
	
	Output: process( stat, shiftreg, data, bitcnt_q )
	begin
		
		wrreq <= '0';
		q <= shiftreg;
		
		case stat is
			
			when RD_RECVDATA =>
				if( bitcnt_q = 0 ) then
					wrreq <= '1';
				end if;
			
			when RD_CRCPASS =>
				wrreq <= '1';
			
			when RD_CRCFAIL =>
				wrreq <= '1';
			
			when others =>
			
		end case;
	end process Output;
	
	Async_output: process( clk, crcerr_r )
	begin
		if( rising_edge( clk ) ) then
			
			crcerr_r <= crcerr_r;
			
			case stat is
				
				when RD_INIT =>
					crcerr_r <= '0';
				
				when RD_CRCPASS =>
					crcerr_r <= '0';
				
				when RD_CRCFAIL =>
					crcerr_r <= '1';
				
				when others =>
				
			end case;
		end if;
	end process Async_output;
	
	crcerr <= crcerr_r;
	
------------- for debug -------------------
--	obitcnt <= bitcnt_q;
--	ocnt <= cnt_q;
--	ocrc <= crc;
-------------------------------------------
	
end RTL;

⌨️ 快捷键说明

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