基於FPGA的ARP協議實現


一、ARP幀存在的作用:

       在網絡通訊時,源主機的應用程序知道目的的IP地址和端口號,卻不知道目的主機的硬件地址,而數據包首先是被網卡接收到再去處理上層協議的,如果接收到的數據包的硬件地址與本機不符,則直接丟棄。因此在通訊前必須獲得目的主機的硬件地址。ARP協議就起這個作用。

 

二、ARP幀的工作原理:

       源主機發出ARP請求,詢問“IP地址是 192.168.0.1的主機的硬件地址是多少”,並將這個請求廣播到本地網段(以太網幀首部的硬件地址填 FF:FF:FF:FF:FF:FF表示廣播),目的主機接收到廣播的ARP請求,發現其中的IP地址與本機相符,則發送一個ARP應答數據包給源主機,將自己的硬件地址填寫在應答包中。

 

三、ARP數據報格式

 ***  以太網目的地址:48'hff_ff_ff_ff_ff_ff,廣播到電腦;

 ***  以太網源地址:48'h00_0a_35_01_fe_c0,開發板的以太網芯片地址(貌似是可以自己設定);

 ***  幀類型:0x0806表示ARP幀;

 *** 硬件類型:0x0001表示以太網類型值;

 *** 協議類型:0x0800表示上層協議為IP協議;

 *** 硬件地址長度:0x6表示以太網的地址長度是6個字節;

 *** 協議地址長度:0x4表示IP地址長度為4個字節;

 *** op:0x1表示ARP請求包,0x2表示ARP應答包;

 *** 發送者硬件地址:源MAC地址(開發板的以太網芯片地址);

 *** 發送者IP:發送方的IP地址;

 *** 目的硬件地址:電腦的MAC地址;

 *** 目標IP地址:電腦的IP地址;

 

四、MAC協議格式

  *** 前導碼:55_55_55_55_55_55_55,是用來實現數據的同步;

  *** SFD:幀起始界定符:8'h5d,表示一幀的開始;

  *** FCS:為確保數據的正確傳輸,在數據的尾部加入了4個字節的循環冗余校驗碼(CRC校驗) ;

 

五、ARP協議是加載在MAC協議上來發送的,如下圖所示:

 

六、代碼設計(參考的小梅哥的設計思路,在小梅哥的設計的基礎上,做了小小的修改)

  1 // Time : 2020.04.06 21:12
  2 // Describe : eth_test 
  3 
  4 module eth_test(
  5       rst_n,
  6     
  7     //MII 接口信號    
  8     mii_tx_clk,
  9     mii_tx_en,
 10     mii_tx_er,
 11     mii_tx_data,
 12     
 13     mii_rx_clk,
 14     mii_rx_dv,
 15     mii_rx_er,
 16     mii_rx_data,
 17     
 18     phy_rst_n
 19 );
 20 
 21 input rst_n;
 22 
 23 input  mii_tx_clk;         //MII接口發送時鍾,由PHY芯片產生,25MHz
 24 output mii_tx_en;           //MII接口發送數據使能信號,高電平有效
 25 output mii_tx_er;           //發送錯誤,用以破壞數據包發送
 26 output reg[3:0]mii_tx_data; //MII接口發送數據線,FPGA通過該數據線將需要發送的數據依次送給PHY芯片
 27 output phy_rst_n;           //PHY 復位信號
 28 
 29 input mii_rx_clk;           //MII接口接收時鍾,由PHY芯片產生,25MHz
 30 input mii_rx_dv;           //MII接口接收數據有效信號,高電平有效
 31 input mii_rx_er;           //接收錯誤,本實例中暫時忽略該信號
 32 input [3:0]mii_rx_data;     //MII接口數據總線,FPGA通過該數據線讀取PHY芯片接收到的以太網數據
 33 
 34 crc32_d4 u0(
 35   .Clk(mii_tx_clk),
 36   .Rst_n(rst_n), 
 37   .Data(mii_tx_data), 
 38   .Enable(CRC_EN),
 39   .Initialize(~mii_tx_en),
 40   .Crc(), 
 41   .CrcError(),
 42   .Crc_eth(CRC_Result)
 43  );
 44 
 45 assign phy_rst_n = 1'b1;
 46 
 47 parameter des_mac     = 48'hff_ff_ff_ff_ff_ff;  //目標MAC地址
 48 parameter src_mac     = 48'h00_0a_35_01_fe_c0;  //源MAC地址
 49 parameter type_length = 16'h08_06;                //數據幀類型
 50 parameter data_length = 12'd92;                   //數據長度(因為MII接口一個字節分兩個時鍾,每個時鍾4位的方式發送,因此本值為實際數據所占字節數的2倍)
 51 
 52 wire[31:0] CRC_Result;
 53 
 54 wire CRC_EN;
 55 
 56 assign CRC_EN = (lsm_cnt > 17 && lsm_cnt <= 137);
 57 
 58 wire tx_go;                // 使能發送
 59 
 60 reg [7:0] lsm_cnt;           //序列機計數器,本以太網幀發送系統使用線性序列機方式設計
 61 reg en_tx;                   //內部的數據幀發送使能信號,高電平時將數據通過MII接口送出
 62 
 63 reg [28:0]cnt;  //發送間隔計數器
 64 always@(posedge mii_tx_clk or negedge rst_n)
 65   if(!rst_n)
 66      cnt <= 28'd0;
 67   else if(cnt == 28'd3500)  // 35000000
 68      cnt <= 28'd0;
 69   else
 70     cnt <= cnt + 1'b1;
 71     
 72 //每671ms啟動一次發送數據    
 73 assign tx_go = (cnt == 28'd3500) ? 1'b1 : 1'b0;  // 35000000
 74 
 75 //根據發送啟動信號產生內部發送使能信號
 76 always@(posedge mii_tx_clk or negedge rst_n) 
 77   if(!rst_n)
 78      en_tx <= 1'd0;
 79   else if(tx_go)
 80      en_tx <= 1'd1;
 81   else if(lsm_cnt >= 145)      //一幀數據發送完成,清零發送使能信號
 82      en_tx <= 1'd0;
 83 
 84 always@(posedge mii_tx_clk or negedge rst_n) //主序列機計數器
 85   if(!rst_n)
 86      lsm_cnt <= 8'd0;
 87   else if(en_tx) begin
 88     if(lsm_cnt == 8'd145)
 89        lsm_cnt <= 8'd0;
 90      else
 91        lsm_cnt <= lsm_cnt + 1'b1;
 92   end
 93   else
 94      lsm_cnt <= 8'd0;    
 95      
 96 /*
 97 always@(posedge mii_tx_clk or negedge rst_n) 
 98   if(!rst_n) begin
 99     mii_tx_data <= 4'd0;
100   end
101   else begin
102 */
103 always@(*) begin
104     case(lsm_cnt)
105        1: mii_tx_data <= 4'h5;  // 前導碼 + 分隔符的一個5
106         2: mii_tx_data <= 4'h5;
107         3: mii_tx_data <= 4'h5;
108         4: mii_tx_data <= 4'h5;
109         5: mii_tx_data <= 4'h5;
110         6: mii_tx_data <= 4'h5;
111         7: mii_tx_data <= 4'h5;
112         8: mii_tx_data <= 4'h5;
113         9: mii_tx_data <= 4'h5;
114         10:mii_tx_data <= 4'h5;
115         11:mii_tx_data <= 4'h5;
116         12:mii_tx_data <= 4'h5;
117         13:mii_tx_data <= 4'h5;
118         14:mii_tx_data <= 4'h5;
119         15:mii_tx_data <= 4'h5;
120             
121         16: mii_tx_data <= 4'hd;  // 分隔符
122         
123         17: mii_tx_data <= des_mac[43:40];  // 目的MAC地址,先發高八位中的低四位 48'hff_ff_ff_ff_ff_ff
124         18: mii_tx_data <= des_mac[47:44];
125         19: mii_tx_data <= des_mac[35:32];
126         20: mii_tx_data <= des_mac[39:36];
127         21: mii_tx_data <= des_mac[27:24];
128         22: mii_tx_data <= des_mac[31:28];
129         23: mii_tx_data <= des_mac[19:16];
130         24: mii_tx_data <= des_mac[23:20];
131         25: mii_tx_data <= des_mac[11:8];
132         26: mii_tx_data <= des_mac[15:12];
133         27: mii_tx_data <= des_mac[3:0];
134         28: mii_tx_data <= des_mac[7:4];    
135     
136                   
137         29: mii_tx_data <= src_mac[43:40];// 0  //源MAC地址 48'h00_0a_35_01_fe_c0
138         30: mii_tx_data <= src_mac[47:44];// 0
139         31: mii_tx_data <= src_mac[35:32];// a
140         32: mii_tx_data <= src_mac[39:36];// 0
141         33: mii_tx_data <= src_mac[27:24];// 5
142         34: mii_tx_data <= src_mac[31:28];// 3
143         35: mii_tx_data <= src_mac[19:16];// 1
144         36: mii_tx_data <= src_mac[23:20];// 0
145         37: mii_tx_data <= src_mac[11:8]; // e
146         38: mii_tx_data <= src_mac[15:12];// f
147         39: mii_tx_data <= src_mac[3:0]; // 0
148         40: mii_tx_data <= src_mac[7:4];    // c
149         
150                     
151         41: mii_tx_data <= type_length[11:8];  //以太網幀類型/長度
152         42: mii_tx_data <= type_length[15:12];
153         43: mii_tx_data <= type_length[3:0];
154         44: mii_tx_data <= type_length[7:4];
155         
156         45: mii_tx_data =    4'h0;
157         46: mii_tx_data =    4'h0;
158         47: mii_tx_data =    4'h1;
159         48: mii_tx_data =    4'h0;
160         
161         //protocol type
162         49: mii_tx_data =    4'h8;
163         50: mii_tx_data =    4'h0;
164         51: mii_tx_data =    4'h0;
165         52: mii_tx_data =    4'h0;
166         
167         //hdwr size
168         53: mii_tx_data =    4'h6;
169         54: mii_tx_data =    4'h0;
170         
171         //protocol size
172         55: mii_tx_data =    4'h4;
173         56: mii_tx_data =    4'h0;
174         
175         //opcode
176         57: mii_tx_data =    4'h0;
177         58: mii_tx_data =    4'h0;
178         59: mii_tx_data =    4'h1;
179         60: mii_tx_data =    4'h0;
180         
181         //sender mac
182         61: mii_tx_data =    4'h0;
183         62: mii_tx_data =    4'h0;
184         63: mii_tx_data =    4'ha;
185         64: mii_tx_data =    4'h0;
186         65: mii_tx_data =    4'h5;
187         66: mii_tx_data =    4'h3;
188         67: mii_tx_data =    4'h1;
189         68: mii_tx_data =    4'h0;
190         69: mii_tx_data =    4'he;
191         70: mii_tx_data =    4'hf;
192         71: mii_tx_data =    4'h0;
193         72: mii_tx_data =    4'hc;
194         
195         //sender ip : 192.168.0.2
196         73: mii_tx_data =    4'h0;//192
197         74: mii_tx_data =    4'hc;
198         
199         75: mii_tx_data =    4'h8;//168
200         76: mii_tx_data =    4'ha;
201         
202         77: mii_tx_data =    4'h0;//0
203         78: mii_tx_data =    4'h0;
204         
205         79: mii_tx_data =    4'h2;
206         80: mii_tx_data =    4'h0;//2
207         
208         //target mac
209         81: mii_tx_data =    4'h4;  // 4  //48'b84 7b eb 48 94 13
210         82: mii_tx_data =    4'hc;  // 8  //48'b34 23 87 99 f4 61
211         83: mii_tx_data =    4'h4;  // b
212         84: mii_tx_data =    4'h5;  // 7
213         85: mii_tx_data =    4'h4;  // b
214         86: mii_tx_data =    4'h4;  // e
215         87: mii_tx_data =    4'h7;  // 8
216         88: mii_tx_data =    4'h9;  // 4
217         89: mii_tx_data =    4'h5;  // 4
218         90: mii_tx_data =    4'hc;  // 9
219         91: mii_tx_data =    4'h7;  // 3
220         92: mii_tx_data =    4'hd;  // 1
221         
222         //target ip : 192.168.0.3
223         93: mii_tx_data =    4'h0;//192
224         94: mii_tx_data =    4'hc;
225         
226         95: mii_tx_data =    4'h8;//168
227         96: mii_tx_data =    4'ha;
228         
229         97: mii_tx_data =    4'h0;//0
230         98: mii_tx_data =    4'h0;
231         
232         99: mii_tx_data =    4'h3;//3
233         100: mii_tx_data = 4'h0;
234         
235         //填充字段,以使整個數據幀長度達到64字節
236         101: mii_tx_data = 4'h0;
237         102: mii_tx_data = 4'h0;
238         103: mii_tx_data = 4'h0;
239         104: mii_tx_data = 4'h0;
240         105: mii_tx_data = 4'hf;
241         106: mii_tx_data = 4'hf;
242         107: mii_tx_data = 4'hf;
243         108: mii_tx_data = 4'hf;
244         109: mii_tx_data = 4'hf;
245         110: mii_tx_data = 4'hf;
246         111: mii_tx_data = 4'hf;
247         112: mii_tx_data = 4'hf;
248         113: mii_tx_data = 4'hf;
249         114: mii_tx_data = 4'hf;
250         115: mii_tx_data = 4'hf;
251         116: mii_tx_data = 4'hf;
252         117: mii_tx_data = 4'h0;
253         118: mii_tx_data = 4'h0;
254         119: mii_tx_data = 4'h3;
255         120: mii_tx_data = 4'h2;
256         121: mii_tx_data = 4'hd;
257         122: mii_tx_data = 4'hc;
258         123: mii_tx_data = 4'h6;
259         124: mii_tx_data = 4'h7;
260         125: mii_tx_data = 4'h3;
261         126: mii_tx_data = 4'h6;
262         127: mii_tx_data = 4'ha;
263         128: mii_tx_data = 4'h1;
264         129: mii_tx_data = 4'h8;
265         130: mii_tx_data = 4'h0;
266         131: mii_tx_data = 4'h6;
267         132: mii_tx_data = 4'h0;
268         133: mii_tx_data = 4'h0;
269         134: mii_tx_data = 4'h0;
270         135: mii_tx_data = 4'h1;
271         136: mii_tx_data = 4'h0;
272         
273         137: mii_tx_data <= CRC_Result[27:24];  //發送CRC 校驗結果
274         138: mii_tx_data <= CRC_Result[31:28];
275         139: mii_tx_data <= CRC_Result[19:16];
276         140: mii_tx_data <= CRC_Result[23:20];
277         141: mii_tx_data <= CRC_Result[11:8];
278         142: mii_tx_data <= CRC_Result[15:12];
279         143: mii_tx_data <= CRC_Result[3:0];
280         144: mii_tx_data <= CRC_Result[7:4];
281 
282         145: mii_tx_data <= 4'd0;
283         default: mii_tx_data <= 4'd0;
284      endcase
285   end
286   
287 /*
288 always@(posedge mii_tx_clk or negedge rst_n)  //MII數據發送使能信號
289   if(!rst_n)
290      mii_tx_en <= 1'b0;
291   else if((lsm_cnt >= 1) && (lsm_cnt <= 144))  // lsm_cnt >= 1
292      mii_tx_en <= 1'b1;
293   else
294      mii_tx_en <= 1'b0;
295 */
296 
297 assign mii_tx_en = ((lsm_cnt >= 1) && (lsm_cnt <= 144)) ? 1'b1 : 1'b0;
298 
299 endmodule
300     
View Code

測試代碼:

 1 `timescale 1ns/1ns
 2 
 3 module eth_test_tb;
 4 
 5     reg rst_n;    
 6     //MII 接口信號    
 7     reg mii_tx_clk;
 8     wire mii_tx_en;
 9     wire mii_tx_er;
10     wire [3:0]mii_tx_data;
11     wire phy_rst_n;
12 
13     eth_test eth_test(
14         .rst_n(rst_n),
15         .mii_tx_clk(mii_tx_clk),
16         .mii_tx_en(mii_tx_en),
17         .mii_tx_er(mii_tx_er),
18         .mii_tx_data(mii_tx_data),
19         .phy_rst_n(phy_rst_n)
20     );
21     
22     initial mii_tx_clk = 1;
23     always #20 mii_tx_clk = ~mii_tx_clk;
24     
25     initial begin
26         rst_n = 0;
27         #201;
28         rst_n = 1;
29         
30         #1000000;
31       
32         $stop;
33     end
34 
35 endmodule
View Code

仿真效果:

 

 圖1

 

 

 圖2

上板效果圖:

 圖3

  注:代碼設計參考了小梅哥的設計,梅哥寫的比較簡單易懂,文字敘述方面也摘抄了梅哥的《基於ac620的fpga系統設計與驗證實戰指南20190516》;

    如果無法收到ARP提示,可能是時序的問題,需要添加時序約束;

    如果收到了ARP提示,但是沒有應答包,那就有可能是電腦上沒有綁定在代碼中設定的目的IP地址(在本文中的 des_ip:192.168.0.3);

 

   如有不當之處,還望各位道友指正~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM