赞
踩
UDP 协议提供了一种低延迟的网络通信方式,通信效率高,但不保证接收的可靠性,常用在以太网图像传输等高速通信场合。
目录
用户数据报协议(User Datagram Protocol, UDP)是一种面向无连接的传输协议,采用这种协议的通讯,无需事先建立连接。
UDP 数据段由 UDP 首部和数据两部分组成,其中首部的长度固定为 8 个字节,首部包括源端口、目的端口、UDP 长度和 16 位校验和。
UDP 协议校验时需要添加 12 字节的伪首部,并且和 IP 协议不同,UDP 协议还需要校验数据。发送数据时,UDP 协议的校验步骤为:
(1)在 UDP 首部前添加 12 字节的伪首部;
(2)将首部校验和部分置零为 0x0000;
(3)以 16bit 为字长进行反码求和(数据不足的需补齐 16bit);
(4)将校验结果填充到 UDP 首部。
接收数据时,UDP 协议的校验步骤为:
(1)在 UDP 首部前添加 12 字节的伪首部;
(2)以 16bit 为字长进行反码求和;
(3)判断校验结果是否为 0xFFFF;
(4)若检验结果为 0xFFFF,校验通过;否则检验失败,丢弃该数据段。
根据反码求和的特性,可以把 UDP 协议的校验分两部分处理,伪首部 + 首部的校验为一部分,UDP 用户数据的校验为另一部分。用户数据的校验需要根据实际的位宽,转换为 16bit。
VHDL 版本
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.std_logic_arith.all;
- use ieee.std_logic_unsigned.all;
-
- entity validate_udp is
- port(
- -- System level
- sys_rst : in std_logic;
- sys_clk : in std_logic;
-
- -- IP and UDP information
- local_ip_addr : in std_logic_vector(4*8-1 downto 0);
- remote_ip_addr : in std_logic_vector(4*8-1 downto 0);
- local_udp_port : in std_logic_vector(2*8-1 downto 0);
- remote_udp_port : in std_logic_vector(2*8-1 downto 0);
- udp_packet_len : in std_logic_vector(2*8-1 downto 0);
-
- -- UDP user data input
- udp_usr_data : in std_logic_vector(7 downto 0);
- udp_usr_wren : in std_logic;
-
- -- UDP checksum output
- udp_checksum : out std_logic_vector(2*8-1 downto 0)
- );
- end entity;
- architecture behav of validate_udp 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 udp_check_info: check_info_t;
-
- signal usr_data_buf: std_logic_vector(15 downto 0);
- signal usr_wren_toggle: std_logic;
- signal usr_wren_toggle_d1: std_logic;
- signal checksum_head: std_logic_vector(15 downto 0);
- signal checksum_data: std_logic_vector(15 downto 0);
-
- function checksum_adder(
- ina: std_logic_vector(15 downto 0);
- inb: std_logic_vector(15 downto 0)
- ) return std_logic_vector is
- variable tmp1,tmp2,tmp: std_logic_vector(31 downto 0);
- begin
- tmp1 := X"0000" & ina;
- tmp2 := X"0000" & inb;
- tmp := tmp1 + tmp2;
- return tmp(15 downto 0) + tmp(31 downto 16);
- end function;
-
- function checksum_out(
- ina: std_logic_vector(15 downto 0);
- inb: std_logic_vector(15 downto 0)
- ) return std_logic_vector is
- variable tmp1,tmp2,tmp: std_logic_vector(31 downto 0);
- begin
- tmp1 := X"0000" & ina;
- tmp2 := X"0000" & inb;
- tmp := tmp1 + tmp2;
- return not(tmp(15 downto 0) + tmp(31 downto 16));
- end function;
-
- begin
- -- todo
- process(sys_rst,sys_clk)
- begin
- if sys_rst = '1' then
- udp_check_info <= (others => (others => '0'));
- elsif rising_edge(sys_clk) then
- udp_check_info(0) <= local_ip_addr(4*8-1 downto 2*8);
- udp_check_info(1) <= local_ip_addr(2*8-1 downto 0*8);
- udp_check_info(2) <= remote_ip_addr(4*8-1 downto 2*8);
- udp_check_info(3) <= remote_ip_addr(2*8-1 downto 0*8);
- udp_check_info(4) <= X"0011"; -- UDP protocol
- udp_check_info(5) <= udp_packet_len;
- udp_check_info(6) <= local_udp_port;
- udp_check_info(7) <= remote_udp_port;
- udp_check_info(8) <= udp_packet_len;
- udp_check_info(9) <= X"0000"; -- UDP Checksum padding
- end if;
- end process;
-
- process(udp_check_info)
- variable tmp: std_logic_vector(31 downto 0);
- begin
- tmp := (others => '0');
- for i in 0 to 9 loop
- tmp := tmp + udp_check_info(i);
- end loop;
- checksum_head <= tmp(15 downto 0) + tmp(31 downto 16);
- end process;
-
- process(sys_rst,sys_clk)
- begin
- if sys_rst = '1' then
- usr_data_buf <= (others => '0');
- usr_wren_toggle <= '0';
- usr_wren_toggle_d1 <= '0';
- elsif rising_edge(sys_clk) then
- if udp_usr_wren = '1' then
- usr_data_buf <= usr_data_buf(7 downto 0) & udp_usr_data;
- else
- usr_data_buf <= (others => '0');
- end if;
-
- if udp_usr_wren = '1' then
- usr_wren_toggle <= not usr_wren_toggle;
- else
- usr_wren_toggle <= '0';
- end if;
-
- usr_wren_toggle_d1 <= usr_wren_toggle;
- end if;
- end process;
-
- process(sys_rst,sys_clk)
- begin
- if sys_rst = '1' then
- checksum_data <= (others => '0');
- elsif rising_edge(sys_clk) then
- if usr_wren_toggle_d1 = '1' then
- checksum_data <= checksum_adder(checksum_data, usr_data_buf);
- else
- checksum_data <= (others => '0');
- end if;
- end if;
- end process;
-
- process(sys_rst,sys_clk)
- begin
- if sys_rst = '1' then
- udp_checksum <= (others => '0');
- elsif rising_edge(sys_clk) then
- udp_checksum <= checksum_out(checksum_head, checksum_data);
- end if;
- end process;
- end architecture;
Verilog 版本
- `timescale 1ns / 1ps
-
- module validate_udp(
- // System level
- sys_rst,
- sys_clk,
-
- // IP and UDP information
- local_ip_addr,
- remote_ip_addr,
- local_udp_port,
- remote_udp_port,
- udp_packet_len,
-
- // UDP user data input
- udp_usr_data,
- udp_usr_wren,
-
- // UDP checksum output
- udp_checksum
- );
-
- // IO ports declarations
- input sys_rst;
- input sys_clk;
- input [4*8-1:0] local_ip_addr;
- input [4*8-1:0] remote_ip_addr;
- input [2*8-1:0] local_udp_port;
- input [2*8-1:0] remote_udp_port;
- input [2*8-1:0] udp_packet_len;
- input [7:0] udp_usr_data;
- input udp_usr_wren;
- output [2*8-1:0] udp_checksum;
- reg [2*8-1:0] udp_checksum;
-
- // internal function declarations
- function [15:0] checksum_adder;
- input [15:0] ina;
- input [15:0] inb;
- integer tmp,tmp1,tmp2;
- begin
- tmp1 = {16'd0, ina};
- tmp2 = {16'd0, inb};
- tmp = tmp1 + tmp2;
- checksum_adder = tmp[15:0] + tmp[31:16];
- end
- endfunction
-
- function [15:0] checksum_output;
- input [15:0] ina;
- input [15:0] inb;
- integer tmp,tmp1,tmp2;
- begin
- tmp1 = {16'd0, ina};
- tmp2 = {16'd0, inb};
- tmp = tmp1 + tmp2;
- checksum_output = ~(tmp[15:0] + tmp[31:16]);
- end
- endfunction
-
- // internal signal declarations
- reg [2*8-1:0] udp_check_info[9:0];
- reg [2*8-1:0] checksum_head,checksum_data;
- reg [4*8-1:0] tmp1,tmp2;
-
- reg [2*8-1:0] usr_data_buf;
- reg usr_wren_toggle,usr_wren_toggle_d1;
-
- integer i;
-
- always@(posedge sys_rst or posedge sys_clk) begin
- if(sys_rst)
- for(i = 0; i < 10; i=i+1)
- udp_check_info[i] <= 16'h0000;
- else begin
- udp_check_info[0] <= local_ip_addr[4*8-1-:16];
- udp_check_info[1] <= local_ip_addr[2*8-1-:16];
- udp_check_info[2] <= remote_ip_addr[4*8-1-:16];
- udp_check_info[3] <= remote_ip_addr[2*8-1-:16];
- udp_check_info[4] <= 16'h0011; // UDP protocol
- udp_check_info[5] <= udp_packet_len;
- udp_check_info[6] <= local_udp_port;
- udp_check_info[7] <= remote_udp_port;
- udp_check_info[8] <= udp_packet_len;
- udp_check_info[9] <= 16'h0000; // UDP checksum bytes padding
- end
- end
-
- always@(*) begin
- tmp1 = 32'd0;
- for(i = 0; i < 10; i=i+1) begin
- tmp1 = tmp1 + udp_check_info[i];
- end
- checksum_head = tmp1[15:0] + tmp1[31:16];
- end
-
- always@(posedge sys_rst or posedge sys_clk) begin
- if(sys_rst) begin
- usr_data_buf <= 16'd0;
- usr_wren_toggle <= 1'd0;
- usr_wren_toggle_d1 <= 1'd0;
- end
- else begin
- if(udp_usr_wren)
- usr_data_buf <= {usr_data_buf[7:0], udp_usr_data};
- else
- usr_data_buf <= 16'd0;
-
- if(udp_usr_wren)
- usr_wren_toggle <= ~usr_wren_toggle;
- else
- usr_wren_toggle <= 1'd0;
-
- usr_wren_toggle_d1 <= usr_wren_toggle;
- end
- end
-
- always@(posedge sys_rst or posedge sys_clk) begin
- if(sys_rst)
- checksum_data <= 16'd0;
- else
- if(usr_wren_toggle_d1)
- checksum_data <= checksum_adder(checksum_data, usr_data_buf);
- else
- checksum_data <= 16'd0;
- end
-
- always@(posedge sys_rst or posedge sys_clk) begin
- if(sys_rst)
- udp_checksum <= 16'd0;
- else
- udp_checksum <= checksum_output(checksum_head, checksum_data);
- end
- endmodule
综合得到的 RTL 电路如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。