使用 FPGA 实现以太网通信时,需要计算 IP 首部的校验和。本文给出了一种计算 IP 数据报校验和的 HDL 实现方法。
目录
1 IP 协议
2 校验过程
3 HDL 描述
1 IP 协议
????????TCP/IP 协议是?TCP、UDP 和 IP 等协议构成的协议簇,作为网络信息传输的规范。在 OSI 网络模型中,TCP 和 UDP 协议由传输层处理,IP 协议由网络层处理。
????????在网络层中,数据以 IP 数据报为单位进行传输。每一个 IP 数据报都由 IP 首部和报文数据两部分组成,其中 IP 首部至少包括?20 个字节,这 20 个字节的含义如下:
2 校验过程
????????IP 数据报只对首部进行校验,发送数据时,按照以下步骤计算 IP 校验和:
(1)把 IP 首部的校验和字段置为?0x0000;
(2)将首部按照 16bit 为字长进行二进制反码求和;
(3)将校验和填充到 IP 首部中。
????????接收数据时,校验数据的步骤为:
(1)将首部(包括校验和)按照 16bit 为字长进行二进制反码求和;
(2)判断计算结果是否等于零;
(3)如果校验和为零,则校验通过;否则,校验失败,丢弃该报文。
3 HDL 描述
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity validate_ip is
port(
-- System level
sys_rst : in std_logic;
sys_clk : in std_logic;
-- IP information
ip_packet_len : in std_logic_vector(2*8-1 downto 0);
identify_code : in std_logic_vector(2*8-1 downto 0);
local_ip_addr : in std_logic_vector(4*8-1 downto 0);
remote_ip_addr : in std_logic_vector(4*8-1 downto 0);
-- IP checksum output
ip_checksum_o : out std_logic_vector(2*8-1 downto 0)
);
end entity;
architecture behav of validate_ip is
-- internal signal declarations
subtype word is std_logic_vector(15 downto 0);
type check_info_t is array(0 to 9) of word;
signal ip_check_info: check_info_t;
signal ip_checksum: std_logic_vector(2*8-1 downto 0);
begin
-- todo
process(sys_rst,sys_clk)
begin
if sys_rst = '1' then
ip_check_info <= (others => (others => '0'));
elsif rising_edge(sys_clk) then
ip_check_info(0) <= X"4500"; -- IPv4, IP head 20 Bytes
ip_check_info(1) <= ip_packet_len;
ip_check_info(2) <= identify_code;
ip_check_info(3) <= X"4000"; -- Don't Fragment, shift 0
ip_check_info(4) <= X"4011"; -- TTL, 64ms, UDP protocol
ip_check_info(5) <= X"0000"; -- IP checksum bytes padding
ip_check_info(6) <= local_ip_addr(4*8-1 downto 2*8);
ip_check_info(7) <= local_ip_addr(2*8-1 downto 0*8);
ip_check_info(8) <= remote_ip_addr(4*8-1 downto 2*8);
ip_check_info(9) <= remote_ip_addr(2*8-1 downto 0*8);
end if;
end process;
process(ip_check_info)
variable tmp: std_logic_vector(31 downto 0);
begin
tmp := (others => '0');
for i in 0 to 9 loop
tmp := tmp + ip_check_info(i);
end loop;
ip_checksum <= not (tmp(15 downto 0) + tmp(31 downto 16));
end process;
process(sys_rst,sys_clk)
begin
if sys_rst = '1' then
ip_checksum_o <= (others => '0');
elsif rising_edge(sys_clk) then
ip_checksum_o <= ip_checksum;
end if;
end process;
end architecture;
综合得到的 RTL 电路图如下:
? ? ? ? 上述综合结果加法器的路径比较长,如果对时序的要求比较严格,可以考虑采用树形结构电路优化,但是会消耗更多的寄存器资源。
|