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:
- clock positive edge triggered
- Reset is active low with initial value
0x0000
- first bit to enter register is LSB because Kermit has Refin true
- Data bus width
32
- Poly
x^15+x^12+x^5+1
orCCITT 16 bit XMODEM type
- 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:
(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;