[米联客-安路飞龙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
本文来米联客(milianke),作者:米联客(milianke),转载请注明原文链接:https://www.cnblogs.com/milianke/p/18351346
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)