otsdaq_prepmodernization  v2_05_02_indev
ip_checksum_calc.vhd
1 -------------------------------------
2 -- Author: Ryan Rivera, FNAL
3 -- Created: Jan 29, 2016
4 --
5 -- xFAA6 is the one's complement checksum (non-inverted) without the dest and src
6 
7 -- x85F9 is the checksum (non-inverted) without
8 -- the data length and lower address word with. Include extra 0x1C for header length
9 --increase above input length
10 --
11 --ID := x3579,
12 --vers/header := x4500,
13 --ToS := 0,
14 --Flags/Frag := 0,
15 --ttl/protocol := x8011,
16 --dest := xC0 A8 85 __
17 --src := xC0 A8 85 __
18 
19 --if (icmp_mode = '0') then -- normal udp mode
20 -- cs_sig <= '0' & x"FAA6"; -- was 85F9 -- ttl/protocol := x8011
21 --else -- icmp ping mode
22 -- cs_sig <= '0' & x"FA96"; -- was 95E9 -- ttl/protocol := x8001
23 --end if;
24 
25 -- correct result is 79FA for source 2 dest 0 on 192.168.133.X
26 -------------------------------------
27 
28 
29 library IEEE;
30 use IEEE.std_logic_1164.all;
31 use ieee.numeric_std.all;
32 
33 
34 use work.params_package.all;
35 
36 entity ip_checksum_calc is
37  port (
38  clk : in std_logic;
39  reset : in std_logic;
40  trigger : in std_logic;
41 
42  icmp_mode : in std_logic;
43 
44  src_in : in std_logic_vector(31 downto 0);
45  dest_in : in std_logic_vector(31 downto 0);
46  length_in : in std_logic_vector(10 downto 0);
47 
48  cs : out std_logic_vector(15 downto 0)
49  );
50 end;
51 
52 
53 architecture arch of ip_checksum_calc is
54 
55  signal trigger_old : std_logic;
56  signal cs_sig : unsigned(16 downto 0) := (others => '0');
57  signal add_sig : unsigned(16 downto 0) := (others => '0');
58  signal state : unsigned(3 downto 0) := (others => '0');
59 
60 begin
61  cs <= std_logic_vector(not cs_sig(15 downto 0));
62 
63  process(clk)
64  begin
65 
66  if (rising_edge(clk)) then
67 
68  trigger_old <= trigger;
69 
70  -- always be adding one's complement over 2 state counts
71  if(state(0) = '1') then
72  cs_sig <= cs_sig + add_sig;
73  elsif(cs_sig(16) = '1') then
74  cs_sig(15 downto 0) <= cs_sig(15 downto 0) + 1;
75  cs_sig(16) <= '0';
76  end if;
77 
78 
79  -- control state counter
80  if (reset = '1' or (trigger_old = '0' and trigger = '1')) then -- reset state
81  state <= (others => '0');
82  add_sig <= (others => '0');
83 
84  if (icmp_mode = '0') then -- normal udp mode
85  cs_sig <= '0' & x"FAA6"; -- was 85F9 -- ttl/protocol := x8011
86  else -- icmp ping mode
87  cs_sig <= '0' & x"FA96"; -- was 95E9 -- ttl/protocol := x8001
88  end if;
89  elsif(state < 9) then
90  state <= state + 1;
91  end if;
92 
93 
94  -- states
95  if( state = 0 ) then
96  add_sig <= '0' & unsigned(src_in(15 downto 0));
97  elsif( state = 2 ) then
98  add_sig <= '0' & unsigned(src_in(31 downto 16));
99  elsif( state = 4 ) then
100  add_sig <= '0' & unsigned(dest_in(15 downto 0));
101  elsif( state = 6 ) then
102  add_sig <= '0' & unsigned(dest_in(31 downto 16));
103  elsif( state = 8 ) then
104  add_sig <= '0' & '0' & x"0" & unsigned(length_in(10 downto 0));
105  elsif( state > 8 ) then
106  add_sig <= (others => '0'); -- add nothing
107  end if;
108 
109  end if;
110 
111  end process;
112 
113 end arch;