[米联客-安路飞龙DR1-FPSOC] UDP通信篇连载-03 IP_ARP层程序设计
软件版本: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.2 IP_ARP层
由于IP和ARP数据包送至MAC层要经过同一个通道,需要对发送的数据包类型进行判断和仲裁,这就需要额外增加一个IP_ARP层。
1 /*******************************uiip_arp_rx模块********************* 2 --以下是米联客设计的uiip_arp_rx模块 3 1.该模块1用于区分接收数据是IP包还是ARP包 4 *********************************************************************/ 5 `timescale 1ns/1ps 6 module uiip_arp_rx 7 ( 8 input wire I_ip_arp_reset, //复位 9 input wire I_ip_arp_rclk, //RX 接收时钟 10 output wire O_ip_rvalid, //接收的有效IP信号 11 output wire [7:0] O_ip_rdata, //接收的IP数据 12 output wire O_arp_rvalid, //接收的有效ARP信号 13 output wire [7:0] O_arp_rdata, //接收的有效ARP数据 14 15 input wire I_mac_rvalid, //MAC接收到的数据有效信号 16 input wire [7:0] I_mac_rdata, //MAC接收的有效数据 17 input wire [15:0] I_mac_rdata_type //MAC接收到的帧类型 18 19 ); 20 reg ip_rx_data_valid; //接收的有效IP信号 21 reg [7:0] ip_rx_data; //接收的IP数据 22 reg arp_rx_data_valid; //接收的有效ARP信号 23 reg [7:0] arp_rx_data; //接收的有效ARP数据 24 25 assign O_ip_rvalid = ip_rx_data_valid; 26 assign O_ip_rdata = ip_rx_data; 27 assign O_arp_rvalid = arp_rx_data_valid; 28 assign O_arp_rdata = arp_rx_data; 29 30 localparam ARP_TYPE = 16'h0806; //ARP包类型 31 localparam IP_TYPE = 16'h0800; //IP 包类型 32 always@(posedge I_ip_arp_rclk or posedge I_ip_arp_reset) begin 33 if(I_ip_arp_reset) begin 34 ip_rx_data_valid <= 1'b0; 35 ip_rx_data <= 8'd0; 36 arp_rx_data_valid <= 1'b0; 37 arp_rx_data <= 8'd0; 38 end 39 else if(I_mac_rvalid) begin 40 if(I_mac_rdata_type == IP_TYPE) begin//IP包 41 ip_rx_data_valid <= 1'b1; 42 ip_rx_data <= I_mac_rdata; 43 end 44 else if(I_mac_rdata_type == ARP_TYPE) begin//ARP包 45 arp_rx_data_valid <= 1'b1; 46 arp_rx_data <= I_mac_rdata; 47 end 48 else begin 49 ip_rx_data_valid <= 1'b0; 50 ip_rx_data <= 8'd0; 51 arp_rx_data_valid <= 1'b0; 52 arp_rx_data <= 8'd0; 53 end 54 end 55 else begin 56 ip_rx_data_valid <= 1'b0; 57 ip_rx_data <= 8'd0; 58 arp_rx_data_valid <= 1'b0; 59 arp_rx_data <= 8'd0; 60 end 61 end 62 63 endmodul
3.2.1 IP_ARP接收模块
该模块接收到MAC帧经过MAC层解包得到的数据包,通过类型字段判断该包是IP包还是ARP包,将其送入对应的模块中处理。
3.2.2 IP_ARP发送模块
该模块接收IP层和ARP层传来的发送请求,通过busy信号与上层协议模块进行握手,来发送对应的数据。该模块的状态机转换图如图所示。
IDLE:如果是IP层发送的请求,且arp_req_pend信号没有挂起时,进入CHECK_MAC_CACHEE状态,进入ARP层查询mac_cache中缓存的MAC地址。如果是ARP层发送的请求,在MAC层非忙时,将arp_tbusy拉高,表示可以发送ARP包,进入WAIT_ARP_PACKET状态。
CHECK_MAC_CACHE:若没有查询到IP地址对应的MAC地址,则使能O_arp_treq_en信号,请求ARP层发送ARP广播包,并且将arp_req_pend挂起(该信号挂起时不能发送IP包),回到IDLE状态,等待ARP层发送请求信号。若查询到MAC地址,进入WAIT_IP_PACKET状态,等待IP层将有效数据发送过来。
WAIT_IP_PACKET:若I_ip_valid拉高,说明IP包有效数据开始传入,接收传来的数据并将其发送至MAC层,进入SEND_IP_PACKET状态。
SEND_IP_PACKET:等待一帧IP包数据全部发送完成时,回到IDLE状态。
WAIT_ARP_PACKET:I_arp_valid拉高,说明ARP包有效数据开始传入,接收传来的数据并将其发送至MAC层,进入SEND_ARP_PACKET状态。
SEND_ARP_PACKET:如果发送的数据包是ARP应答包,数据全部发送完成时,回到IDLE状态。如果发送的数据包是ARP请求包,则要进入SEND_ARP_REPLY状态,等待接收到对方发送ARP应答包。
SEND_ARP_REPLY:接收到ARP应答包后,将arp_req_pend信号拉低,回到IDLE状态。若超时未收到应答,则回到IDLE状态,此时由于arp_req_pend信号一直为高,该模块会持续发送ARP请求直至收到应答。
1 always@(posedge I_ip_arp_clk or posedge I_ip_arp_reset)begin 2 if(I_ip_arp_reset) begin 3 O_mac_cache_ren <= 1'b0; //查询MAC cache 4 O_mac_cache_rip_addr <= 32'd0; //查询MAC cache地址 5 O_arp_tbusy <= 1'b0; //ip_arp_tx arp 发送准备好 6 O_arp_treq_en <= 1'b0; //ip_arp_tx arp请求发送ARP包(当发送IP包,没有找打cache中的MAC的时候发送) 7 O_arp_treq_ip_addr <= 32'd0; //ARP可以发送模块通过发送带有目的IP地址的ARP请求,获取目的远程主机的MAC地址 8 9 O_ip_tbusy <= 1'b0; //ip_arp_tx可以发送IP包 10 11 O_mac_tdata_type <= 2'd0; //MAC发送数据类型 12 O_mac_tvalid <= 1'b0; //MAC发送数据有效 13 O_mac_tdata <= 8'd0; //MAC发送数据 14 O_mac_tdest_addr <= 48'd0; //MAC发送地址 15 16 tmac_addr_temp <= 48'd0; 17 arp_req_pend <= 1'b0; 18 dst_ip_unreachable <= 1'b0; 19 arp_wait_time <= 30'd0; 20 STATE <= IDLE; 21 end 22 else begin 23 case(STATE) 24 IDLE:begin 25 O_arp_treq_en <= 1'b0; 26 if(!I_mac_tbusy) begin//MAC层不忙 27 if(I_arp_treq) begin//是否有ARP请求 28 O_arp_tbusy <= 1'b1; //可以发送ARP包 29 O_ip_tbusy <= 1'b0; 30 STATE <= WAIT_ARP_PACKET;//等待ARP响应 31 end 32 else if(I_ip_treq && ~arp_req_pend) begin //如果是IP请求,并且之前的ARP请求没有pend 33 O_arp_tbusy <= 1'b0; 34 O_ip_tbusy <= 1'b0; 35 O_mac_cache_ren <= 1'b1; //如果是IP请求,先从mac cache通过IP地址获取MAC地址 36 O_mac_cache_rip_addr <= I_ip_tdest_addr; //通过IP地址查询MAC cache 37 STATE <= CHECK_MAC_CACHE; 38 end 39 else begin 40 O_arp_tbusy <= 1'b0; 41 O_ip_tbusy <= 1'b0; 42 STATE <= IDLE; 43 end 44 end 45 else begin 46 O_arp_tbusy <= 1'b0; 47 O_ip_tbusy <= 1'b0; 48 O_mac_cache_ren <= 1'b0; 49 O_mac_cache_rip_addr <= 48'd0; 50 STATE <= IDLE; 51 end 52 end 53 CHECK_MAC_CACHE:begin//查询MAC cache,如果没有查到MAC会请求ARP层发送ARP请求 54 O_mac_cache_ren <= 1'b0; 55 if(I_mac_cache_rdone) begin //MAC cache查询完成 56 if(I_mac_cache_rdest_addr == 48'd0) begin //如果没有查询到对应的MAC,请求ARP层发送ARP请求 57 O_arp_treq_en <= 1'b1; //请求ARP层发送ARP 58 O_ip_tbusy <= 1'b0; 59 O_arp_treq_ip_addr <= O_mac_cache_rip_addr; //如果没有查询到MAC需要根据提供的IP地址请求ARP层发送ARP包获取MAC 60 arp_req_pend <= 1'b1; //arp请求Pend结束前不处理其他的arp请求 61 STATE <= IDLE; //回到IDLE状态,等待ARP层发送ARP包 62 end 63 else begin 64 tmac_addr_temp <= I_mac_cache_rdest_addr; //从MAC cache查询到MAC地址 65 O_ip_tbusy <= 1'b1; //返回IP层的ACK 66 O_arp_treq_en <= 1'b0; 67 arp_req_pend <= 1'b0; 68 STATE <= WAIT_IP_PACKET; 69 end 70 end 71 else 72 STATE <= CHECK_MAC_CACHE; 73 end 74 WAIT_ARP_REPLY:begin//等待远程主机的ARP响应(ARP层的recieve模块会接收到ARP响应) 75 if(I_arp_treply_done) begin//响应 76 arp_req_pend <= 1'b0; 77 arp_wait_time <= 30'd0; 78 dst_ip_unreachable <= 1'b0; 79 STATE <= IDLE; 80 end 81 else begin 82 if(arp_wait_time == ARP_TIMEOUT_VALUE) begin//超时,未收到响应 83 arp_req_pend <= 1'b1; 84 O_arp_tbusy <= 1'b0; 85 O_arp_treq_en <= 1'b1; 86 O_arp_treq_ip_addr <= I_ip_tdest_addr; 87 dst_ip_unreachable <= 1'b1; 88 arp_wait_time <= 30'd0; 89 STATE <= IDLE; 90 end 91 else begin 92 arp_req_pend <= 1'b1; 93 O_arp_tbusy <= 1'b1; 94 dst_ip_unreachable <= 1'b0; 95 arp_wait_time <= arp_wait_time + 1'b1; 96 STATE <= WAIT_ARP_REPLY; 97 end 98 end 99 end 100 WAIT_ARP_PACKET:begin//ARP包有效,打拍后直接输出给MAC层 101 if(I_arp_tvalid) begin 102 O_mac_tdata_type <= {1'b1,I_arp_tdata_type};//2'b10:arp reply; 2'b11:arp request ;2'b01 ip 103 O_mac_tvalid <= 1'b1; 104 O_mac_tdata <= I_arp_tdata; 105 O_mac_tdest_addr <= I_arp_tdest_mac_addr; 106 STATE <= SEND_ARP_PACKET; 107 end 108 else begin 109 O_mac_tdata_type <= 2'd0; 110 O_mac_tvalid <= 1'b0; 111 O_mac_tdata <= 8'd0; 112 O_mac_tdest_addr <= 48'd0; 113 STATE <= WAIT_ARP_PACKET; 114 end 115 end 116 SEND_ARP_PACKET:begin //继续打拍后输出给MAC层 117 if(I_arp_tvalid) begin //如果ARP包有效 118 O_mac_tvalid <= 1'b1; 119 O_mac_tdata <= I_arp_tdata; 120 STATE <= SEND_ARP_PACKET; 121 end 122 else begin 123 O_arp_tbusy <= 1'b0; 124 O_mac_tdata_type <= 2'd0; 125 O_mac_tvalid <= 1'b0; 126 O_mac_tdata <= 8'd0; 127 O_mac_tdest_addr <= 48'd0; 128 if(arp_req_pend) //如果该信号有效,代表IP层发送IP包的时候没有从本地cache查询到MAC地址,而发送的ARP请求包,因此下一步等待远程主机发送ARP响应 129 STATE <= WAIT_ARP_REPLY; 130 else 131 STATE <= IDLE; //如果是单纯的ARP层发送的包,到此结束 132 end 133 end 134 WAIT_IP_PACKET:begin //IP包的传输 135 if(I_ip_tvalid) begin 136 O_mac_tdata_type <= 2'b01; 137 O_mac_tvalid <= 1'b1; 138 O_mac_tdata <= I_ip_tdata; 139 O_mac_tdest_addr <= tmac_addr_temp; 140 STATE <= SEND_IP_PACKET; 141 end 142 else begin 143 O_mac_tdata_type <= 2'd0; 144 O_mac_tvalid <= 1'b0; 145 O_mac_tdata <= 8'd0; 146 O_mac_tdest_addr <= 48'd0; 147 STATE <= WAIT_IP_PACKET; 148 end 149 end 150 SEND_IP_PACKET:begin //IP包的传输 151 if(I_ip_tvalid) begin 152 O_mac_tvalid <= 1'b1; 153 O_mac_tdata <= I_ip_tdata; 154 STATE <= SEND_IP_PACKET; 155 end 156 else begin 157 O_ip_tbusy <= 1'b0; 158 O_mac_tdata_type <= 2'd0; 159 O_mac_tvalid <= 1'b0; 160 O_mac_tdata <= 8'd0; 161 O_mac_tdest_addr <= 48'd0; 162 STATE <= IDLE; 163 end 164 end 165 endcase 166 end 167 end
本文来米联客(milianke),作者:米联客(milianke),转载请注明原文链接:https://www.cnblogs.com/milianke/p/18351341
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)