-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcrc.vhd
131 lines (96 loc) · 2.86 KB
/
crc.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- Default parameters produce a CRC16-CCITT output.
-- When checking, correct reception is signaled by a zero in the crc
-- output.
--
-- Parameters:
--
-- CRC_WIDTH bit width of the crc output;
--
-- DATA_WIDTH bit width of the data input (must be at least 2);
--
-- INIT_VAL initialization value of the crc register,
-- suggested values are all-zeros and all-ones;
--
-- POLY Polynomial (remeber to reverse it)
-- i.e. CCITT 1021h has POLY = 'h8408.
--
--------------------------------------------------------------------
entity crc is
generic(
CRC_WIDTH : natural := 16;
DATA_WIDTH : natural := 80;--16
INIT_VAL : std_logic_vector((2*8)-1 downto 0) := x"ffff";
POLY : std_logic_vector((2*8)-1 downto 0) := x"8408"
);
port (
clk : in std_logic;
rst : in std_logic;
d_i : in std_logic_vector(DATA_WIDTH-1 downto 0);
init_i : in std_logic;
d_valid_i : in std_logic;
crc_o : out std_logic_vector(CRC_WIDTH-1 downto 0)
);
end entity crc;
architecture RTL of crc is
--! Internal Wires and Regs
signal next_crc : std_logic_vector(CRC_WIDTH-1 downto 0);
signal crc_int : std_logic_vector(CRC_WIDTH-1 downto 0);
type crc_array_t is array (integer range<>) of std_logic_vector((CRC_WIDTH-1) downto 0);
--
function crc_atom (
crc_in : std_logic_vector(CRC_WIDTH - 1 downto 0);
d : std_logic
)
return std_logic_vector is
variable value : std_logic_vector(crc_in'high downto 0);
begin
if ((crc_in(0) xor d)='0') then
value := std_logic_vector(unsigned(crc_in) srl 1);
else
value := (std_logic_vector(unsigned(crc_in) srl 1)) xor POLY((CRC_WIDTH-1) downto 0);
end if;
return value;
end function crc_atom;
function crc_calc (
crc_i : std_logic_vector(CRC_WIDTH-1 downto 0);
d : std_logic_vector(DATA_WIDTH-1 downto 0)
)
return std_logic_vector is
variable p_crc : crc_array_t(0 to DATA_WIDTH-2);
variable value : std_logic_vector(CRC_WIDTH-1 downto 0);
begin
p_crc(0) := crc_atom(crc_i, d(0));
for i in 1 to DATA_WIDTH-2 loop
p_crc(i) := crc_atom(p_crc(i-1), d(i));
end loop;
value := crc_atom(p_crc(DATA_WIDTH-2), d(DATA_WIDTH-1));
return value;
end function crc_calc;
begin
async_proc : process(d_i,crc_int,init_i) is
begin
if (init_i = '1') then
next_crc <= crc_calc(INIT_VAL, d_i);
else
next_crc <= crc_calc(crc_int,d_i);
end if;
end process async_proc;
sync_proc : process (clk, rst) is
begin
if rst = '1' then
crc_int <= INIT_VAL;
elsif rising_edge(clk) then
if (init_i and (not d_valid_i))='1' then
crc_int <=INIT_VAL;
elsif (d_valid_i='1') then
crc_int <= next_crc;
else
crc_int <= crc_int;
end if;
end if;
end process sync_proc;
crc_o <= crc_int;
end architecture RTL;