📄 sdtestbench.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 + -