SURF  1.0
Crc32Parallel.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : Crc32.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2013-05-01
5 -- Last update: 2017-02-23
6 -------------------------------------------------------------------------------
7 -- Description:
8 -- This is an implementation of an 1-to-8-byte input CRC32 calculation.
9 -- The polynomial is fixed to 0x04C11DB7, the "standard CRC32 polynomial."
10 -- The initialization value is configurable, but defaults to 0xFFFFFFFF.
11 --
12 -- This implementation is direct, so no bytes need to be appended to the data.
13 --
14 -- Bytes are reversed on input before being used for the CRC calculation,
15 -- and the CRC register is reversed on output just before a final XOR with
16 -- 0xFFFFFFFF.
17 --
18 -- This version utilizes parallel CRC calculations, and as a result generally
19 -- should meet much tighter timing constraints and run at higher frequencies.
20 -- (relative to Crc32.vhd and CRC32Rtl.vhd).
21 --
22 -- With a data input size of 4 bytes, this module is compatible with the
23 -- previous CRC32Rtl.vhdl module in the StdLib.
24 -------------------------------------------------------------------------------
25 -- This file is part of 'SLAC Firmware Standard Library'.
26 -- It is subject to the license terms in the LICENSE.txt file found in the
27 -- top-level directory of this distribution and at:
28 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
29 -- No part of 'SLAC Firmware Standard Library', including this file,
30 -- may be copied, modified, propagated, or distributed except according to
31 -- the terms contained in the LICENSE.txt file.
32 -------------------------------------------------------------------------------
33 
34 library ieee;
35 use ieee.std_logic_1164.all;
36 use ieee.std_logic_arith.all;
37 use ieee.std_logic_unsigned.all;
38 use work.StdRtlPkg.all;
39 use work.CrcPkg.all;
40 
41 --! @see entity
42  --! @ingroup base_general
43 entity Crc32Parallel is
44  generic (
45  BYTE_WIDTH_G : integer := 4; -- Maximum byte width (1-8 supported)
46  CRC_INIT_G : slv(31 downto 0) := x"FFFFFFFF";
47  TPD_G : time := 0.5 ns
48  );
49  port (
50  crcOut : out slv(31 downto 0); -- CRC output
51  crcClk : in sl; -- system clock
52  crcDataValid : in sl; -- indicate that new data arrived and CRC can be computed
53  crcDataWidth : in slv(2 downto 0); -- indicate width in bytes minus 1, 0 - 1 byte, 1 - 2 bytes ... , 7 - 8 bytes
54  crcIn : in slv((BYTE_WIDTH_G*8-1) downto 0); -- input data for CRC calculation
55  crcReset : in sl -- initializes CRC logic to CRC_INIT_G
56  );
57 end Crc32Parallel;
58 
59 architecture rtl of Crc32Parallel is
60 
61  type RegType is record
62  crc : slv(31 downto 0);
63  data : slv((BYTE_WIDTH_G*8-1) downto 0);
64  valid : sl;
65  byteWidth : slv(2 downto 0);
66  end record RegType;
67 
68  constant REG_INIT_C : RegType := (
69  crc => CRC_INIT_G,
70  data => (others => '0'),
71  valid => '0',
72  byteWidth => (others => '0')
73  );
74 
75  signal r : RegType := REG_INIT_C;
76  signal rin : RegType;
77 
78 begin
79 
80  assert (BYTE_WIDTH_G > 0 and BYTE_WIDTH_G <= 8) report "BYTE_WIDTH_G must be in the range [1,8]" severity failure;
81 
82  comb : process(crcIn,crcDataWidth,crcReset,crcDataValid,r)
83  variable v : RegType;
84  variable prevCrc : slv(31 downto 0);
85  begin
86  v := r;
87 
88  v.byteWidth := crcDataWidth;
89  v.valid := crcDataValid;
90 
91  -- Transpose the input data
92  for byte in (BYTE_WIDTH_G-1) downto 0 loop
93  if (crcDataWidth >= BYTE_WIDTH_G-byte-1) then
94  for b in 0 to 7 loop
95  v.data((byte+1)*8-1-b) := crcIn(byte*8+b);
96  end loop;
97  else
98  v.data((byte+1)*8-1 downto byte*8) := (others => '0');
99  end if;
100  end loop;
101 
102  if (crcReset = '0') then
103  prevCrc := r.crc;
104  else
105  prevCrc := CRC_INIT_G;
106  end if;
107 
108  -- Calculate CRC in parallel - implementation used depends on the
109  -- byte width in use.
110  if (r.valid = '1') then
111  case(r.byteWidth) is
112  when "000" =>
113  v.crc := crc32Parallel1Byte(prevCrc, r.data(BYTE_WIDTH_G*8-1 downto (BYTE_WIDTH_G-1)*8));
114  when "001" =>
115  if (BYTE_WIDTH_G >= 2) then
116  v.crc := crc32Parallel2Byte(prevCrc, r.data(BYTE_WIDTH_G*8-1 downto (BYTE_WIDTH_G-2)*8));
117  end if;
118  when "010" =>
119  if (BYTE_WIDTH_G >= 3) then
120  v.crc := crc32Parallel3Byte(prevCrc, r.data(BYTE_WIDTH_G*8-1 downto (BYTE_WIDTH_G-3)*8));
121  end if;
122  when "011" =>
123  if (BYTE_WIDTH_G >= 4) then
124  v.crc := crc32Parallel4Byte(prevCrc, r.data(BYTE_WIDTH_G*8-1 downto (BYTE_WIDTH_G-4)*8));
125  end if;
126  when "100" =>
127  if (BYTE_WIDTH_G >= 5) then
128  v.crc := crc32Parallel5Byte(prevCrc, r.data(BYTE_WIDTH_G*8-1 downto (BYTE_WIDTH_G-5)*8));
129  end if;
130  when "101" =>
131  if (BYTE_WIDTH_G >= 6) then
132  v.crc := crc32Parallel6Byte(prevCrc, r.data(BYTE_WIDTH_G*8-1 downto (BYTE_WIDTH_G-6)*8));
133  end if;
134  when "110" =>
135  if (BYTE_WIDTH_G >= 7) then
136  v.crc := crc32Parallel7Byte(prevCrc, r.data(BYTE_WIDTH_G*8-1 downto (BYTE_WIDTH_G-7)*8));
137  end if;
138  when "111" =>
139  if (BYTE_WIDTH_G = 8) then
140  v.crc := crc32Parallel8Byte(prevCrc, r.data(BYTE_WIDTH_G*8-1 downto (BYTE_WIDTH_G-8)*8));
141  end if;
142  when others => v.crc := (others => '0');
143  end case;
144  else
145  v.crc := prevCrc;
146  end if;
147 
148  rin <= v;
149 
150  -- Transpose each byte in the data out and invert
151  -- This inversion is equivalent to an XOR of the CRC register with xFFFFFFFF
152  for byte in 0 to 3 loop
153  for b in 0 to 7 loop
154  crcOut(byte*8+b) <= not(r.crc((byte+1)*8-1-b));
155  end loop;
156  end loop;
157 
158  end process;
159 
160  seq : process (crcClk) is
161  begin
162  if (rising_edge(crcClk)) then
163  r <= rin after TPD_G;
164  end if;
165  end process seq;
166 
167 end rtl;
std_logic sl
Definition: StdRtlPkg.vhd:28
out crcOutslv( 31 downto 0)
in crcDataWidthslv( 2 downto 0)
_library_ ieeeieee
Definition: Crc32.vhd:28
TPD_Gtime := 0.5 ns
CRC_INIT_Gslv( 31 downto 0) := x"FFFFFFFF"
in crcInslv(( BYTE_WIDTH_G* 8- 1) downto 0)
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
BYTE_WIDTH_Ginteger := 4