OpenCores
URL https://opencores.org/ocsvn/tcp_ip_core_w_dhcp/tcp_ip_core_w_dhcp/trunk

Subversion Repositories tcp_ip_core_w_dhcp

[/] [tcp_ip_core_w_dhcp/] [trunk/] [checksum_calc.vhd] - Rev 2

Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    12:51:09 12/30/2014 
-- Design Name: 
-- Module Name:    checksum_calc - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity checksum_calc is
    Port ( CLK_IN 						: in  STD_LOGIC;
           RST_IN 						: in  STD_LOGIC;
           CHECKSUM_CALC_IN 			: in  STD_LOGIC;
           START_ADDR_IN 				: in  STD_LOGIC_VECTOR (10 downto 0);
           COUNT_IN 						: in  STD_LOGIC_VECTOR (10 downto 0);
           VALUE_IN 						: in  STD_LOGIC_VECTOR (7 downto 0);
           VALUE_ADDR_OUT 				: out STD_LOGIC_VECTOR (10 downto 0);
			  CHECKSUM_INIT_IN			: in  STD_LOGIC_VECTOR (15 downto 0);
			  CHECKSUM_SET_INIT_IN		: in  STD_LOGIC;
			  CHECKSUM_ODD_LENGTH_IN	: in  STD_LOGIC;
           CHECKSUM_OUT 				: out STD_LOGIC_VECTOR (15 downto 0);
           CHECKSUM_DONE_OUT 			: out STD_LOGIC);
end checksum_calc;
 
architecture Behavioral of checksum_calc is
 
type CC_ST is (	IDLE,
						SET_INITIAL_VALUE0,
						SET_INITIAL_VALUE1,
						LOAD_START_ADDR,
						INC_ADDR0,
						INC_ADDR1,
						LOAD_VALUE_LSB,
						ADD_VALUE,
						CHECK_COUNT,
						CHECK_REMAINDER,
						ADD_REMAINDER,
						ONES_COMPLEMENT,
						COMPLETE
						);
 
signal cc_state, cc_next_state : CC_ST := IDLE;
 
signal rd_addr 								: unsigned(10 downto 0);
signal value, checksum_reg_inv			: unsigned(15 downto 0);
signal checksum_reg							: unsigned(31 downto 0);
signal count 									: unsigned(10 downto 0);
signal checksum_odd 							: std_logic;
 
begin
 
	VALUE_ADDR_OUT <= std_logic_vector(rd_addr);
	CHECKSUM_OUT <= std_logic_vector(checksum_reg_inv);
	CHECKSUM_DONE_OUT <= '1' when cc_state = COMPLETE else '0';
 
	SYNC_PROC: process(CLK_IN)
   begin
      if rising_edge(CLK_IN) then
			cc_state <= cc_next_state;
      end if;
   end process;
 
	NEXT_STATE_DECODE: process (cc_state, CHECKSUM_CALC_IN, count, CHECKSUM_SET_INIT_IN)
   begin
      cc_next_state <= cc_state;  --default is to stay in current state
      case (cc_state) is
         when IDLE =>
				if CHECKSUM_CALC_IN = '1' then
					cc_next_state <= LOAD_START_ADDR;
				elsif CHECKSUM_SET_INIT_IN = '1' then
					cc_next_state <= SET_INITIAL_VALUE0;
				end if;
			when SET_INITIAL_VALUE0 =>
				cc_next_state <= SET_INITIAL_VALUE1;
			when SET_INITIAL_VALUE1 =>
				if CHECKSUM_CALC_IN = '1' then
					cc_next_state <= LOAD_START_ADDR;
				end if;
			when LOAD_START_ADDR =>
				cc_next_state <= INC_ADDR0;
			when INC_ADDR0 =>
				cc_next_state <= INC_ADDR1;			
			when INC_ADDR1 =>
				cc_next_state <= LOAD_VALUE_LSB;
			when LOAD_VALUE_LSB =>
				cc_next_state <= ADD_VALUE;
			when ADD_VALUE =>
				cc_next_state <= CHECK_COUNT;
			when CHECK_COUNT =>
				if count = "00000000000" then
					cc_next_state <= CHECK_REMAINDER;
				else
					cc_next_state <= INC_ADDR0;
				end if;
 
			when CHECK_REMAINDER =>
				if checksum_reg(31 downto 16) = X"0000" then
					cc_next_state <= ONES_COMPLEMENT;
				else
					cc_next_state <= ADD_REMAINDER;
				end if;
			when ADD_REMAINDER =>
				cc_next_state <= CHECK_REMAINDER;
 
 
			when ONES_COMPLEMENT =>
				cc_next_state <= COMPLETE;
 
			when COMPLETE =>
				cc_next_state <= IDLE;
 
		end case;
	end process;
 
	RD_ADDR_PROC: process(CLK_IN)
   begin
      if rising_edge(CLK_IN) then
			if cc_state = LOAD_START_ADDR then
				rd_addr <= unsigned(START_ADDR_IN);
			elsif cc_state = INC_ADDR0 then
				rd_addr <= rd_addr + 1;
			elsif cc_state = INC_ADDR1 then
				rd_addr <= rd_addr + 1;
			end if;
			if CHECKSUM_CALC_IN = '1' then
				checksum_odd <= CHECKSUM_ODD_LENGTH_IN;
			end if;
      end if;
   end process;
 
	LOAD_VALUE_PROC: process(CLK_IN)
   begin
      if rising_edge(CLK_IN) then
			if cc_state = INC_ADDR1 then
				value(15 downto 8) <= unsigned(VALUE_IN);
			end if;
			if cc_state = LOAD_VALUE_LSB then
				if checksum_odd = '1' and count = "00000000001" then
					value(7 downto 0) <= X"00";
				else
					value(7 downto 0) <= unsigned(VALUE_IN);
				end if;
			end if;
      end if;
   end process;
 
	ADD_VALUE_TO_CHECKSUM: process(CLK_IN)
	begin
      if rising_edge(CLK_IN) then
			if cc_state = IDLE then
				checksum_reg <= (others => '0');
			elsif cc_state = SET_INITIAL_VALUE0 then
				checksum_reg(15 downto 0) <= unsigned(CHECKSUM_INIT_IN);
				checksum_reg(31 downto 16) <= (others => '0');
			elsif cc_state = ADD_VALUE then
				checksum_reg <= checksum_reg + unsigned(X"0000" & value);
			elsif cc_state = ADD_REMAINDER then
				checksum_reg <= unsigned(X"0000" & checksum_reg(15 downto 0)) + unsigned(X"0000" & checksum_reg(31 downto 16));
			end if;
			if cc_state = ONES_COMPLEMENT then
				checksum_reg_inv <= not(checksum_reg(15 downto 0));
			end if;
		end if;
	end process;
 
	COUNT_PROC: process(CLK_IN)
	begin
      if rising_edge(CLK_IN) then
			if (cc_state = IDLE or cc_state = SET_INITIAL_VALUE1) and CHECKSUM_CALC_IN = '1' then
				count <= unsigned(COUNT_IN);
			elsif cc_state = ADD_VALUE then
				count <= count - 1;
			end if;
		end if;
	end process;
 
end Behavioral;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.