--345678901234567890123456789012345678901234567890123456789012345678901234567890 -------------------------------------------------------------------------------- -- -- chopped up by kelby anderson -- -- -- File name : crcgen.vhd -- -- -- -- Author : Erik Brandin, CERN, EP-Division -- -- -- -- Description : A 16 bit CRC with 16 bit look-ahead. Uses the CRC-CCITT -- -- polynomial x^16+x^12+x^5+1 -- -- To increase speed the CRC calculation is split into two clock-- -- cycles. The first cycle only the part that includes the data -- -- is XORed into signal q1, and at the next cycle this result is-- -- XORed with the previous state of the CRC, q0. -- -- With this scheme the maximum frequency is greatly increased -- -- since the numbers of XOR gates on one signal is reduces from -- -- 15 to 8. -- -- -- -- The transmitter should use the entity CRCTX which has an -- -- output multiplexer to insert the CRCC. -- -- -- -- The receiver should use the entity CRCRX which has a ERROR -- -- output that is acitve high with a latency of two clockcycles -- -- -- -- Both these entities uses CRCGEN generate CRC or calculate -- -- ERROR state. -- -- -- -- Notes : -- -- -- -- Uses files : crcgen.vhd -- -- -- -------------------------------------------------------------------------------- -- Revision History -- -------------------------------------------------------------------------------- -- Version | Date |Author| Modifications -- -------------------------------------------------------------------------------- -- | 22-07-99 | EB | Original version -- -- | | | -- -------------------------------------------------------------------------------- library IEEE; use IEEE.Std_Logic_1164.all; -------------------------------------------------------------------------------- entity CRCGEN is -------------------------------------------------------------------------------- port ( CLK : in std_logic; -- Input clock CLRCRC: in std_logic; -- Synchronous clear active -- high. A Clear signal has -- to be asserted before or -- the same cycle the first -- data word is written CALC : in std_logic; -- Calculate CRC on DIN D : in std_logic_vector (15 downto 0); -- Data Input Q : out std_logic_vector (15 downto 0) -- CRC quotient. One clock -- cycle latancy from last -- word in to CRC out. ); end CRCGEN; -------------------------------------------------------------------------------- architecture behaviour of CRCGEN is -------------------------------------------------------------------------------- signal q0 : std_logic_vector (15 downto 0); -- Internal quotient signal signal k1 : std_logic_vector (15 downto 0); signal q1 : std_logic_vector (15 downto 0); -- Partial CRC quotient signal nxt : std_logic; -- If high, q1 contains -- partial CRC signal nxt_clr: std_logic_vector (1 downto 0); -- signal used to append nxt and -- clr for case statement signal clk_n : std_logic; -------------------------------------------------------------------------------- begin -------------------------------------------------------------------------------- clk_n <= not CLK; Q <= q0; nxt_clr(1) <= nxt; nxt_clr(0) <= CLRCRC; -------------------------------------------------------------------------------- -- CRC1 calculates the part of the CRC only containing the data, and store the -- intermediate result in q1. This calculation is down even when no data is -- avilable. If CALC = '0' q1 will not be used. crc1: process(CLK,clk_n) begin if (CLK'event and CLK = '1') then q1(15) <= D(12) xor D(11) xor D(8) xor D(4) xor D(0); q1(14) <= D(13) xor D(12) xor D(9) xor D(5) xor D(1); q1(13) <= D(14) xor D(13) xor D(10) xor D(6) xor D(2); q1(12) <= D(15) xor D(14) xor D(11) xor D(7) xor D(3); q1(11) <= D(15) xor D(12) xor D(8) xor D(4); q1(10) <= D(13) xor D(12) xor D(11) xor D(9) xor D(8) xor D(5) xor D(4) xor D(0); q1(9) <= D(14) xor D(13) xor D(12) xor D(10) xor D(9) xor D(6) xor D(5) xor D(1); q1(8) <= D(15) xor D(14) xor D(13) xor D(11) xor D(10) xor D(7) xor D(6) xor D(2); q1(7) <= D(15) xor D(14) xor D(12) xor D(11) xor D(8) xor D(7) xor D(3); q1(6) <= D(15) xor D(13) xor D(12) xor D(9) xor D(8) xor D(4); q1(5) <= D(14) xor D(13) xor D(10) xor D(9) xor D(5); q1(4) <= D(15) xor D(14) xor D(11) xor D(10) xor D(6); q1(3) <= D(15) xor D(8) xor D(7) xor D(4) xor D(0); q1(2) <= D(9) xor D(8) xor D(5) xor D(1); q1(1) <= D(10) xor D(9) xor D(6) xor D(2); q1(0) <= D(11) xor D(10) xor D(7) xor D(3); nxt <= CALC; end if; if (clk_n'event and clk_n = '1') then k1 <= q1; end if; end process crc1; -------------------------------------------------------------------------------- -- CRC0 calculates the part of the CRC that uses the previous value of the CRC. -- -- the following cases are possible -- -- nxt | CLRCRC |Meaning |Action -------+--------+---------------------------+----------------------------------- -- 1 | |data written previos cycle |Calculate CRC (q0) using previous -- | 0 |no reset signal |value of q0 and q1 -------+--------+---------------------------+----------------------------------- -- 1 | |Data written |Calculate CRC using previous q1 and -- | 1 |Reset signal active |a reduced calculation being equal -- | | |to q0 being all 1. -------+--------+---------------------------+----------------------------------- -- 0 | |No data written |q0 is unchanged -- | 0 |No resetr signal | -------+--------+---------------------------+----------------------------------- -- 0 | |No data written |Reset CRC calculator by presetting -- | 1 |Reset signal active |q0 to all 1. -------+--------+---------------------------+----------------------------------- -- -- The second of the above cases is the most complicated: -- To clear previous result without having to preset q to all 1, one can -- do this by performing q <= q1 xor #F0B8, which is equal to presetting -- q to all 1 in the previous cycle. -- This is needed in the following case in the receiver: -- -- Clock cycle | Input | q0 | q1 ---------------+-------+--------+-------- -- 1 | Data | - | - -- 2 | Data | - | q1_1 -- 3 | - | q0_1 | q1_2 -- 4 | CRC | q0_2 | - -- 5 | Data | q0_2 | q1_crc -- 6 | Data | q0_crc | q1_5 -- 7 | Data | q0_5 | q1_6 -- -- where qx_y indicates the value of the qx register containing CRC data from -- beginning of CRC block to clock cycle y. The problem arises when a new CRC -- block starts on the clock cycle after a CRC is sent. There is no time to -- preset q0 register to all 1, so this is emulated bu calulating what the -- effect would be. The operations below is merely the same operations as the -- one above with q0 registers set to all 1. crc0:process(CLK) -- kja chenged to clk_n don't want to use q1's as they begin -- change on CLK edge if (CLK'event and CLK ='1') then case nxt_clr is when "10" => q0(15) <= k1(15) xor q0(15) xor q0(11) xor q0(7) xor q0(4) xor q0(3); q0(14) <= k1(14) xor q0(14) xor q0(10) xor q0(6) xor q0(3) xor q0(2); q0(13) <= k1(13) xor q0(13) xor q0(9) xor q0(5) xor q0(2) xor q0(1); q0(12) <= k1(12) xor q0(12) xor q0(8) xor q0(4) xor q0(1) xor q0(0); q0(11) <= k1(11) xor q0(11) xor q0(7) xor q0(3) xor q0(0); q0(10) <= k1(10) xor q0(15) xor q0(11) xor q0(10) xor q0(7) xor q0(6) xor q0(4) xor q0(3) xor q0(2); q0(9) <= k1(9) xor q0(14) xor q0(10) xor q0(9) xor q0(6) xor q0(5) xor q0(3) xor q0(2) xor q0(1); q0(8) <= k1(8) xor q0(13) xor q0(9) xor q0(8) xor q0(5) xor q0(4) xor q0(2) xor q0(1) xor q0(0); q0(7) <= k1(7) xor q0(12) xor q0(8) xor q0(7) xor q0(4) xor q0(3) xor q0(1) xor q0(0); q0(6) <= k1(6) xor q0(11) xor q0(7) xor q0(6) xor q0(3) xor q0(2) xor q0(0); q0(5) <= k1(5) xor q0(10) xor q0(6) xor q0(5) xor q0(2) xor q0(1); q0(4) <= k1(4) xor q0(9) xor q0(5) xor q0(4) xor q0(1) xor q0(0); q0(3) <= k1(3) xor q0(15) xor q0(11) xor q0(8) xor q0(7) xor q0(0); q0(2) <= k1(2) xor q0(14) xor q0(10) xor q0(7) xor q0(6); q0(1) <= k1(1) xor q0(13) xor q0(9) xor q0(6) xor q0(5); q0(0) <= k1(0) xor q0(12) xor q0(8) xor q0(5) xor q0(4); when "11" => q0(15) <= not k1(15); q0(14) <= not k1(14); q0(13) <= not k1(13); q0(12) <= not k1(12); q0(11) <= k1(11); q0(10) <= k1(10); q0(9) <= k1(9); q0(8) <= k1(8); q0(7) <= not k1(7); q0(6) <= k1(6); q0(5) <= not k1(5); q0(4) <= not k1(4); q0(3) <= not k1(3); q0(2) <= k1(2); q0(1) <= k1(1); q0(0) <= k1(0); when "00" => q0 <= q0; when others => q0 <= (others => '1'); end case; end if; end process crc0; -------------------------------------------------------------------------------- end behaviour; -------------------------------------------------------------------------------- -- END OF FILE --------------------------------------------------------------------------------