1 |
145 |
lanttu |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Title : IP checksum counter
|
3 |
|
|
-- Project :
|
4 |
|
|
-------------------------------------------------------------------------------
|
5 |
|
|
-- File : ip_checksum.vhd
|
6 |
|
|
-- Author : Jussi Nieminen <niemin95@galapagosinkeiju.cs.tut.fi>
|
7 |
|
|
-- Company :
|
8 |
|
|
-- Last update: 2009/09/29
|
9 |
|
|
-- Platform :
|
10 |
|
|
-------------------------------------------------------------------------------
|
11 |
|
|
-- Description: Counts 1's complement checksum for IP header
|
12 |
|
|
-------------------------------------------------------------------------------
|
13 |
|
|
-- Revisions :
|
14 |
|
|
-- Date Version Author Description
|
15 |
|
|
-- 2009/09/29 1.0 niemin95 Created
|
16 |
|
|
-------------------------------------------------------------------------------
|
17 |
|
|
|
18 |
|
|
library ieee;
|
19 |
|
|
use ieee.std_logic_1164.all;
|
20 |
|
|
use ieee.numeric_std.all;
|
21 |
|
|
use work.udp_ip_pkg.all;
|
22 |
|
|
|
23 |
|
|
entity ip_checksum is
|
24 |
|
|
|
25 |
|
|
generic (
|
26 |
|
|
-- this comes from the protocol, flags etc. field that are currently constants
|
27 |
|
|
pre_counted_part_g : std_logic_vector( ip_checksum_w_c-1 downto 0 ) := (others => '0')
|
28 |
|
|
);
|
29 |
|
|
|
30 |
|
|
port (
|
31 |
|
|
total_length_field_in : in std_logic_vector( 15 downto 0 );
|
32 |
|
|
source_addr_field_in : in std_logic_vector( ip_addr_w_c-1 downto 0 );
|
33 |
|
|
dest_addr_field_in : in std_logic_vector( ip_addr_w_c-1 downto 0 );
|
34 |
|
|
header_checksum_out : out std_logic_vector( ip_checksum_w_c-1 downto 0 )
|
35 |
|
|
);
|
36 |
|
|
|
37 |
|
|
end ip_checksum;
|
38 |
|
|
|
39 |
|
|
|
40 |
|
|
architecture rtl of ip_checksum is
|
41 |
|
|
|
42 |
|
|
-- currently we have 5 additions, which means that the overflowing part of
|
43 |
|
|
-- the additions can be at most 3-bits wide
|
44 |
|
|
constant middle_sum_w_c : integer := ip_checksum_w_c + 3;
|
45 |
|
|
signal middle_sum_int : integer range 0 to 2**middle_sum_w_c-1;
|
46 |
|
|
signal middle_sum_slv : std_logic_vector( middle_sum_w_c-1 downto 0 );
|
47 |
|
|
|
48 |
|
|
subtype addend_integer is integer range 0 to 2**ip_checksum_w_c-1;
|
49 |
|
|
signal length_int : addend_integer;
|
50 |
|
|
signal source_addr_high_int : addend_integer;
|
51 |
|
|
signal source_addr_low_int : addend_integer;
|
52 |
|
|
signal dest_addr_high_int : addend_integer;
|
53 |
|
|
signal dest_addr_low_int : addend_integer;
|
54 |
|
|
|
55 |
|
|
-------------------------------------------------------------------------------
|
56 |
|
|
begin -- rtl
|
57 |
|
|
-------------------------------------------------------------------------------
|
58 |
|
|
|
59 |
|
|
middle_sum_slv <= std_logic_vector( to_unsigned( middle_sum_int, middle_sum_w_c ));
|
60 |
|
|
|
61 |
|
|
length_int <= to_integer( unsigned( total_length_field_in ));
|
62 |
|
|
source_addr_high_int <= to_integer( unsigned( source_addr_field_in( ip_addr_w_c-1 downto 16 ) ));
|
63 |
|
|
source_addr_low_int <= to_integer( unsigned( source_addr_field_in( 15 downto 0 ) ));
|
64 |
|
|
dest_addr_high_int <= to_integer( unsigned( dest_addr_field_in( ip_addr_w_c-1 downto 16 ) ));
|
65 |
|
|
dest_addr_low_int <= to_integer( unsigned( dest_addr_field_in( 15 downto 0 ) ));
|
66 |
|
|
|
67 |
|
|
|
68 |
|
|
count_checksum : process (length_int, source_addr_high_int, source_addr_low_int,
|
69 |
|
|
dest_addr_high_int, dest_addr_low_int, middle_sum_slv)
|
70 |
|
|
|
71 |
|
|
variable middle_sum_v : std_logic_vector( ip_checksum_w_c downto 0 );
|
72 |
|
|
variable final_sum_v : integer range 0 to 2**ip_checksum_w_c - 1;
|
73 |
|
|
variable final_checksum_v : std_logic_vector( ip_checksum_w_c-1 downto 0 );
|
74 |
|
|
|
75 |
|
|
begin -- process count_checksum
|
76 |
|
|
|
77 |
|
|
middle_sum_int <= to_integer( unsigned( pre_counted_part_g ))+
|
78 |
|
|
length_int + source_addr_high_int + source_addr_low_int +
|
79 |
|
|
dest_addr_high_int + dest_addr_low_int;
|
80 |
|
|
|
81 |
|
|
middle_sum_v :=
|
82 |
|
|
std_logic_vector( to_unsigned(
|
83 |
|
|
to_integer( unsigned( middle_sum_slv( ip_checksum_w_c-1 downto 0 ) )) +
|
84 |
|
|
to_integer( unsigned( middle_sum_slv( middle_sum_w_c-1 downto ip_checksum_w_c ) )),
|
85 |
|
|
ip_checksum_w_c+1 ));
|
86 |
|
|
|
87 |
|
|
final_sum_v := to_integer( unsigned( middle_sum_v( ip_checksum_w_c-1 downto 0 ) )) +
|
88 |
|
|
to_integer( unsigned( middle_sum_v( ip_checksum_w_c downto ip_checksum_w_c ) ));
|
89 |
|
|
|
90 |
|
|
final_checksum_v := not std_logic_vector( to_unsigned( final_sum_v, ip_checksum_w_c ));
|
91 |
|
|
|
92 |
|
|
header_checksum_out <= final_checksum_v;
|
93 |
|
|
|
94 |
|
|
end process count_checksum;
|
95 |
|
|
|
96 |
|
|
|
97 |
|
|
end rtl;
|