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