2

I am trying to implement CCITT 16 true type (Kermit) in VHDL language.

Here are the parameters:

width=16
poly=0x1021
init=0x0000
refin=true
refout=true
xorout=0x0000
check=0x2189
residue=0x0000
name="KERMIT"

I have 32-bit data and want to generate 16-bit CRC Kermit type. I used CRC Generator to generate the VHDL code. The settings/parameters used to generate code are:

  1. clock positive edge triggered
  2. Reset is active low with initial value 0x0000
  3. first bit to enter register is LSB because Kermit has Refin true
  4. Data bus width 32
  5. Poly x^15+x^12+x^5+1 or CCITT 16 bit XMODEM type
  6. Initial value 0x0000

Here is an example:

Data_in:                 0x54091010
CRC value kermit:        0xBEF4
CRC value Xmodem:        0x3019
CRC generated from code: 0x980C

Here is the simulation from Modelsim: simulation waveform (click to enlarge)

If you observe the simulation wave picture then you will find the code generates correct XModem CRC but since REFIn and REFOUT is true for Kermit the CRC was reflected i.e. 0x980C (0x3019 non reflected CRC). The next step is to XOR it with initial value 0x0000 which produces the same CRC i.e. 0x980C.

The data was also reflected before the final CRC.

Please let me know if I am doing some mistake as I am confused because of many CRC formats.

-- ********************************
--           Specification 
-- ********************************
-- File Name       : CRC16_DATA32.vhd    
-- Description     : CRC Engine ENTITY 
-- Clock           : Positive Edge 
-- Reset           : Active Low
-- First Serial    : MSB 
-- Data Bus Width  : 32 bits 
-- Polynomial      : (0 5 12 16)                   
-- Date            : 14-Sep-2017  
-- Version         : 1.0        
-- ########################################################################

LIBRARY IEEE ;
USE ieee.std_logic_1164.all ;
USE ieee.std_logic_arith.all ;
USE ieee.std_logic_unsigned.all ;

ENTITY crc_gen IS 
   PORT(           
           clock                : IN  STD_LOGIC; 
           reset                : IN  STD_LOGIC; 

           data_i               : IN  STD_LOGIC_VECTOR(31 DOWNTO 0); 
           data_valid           : IN  STD_LOGIC; 
       data_o               : OUT  STD_LOGIC_VECTOR(31 DOWNTO 0);

           crc              : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); 
           crc_valid            : OUT STD_LOGIC;

       crc_c_o                  : out STD_LOGIC_VECTOR(15 DOWNTO 0);
       crc_i_o                  : out STD_LOGIC_VECTOR(15 DOWNTO 0);

       crc_inv_o            : out STD_LOGIC_VECTOR(15 DOWNTO 0);    
       crc_xor_o                : out STD_LOGIC_VECTOR(15 DOWNTO 0));
END crc_gen; 

ARCHITECTURE behave OF crc_gen IS 

function reverse_any_vector (a: in std_logic_vector)
return std_logic_vector is
  variable result: std_logic_vector(a'RANGE);
  alias aa: std_logic_vector(a'REVERSE_RANGE) is a;
begin
  for i in aa'RANGE loop
    result(i) := aa(i);
  end loop;
  return result;
end; -- function reverse_any_vector

function crc_xor(b: in std_logic_vector; c: in std_logic_vector)
    return std_logic_vector is
    variable crc_xor_c: std_logic_vector (15 downto 0);
begin
        crc_xor_c := b xor c;
        return crc_xor_c;
end;


    SIGNAL crc_r                : STD_LOGIC_VECTOR(15 DOWNTO 0);--reverse crc value
    SIGNAL crc_c                : STD_LOGIC_VECTOR(15 DOWNTO 0);-- computing crc value
    SIGNAL crc_i                : STD_LOGIC_VECTOR(15 DOWNTO 0); --initial crc value 
    SIGNAL crc_inv_i            : STD_LOGIC_VECTOR(15 DOWNTO 0);    
    SIGNAL crc_xor_i            : STD_LOGIC_VECTOR(15 DOWNTO 0);
    SIGNAL data         : STD_LOGIC_VECTOR(31 DOWNTO 0);
    SIGNAL clk_count        : INTEGER range 0 to 3;

BEGIN 



crc_c(0) <= data(31) XOR data(27) XOR data(20) XOR data(11) XOR data(4) XOR crc_i(11) XOR crc_i(4) XOR data(3) XOR crc_i(12) XOR data(9) XOR crc_i(6) XOR data(12) XOR crc_i(3) XOR data(23) XOR data(5) XOR crc_i(10) XOR data(19); 
crc_c(1) <= data(30) XOR data(26) XOR data(19) XOR data(10) XOR data(3) XOR crc_i(12) XOR crc_i(5) XOR data(2) XOR crc_i(13) XOR data(8) XOR crc_i(7) XOR data(11) XOR crc_i(4) XOR data(22) XOR data(4) XOR crc_i(11) XOR data(18); 
crc_c(2) <= data(29) XOR data(25) XOR data(18) XOR data(9) XOR data(2) XOR crc_i(13) XOR crc_i(6) XOR data(1) XOR crc_i(14) XOR data(7) XOR crc_i(8) XOR data(10) XOR crc_i(5) XOR data(21) XOR data(3) XOR crc_i(12) XOR data(17); 
crc_c(3) <= data(28) XOR data(24) XOR data(17) XOR data(8) XOR data(1) XOR crc_i(14) XOR crc_i(7) XOR data(0) XOR crc_i(15) XOR data(6) XOR crc_i(9) XOR data(9) XOR crc_i(6) XOR data(20) XOR data(2) XOR crc_i(13) XOR data(16); 
crc_c(4) <= data(27) XOR data(23) XOR data(16) XOR data(7) XOR data(0) XOR crc_i(15) XOR crc_i(8) XOR data(5) XOR crc_i(10) XOR data(8) XOR crc_i(7) XOR data(19) XOR data(1) XOR crc_i(14) XOR data(15) XOR crc_i(0); 
crc_c(5) <= data(31) XOR data(26) XOR data(22) XOR data(15) XOR data(6) XOR crc_i(9) XOR crc_i(0) XOR data(7) XOR crc_i(8) XOR data(18) XOR data(0) XOR crc_i(15) XOR data(14) XOR crc_i(1) XOR data(27) XOR data(20) XOR data(11) XOR crc_i(4) XOR data(3) XOR crc_i(12) XOR data(9) XOR crc_i(6) XOR data(12) XOR crc_i(3) XOR data(23) XOR data(5) XOR crc_i(10) XOR data(19); 
crc_c(6) <= data(30) XOR data(25) XOR data(21) XOR data(14) XOR data(5) XOR crc_i(10) XOR crc_i(1) XOR data(6) XOR crc_i(9) XOR data(17) XOR data(13) XOR crc_i(2) XOR data(26) XOR data(19) XOR data(10) XOR crc_i(5) XOR data(2) XOR crc_i(13) XOR data(8) XOR crc_i(7) XOR data(11) XOR crc_i(4) XOR data(22) XOR data(4) XOR crc_i(11) XOR data(18); 
crc_c(7) <= data(29) XOR data(24) XOR data(20) XOR data(13) XOR data(4) XOR crc_i(11) XOR crc_i(2) XOR data(5) XOR crc_i(10) XOR data(16) XOR data(12) XOR crc_i(3) XOR data(25) XOR data(18) XOR data(9) XOR crc_i(6) XOR data(1) XOR crc_i(14) XOR data(7) XOR crc_i(8) XOR data(10) XOR crc_i(5) XOR data(21) XOR data(3) XOR crc_i(12) XOR data(17); 
crc_c(8) <= data(28) XOR data(23) XOR data(19) XOR data(12) XOR data(3) XOR crc_i(12) XOR crc_i(3) XOR data(4) XOR crc_i(11) XOR data(15) XOR data(11) XOR crc_i(0) XOR crc_i(4) XOR data(24) XOR data(17) XOR data(8) XOR crc_i(7) XOR data(0) XOR crc_i(15) XOR data(6) XOR crc_i(9) XOR data(9) XOR crc_i(6) XOR data(20) XOR data(2) XOR crc_i(13) XOR data(16); 
crc_c(9) <= data(27) XOR data(22) XOR data(18) XOR data(11) XOR data(2) XOR crc_i(13) XOR crc_i(4) XOR data(3) XOR crc_i(12) XOR data(14) XOR data(10) XOR crc_i(1) XOR crc_i(5) XOR data(23) XOR data(16) XOR data(7) XOR crc_i(8) XOR data(5) XOR crc_i(10) XOR data(8) XOR crc_i(7) XOR data(19) XOR data(1) XOR crc_i(14) XOR data(15) XOR crc_i(0); 
crc_c(10) <= data(26) XOR data(21) XOR data(17) XOR data(10) XOR data(1) XOR crc_i(14) XOR crc_i(5) XOR data(2) XOR crc_i(13) XOR data(13) XOR data(9) XOR crc_i(2) XOR crc_i(6) XOR data(22) XOR data(15) XOR data(6) XOR crc_i(9) XOR data(4) XOR crc_i(0) XOR crc_i(11) XOR data(7) XOR crc_i(8) XOR data(18) XOR data(0) XOR crc_i(15) XOR data(14) XOR crc_i(1); 
crc_c(11) <= data(25) XOR data(20) XOR data(16) XOR data(9) XOR data(0) XOR crc_i(15) XOR crc_i(6) XOR data(1) XOR crc_i(14) XOR data(12) XOR data(8) XOR crc_i(3) XOR crc_i(7) XOR data(21) XOR data(14) XOR data(5) XOR crc_i(10) XOR data(3) XOR crc_i(1) XOR crc_i(12) XOR data(6) XOR crc_i(9) XOR data(17) XOR data(13) XOR crc_i(2); 
crc_c(12) <= data(31) XOR data(24) XOR data(15) XOR data(8) XOR crc_i(7) XOR data(0) XOR crc_i(15) XOR crc_i(0) XOR data(7) XOR crc_i(8) XOR data(13) XOR data(2) XOR crc_i(2) XOR crc_i(13) XOR data(16) XOR data(27) XOR data(3) XOR crc_i(12) XOR data(9) XOR crc_i(6) XOR data(23); 
crc_c(13) <= data(30) XOR data(23) XOR data(14) XOR data(7) XOR crc_i(8) XOR crc_i(1) XOR data(6) XOR crc_i(9) XOR data(12) XOR data(1) XOR crc_i(3) XOR crc_i(14) XOR data(15) XOR crc_i(0) XOR data(26) XOR data(2) XOR crc_i(13) XOR data(8) XOR crc_i(7) XOR data(22); 
crc_c(14) <= data(29) XOR data(22) XOR data(13) XOR data(6) XOR crc_i(9) XOR crc_i(2) XOR data(5) XOR crc_i(10) XOR data(11) XOR data(0) XOR crc_i(4) XOR crc_i(15) XOR data(14) XOR crc_i(1) XOR data(25) XOR data(1) XOR crc_i(14) XOR data(7) XOR crc_i(8) XOR data(21); 
crc_c(15) <= data(28) XOR data(21) XOR data(12) XOR data(5) XOR crc_i(10) XOR crc_i(3) XOR data(4) XOR crc_i(11) XOR data(10) XOR crc_i(5) XOR data(13) XOR crc_i(2) XOR data(24) XOR data(0) XOR crc_i(15) XOR data(6) XOR crc_i(9) XOR data(20); 

crc_gen_process : PROCESS(clock, reset) 

BEGIN                                    
 IF(reset = '0') THEN  
    crc_r <= "0000000000000000" ;
    crc_valid <='0';
    clk_count <= 0 ;
 ELSIF( clock 'EVENT AND clock = '1') THEN 
        if (data_valid = '1' and clk_count = 0) then
    --data<=data_i;
    data <= reverse_any_vector (data_i); 
    crc_i <= "0000000000000000" ;
    crc_valid <='0';
    clk_count<= clk_count+1;
    elsif (data_valid = '1' and clk_count = 1) then
    crc_inv_i <= reverse_any_vector (crc_c); 
    crc_valid <='0';
    clk_count<= clk_count+1;
    elsif (data_valid = '1' and clk_count = 2) then
    crc_xor_i <= crc_xor (x"0000", crc_inv_i);
    crc_valid <='0';
    clk_count<= clk_count+1;
    elsif (data_valid = '1' and clk_count = 3) then
    crc_r <= crc_xor_i;
    crc_valid <='1';
    clk_count <= 0 ;
    END IF; 
 END IF;    
END PROCESS crc_gen_process;      




data_o <= data;
crc_c_o <= crc_c;
crc_i_o <= crc_i;
crc_inv_o <= crc_inv_i;
crc_xor_o <= crc_xor_i;
crc <= crc_r;


END behave;

    ****************************************************************************
Simulation testbench
****************************************************************************
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY crc_check_test IS
END crc_check_test;

ARCHITECTURE behavior OF crc_check_test IS 
component crc_gen 
port (
       clock                : IN  STD_LOGIC; 
           reset                : IN  STD_LOGIC; 

           data_i               : IN  STD_LOGIC_VECTOR(31 DOWNTO 0); 
           data_valid           : IN  STD_LOGIC; 
       data_o               : OUT  STD_LOGIC_VECTOR(31 DOWNTO 0);

           crc              : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); 
           crc_valid            : OUT STD_LOGIC;

       crc_c_o                  : out STD_LOGIC_VECTOR(15 DOWNTO 0);
       crc_i_o                  : out STD_LOGIC_VECTOR(15 DOWNTO 0);

       crc_inv_o            : out STD_LOGIC_VECTOR(15 DOWNTO 0);    
       crc_xor_o                : out STD_LOGIC_VECTOR(15 DOWNTO 0));

 end component crc_gen;
signal clock: std_logic :='0';
signal reset: std_logic :='0';
signal data_i: std_logic_vector(31 DOWNTO 0):= x"54_09_10_10";
signal data_valid: std_logic :='0';
signal data_o: std_logic_vector(31 DOWNTO 0);

signal crc              : std_logic_vector(15 DOWNTO 0);--:="0000_0000_0000_0000";
signal crc_valid            : std_logic; -- :='0';
SIGNAL crc_c_o                  : STD_LOGIC_VECTOR(15 DOWNTO 0);
SIGNAL crc_i_o                  : STD_LOGIC_VECTOR(15 DOWNTO 0);
SIGNAL crc_inv_o                : STD_LOGIC_VECTOR(15 DOWNTO 0);    
SIGNAL crc_xor_o                : STD_LOGIC_VECTOR(15 DOWNTO 0);

constant clock_period : time := 20 ns;


BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: crc_gen  PORT MAP (
            clock=>clock,
            reset=>reset,
            data_i=>data_i,
            data_valid=>data_valid,
            data_o=>data_o,
            crc=>crc,
            crc_valid=>crc_valid,
            crc_c_o => crc_c_o,
            crc_i_o => crc_i_o,
            crc_inv_o => crc_inv_o,
            crc_xor_o  => crc_xor_o);


clock_process :process
begin
clock <= '0';
wait for clock_period/2;
clock <= '1';
wait for clock_period/2;
end process;

stop_simulation :process
begin
wait for 600 ns; --run the simulation for this duration
assert false
report "simulation ended"
severity failure;
end process ; 


   -- Applying inputs to the entity under test
   stim_proc: process
   begin        
        reset <= '0'; data_valid <= '0';    wait for 100 ns;
    reset <= '1'; data_valid <= '1';    wait for 300 ns;
        reset <= '1'; data_valid <= '0';    wait for 100 ns;

        wait;
   end process;

END;
Paebbels
  • 15,573
  • 13
  • 70
  • 139
  • Please provide us with a complete verifiable example, so we can reproduce your error. – JHBonarius Sep 19 '17 at 07:57
  • @JHBonarius I have updated my post with simulation testbench and code. Please go through it. – Gaurav Bhatia Sep 19 '17 at 12:51
  • The [PoC Library](https://github.com/vlsi-eda/poc) provides a generic CRC implementation in VHDL. You need to provide the polynomial and init value. Final XOR-ing needs to be calculated outside of the module. It was tested with several 8-bit, 16-bit and 32-bit CRCs. Here is the link to the component: [PoC.comm.crc](https://github.com/VLSI-EDA/PoC/blob/master/src/comm/comm_crc.vhdl?ts=2). A documentation is provided [here](http://poc-library.readthedocs.io/en/latest/IPCores/comm/comm_crc.html). – Paebbels Sep 20 '17 at 07:54
  • @Paebbels I want to implement parallel CRC because I will have long data length to be sent over USB. The link which you provided has serial implementation which computes CRC after n clock cycles. – Gaurav Bhatia Sep 20 '17 at 12:56
  • No it's parallel :) The for loop is inside of the rising_edge. It will unroll the xor calculation. – Paebbels Sep 20 '17 at 16:21
  • @Paebbels if I reverse my data stream then it should satisfy REFIn condition but to satisfy REFOut do I need to xor the present CRC with previous CRC (which also reversed first) of adjacent byte. – Gaurav Bhatia Sep 20 '17 at 22:44
  • What does `ref` mean? Is it `reverse` ? If so, you need to reverse the input and the output. It doesn't effect the xor operations. It's a pre and post calculation. – Paebbels Sep 21 '17 at 16:39
  • @Paebbels So that means my code should run fine if I reverse the data bit before xor funtion and then reverse the computed crc generated from reverse data stream but this is not the case. I am getting 0x3019 (x-modem crc) which has reverse false for both input (data) and output(crc). I want to have Kermit. Is it something I need to change in the main xor operation? – Gaurav Bhatia Sep 21 '17 at 17:11
  • @Paebbels I got the correct output. My code was giving correct output for each byte individually. Sending **byte by byte** inside a for loop to the crc_generation function solved the issue to get output in single clock cycle .So, I took my **previous crc as input for next crc generation** as the logic suggested. In the end reverse the crc block which is the correct output. – Gaurav Bhatia Sep 26 '17 at 15:18

1 Answers1

-1

i know its a old post but i wanted to say you have to put it cyclic or in other word close the loop by feeding output back to input but your last comment clarify your own question.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 17 '22 at 19:00