[米联客-安路飞龙DR1-FPSOC] UDP通信篇连载-06 UDP层程序设计

软件版本:Anlogic -TD5.9.1-DR1_ES1.1

操作系统:WIN10 64bit

硬件平台:适用安路(Anlogic)FPGA

实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板

板卡获取平台:https://milianke.tmall.com/

登录"米联客"FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

3.5 UDP

该层实现用户数据和UDP报文的互转,相比于其它层次的设计,该层的逻辑相对简单。

3.5.1 UDP接收模块

通过计数器将UDP报文头部信息拆解,提取出端口号和长度信息。通过提取的长度对有效数据进行计数,从而得到有效数据并发送给用户端。

 1 always@(posedge I_R_udp_clk or posedge I_reset) begin
 2     if(I_reset) begin
 3         cnt                 <=  4'd0;
 4         O_R_udp_valid       <=  1'b0;
 5         O_R_udp_data        <=  8'd0;
 6         O_R_udp_len         <=  16'd0;
 7         udp_src_port        <=  16'd0;
 8         udp_dest_port       <=  16'd0;
 9         udp_pkg_len         <=  16'd0;
10         udp_data_cnt        <=  16'd0;
11     end
12     else if(I_udp_ip_rvalid) begin
13         udp_data_cnt    <=  udp_data_cnt + 1'b1;
14         case(cnt)
15             0   :begin  udp_src_port[15:8]  <=  I_udp_ip_rdata; cnt <=  cnt + 1'b1;end  //UDP接收源端口(远程主机端口)
16             1   :begin  udp_src_port[7:0]   <=  I_udp_ip_rdata; cnt <=  cnt + 1'b1;end  //UDP接收源端口(远程主机端口)
17             2   :begin  udp_dest_port[15:8] <=  I_udp_ip_rdata; cnt <=  cnt + 1'b1;end  //UDP接收目的端口(本地主机端口)
18             3   :begin  udp_dest_port[7:0]  <=  I_udp_ip_rdata; cnt <=  cnt + 1'b1;end  //UDP接收目的端口(本地主机端口)
19             4   :begin  udp_pkg_len[15:8]   <=  I_udp_ip_rdata; cnt <=  cnt + 1'b1;end  //UDP数据包长度
20             5   :begin  udp_pkg_len[7:0]    <=  I_udp_ip_rdata; cnt <=  cnt + 1'b1;end  //UDP数据包长度
21             6   :begin  cnt <=  cnt + 1'b1;end                                          //跳过检验和
22             7   :begin  cnt <=  cnt + 1'b1;end                                          //跳过校验和
23             8   :begin
24                 O_R_udp_valid       <=  1'b1;                                           //UDP接收数据有效
25                 O_R_udp_data        <=  I_udp_ip_rdata;
26                 O_R_udp_len         <=  udp_pkg_len - 16'd8;
27                 cnt                 <=  cnt + 1'b1;
28             end
29             9   :begin
30                 if(udp_pkg_len < 16'd26) begin
31                     if(udp_data_cnt == udp_pkg_len) begin
32                         O_R_udp_valid       <=  1'b0;
33                         O_R_udp_data        <=  8'd0;
34                         cnt                 <=  cnt + 1'b1;
35                     end     
36                     else begin
37                         O_R_udp_valid       <=  1'b1;
38                         O_R_udp_data        <=  I_udp_ip_rdata;
39                         cnt                 <=  cnt;                    
40                     end         
41                 end
42                 else begin
43                     O_R_udp_valid       <=  1'b1;
44                     O_R_udp_data        <=  I_udp_ip_rdata;
45                     cnt                 <=  cnt;
46                 end
47             end
48             10  :begin
49                 O_R_udp_valid       <=  1'b0;
50                 O_R_udp_data        <=  8'd0;
51                 cnt                 <=  cnt;
52             end
53             default:    cnt <=  4'd0;
54         endcase 
55     end
56     else if(!I_udp_ip_rvalid) begin
57         udp_pkg_len         <=  16'd0;
58         udp_src_port        <=  16'd0;
59         udp_dest_port       <=  16'd0;
60         udp_data_cnt        <=  16'd0;
61         O_R_udp_len         <=  16'd0;
62         O_R_udp_data        <=  8'd0;
63         O_R_udp_valid       <=  1'b0;
64         cnt                 <=  4'd0;
65     end
66 end

 

 

3.5.2 UDP发送模块

状态机转换图如下:

IDLE:当用户端发送写请求,且uiip_tx模块不忙时,进入WAIT_ACK状态。

WAIT_ACK:等待uiip_tx模块将udp_ip_tbusy信号拉高,完成握手,进入SEND_UDP_HEADER状态,开始发送UDP报文头部。

SEND_UDP_HEADER:将8个字节的UDP报文头部添加在有效数据之前,头部数据发送完成后,进入SEND_UDP_PACKET状态。

SEND_UDP_PACKET:将经过shift_ram移位8位的数据拼接在包头之后,通过计数器判断发送数据的数量,待数据发送完成后,回到IDLE状态,等待下一次发送请求。

 1 always@(posedge I_W_udp_clk or posedge I_reset) begin
 2     if(I_reset) begin
 3         cnt                 <=  4'd0;
 4         O_udp_ip_tvalid     <=  1'b0;
 5         O_udp_ip_tdata      <=  8'd0;
 6         O_udp_ip_tpkg_len   <=  16'd0;
 7         trans_data_cnt      <=  16'd0;
 8         STATE               <=  IDLE;
 9     end
10     else begin
11         case(STATE)
12             IDLE:begin
13                 if(I_W_udp_req & (~I_udp_ip_tbusy)) //当有写UDP请求,并且ip_tx模块不忙(当I_udp_ip_tbusy=1代表正在ip层正在传输数据)
14                     STATE   <=  WAIT_ACK;           //进入WAIT_ACK
15                 else
16                     STATE   <=  IDLE;
17             end
18             WAIT_ACK:begin
19                 if(I_udp_ip_tbusy)                  //如果ip_tx模块准备好,代表udp_layer可以发送数据
20                     STATE   <=  SEND_UDP_HEADER;
21                 else
22                     STATE   <=  WAIT_ACK;
23             end
24             SEND_UDP_HEADER:begin
25                 case(cnt)
26                     0   :begin
27                         if(I_W_udp_valid) begin
28                             O_udp_ip_tvalid     <=  1'b1;                   //udp包数据有效
29                             O_udp_ip_tdata      <=  I_udp_local_port[15:8]; //UDP报文源端口              
30                             O_udp_ip_tpkg_len   <=  I_W_udp_len + 16'h0008; //UDP报文长度,其中8bytes为udp首部       
31          
32                             cnt                 <=  cnt + 1'b1;
33                         end
34                         else
35                             cnt                 <=  0;
36                     end
37                     1   :begin
38                         O_udp_ip_tdata          <=  I_udp_local_port[7:0];  //UDP报文源端口
39                         cnt                     <=  cnt + 1'b1;
40                     end
41                     2   :begin
42                         O_udp_ip_tdata          <=  I_udp_dest_port[15:8];  //UDP报文目的端口
43                         cnt                     <=  cnt + 1'b1;
44                     end
45                     3   :begin
46                         O_udp_ip_tdata          <=  I_udp_dest_port[7:0];   //UDP报文目的端口
47                         cnt                     <=  cnt + 1'b1;
48                     end
49                     4   :begin
50                         O_udp_ip_tdata          <=  O_udp_ip_tpkg_len[15:8];//UDP报文长度
51                         cnt                     <=  cnt + 1'b1;
52                     end
53                     5   :begin
54                         O_udp_ip_tdata          <=  O_udp_ip_tpkg_len[7:0]; //UDP报文长度
55                         cnt                     <=  cnt + 1'b1;
56                     end
57                     6   :begin
58                         O_udp_ip_tdata          <=  CHECKSUM[7:0];          //校验和
59                         cnt                     <=  cnt + 1'b1;
60                     end
61                     7   :begin
62                         O_udp_ip_tdata          <=  CHECKSUM [7:0];         //校验和
63                         cnt                     <=  0;
64                         STATE                   <=  SEND_UDP_PACKET;
65                     end
66                     default: cnt    <=  0;
67                 endcase
68             end
69             SEND_UDP_PACKET:begin
70                 if(trans_data_cnt != (O_udp_ip_tpkg_len - 16'd8)) begin
71                     O_udp_ip_tvalid     <=  1'b1;
72                     O_udp_ip_tdata      <=  shift_data_out;
73                     trans_data_cnt      <=  trans_data_cnt + 1'b1;
74                     STATE               <=  SEND_UDP_PACKET;
75                 end
76                 else begin
77                     trans_data_cnt      <=  16'd0;
78                     O_udp_ip_tdata      <=  8'd0;
79                     O_udp_ip_tvalid     <=  1'b0;
80                     O_udp_ip_tpkg_len   <=  16'd0;
81                     cnt                 <=  0;
82                     STATE               <=  IDLE;
83                 end
84             end
85             default: STATE          <=  IDLE;
86         endcase
87     end
88  end

 

posted @ 2024-08-09 18:57  米联客(milianke)  阅读(4)  评论(0编辑  收藏  举报