📄 sd_wr.vhd
字号:
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 + -