用WIRESHARK抓数据包做成测试文件用以Verilog仿真
要写协议解析必须对工作原理和流程滚瓜乱熟。我们使用ping命令时候,电脑知道一个ip地址(还要不是域名,否则要进行地址解析了),而在局域网络下,使用MAC地址来标识每一个网卡或者网络节点,这个MAC地址是48位。所以我们电脑要在局域网上发广播,谁是这个ip,这是arp-request?谁是的话回复一下,回复使用的arp-reply。我们现在就是要实现对这个arp-request的解析,对之解析要做两件事情:1,首先是从这个广播的请求包里获取到发送放ip和mac的地址对应存入本地的arp-cache,这样咱们自己用的时候就不需要在发送arp-request了;2,根据提取的ip和mac信息产生一个arp-reply的数据包发给网络,让对方知道咱们的物理地址(mac地址)。
看图说话
看到我们ping同一网段但是不存在的ip地址,也就说你跟你的ip地址前三个字节相同 后面不同,但是这个IP还没有被占用,如果被占用就是在arp表里面有记录,就不必发送arp请求包,咱们也就抓不到了~。
看到这个解析的信息也很有趣,who has 192.168.31.200?Tell 192.168.31.39 。估计其他无关电脑收到了后自言自语“You ask me ,I ask who?!”
我们拷贝下来上图蓝色框内的原始数据,这是mac层的数据,已经去掉了7字节前缀1自己起始自己,以及后面字节的CRC校验。我们拷贝这些数据正好给mac接收部分进行激励仿真。
数据包上点右键拷贝后再每个字节换行,做成下图文本文件:
这就做成一个存储初始化文件,我们可以使用readmemh函数来读写这些内容初始化我们的寄存器。
module mac_rx_tb ;
reg rst = 0 ,clk = 0 ;
always #5 clk = ~clk ;
integer i;
reg[7:0] mem[0:255] ;
initial begin
$readmemh("arp_req.txt",mem);
$dumpfile("mac_rx_tb.vcd");
$dumpvars;
rst = 1;
@(posedge clk) ;@(posedge clk) ;
rst = 0;
@(posedge clk) ;
for(i=0;i<( 1 + 2048 );i=i+1)@(posedge clk);
$finish ;
end
reg [5:0] addr = 0; always @ (posedge clk )if (rst ) addr<=0; else addr <= (addr == 41)?0:(addr+1) ;
reg [7:0] s_din ;
reg s_sof = 0,s_eof = 0;
always@(posedge clk) s_sof <= (addr==0) ;
always@(posedge clk) s_eof <= (addr==41) ;
always@(posedge clk) s_din <= mem[addr] ;
wire [47:0] cfg_my_mac = 48'h112233445566;
wire [31:0] cfg_my_ip = {8'd192,8'd168,8'd31,8'd200} ;
mac_rx mac_rx (
.clk( clk ),
.rst( rst ),
.s_din( s_din ),
.s_valid( s_valid ),
.s_sof( s_sof ),
.s_eof(e_sfo ),
.cfg_my_ip( cfg_my_ip),
.cfg_my_mac( 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( 1'b1)
);
endmodule
这里addr没有在复位时候初始位0是因为0这个地址被作为一帧的开头,这里避开这个敏感地址。
我们看到这里激励变量做好了,下一步就是跟进这些代码进行调试了.