zlib est LSB first ou MSB first ? #define CRC32_POLY (0x04C11DB7) /* (32,26,23,22,16,12,11,10,8,7,5,4,2,1,0) */ #define CRC32_POLY_REV (0xEDB88320) /* same but bit reversed */ /* This is the (slow) reference implementation */ U32 CRC32_bit(U32 crc, U8 *p, int size) { int i; while (size--) { crc ^= *(p++); for (i=0; i<8; i++) { if (crc & 1) crc = (crc>>1) ^ CRC32_POLY_REV; else crc >>= 1; } } return crc; } #define CRC32_SINGLE { t = crc ^ *(p++); crc = CRC32_LUT[ t & 255] ^ (crc>>8); } 4 registres en écriture : A1 A0 0 0 CRC32_lo 0 1 CRC32_hi // pour YASEP16 1 0 8 bits 1 1 16 bits 2 registres en lecture : A0 (A1 ignored) 0 CRC32_lo 1 CRC32_hi // pour YASEP16 registre à décalage 4*4=16 bits + registre 4 bits "valid" reset => valid="0000" synchronous reset ? (en vrai pas besoin car auto-flush) critical datapath : 4 XOR avec 14 fanout chaque, 1 MUX -- calcule 4 bits d'un coup : ------------------------------------------------------------------------------------ -- version MSB-first (à vérifier) ------------------------------------------------------------------------------------ entity SR_CRC32_16 is port( CRC32_input : in SULVY16; CRC32_output : out SULVY16; SR_Addr0, SR_Addr1, CK_data, CRC32_write : SULV); end SR_CRC32_16; architecture multicycle of SR_CRC32_16 is constant CRC32_polynomial : SULVY(32) = "0000_0100_1100_0001_0001_1101_1011_0111"; -- 0x04C11DB7 => fanout : 14 -- internal state : signal CRC_in, CRC32_hi, CRC32_lo : SULVY16; signal CRC_valid : SULV4; -- 1-hot encoded state -- a 2-bit counter would be better with 4LUT-based architectures begin process(CRC32_input, SR_Addr0, SR_Addr1, CK_data, CRC32_write, CRC_in, CRC32_hi, CRC32_lo, CRC_valid) is variable CRC_tmp : SULVY32; variable i : integer; -- ? variable valid : SULV4; -- std_ulogic_vector(CRC32_width-1 downto 0); begin -- asynchronous read port : if (SR_Addr0 = '0') then CRC32_output<=CRC32_lo; else CRC32_output<=CRC32_hi; end if; if (CK_data'event and CK_data='1') then if (CRC32_write = '1') then -- data are written if (SR_Addr1 = '0') then -- write the CRC register if (SR_Addr0 = '0') then CRC32_lo <= CRC32_input; else CRC32_hi <= CRC32_input(); end if; else -- write the input data if (SR_Addr0 = '0') then -- combine the CRC with the data CRC_valid <= '0011'; -- 8 bits CRC_in(15 downto 8) <= CRC_input(7 downto 0); -- bit reverse ????? else CRC_valid <= '1111'; -- 16 bits CRC_in <= CRC_input; -- bit reverse ????? end if; end if; else -- compute 4 bits if available if (valid(0) = '1') then CRC_tmp := CRC_in; -- 4 logic layers : for i=0 to 3 do -- shift & xor the CRC register if (CRC_in(15-i) = '1') then -- big fanout ! another tmp register could make it faster CRC_tmp := CRC_tmp(31 downto 1) & CRC_tmp(0)) xor CRC32_polynomial; else CRC_tmp := CRC_tmp(31 downto 1) & CRC_tmp(0); end if; done; -- write back the result CRC32_hi <= CRC_tmp(31 downto 16); CRC32_lo <= CRC_tmp(15 downto 0); -- shift down the enable bit by 1 position valid <= '0' & valid(3 downto 1); -- shift up the input data by 4 positions CRC_in <= CRC_in(11 downto 0) & "0000"; end if; end if; -- CRC32_select end if; -- end CK'event end process; end multicycle;