From f48a1fad1d73ac7f569e6c50c31592dd486bf8b9 Mon Sep 17 00:00:00 2001 From: Reinier van der Walle <walle@astron.nl> Date: Fri, 21 Jul 2017 06:48:36 +0000 Subject: [PATCH] added comments --- .../io/eth/src/vhdl/eth_checksum_10g.vhd | 103 ++++++++++-------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/libraries/io/eth/src/vhdl/eth_checksum_10g.vhd b/libraries/io/eth/src/vhdl/eth_checksum_10g.vhd index 17ba139d8a..0b6b283935 100644 --- a/libraries/io/eth/src/vhdl/eth_checksum_10g.vhd +++ b/libraries/io/eth/src/vhdl/eth_checksum_10g.vhd @@ -25,26 +25,15 @@ USE IEEE.std_logic_1164.ALL; USE IEEE.numeric_std.ALL; USE common_lib.common_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; - --- Purpose: --- Can be used to calculate the checksum for IPv4, ICMP and UDP, provided --- the correct words are provided between sop and eop. --- Description: --- Determine the 16 bit 1-complement checksum according IPv4 to for the valid --- words between snk_in.sop and snk_in.eop, taking in account snk_in.empty. --- . For checksum verification the result should be 0 when the words are OK. --- . For checksum calculation the result should be used at the checksum field --- in the packet header. --- Remarks: --- . At the snk_in.sop the checksum is initialized to 0. --- . At the snk_in.eop the snk_in.empty LSBytes are padded with 0. --- . The words do not need to be provided in order, because the checksum is --- based on addition. --- . Assume that snk_in.sop and snk_in.eop are only active when snk_in.valid --- is active. --- . Assume that between packets so from snk_in.eop to next snk_in.sop the --- snk_in.valid is inactive and that snk_in.valid is only active for new --- data. +---------------------------------------------------------------------------------- +-- Purpose: -- +-- Can be used to calculate and insert the checksum for the IP header -- +-- in a 10GbE package, if the correct longwords are provided. -- +-- Description: -- +-- Determine the 16 bit 1-complement checksum according IPv4 to for the valid -- +-- words between snk_in.sop and the last ip header field. -- +-- After calculation, the checksum is inserted in the outgoing stream -- +---------------------------------------------------------------------------------- ENTITY eth_checksum_10g IS PORT ( @@ -61,23 +50,24 @@ END eth_checksum_10g; ARCHITECTURE rtl OF eth_checksum_10g IS - CONSTANT c_cin_w : NATURAL := 4; --true_log2(c_nof_half_words - 1); + CONSTANT c_cin_w : NATURAL := 4; --bit width of carry CONSTANT c_pipeline_delay : NATURAL := 2; - SIGNAL sum : UNSIGNED(c_halfword_w + c_cin_w -1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL checksum : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0); + SIGNAL sum : UNSIGNED(c_halfword_w + c_cin_w -1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL checksum : STD_LOGIC_VECTOR(c_halfword_w-1 DOWNTO 0); + SIGNAL cnt_clr, cnt_p_clr : STD_LOGIC; + SIGNAL cnt_en, cnt_p_en : STD_LOGIC; + SIGNAL count, count_p : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL dp_pipeline_src_out : t_dp_sosi; - SIGNAL cnt_clr : STD_LOGIC; - SIGNAL cnt_en : STD_LOGIC; - SIGNAL count : STD_LOGIC_VECTOR(31 DOWNTO 0); - BEGIN + ------------------------------------------------- + -- process to calculate the ip_header_checksum -- + ------------------------------------------------- p_calc_chksum : PROCESS(clk) BEGIN IF rst = '1' THEN sum <= (OTHERS => '0'); - --checksum <= (OTHERS => '0'); ELSIF RISING_EDGE(clk) THEN IF cnt_clr = '1' THEN @@ -85,37 +75,43 @@ BEGIN ELSIF cnt_en = '1' THEN CASE TO_UINT(count) IS - WHEN 0 => - sum <= sum + UNSIGNED(snk_in.data(c_halfword_w-1 DOWNTO 0)); + WHEN 0 => -- 0 is the cycle after the sop due to the common_counter latency + sum <= sum + UNSIGNED(snk_in.data(c_halfword_w-1 DOWNTO 0)); -- ip_version, ip_header_length, ip_services WHEN 1 => - sum <= sum + UNSIGNED(snk_in.data(c_halfword_w*4 -1 DOWNTO c_halfword_w *3)) - + UNSIGNED(snk_in.data(c_halfword_w*3 -1 DOWNTO c_halfword_w *2)) - + UNSIGNED(snk_in.data(c_halfword_w*2 -1 DOWNTO c_halfword_w)) - + UNSIGNED(snk_in.data(c_halfword_w -1 DOWNTO 0)); - WHEN 2 => - sum <= sum + UNSIGNED(snk_in.data(c_halfword_w*3 -1 DOWNTO c_halfword_w *2)) - + UNSIGNED(snk_in.data(c_halfword_w*2 -1 DOWNTO c_halfword_w)) - + UNSIGNED(snk_in.data(c_halfword_w -1 DOWNTO 0)); + sum <= sum + UNSIGNED(snk_in.data(c_halfword_w*4 -1 DOWNTO c_halfword_w *3)) -- ip_total_length + + UNSIGNED(snk_in.data(c_halfword_w*3 -1 DOWNTO c_halfword_w *2)) -- ip_identification + + UNSIGNED(snk_in.data(c_halfword_w*2 -1 DOWNTO c_halfword_w)) -- ip_flags, ip_fragment_offset + + UNSIGNED(snk_in.data(c_halfword_w -1 DOWNTO 0)); -- ip_time_to_live, ip_protocol + WHEN 2 => -- skip ip_header_checksum + sum <= sum + UNSIGNED(snk_in.data(c_halfword_w*3 -1 DOWNTO c_halfword_w *2)) -- ip_src_addr(1/2) + + UNSIGNED(snk_in.data(c_halfword_w*2 -1 DOWNTO c_halfword_w)) -- ip_src_addr(2/2) + + UNSIGNED(snk_in.data(c_halfword_w -1 DOWNTO 0)); -- ip_dst_addr(1/2) WHEN 3 => - sum <= sum + UNSIGNED(snk_in.data(c_halfword_w*4 -1 DOWNTO c_halfword_w *3)); + sum <= sum + UNSIGNED(snk_in.data(c_halfword_w*4 -1 DOWNTO c_halfword_w *3));-- ip_dst_addr(2/2) WHEN OTHERS => END CASE; END IF; END IF; - END PROCESS; + END PROCESS; - checksum <= NOT(STD_LOGIC_VECTOR(sum(c_halfword_w-1 DOWNTO 0)+sum(sum'HIGH DOWNTO c_halfword_w))); + --------------------------------------------------- + -- process to insert checksum in outgoing stream -- + --------------------------------------------------- + checksum <= NOT(STD_LOGIC_VECTOR(sum(c_halfword_w-1 DOWNTO 0)+sum(sum'HIGH DOWNTO c_halfword_w))); -- checksum = inverted (sum + carry) p_insert_chksum : PROCESS(dp_pipeline_src_out, checksum, count) BEGIN src_out <= dp_pipeline_src_out; - IF TO_UINT(count) = 2+c_pipeline_delay THEN + IF TO_UINT(count_p) = 2 THEN src_out.data(c_halfword_w*4 -1 DOWNTO c_halfword_w *3) <= checksum; END IF; END PROCESS; - cnt_en <= snk_in.valid; - cnt_clr <= snk_in.sop; + ------------------------------------------------------------------------------------------- + -- useing common_counter to keep track of the word alignment during checksum calculation -- + ------------------------------------------------------------------------------------------- + cnt_en <= snk_in.valid; -- only count when valid + cnt_clr <= snk_in.sop; -- restart counter on sop u_calc_counter : ENTITY common_lib.common_counter PORT MAP ( @@ -124,8 +120,25 @@ BEGIN cnt_clr => cnt_clr, cnt_en => cnt_en, count => count - ); + ); + ----------------------------------------------------------------------------------------- + -- useing common_counter to keep track of the word alignment during checksum insertion -- + ----------------------------------------------------------------------------------------- + cnt_p_en <= dp_pipeline_src_out.valid; -- only count when valid + cnt_p_clr <= dp_pipeline_src_out.sop; -- restart counter on sop + + u_pipe_counter : ENTITY common_lib.common_counter + PORT MAP ( + rst => rst, + clk => clk, + cnt_clr => cnt_p_clr, + cnt_en => cnt_p_en, + count => count_p + ); + -------------------------------------------------------------------------------- + -- useing dp_pipeline to make room for the checksum calculation and insertion -- + -------------------------------------------------------------------------------- u_dp_pipeline : ENTITY dp_lib.dp_pipeline GENERIC MAP ( g_pipeline => c_pipeline_delay -- GitLab