[米联客-安路飞龙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_trequiip_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
posted @ 2024-08-09 18:56  米联客(milianke)  阅读(1)  评论(0编辑  收藏  举报