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

📄 sdtestbench.vhd

📁 这是一个SD卡的TESTBENCH,源码中有如何产生一个特定的命令序列的样例。支持产生任何的SD卡交互过程中用到的命令序列。
💻 VHD
字号:
---------------------------------------------------------------------------------------------------
--
-- Title       : SDTestBench
-- Design      : SDCardTest
-- Author      : Huarui
-- Company     : Tsinghua
--
---------------------------------------------------------------------------------------------------

--
-- Description : 
--
---------------------------------------------------------------------------------------------------

--{{ Section below this comment is automatically maintained
--   and may be overwritten
--{entity {SDTestBench} architecture {SDTestBench}}


--SD卡的TestBench
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;  
use ieee.std_logic_arith.all; 
use work.PCK_CRC7_D40.all;
entity TestBenchSDTester is 
end entity TestBenchSDTester;
architecture TestBenchSDTesterArc of TestBenchSDTester is 

component CRC16Generator
	PORT ( RST:in std_logic;--异步清零
		TestData:in std_logic;--在时钟上升沿时读入的数据
		Clock:in std_logic;--控制时钟
		Hold:in std_logic;--保持数据,为1时则即使读入新数据输出不变
		CRC:out std_logic_vector(15 downto 0)); --16位CRC校验码
end component ;
component sdcard_spi 
	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;
		do:out std_logic
	); 
end component;
constant Period:time:=50 ns;
constant Period8:time:=400 ns;
constant WaitPeriod:time:=100 ns;

--Single Start Token
constant SinStarToken:std_logic_vector(7 downto 0):="11111110";

--Single Start Token
constant MulStarToken:std_logic_vector(7 downto 0):="11111100";

--Multiple Stop Token
constant MulStopToken:std_logic_vector(7 downto 0):="11111101";



type DatTokenType is (SinStart,MulStart,MulStop);
--第一部分,与SD卡的HDL相对接的一些signal,
signal Rst:std_logic:='0';
signal Cs:std_logic:='1';
signal TempCs:std_logic:='0';
signal TempDin:std_logic:='0';
signal TempDout:std_logic:='0';
signal CsBack:std_logic:='1';  --每当到8个时钟时,CS为CsBack
signal Clock1:std_logic:='1'; 
signal ClockCheck:std_logic:='0';
signal Clock8:std_logic:='0';
signal ClockRandom:std_logic:='0';--随机时钟
signal Din:std_logic:='1';
signal Dout:std_logic:='0';	

signal Clock1Cnt:integer:=0; 


--第二部分,与测试端相对应的一些signal; 
signal CmdTrans:boolean:=true;--发送的是cmd还是Data
signal CmdStart:std_logic:='0';
signal CmdEnable:std_logic:='1';--为1时组装以CmdId为号的command;默认下不允许发送命令
signal CmdBuffer:std_logic_vector(47 downto 0):=(others=>'0'); --存储要发送的Cmd信息
signal CmdSendBuffer:std_logic_vector(47 downto 0):=(others=>'0');--发送的触发器Buffer.
--signal CmdBufferBack:std_logic_vector(47 downto 0):=(others=>'0');
signal CmdPrepared:std_logic:='0';--为1时发送Cmd;
signal CmdId:std_logic_vector(5 downto 0); --表示要发送的命令的ID;
signal CmdIdUns: integer range 0 to 63:=0;
signal CmdSending:std_logic:='0';--在时钟14,15时为1.
signal CmdSended:integer:=48;--已经发送出去的位数. 
signal CmdArg:std_logic_vector(31 downto 0):=(others=>'0');--Cmd的Argument部分	  
--signal CmdSendFinished:std_logic;


--第三部分,发送Data相对应的一些signal 
signal DatNedCRC16:std_logic:='1';
signal DatByteNum:integer range 0 to 512:=0;--传送的DataBlock的长度0 to 512,表示发送的DataBlock中数据部分的长度.
signal DatEnable:std_logic:='1';											  
signal DatStart:std_logic:='0';
signal DatRandom:integer:=0;--从0开始,到289,与Clock1Cnt相乘取模为随便  
signal DatBuffer:std_logic_vector(7 downto 0):=(others=>'0');--发送的DatBuffer
signal DatSendBuffer:std_logic_vector(7 downto 0):=(others=>'0');--即时发送的DatBufferBack 
signal DatSending:std_logic:='0';
signal DatSended:integer :=4120;--已经发送出去的位数
signal DatToken:DatTokenType:=SinStart;--DataToken的类型   

signal CRC16Rst:std_logic:='0';
signal CRC16Hold:std_logic:='0';
signal CRC16Out:std_logic_vector(15 downto 0):=(others=>'0');  

begin 	

	UUT1: entity work.sdcard_spi
		port map (Rst,TempCs,Clock8,TempDin,TempDout);
		
	--一个时钟周期为50ns;
	--一个Period8 为 400ns;
	--ConCurent;  
	
	CmdTrans<=true  after 0 ns,
	false after 40*Period8,
	true after 1250*Period8;
	
	CsBack<='0' after 1/2*Period8;
	
	DatToken<=SinStart after 0ns;
	--MulStart after 10*Period8,
	--MulStop after 1000*Period8;
	
	DatStart<='1' after 40*Period8,
	'0' after 41*Period8;
	--'1' after 10*Period8,
	--'0' after 11*Period8,
	--'1' after 1000*Period8,
	--'0' after 1001*Period8;
	
	
	DatByteNum<=512 after 0ns,
	512 after 10*Period8,
	512 after 1001*Period8;
	
	
		--CmdId<=conv_std_logic_vector(0,6) after 0*Period8, --0
		--conv_std_logic_vector(25,6) after 9*Period8;	--5
	CmdIdUns<=0 after 0*Period8,
	55 after 10*Period8,
	41 after 20*Period8,
	24 after 30*Period8,
	17 after 1250*Period8;
		
		--要覆盖整个周期,下一个周期发送	
		--400秒决定发送Cmd
	CmdStart<='1' after 0*Period8,--0ns
		'0' after 1*Period8,--1
		'1' after 10*Period8,
		'0' after 11*Period8,
		'1' after 20*Period8,
		'0' after 21*Period8,
		'1' after 30*Period8,
		'0' after 31*Period8,
		'1' after 1250*Period8,
		'0' after 1251*Period8;
	
	CmdArg(3 downto 0)<="0001" after 30*Period8,
	"0000" after 1250*Period8;
	
	
	
	Clock1Process: process(Clock1)
	begin 									 
		--50 ns;
		Clock1<=not Clock1 after  Period/2;
	end process;
	
	
	--产生Clock1Cnt;
	Clock1CntProcess:
	process(Clock1)
	begin 
		if (Clock1='1' or Clock1='0') and Clock1'event then 
			If Clock1Cnt+1>=16 then 
				Clock1Cnt<=0;
			else
				Clock1Cnt<=Clock1Cnt+1;	
			end if;
		end if;
	end process;
	
	
	DatRandomProcess:
	process(Clock1)
	begin
		if Clock1='1' and Clock1'event then 
			if DatRandom+1>289 then 
				DatRandom<=0;
			else
				DatRandom<=DatRandom+1;
			end if;
		end if ;
	end process;
	
	
	Clock8Process: process(Clock8)
	begin
		Clock8<=not Clock8 after Period*4;	
	end process;						  
	
	ClockCheckProcess: process(ClockCheck)
	begin 		
		ClockCheck<=not ClockCheck after Period/4;
	end process;  
	
	ClockRandomProcess:
	process(ClockRandom)
	begin
		ClockRandom<=not ClockRandom after 3*Period/2;
	end process;
	
	CRC16GeneratorMap: CRC16Generator port map (RST=>CRC16Rst,TestData=>Din,Clock=>Clock1,Hold=>CRC16Hold,CRC=>CRC16Out);
	
	--0,1,2,3,....,14,15,0
	--产生CS信号
	MakeCsprocess:
	process(Clock1,CsBack)
	begin 													 
		If Clock1='0' and Clock1'event and Clock1Cnt=14 then 
			Cs<=CsBack;
		end if;				
	end process;
	
	
	
	--产生发送命令的使有信号.
	--MakeCmdEnableProcess:
	process(CmdStart)
	begin 	
		if CmdStart='1' and CmdStart'event then 
			CmdEnable<='1';
		end if;
	end process;  
	
	
	CmdIdProcess:
	process(CmdIdUns)
	begin
		CmdId<=conv_std_logic_vector(CmdIdUns,6);
	end process;
	
	
	--千万不能写出一个空的process,一个空的process......
	--SendCommandProcess: process
	--begin		
	--end process;
	
	--当CmdEnable为1时组装命令Buffer.
	MakeCommandProcess:
	process (CmdEnable,Clock1)
	begin 		
		If CmdEnable='1'  and Clock1='1' and Clock1'event  then 	--可以组装Cmd
			CmdBuffer(47)<='0';
			CmdBuffer(46)<='1';	   
			CmdBuffer(45 downto 40)<=CmdId;	
			CmdBuffer(39 downto 8)<=CmdArg(31 downto 0); 
			CmdBuffer(7 downto 1)<=nextCRC7_D40(CmdBuffer(47 downto 8),"0000000");
			CmdBuffer(0)<='1';--The End Bit;
			CmdPrepared<='1';
			
		end if;
	end process;
	
	
	SendCommandConditionProcess:
	process(Clock1,CmdStart,CmdEnable,CmdPrepared,Clock1Cnt,CmdTrans)
	begin		
		If  Clock1='1' and Clock1'event and CmdTrans=true then 
			--CmdSending 覆盖14,15
			if Clock1Cnt=13	and CmdEnable='1' and CmdStart='1'   then 
				CmdSending<='1';--发送条件满足
			else
				CmdSending<='0';
			end if;
		end if;
	end process;  
	
	SendDataProcess:
	process(Clock1,DatStart,DatEnable,Clock1Cnt,CmdTrans)
	begin 
		If Clock1='1' and Clock1'event and CmdTrans=false then 
			if Clock1Cnt=13 and DatEnable='1' and DatStart='1' then 
				DatSending<='1';
			else
				DatSending<='0';
			end if;
		end if;
	end process;
	
	CRC16RstProcess:--14时为1, 清零
	process(Clock1,DatStart,DatEnable,Clock1Cnt,CmdTrans)
	begin 
		If Clock1'event and CmdTrans=false then 
			if Clock1='1' and Clock1Cnt=13 and DatEnable='1' and DatStart='1' then 
				CRC16Rst<='1';
			else
				CRC16Rst<='0';	
			end if;
		end if;
	end process;

	--找到了发送的条件
	SendingCommandProcess:
	process(Clock1,CmdEnable,CmdSending,CmdSendBuffer,DatEnable,DatSending,DatSendBuffer)
	begin			 
		if   Clock1='0' and Clock1'event then 
		   
		   if  CmdTrans=true then 
			   if CmdEnable='1' then 
			
					if CmdSending ='1'  then--CmdSending 在14,15 时为1
						CmdSendBuffer(47 downto 1)<=CmdBuffer(46 downto 0);
						Din<=CmdBuffer(47);
						CmdSended<=1;				
					elsif CmdSended<48 then  
						CmdSendBuffer(47 downto 1)<=CmdSendBuffer(46 downto 0);--触发器移位
						Din<=CmdSendBuffer(47);
						CmdSended<=CmdSended+1;
					end if;
				end if;	
			
			--if CmdSended+1>=48 then 
			--	CmdSending<='0';--结束发送
			--	CmdPrepared<='0';--要发送的命令未准备好.
			--	CmdSended<=0;--发送的数为0;					  
			--	CmdEnable<='0';--当前禁止发送命令
			--	assert (false) report "line 181";
			--end if;
		   
		  else --发送Data
			  if DatEnable='1' then 
				  if DatSending='1' then
					  Case DatToken is 
						  when SinStart=> Din<=SinStarToken(7);
						  DatSendBuffer(7 downto 1)<=SinStarToken(6 downto 0);
						  when MulStart=> Din<=MulStarToken(7);
						  DatSendBuffer(7 downto 1)<=MulStarToken(6 downto 0);
						  when MulStop=> Din<=MulStopToken(7);
						  DatSendBuffer(7 downto 1)<=MulStarToken(6 downto 0);
						  when others=> assert (false) report "Error, DatToken tyep error";
					  end case;
					  DatSended<=1;
				  else--DataSending不为1 
					  if DatSended<8 then --之前发送的小于8比特
						  Din<=DatSendBuffer(7);
						  DatSendBuffer(7 downto 1)<=DatSendBuffer(6 downto 0);
						  DatSended<=DatSended+1;
					  elsif DatToken=MulStop then --DatSended<8+DatByteNum then 
						  		Din<='1';
					  elsif DatSended<8+DatByteNum*8 then 
						  if DatSended mod 8=0 then --8bit 已经发完,再入一个新的BUFFER进来
							  Din<=DatBuffer(7);
							  DatSendBuffer(7 downto 1)<=DatBuffer(6 downto 0);
							  DatSended<=DatSended+1;
						  else 
							  Din<=DatSendBuffer(7);
							  DatSendBuffer(7 downto 1)<=DatSendBuffer(6 downto 0);
							  DatSended<=DatSended+1;
						  end if;
					  elsif DatSended<8+DatByteNum*8+16 then--没发送完CRC;
						  if DatSended=8+DatByteNum*8 then --正好发送完Token和DataBlock
							  CRC16Hold<='1';
							  Din<=CRC16Out(15);
						  	  DatSendBuffer(7 downto 1)<=CRC16Out(14 downto 8);
							  DatSended<=DatSended+1;
						  elsif DatSended=8+DatByteNum*8+8 then 
							  Din<=CRC16Out(7);
							  DatSendBuffer(7 downto 1)<=CRC16Out(6 downto 0);
							  DatSended<=DatSended+1;
						  else Din<=DatSendBuffer(7);
							  DatSendBuffer(7 downto 1)<=DatSendBuffer(6 downto 0);	
							  DatSended<=DatSended+1;
						  end if;
					  else --发送完了所有的东西
						  Din<='1';
						  CRC16Hold<='0';
						  DatSended<=4120;
					  end if;
					  
				  end if;-- if DatSending='1' then
			  end if;--if DatEnable='1' then
			  
		  end if;--if  CmdTrans=true then 
		end if;--if   Clock1='0' and Clock1'event then
	end process;
	
	
	--产生随机发送数据
	RandomDataProcess:
	process(Clock1,DatRandom,Clock1Cnt)
	begin
		if Clock1='1' and Clock1'event then 
			DatBuffer<=conv_std_logic_vector(Clock1Cnt*DatRandom,8);
		end if;
	end process;
	
end architecture TestBenchSDTesterArc;

⌨️ 快捷键说明

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