📄 crc16.vhd
字号:
-- File: crc16.vhd
--{entity {crc16} architecture {crc16}}
library IEEE;
use IEEE.std_logic_1164.all;
use work.PCK_CRC16_D8.all;
entity CRC16 is
port (
DATA: in STD_LOGIC_VECTOR (7 downto 0);
WR: in STD_LOGIC;
RD: in STD_LOGIC;
ENABLE: in STD_LOGIC;
WRITE_CRC_EN: in std_logic; -- tells CRC_OUT to reset result ready because tx finished reading the results
CRC_OUT: buffer STD_LOGIC_VECTOR (15 downto 0);
RESULT_READY: out std_logic;
CLK: in STD_LOGIC;
RX_TX: in STD_LOGIC;
CRC_RX_RESULT : out STD_LOGIC_VECTOR (7 downto 0);
IGNORE_DATA: out STD_LOGIC;
RESET: in STD_LOGIC
);
end CRC16;
architecture CRC16 of CRC16 is
signal data_in : std_logic_vector ( 7 downto 0); -- data bus
signal tx_flag :std_logic; -- '1' signal new write cycle begun
signal rx_flag :std_logic; -- '1' signal new read cycle begun
signal tx_start_crc_flag : std_logic; -- '1' new Tx calculation begun
signal rx_start_crc_flag : std_logic; -- '1' new Rx calculation begun
signal preamble_skip :integer range 3 downto 0; -- '0' means we need to skeep the first write (it is preamble)
signal crc_count :integer range 7 downto 0; -- read cycle counter
begin
process (CLK, RESET)
variable crc_state : std_logic_vector(1 downto 0);
begin
if RESET='1' then --asynchronous RESET active High
CRC_OUT <= (others => '0');
data_in <= (others => '0');
rx_flag <= '0';
tx_flag <= '0';
result_ready <= '0';
rx_start_crc_flag <= '0';
tx_start_crc_flag <= '0';
preamble_skip <= 0;
crc_count <= 0;
crc_rx_result <= (others => '0');
IGNORE_DATA <= '0';
elsif (CLK'event and CLK='1') then
-- when transmitter finished reading the Tx CRC_OUT result he clears write_crc_enable
-- for 1 clock period ,when it happens we clear CRC_OUT register and result ready
crc_state := enable & RX_TX;
if write_crc_en = '0' then
result_ready <= '0';
CRC_OUT <= (others => '0');
end if;
-- these states reflects the CRC_ENABLE and RECEIVE port of the logic
-- 1. "10" in this state we perform CRC_OUT calaularion on transmitted data
-- and store the result in a 16 bit register.
-- 2. "00" in this state if we came from the previous state we sets result ready
-- for the Tx block and clear all flags for the next time.
-- 3. "11" in this state we calculate CRC_OUT for incoming packet, every read cycle
-- by the cpu generate a new check.and store the result in a 16 bit register.
-- 4. "01" in this state we transfer the result to the cpu, in two cycles
-- first the low CRC_OUT then the high CRC_OUT. we implement a read_cycle_counter that
-- help us to ignore the CRC_OUT data of the incoming packet from our CRC_OUT calculation,
-- and to put out on the bus our result in the apropriate time. to do so we need from the
-- cpu to clear the CRC_ENABLE before the CRC_OUT data of the incoming packet is
-- loaded to the system, the cpu reads the result we clear the CRC_OUT register and the flags
case crc_state is
when "11" =>
if tx_start_crc_flag ='0' then
CRC_OUT <= (others => '0');
tx_start_crc_flag <= '1';
end if;
if preamble_skip = 2 then
if (wr='1' and tx_flag='0') then
data_in <= data;
tx_flag <= '1';
elsif (wr='0' and tx_flag='1') then
CRC_OUT <= nextcrc16_d8(data_in,CRC_OUT);
tx_flag <= '0';
end if;
else
if (wr='1' and tx_flag='0') then
tx_flag <= '1';
elsif (wr='0' and tx_flag='1') then
preamble_skip <=preamble_skip+1;
tx_flag <= '0';
end if;
end if;
when "01" =>
if tx_start_crc_flag = '1' then
result_ready <= '1';
tx_start_crc_flag <= '0';
tx_flag <= '0';
preamble_skip <=0;
end if;
when "10" =>
if rx_start_crc_flag ='0' then
CRC_OUT <= (others => '0');
rx_start_crc_flag <= '1';
crc_count <= 0;
IGNORE_DATA <= '0';
end if;
if (rd='1' and rx_flag='0' ) then
data_in <= data;
rx_flag <= '1';
elsif (rd='0' and rx_flag='1') then
CRC_OUT <= nextcrc16_d8(data_in,CRC_OUT);
rx_flag <= '0';
end if;
when "00" =>
if(rd = '1' and crc_count =0 ) then
crc_count <= crc_count+1;
end if;
if (rd = '0' and crc_count =1) then -- first read end of crc-low of rcv pkt
crc_count <= crc_count+1;
end if;
if (rd = '1' and crc_count =2) then
crc_count <= crc_count+1;
end if;
if (rd = '0' and crc_count =3) then -- second read end of crc-high of rcv pkt
crc_count <= crc_count+1;
end if;
if(rd = '1' and crc_count =4 ) then
crc_count <= crc_count+1;
end if;
if (rd = '0' and crc_count =5) then -- end of reading of the low CRC_OUT result
crc_count <= crc_count+1;
end if;
if (rd = '1' and crc_count =6) then
crc_count <= crc_count+1;
end if;
if (rd = '0' and crc_count =7) then -- end of reading of the high CRC_OUT result
crc_count <= 0;
rx_flag <= '0';
rx_start_crc_flag <= '0';
IGNORE_DATA <= '0';
CRC_OUT <= (others => '0');
end if;
if (rx_start_crc_flag = '1') then
case crc_count is
when 4 =>
crc_rx_result <= CRC_OUT( 7 downto 0);
IGNORE_DATA <= '1';
when 6 =>
crc_rx_result <= CRC_OUT( 15 downto 8);
when others => null;
end case;
end if;
when others => null;
end case;
end if;
end process;
end CRC16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -