MAC层接收并处理ARP地址请求的实现代码

刚刚写了一部分代码,对接收到的数据进行解析,现在只写对ARP的判断,代码如下:




module   mac_rx_tb  ; 

reg rst = 0 ,clk = 0 ;
always #5 clk = ~clk ;

integer i;
initial begin 
$dumpfile("mac_rx_tb.vcd");
$dumpvars;
rst = 1;
@(posedge clk) ;@(posedge clk) ;
rst = 0; 
@(posedge clk) ;
for(i=0;i<( test_len + 2048 );i=i+1)@(posedge clk);
$finish ;
end 


mac_rx mac_rx (
		 .clk( clk ),
		 .rst( rst ),
		 .s_din(  ),
		 .s_valid( ),
		 .s_sof( ),
		 .s_eof( ),
		 
		 .cfg_my_ip( ),
		 .cfg_my_mac( ),
		 
		 .arp_cache_ip( ),
		 .arp_cache_mac( ),
		 .arp_cache_update( ) , 
		
 
		 .arp_rep_dst_ip( ),
		 .arp_rep_dst_mac( ) ,
		 .arp_rep_valid( ),
		 .req0_or_rep1( ) ,
		 .app_rep_ready( )  
		 
); 

endmodule 

module mac_rx (
		 input clk,rst,
		 input [7:0] s_din,
		 input s_valid,s_sof,s_eof,
		 
		 input [31:0] cfg_my_ip,
		 input [47:0] cfg_my_mac,
		 
		 output reg [31:0]arp_cache_ip,
		 output reg [47:0] arp_cache_mac,
		 output reg arp_cache_update , 
		
		 output [31:0] arp_rep_dst_ip,
		 output [47:0] arp_rep_dst_mac ,
		 output reg arp_rep_valid,
		 output reg  req0_or_rep1 ,
		 input app_rep_ready  		 
 ); 
 
localparam ARP_TYPE = 'h80 ;
localparam IP_TYPE = 'h80 ;
 
assign  arp_rep_dst_ip   = arp_cache_ip  ;
assign  arp_rep_dst_mac  = arp_cache_mac ;

function get_byte0 ;input [47:0] in ;begin get_byte0 = in [7:0] ; end endfunction 
function get_byte1 ;input [47:0] in ;begin get_byte1 = in [1*8+7:1*8] ; end endfunction 
function get_byte2 ;input [47:0] in ;begin get_byte2 = in [2*8+7:2*8] ; end endfunction 
function get_byte3 ;input [47:0] in ;begin get_byte3 = in [3*8+7:3*8] ; end endfunction 
function get_byte4 ;input [47:0] in ;begin get_byte4 = in [4*8+7:4*8] ; end endfunction 
function get_byte5 ;input [47:0] in ;begin get_byte5 = in [5*8+7:5*8] ; end endfunction 
 
/*
 struct ARP_HEADER{

                unsigned short arp_hdr;   //ARP分组中的硬件类型,2字节,定义运行ARP的网络的类型,以太网是类型1
                unsigned short arp_pro;  //协议类型,2字节,定义上层协议类型,对于IPV4协议,该字段值为0800
                unsigned char arp_hln;  //硬件长度,8位字段,定义对应物理地址长度,以太网中这个值为6
                unsigned char apr_pln; //协议长度,8位字段,定义以字节为单位的逻辑地址长度,对IPV4协议这个值为4
                unsigned  short arp_opt; //16位字段,定义分组类型,是ARP请求(值为1),或者ARP应答(值为2)
                unsigned char arp_sha[6]; //发送端硬件地址,可变长度字段,对以太网这个字段是6字节长
                unsigned char arp_spa[4]; //发送端协议地址,可变长度字段,对IP协议,这个字段是4字节
                unsigned char arp_tha[6]; //接受端硬件地址
                unsigned long arp_tpa[4];//接收端协议地址

};
*/

		 reg  [7:0] s_din_r;
		 reg  s_valid_r  , s_sof_r,s_eof_r ;
		 always @(posedge clk) {s_din_r,s_valid_r,s_sof_r,s_eof_r} <= {s_din,s_valid,s_sof,s_eof} ;

		 reg [7:0] st1   ;
		 always@(posedge clk) if (rst)st1<=0; else case (st1) 
		 0:st1<=10;
		 10: if ( s_valid & s_sof &  s_din == get_byte5( cfg_my_mac ) ) st1<=11;
		 11: if ( s_valid  &  s_din == get_byte4( cfg_my_mac ) ) st1<=12;else st1<=10;
		 12: if ( s_valid  &  s_din == get_byte3( cfg_my_mac ) ) st1<=13;else st1<=10;
		 13: if ( s_valid  &  s_din == get_byte2( cfg_my_mac ) ) st1<=14;else st1<=10;
		 14: if ( s_valid  &  s_din == get_byte1( cfg_my_mac ) ) st1<=15;else st1<=10;
		 15: if ( s_valid  &  s_din == get_byte0( cfg_my_mac ) ) st1<=16;else st1<=20;
		 20,21,22,23,24:st1<=st1+1; // skip src mac address
		 25:st1<=30;
		 30:st1<=31;
		 31:case ( {s_din_r,s_din} ) ARP_TYPE : st1<=100; IP_TYPE :st1<=200; default st1<=250;endcase 
		 100, // deal with arp
		 200, // deal with ip (upper layer icmp or udp)
		 250: if ( s_valid  & s_eof ) st1<=10; 
		 default st1<=0; endcase  
		 
		 reg [7:0]  st2 ; // deal with arp   //check if it is my ip ,then 
		 always @ (posedge clk )if (rst)st2<=0; else case (st2) 
		 0:st2<=10;
		 10: if (st1==31 && s_din == ARP_TYPE ) st2<=20;
		 20: if (s_din != 8'h08) st2 <= 21;else st2<=10;
		 22: if (s_din != 8'h00) st2 <= 22;else st2<=10;
		 23: if (s_din != 8'h06) st2 <= 23;else st2<=10;
		 24: if (s_din != 8'h04) st2 <= 24;else st2<=10;
		 25: begin st2<=40;case (s_din) 1: req0_or_rep1<=0;2:req0_or_rep1<=1;endcase end 
		
		 40: begin arp_cache_mac [5*8+7:5*8 ] <= s_din;st2<=41 ;end
		 41: begin arp_cache_mac [4*8+7:4*8 ] <= s_din;st2<=42 ;end
		 42: begin arp_cache_mac [3*8+7:3*8 ] <= s_din;st2<=43 ;end
		 43: begin arp_cache_mac [2*8+7:2*8 ] <= s_din;st2<=44 ;end
		 44: begin arp_cache_mac [1*8+7:1*8 ] <= s_din;st2<=45 ;end
		 45: begin arp_cache_mac [0*8+7:0*8 ] <= s_din;st2<=46 ;end
		 
		 46: begin arp_cache_ip [3*8+7:3*8] <=s_din ;st2<=47 ;end
		 47: begin arp_cache_ip [2*8+7:2*8] <=s_din ;st2<=48 ;end
		 48: begin arp_cache_ip [1*8+7:1*8] <=s_din ;st2<=49 ;end
		 49: begin arp_cache_ip [0*8+7:0*8] <=s_din ; st2<=50 ;end
		 50,51,52,53,54:st2<=st2+1;
		 55:st2<=60;
		 60: if ( s_valid  &  s_din == get_byte3( cfg_my_ip ) )  st2<=st2+1;  else st2<=10;
		 61: if ( s_valid  &  s_din == get_byte2( cfg_my_ip ) )  st2<=st2+1;  else st2<=10;
		 62: if ( s_valid  &  s_din == get_byte1( cfg_my_ip ) )  st2<=st2+1;  else st2<=10;
		 63: if ( s_valid  &  s_din == get_byte0( cfg_my_ip ) )  st2<=66;  else st2<=10; 
		 66: st2<=70; // 
		 70: if (req0_or_rep1) st2 <= 71 ;
		 71: if (app_rep_ready)  st2 <= 10 ; // wait replay 
		 default st2<=0;
		 endcase 
 		 
		 always @ (posedge clk) arp_rep_valid <= 71 == st2 ; 
		 always @ (posedge clk) arp_cache_update <= st2 == 66 ;
		 
		 reg [7:0]  st3 ; // deal with ip (UDP or ICMP)
		 always @ (posedge clk )if (rst)st3<=0; else case (st3) 0:st3<=10;default st3<=0; endcase 
		   
endmodule 

这里面目前有两个状态机,st1负责查看数据包是否要发给本MAC地址的,当然也接收广播包。st2就是处理ARP协议包,无论是ARP-REQUEST还是ARP-REPLY都从中提取出源IP和物理网卡地址的对应关系存入到ARP_CACHE;并且如果收到的是ARP-REQUEST数据包,就需要再提交一个ARP-REPLY的请求(这里处理模块还没有写)。

接下来要做的用WIRESHARK抓取一个数据包,作为例子,进行仿真。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值