当前位置:   article > 正文

【以太网通信】FPGA 实现 UDP 协议的校验_udp协议fpga

udp协议fpga

UDP 协议提供了一种低延迟的网络通信方式,通信效率高,但不保证接收的可靠性,常用在以太网图像传输等高速通信场合。

目录

1 UDP 协议

2 校验过程

3 HDL 描述


1 UDP 协议

        用户数据报协议(User Datagram Protocol, UDP)是一种面向无连接的传输协议,采用这种协议的通讯,无需事先建立连接。

        UDP 数据段由 UDP 首部和数据两部分组成,其中首部的长度固定为 8 个字节,首部包括源端口、目的端口、UDP 长度和 16 位校验和。

2 校验过程

        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,校验通过;否则检验失败,丢弃该数据段。

3 HDL 描述

        根据反码求和的特性,可以把 UDP 协议的校验分两部分处理,伪首部 + 首部的校验为一部分,UDP 用户数据的校验为另一部分。用户数据的校验需要根据实际的位宽,转换为 16bit。

VHDL 版本

  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. use ieee.std_logic_arith.all;
  4. use ieee.std_logic_unsigned.all;
  5. entity validate_udp is
  6. port(
  7. -- System level
  8. sys_rst : in std_logic;
  9. sys_clk : in std_logic;
  10. -- IP and UDP information
  11. local_ip_addr : in std_logic_vector(4*8-1 downto 0);
  12. remote_ip_addr : in std_logic_vector(4*8-1 downto 0);
  13. local_udp_port : in std_logic_vector(2*8-1 downto 0);
  14. remote_udp_port : in std_logic_vector(2*8-1 downto 0);
  15. udp_packet_len : in std_logic_vector(2*8-1 downto 0);
  16. -- UDP user data input
  17. udp_usr_data : in std_logic_vector(7 downto 0);
  18. udp_usr_wren : in std_logic;
  19. -- UDP checksum output
  20. udp_checksum : out std_logic_vector(2*8-1 downto 0)
  21. );
  22. end entity;
  23. architecture behav of validate_udp is
  24. -- internal signal declarations
  25. subtype word is std_logic_vector(15 downto 0);
  26. type check_info_t is array(0 to 9) of word;
  27. signal udp_check_info: check_info_t;
  28. signal usr_data_buf: std_logic_vector(15 downto 0);
  29. signal usr_wren_toggle: std_logic;
  30. signal usr_wren_toggle_d1: std_logic;
  31. signal checksum_head: std_logic_vector(15 downto 0);
  32. signal checksum_data: std_logic_vector(15 downto 0);
  33. function checksum_adder(
  34. ina: std_logic_vector(15 downto 0);
  35. inb: std_logic_vector(15 downto 0)
  36. ) return std_logic_vector is
  37. variable tmp1,tmp2,tmp: std_logic_vector(31 downto 0);
  38. begin
  39. tmp1 := X"0000" & ina;
  40. tmp2 := X"0000" & inb;
  41. tmp := tmp1 + tmp2;
  42. return tmp(15 downto 0) + tmp(31 downto 16);
  43. end function;
  44. function checksum_out(
  45. ina: std_logic_vector(15 downto 0);
  46. inb: std_logic_vector(15 downto 0)
  47. ) return std_logic_vector is
  48. variable tmp1,tmp2,tmp: std_logic_vector(31 downto 0);
  49. begin
  50. tmp1 := X"0000" & ina;
  51. tmp2 := X"0000" & inb;
  52. tmp := tmp1 + tmp2;
  53. return not(tmp(15 downto 0) + tmp(31 downto 16));
  54. end function;
  55. begin
  56. -- todo
  57. process(sys_rst,sys_clk)
  58. begin
  59. if sys_rst = '1' then
  60. udp_check_info <= (others => (others => '0'));
  61. elsif rising_edge(sys_clk) then
  62. udp_check_info(0) <= local_ip_addr(4*8-1 downto 2*8);
  63. udp_check_info(1) <= local_ip_addr(2*8-1 downto 0*8);
  64. udp_check_info(2) <= remote_ip_addr(4*8-1 downto 2*8);
  65. udp_check_info(3) <= remote_ip_addr(2*8-1 downto 0*8);
  66. udp_check_info(4) <= X"0011"; -- UDP protocol
  67. udp_check_info(5) <= udp_packet_len;
  68. udp_check_info(6) <= local_udp_port;
  69. udp_check_info(7) <= remote_udp_port;
  70. udp_check_info(8) <= udp_packet_len;
  71. udp_check_info(9) <= X"0000"; -- UDP Checksum padding
  72. end if;
  73. end process;
  74. process(udp_check_info)
  75. variable tmp: std_logic_vector(31 downto 0);
  76. begin
  77. tmp := (others => '0');
  78. for i in 0 to 9 loop
  79. tmp := tmp + udp_check_info(i);
  80. end loop;
  81. checksum_head <= tmp(15 downto 0) + tmp(31 downto 16);
  82. end process;
  83. process(sys_rst,sys_clk)
  84. begin
  85. if sys_rst = '1' then
  86. usr_data_buf <= (others => '0');
  87. usr_wren_toggle <= '0';
  88. usr_wren_toggle_d1 <= '0';
  89. elsif rising_edge(sys_clk) then
  90. if udp_usr_wren = '1' then
  91. usr_data_buf <= usr_data_buf(7 downto 0) & udp_usr_data;
  92. else
  93. usr_data_buf <= (others => '0');
  94. end if;
  95. if udp_usr_wren = '1' then
  96. usr_wren_toggle <= not usr_wren_toggle;
  97. else
  98. usr_wren_toggle <= '0';
  99. end if;
  100. usr_wren_toggle_d1 <= usr_wren_toggle;
  101. end if;
  102. end process;
  103. process(sys_rst,sys_clk)
  104. begin
  105. if sys_rst = '1' then
  106. checksum_data <= (others => '0');
  107. elsif rising_edge(sys_clk) then
  108. if usr_wren_toggle_d1 = '1' then
  109. checksum_data <= checksum_adder(checksum_data, usr_data_buf);
  110. else
  111. checksum_data <= (others => '0');
  112. end if;
  113. end if;
  114. end process;
  115. process(sys_rst,sys_clk)
  116. begin
  117. if sys_rst = '1' then
  118. udp_checksum <= (others => '0');
  119. elsif rising_edge(sys_clk) then
  120. udp_checksum <= checksum_out(checksum_head, checksum_data);
  121. end if;
  122. end process;
  123. end architecture;

Verilog 版本

  1. `timescale 1ns / 1ps
  2. module validate_udp(
  3. // System level
  4. sys_rst,
  5. sys_clk,
  6. // IP and UDP information
  7. local_ip_addr,
  8. remote_ip_addr,
  9. local_udp_port,
  10. remote_udp_port,
  11. udp_packet_len,
  12. // UDP user data input
  13. udp_usr_data,
  14. udp_usr_wren,
  15. // UDP checksum output
  16. udp_checksum
  17. );
  18. // IO ports declarations
  19. input sys_rst;
  20. input sys_clk;
  21. input [4*8-1:0] local_ip_addr;
  22. input [4*8-1:0] remote_ip_addr;
  23. input [2*8-1:0] local_udp_port;
  24. input [2*8-1:0] remote_udp_port;
  25. input [2*8-1:0] udp_packet_len;
  26. input [7:0] udp_usr_data;
  27. input udp_usr_wren;
  28. output [2*8-1:0] udp_checksum;
  29. reg [2*8-1:0] udp_checksum;
  30. // internal function declarations
  31. function [15:0] checksum_adder;
  32. input [15:0] ina;
  33. input [15:0] inb;
  34. integer tmp,tmp1,tmp2;
  35. begin
  36. tmp1 = {16'd0, ina};
  37. tmp2 = {16'd0, inb};
  38. tmp = tmp1 + tmp2;
  39. checksum_adder = tmp[15:0] + tmp[31:16];
  40. end
  41. endfunction
  42. function [15:0] checksum_output;
  43. input [15:0] ina;
  44. input [15:0] inb;
  45. integer tmp,tmp1,tmp2;
  46. begin
  47. tmp1 = {16'd0, ina};
  48. tmp2 = {16'd0, inb};
  49. tmp = tmp1 + tmp2;
  50. checksum_output = ~(tmp[15:0] + tmp[31:16]);
  51. end
  52. endfunction
  53. // internal signal declarations
  54. reg [2*8-1:0] udp_check_info[9:0];
  55. reg [2*8-1:0] checksum_head,checksum_data;
  56. reg [4*8-1:0] tmp1,tmp2;
  57. reg [2*8-1:0] usr_data_buf;
  58. reg usr_wren_toggle,usr_wren_toggle_d1;
  59. integer i;
  60. always@(posedge sys_rst or posedge sys_clk) begin
  61. if(sys_rst)
  62. for(i = 0; i < 10; i=i+1)
  63. udp_check_info[i] <= 16'h0000;
  64. else begin
  65. udp_check_info[0] <= local_ip_addr[4*8-1-:16];
  66. udp_check_info[1] <= local_ip_addr[2*8-1-:16];
  67. udp_check_info[2] <= remote_ip_addr[4*8-1-:16];
  68. udp_check_info[3] <= remote_ip_addr[2*8-1-:16];
  69. udp_check_info[4] <= 16'h0011; // UDP protocol
  70. udp_check_info[5] <= udp_packet_len;
  71. udp_check_info[6] <= local_udp_port;
  72. udp_check_info[7] <= remote_udp_port;
  73. udp_check_info[8] <= udp_packet_len;
  74. udp_check_info[9] <= 16'h0000; // UDP checksum bytes padding
  75. end
  76. end
  77. always@(*) begin
  78. tmp1 = 32'd0;
  79. for(i = 0; i < 10; i=i+1) begin
  80. tmp1 = tmp1 + udp_check_info[i];
  81. end
  82. checksum_head = tmp1[15:0] + tmp1[31:16];
  83. end
  84. always@(posedge sys_rst or posedge sys_clk) begin
  85. if(sys_rst) begin
  86. usr_data_buf <= 16'd0;
  87. usr_wren_toggle <= 1'd0;
  88. usr_wren_toggle_d1 <= 1'd0;
  89. end
  90. else begin
  91. if(udp_usr_wren)
  92. usr_data_buf <= {usr_data_buf[7:0], udp_usr_data};
  93. else
  94. usr_data_buf <= 16'd0;
  95. if(udp_usr_wren)
  96. usr_wren_toggle <= ~usr_wren_toggle;
  97. else
  98. usr_wren_toggle <= 1'd0;
  99. usr_wren_toggle_d1 <= usr_wren_toggle;
  100. end
  101. end
  102. always@(posedge sys_rst or posedge sys_clk) begin
  103. if(sys_rst)
  104. checksum_data <= 16'd0;
  105. else
  106. if(usr_wren_toggle_d1)
  107. checksum_data <= checksum_adder(checksum_data, usr_data_buf);
  108. else
  109. checksum_data <= 16'd0;
  110. end
  111. always@(posedge sys_rst or posedge sys_clk) begin
  112. if(sys_rst)
  113. udp_checksum <= 16'd0;
  114. else
  115. udp_checksum <= checksum_output(checksum_head, checksum_data);
  116. end
  117. endmodule

        综合得到的 RTL 电路如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/950454
推荐阅读
相关标签
  

闽ICP备14008679号