[米联客-安路飞龙DR1-FPSOC] UDP通信篇连载-05 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.4 ARP层
该层具有接收ARP请求、发送ARP回复,和发送ARP请求、接收ARP回复的功能,并将接收到的对端的地址信息存入cache中。
3.4.1 ARP接收模块
该模块通过计数器接收28字节ARP信息字段。信息接收完成后,通过接收到的操作码判断接收到的数据包是ARP请求包还是ARP应答包。如果是应答包,将接收到的地址信息写入cache中;如果是请求包,判断目的IP地址与本地IP地址是否一致,若一致,将地址信息写入cache中,且发送至uiarp_rx模块,若不一致,则过滤该包。
1 if(OPER == ARP_REQUEST) begin//如果是ARP请求 ARP_REQUEST = 16'h0001(16’h01 ARP请求包 ; 16’h02 ARP应答) 2 if(TPA == I_ip_local_addr) begin //比较接收到的ARP包里面的IP地址是否和本地IP地址一致 3 O_arp_req_ip_addr <= SPA; //发送IP(远端源IP地址) 4 O_arp_req_mac_addr <= SHA; //发送方MAC(远端源地址MAC) 5 O_arp_req_valid <= 1'b1; //设置ARP请求有效(通知发送ARP发送模块发送一个ARP应答给远端主机),保存远端主机的IP地址和MAC地址到cache 6 O_arp_reply_done <= 1'b0; 7 end 8 else begin 9 O_arp_req_ip_addr <= 32'd0; 10 O_arp_req_mac_addr <= 48'd0; 11 O_arp_req_valid <= 1'b0; 12 O_arp_reply_done <= 1'b0; 13 end 14 en
3.4.2 ARP发送模块
该模块对ARP应答和ARP请求同时进行处理,首先对这两种逻辑进行仲裁,以避免发送冲突。如果既没有ARP应答也没有ARP请求,且内部ARP包发送逻辑非忙,则处理缓存的有效信号;如果只有ARP应答,没有ARP请求,且发送逻辑非忙,则请求发送ARP应答包,若发送逻辑忙,则将发送ARP应答包的请求缓存至reply_buffer_valid中,等待非忙时发出;如果只有ARP请求,没有ARP应答,且发送逻辑非忙,则请求发送ARP请求包,若发送逻辑忙,则将发送ARP请求包的请求缓存至request_buffer_valid中,等待非忙时发出;若ARP应答和ARP请求同时为高,则优先发送ARP请求,缓存ARP应答。
1 case({I_arp_treq_en, I_arp_rreply_en})//本状态机实现了即便是同时有ARP应答或者ARP请求,都能确保完成发送 2 2'b00:begin 3 if((!O_arp_treq) && (!O_arp_tvalid)) begin//没有arp_treq请求,并且arp_tvalid为0 代表没有要发送的ARP数据 4 if(request_buffer_valid) begin//如果有未发送完的ARP请求,则继续发送 5 OPER <= ARP_REQUEST; 6 TPA <= ip_request_buffer; 7 THA <= 48'd0; 8 request_buffer_valid <= 1'b0;//清除request_buffer_valid 9 O_arp_treq <= 1'b1; 10 end 11 else if(reply_buffer_valid) begin//如果有未发送完的ARP应答,则继续发送 12 OPER <= ARP_REPLY; 13 TPA <= ip_reply_buffer; 14 THA <= mac_reply_buffer; 15 reply_buffer_valid <= 1'b0;//清除request_buffer_valid 16 O_arp_treq <= 1'b1; 17 end 18 end 19 end 20 2'b01:begin//发送ARP应答 21 if((!O_arp_treq) && (!O_arp_tvalid)) begin 22 OPER <= ARP_REPLY; 23 TPA <= I_arp_rreply_ip_addr; 24 THA <= I_arp_rreply_mac_addr; 25 O_arp_treq <= 1'b1; 26 end 27 else begin//需要arp应答 28 ip_reply_buffer <= I_arp_rreply_ip_addr;//寄存目的地址IP 29 mac_reply_buffer <= I_arp_rreply_mac_addr;//寄存目的地址MAC 30 reply_buffer_valid <= 1'b1;//需要发送ARP应答 31 end 32 end 33 2'b10:begin//发送ARP请求,当ip_arp_tx发送IP包查询MAC没有查询到,执行ARP请求,请求远程主机提供MAC 34 if((!O_arp_treq) && (!O_arp_tvalid)) begin 35 OPER <= ARP_REQUEST; 36 TPA <= I_arp_tip_addr; 37 THA <= 48'd0; 38 O_arp_treq <= 1'b1;//ARP 发送 39 end 40 else begin//arp请求包 41 ip_request_buffer <= I_arp_tip_addr; 42 request_buffer_valid <= 1'b1;//ARP 请求有效标志 43 end 44 end 45 2'b11:begin//既有ARP请求,又有ARP应答 46 if((!O_arp_treq) && (!O_arp_tvalid)) begin 47 OPER <= ARP_REQUEST; 48 TPA <= I_arp_tip_addr; 49 THA <= 48'd0; 50 O_arp_treq <= 1'b1;//ARP 发送 51 end 52 else begin 53 ip_request_buffer <= I_arp_tip_addr; 54 request_buffer_valid <= 1'b1;//ARP请求有效 55 end 56 ip_reply_buffer <= I_arp_rreply_ip_addr; 57 mac_reply_buffer <= I_arp_rreply_mac_addr; 58 reply_buffer_valid <= 1'b1; //ARP应答有效 59 end 60 endcase
若O_arp_treq和uiip_arp_tx模块发送的I_arp_tbusy完成握手,则开始发送ARP包,并且通过判断ARP包的类型来确定发送的目的地址。通过计数器cnt发送28字节有效数据,再通过计数器pad_cnt在末尾补18个字节的0,即完成发送,开始等待下一次握手。
1 case(STATE) 2 WAIT_BUFFER_READY:begin 3 if(O_arp_treq && I_arp_tbusy) begin 4 O_arp_tdata <= HTYPE[15:8]; //硬件类型-以太网类型 5 O_arp_tvalid <= 1'b1; //ARP数据有效 6 cnt <= cnt + 1'b1; 7 if(OPER == ARP_REQUEST) begin //如果是ARP请求 8 O_arp_tdest_mac_addr <= 48'hff_ff_ff_ff_ff_ff; //ARP目的地址为广播地址 9 O_arp_ttype <= 1'b1; //通知ip_arp_tx ARP类型为ARP请求 10 end 11 else begin 12 O_arp_tdest_mac_addr <= THA; 13 O_arp_ttype <= 1'b0; //通知ip_arp_tx ARP类型为ARP应答 14 end 15 O_arp_treq <= 1'b0; 16 STATE <= SEND_ARP_PACKET; 17 end 18 else 19 STATE <= WAIT_BUFFER_READY; 20 end 21 SEND_ARP_PACKET:begin 22 case(cnt) 23 1: begin O_arp_tdata <= HTYPE[7:0]; cnt <= cnt + 1'b1;end 24 2: begin O_arp_tdata <= PTYPE[15:8]; cnt <= cnt + 1'b1;end 25 3: begin O_arp_tdata <= PTYPE[7:0]; cnt <= cnt + 1'b1;end 26 4: begin O_arp_tdata <= HLEN; cnt <= cnt + 1'b1;end 27 5: begin O_arp_tdata <= PLEN; cnt <= cnt + 1'b1;end 28 6: begin O_arp_tdata <= OPER[15:8]; cnt <= cnt + 1'b1;end 29 7: begin O_arp_tdata <= OPER[7:0]; cnt <= cnt + 1'b1;end 30 8: begin O_arp_tdata <= I_mac_local_addr[47:40]; cnt <= cnt + 1'b1;end 31 9: begin O_arp_tdata <= I_mac_local_addr[39:32]; cnt <= cnt + 1'b1;end 32 10: begin O_arp_tdata <= I_mac_local_addr[31:24]; cnt <= cnt + 1'b1;end 33 11: begin O_arp_tdata <= I_mac_local_addr[23:16]; cnt <= cnt + 1'b1;end 34 12: begin O_arp_tdata <= I_mac_local_addr[15:8]; cnt <= cnt + 1'b1;end 35 13: begin O_arp_tdata <= I_mac_local_addr[7:0]; cnt <= cnt + 1'b1;end 36 14: begin O_arp_tdata <= I_ip_local_addr[31:24]; cnt <= cnt + 1'b1;end 37 15: begin O_arp_tdata <= I_ip_local_addr[23:16]; cnt <= cnt + 1'b1;end 38 16: begin O_arp_tdata <= I_ip_local_addr[15:8]; cnt <= cnt + 1'b1;end 39 17: begin O_arp_tdata <= I_ip_local_addr[7:0]; cnt <= cnt + 1'b1;end 40 18: begin O_arp_tdata <= THA[47:40]; cnt <= cnt + 1'b1;end 41 19: begin O_arp_tdata <= THA[39:32]; cnt <= cnt + 1'b1;end 42 20: begin O_arp_tdata <= THA[31:24]; cnt <= cnt + 1'b1;end 43 21: begin O_arp_tdata <= THA[23:16]; cnt <= cnt + 1'b1;end 44 22: begin O_arp_tdata <= THA[15:8]; cnt <= cnt + 1'b1;end 45 23: begin O_arp_tdata <= THA[7:0]; cnt <= cnt + 1'b1;end 46 24: begin O_arp_tdata <= TPA[31:24]; cnt <= cnt + 1'b1;end 47 25: begin O_arp_tdata <= TPA[23:16]; cnt <= cnt + 1'b1;end 48 26: begin O_arp_tdata <= TPA[15:8]; cnt <= cnt + 1'b1;end 49 27: begin O_arp_tdata <= TPA[7:0]; cnt <= cnt + 1'b1;end 50 28: begin 51 O_arp_tdata <= 8'd0; 52 if(pad_cnt == 5'd17) begin //通过在末尾添加0以确保数据长度为46 53 cnt <= cnt + 1'b1; 54 pad_cnt <= 5'd0; 55 end 56 else begin 57 cnt <= cnt; 58 pad_cnt <= pad_cnt + 1'b1; 59 end 60 end 61 29: begin 62 O_arp_tdata <= 8'd0; 63 O_arp_tvalid <= 1'b0; 64 O_arp_tdest_mac_addr <= 48'd0; 65 O_arp_ttype <= 1'b0; 66 cnt <= 5'd0; 67 STATE <= WAIT_BUFFER_READY; 68 end 69 default:begin 70 O_arp_tdata <= 8'd0; 71 O_arp_tvalid <= 1'b0; 72 cnt <= 5'd0; 73 STATE <= WAIT_BUFFER_READY; 74 end 75 endcase 76 end 77 endcase 78 end 79 endcase(STATE) 80 WAIT_BUFFER_READY:begin 81 if(O_arp_treq && I_arp_tbusy) begin 82 O_arp_tdata <= HTYPE[15:8]; //硬件类型-以太网类型 83 O_arp_tvalid <= 1'b1; //ARP数据有效 84 cnt <= cnt + 1'b1; 85 if(OPER == ARP_REQUEST) begin //如果是ARP请求 86 O_arp_tdest_mac_addr <= 48'hff_ff_ff_ff_ff_ff; //ARP目的地址为广播地址 87 O_arp_ttype <= 1'b1; //通知ip_arp_tx ARP类型为ARP请求 88 end 89 else begin 90 O_arp_tdest_mac_addr <= THA; 91 O_arp_ttype <= 1'b0; //通知ip_arp_tx ARP类型为ARP应答 92 end 93 O_arp_treq <= 1'b0; 94 STATE <= SEND_ARP_PACKET; 95 end 96 else 97 STATE <= WAIT_BUFFER_READY; 98 end 99 SEND_ARP_PACKET:begin 100 case(cnt) 101 1: begin O_arp_tdata <= HTYPE[7:0]; cnt <= cnt + 1'b1;end 102 2: begin O_arp_tdata <= PTYPE[15:8]; cnt <= cnt + 1'b1;end 103 3: begin O_arp_tdata <= PTYPE[7:0]; cnt <= cnt + 1'b1;end 104 4: begin O_arp_tdata <= HLEN; cnt <= cnt + 1'b1;end 105 5: begin O_arp_tdata <= PLEN; cnt <= cnt + 1'b1;end 106 6: begin O_arp_tdata <= OPER[15:8]; cnt <= cnt + 1'b1;end 107 7: begin O_arp_tdata <= OPER[7:0]; cnt <= cnt + 1'b1;end 108 8: begin O_arp_tdata <= I_mac_local_addr[47:40]; cnt <= cnt + 1'b1;end 109 9: begin O_arp_tdata <= I_mac_local_addr[39:32]; cnt <= cnt + 1'b1;end 110 10: begin O_arp_tdata <= I_mac_local_addr[31:24]; cnt <= cnt + 1'b1;end 111 11: begin O_arp_tdata <= I_mac_local_addr[23:16]; cnt <= cnt + 1'b1;end 112 12: begin O_arp_tdata <= I_mac_local_addr[15:8]; cnt <= cnt + 1'b1;end 113 13: begin O_arp_tdata <= I_mac_local_addr[7:0]; cnt <= cnt + 1'b1;end 114 14: begin O_arp_tdata <= I_ip_local_addr[31:24]; cnt <= cnt + 1'b1;end 115 15: begin O_arp_tdata <= I_ip_local_addr[23:16]; cnt <= cnt + 1'b1;end 116 16: begin O_arp_tdata <= I_ip_local_addr[15:8]; cnt <= cnt + 1'b1;end 117 17: begin O_arp_tdata <= I_ip_local_addr[7:0]; cnt <= cnt + 1'b1;end 118 18: begin O_arp_tdata <= THA[47:40]; cnt <= cnt + 1'b1;end 119 19: begin O_arp_tdata <= THA[39:32]; cnt <= cnt + 1'b1;end 120 20: begin O_arp_tdata <= THA[31:24]; cnt <= cnt + 1'b1;end 121 21: begin O_arp_tdata <= THA[23:16]; cnt <= cnt + 1'b1;end 122 22: begin O_arp_tdata <= THA[15:8]; cnt <= cnt + 1'b1;end 123 23: begin O_arp_tdata <= THA[7:0]; cnt <= cnt + 1'b1;end 124 24: begin O_arp_tdata <= TPA[31:24]; cnt <= cnt + 1'b1;end 125 25: begin O_arp_tdata <= TPA[23:16]; cnt <= cnt + 1'b1;end 126 26: begin O_arp_tdata <= TPA[15:8]; cnt <= cnt + 1'b1;end 127 27: begin O_arp_tdata <= TPA[7:0]; cnt <= cnt + 1'b1;end 128 28: begin 129 O_arp_tdata <= 8'd0; 130 if(pad_cnt == 5'd17) begin //通过在末尾添加0以确保数据长度为46 131 cnt <= cnt + 1'b1; 132 pad_cnt <= 5'd0; 133 end 134 else begin 135 cnt <= cnt; 136 pad_cnt <= pad_cnt + 1'b1; 137 end 138 end 139 29: begin 140 O_arp_tdata <= 8'd0; 141 O_arp_tvalid <= 1'b0; 142 O_arp_tdest_mac_addr <= 48'd0; 143 O_arp_ttype <= 1'b0; 144 cnt <= 5'd0; 145 STATE <= WAIT_BUFFER_READY; 146 end 147 default:begin 148 O_arp_tdata <= 8'd0; 149 O_arp_tvalid <= 1'b0; 150 cnt <= 5'd0; 151 STATE <= WAIT_BUFFER_READY; 152 end 153 endcase 154 end 155 endcase 156 end 157 end
3.4.3 CACHE模块
mac_cache模块相当于一个RAM,通过IP作为地址,写入或读出MAC地址。写入mac_cache模块的地址信息远程主机发送的ARP应答包或ARP请求包中的地址,在IP层发送UDP数据报文时,需要在mac_cache中读出和IP地址对应的MAC地址。
1 `timescale 1ns/1ps 2 module mac_cache 3 ( 4 input wire I_wclk, 5 input wire I_reset, 6 input wire I_wen, 7 input wire [31:0] I_wip_addr, 8 input wire [47:0] I_wmac_addr, 9 10 input wire I_rclk, 11 input wire I_ren, 12 input wire [31:0] I_rip_addr, 13 output reg [47:0] O_rmac_addr, 14 output reg O_rmac_done 15 ); 16 reg mac_cache_flag [0:3]; 17 reg [31:0] ip_address_cache [0:3]; 18 reg [47:0] mac_address_cache [0:3]; 19 reg [1:0] index; 20 21 always@(posedge I_wclk or posedge I_reset) begin 22 if(I_reset) begin 23 mac_cache_flag[0] <= 1'b0; 24 ip_address_cache[0] <= 32'd0; 25 mac_address_cache[0] <= 48'd0; 26 mac_cache_flag[1] <= 1'b0; 27 ip_address_cache[1] <= 32'd0; 28 mac_address_cache[1] <= 48'd0; 29 mac_cache_flag[2] <= 1'b0; 30 ip_address_cache[2] <= 32'd0; 31 mac_address_cache[2] <= 48'd0; 32 mac_cache_flag[3] <= 1'b0; 33 ip_address_cache[3] <= 32'd0; 34 mac_address_cache[3] <= 48'd0; 35 index <= 2'd0; 36 end 37 else begin 38 if(I_wen) begin 39 if(mac_cache_flag[0] && ip_address_cache[0] == I_wip_addr) 40 mac_address_cache[0] <= I_wmac_addr; 41 else if(mac_cache_flag[1] && ip_address_cache[1] == I_wip_addr) 42 mac_address_cache[1] <= I_wmac_addr; 43 else if(mac_cache_flag[2] && ip_address_cache[2] == I_wip_addr) 44 mac_address_cache[2] <= I_wmac_addr; 45 else if(mac_cache_flag[3] && ip_address_cache[3] == I_wip_addr) 46 mac_address_cache[3] <= I_wmac_addr; 47 else begin 48 mac_cache_flag[index] <= 1'b1; 49 ip_address_cache[index] <= I_wip_addr; 50 mac_address_cache[index] <= I_wmac_addr; 51 index <= index + 1'b1; 52 end 53 end 54 else begin 55 mac_cache_flag[0] <= mac_cache_flag[0]; 56 ip_address_cache[0] <= ip_address_cache[0]; 57 mac_address_cache[0] <= mac_address_cache[0]; 58 mac_cache_flag[1] <= mac_cache_flag[1]; 59 ip_address_cache[1] <= ip_address_cache[1]; 60 mac_address_cache[1] <= mac_address_cache[1]; 61 mac_cache_flag[2] <= mac_cache_flag[2]; 62 ip_address_cache[2] <= ip_address_cache[2]; 63 mac_address_cache[2] <= mac_address_cache[2]; 64 mac_cache_flag[3] <= mac_cache_flag[3]; 65 ip_address_cache[3] <= ip_address_cache[3]; 66 mac_address_cache[3] <= mac_address_cache[3]; 67 end 68 end 69 end 70 71 always@(posedge I_rclk or posedge I_reset) begin 72 if(I_reset) begin 73 O_rmac_addr <= 48'd0; 74 O_rmac_done <= 1'b0; 75 end 76 else begin 77 if(I_ren) begin 78 O_rmac_done <= 1'b1; 79 if(mac_cache_flag[0] && I_rip_addr == ip_address_cache[0]) 80 O_rmac_addr <= mac_address_cache[0]; 81 else if(mac_cache_flag[1] && I_rip_addr == ip_address_cache[1]) 82 O_rmac_addr <= mac_address_cache[1]; 83 else if(mac_cache_flag[2] && I_rip_addr == ip_address_cache[2]) 84 O_rmac_addr <= mac_address_cache[2]; 85 else if(mac_cache_flag[3] && I_rip_addr == ip_address_cache[3]) 86 O_rmac_addr <= mac_address_cache[3]; 87 else 88 O_rmac_addr <= 48'd0; 89 end 90 else begin 91 O_rmac_addr <= O_rmac_addr; 92 O_rmac_done <= 1'b0; 93 end 94 end 95 end 96 endmodule
本文来米联客(milianke),作者:米联客(milianke),转载请注明原文链接:https://www.cnblogs.com/milianke/p/18351343