这里根据千兆以太网的arp模块修改而成。逻辑比较简单,这里不多啰嗦,写好了代码直接上代码:
module tb_arp_gen ;
reg clk = 0 , rst = 1 ;
always #5 clk = ~clk ;
initial begin
$dumpfile("v.vcd");
$dumpvars(0);
end
wire [31:0] my_ip = {8'd192,8'd168,8'd1,8'd3} ;
wire [31:0] dst_ip = {8'd192,8'd168,8'd1,8'd5} ;
wire [47:0] my_mac = {48'h0400} ;
wire [47:0] dst_mac = {48'h0200} ;
reg req0_rep1 =0;
reg arp_load = 0 ;
initial begin
#100;rst=0;
@(posedge clk );
arp_load = 1;
@(posedge clk );
arp_load = 0;
@(posedge clk );@(posedge clk );@(posedge clk );@(posedge clk );@(posedge clk );@(posedge clk );@(posedge clk );
$finish ;
end
arp_gen arp_gen (
.clk(clk ) ,
.rst(rst ) ,
.my_ip(my_ip ),
.dst_ip(dst_ip ),
.my_mac(my_mac ),
.dst_mac(dst_mac ),
.req0_rep1(req0_rep1 ) ,
.arp_load(arp_load ),
.arp_m_valid( ),
.arp_m_ready( 1'b1 ),
.arp_m_data( ),
.arp_m_byte_cnt( ),
.arp_m_last( )
);
endmodule
/*
arp_gen arp_gen (
.clk( ) ,
.rst( ) ,
.my_ip( ),
.dst_ip( ),
.my_mac( ),
.dst_mac( ),
.req0_rep1( ) ,
.arp_load( ),
.arp_m_valid( ),
.arp_m_ready( ),
.arp_m_data( ),
.arp_m_byte_cnt( ),
.arp_m_last( )
);
*/
module arp_gen (
input clk , rst , // 请求发送接口
input [31:0] my_ip,dst_ip,
input [47:0] my_mac,dst_mac,
input req0_rep1 ,
input arp_load,
output reg arp_m_valid,
input arp_m_ready,
output reg [63:0] arp_m_data, // 接mac接口
output reg [3:0] arp_m_byte_cnt,
output reg arp_m_last
);
reg [7:0] st ;
always@(posedge clk) if (rst)st<=0; else case (st)
0 : st <= 10;
10: if ( arp_load ) st<=20;
20: if ( arp_m_ready & arp_m_valid ) st<=30;
30: st<=31;
31:st<=32;
32:st<=10;
default st<=0;
endcase
always @ (posedge clk) case (st) 20,30,31:arp_m_valid<=1;default arp_m_valid<=0;endcase
function [7:0]get_byte0;input[47:0]in;begin get_byte0=in[0*8 +: 8]; end endfunction
function [7:0]get_byte1;input[47:0]in;begin get_byte1=in[1*8 +: 8 ]; end endfunction
function [7:0]get_byte2;input[47:0]in;begin get_byte2=in[2*8 +: 8]; end endfunction
function [7:0]get_byte3;input[47:0]in;begin get_byte3=in[3*8 +: 8]; end endfunction
function [7:0]get_byte4;input[47:0]in;begin get_byte4=in[4*8 +: 8]; end endfunction
function [7:0]get_byte5;input[47:0]in;begin get_byte5=in[5*8 +: 8]; end endfunction
/*
function [7:0]get_byte0;input[47:0]in;begin get_byte0=in[7:0]; end endfunction
function [7:0]get_byte1;input[47:0]in;begin get_byte1=in[1*8+7:1*8]; end endfunction
function [7:0]get_byte2;input[47:0]in;begin get_byte2=in[2*8+7:2*8]; end endfunction
function [7:0]get_byte3;input[47:0]in;begin get_byte3=in[3*8+7:3*8]; end endfunction
function [7:0]get_byte4;input[47:0]in;begin get_byte4=in[4*8+7:4*8]; end endfunction
function [7:0]get_byte5;input[47:0]in;begin get_byte5=in[5*8+7:5*8]; end endfunction
*/
reg [31:0] my_ipr,dst_ipr;
reg [47:0] my_macr,dst_macr;
reg req0_rep1r;
always @ (posedge clk) if (arp_load){my_ipr,dst_ipr, my_macr,dst_macr,req0_rep1r} <= {my_ip,dst_ip, my_mac,dst_mac,req0_rep1};
always@(posedge clk ) case (st)
30:begin
/*
18-2:arp_data <= get_byte1(my_ipr) ;
19-2:arp_data <= get_byte0(my_ipr) ; //source ip
20-2:arp_data <= get_byte5 (dst_macr) ;
21-2:arp_data <= get_byte4 (dst_macr) ;
22-2:arp_data <= get_byte3 (dst_macr) ;
23-2:arp_data <= get_byte2 (dst_macr) ;
24-2:arp_data <= get_byte1 (dst_macr) ;
25-2:arp_data <= get_byte0 (dst_macr) ; // target mac .zero if ARP request
*/
arp_m_data[0*8 +: 8] <=get_byte1 (my_ipr) ;
arp_m_data[1*8 +: 8] <=get_byte0 (my_ipr) ;
arp_m_data[2*8 +: 8] <=get_byte5 (dst_macr) ;
arp_m_data[3*8 +: 8] <=get_byte4 (dst_macr) ;
arp_m_data[4*8 +: 8] <=get_byte3 (dst_macr) ;
arp_m_data[5*8 +: 8] <=get_byte2 (dst_macr) ;
arp_m_data[6*8 +: 8] <=get_byte1 (dst_macr) ;
arp_m_data[7*8 +: 8] <=get_byte0 (dst_macr) ;
arp_m_byte_cnt <= 8 ;
end
31:begin
/*
26-2:arp_data <=get_byte3(dst_ipr) ;
27-2:arp_data <=get_byte2(dst_ipr) ;
28-2:arp_data <=get_byte1(dst_ipr) ;
29-2:arp_data <=get_byte0(dst_ipr) ;// dst ip
*/
arp_m_data[0*8 +: 8] <=get_byte3 (dst_ipr) ;
arp_m_data[1*8 +: 8] <=get_byte2 (dst_ipr) ;
arp_m_data[2*8 +: 8] <=get_byte1 (dst_ipr) ;
arp_m_data[3*8 +: 8] <=get_byte0 (dst_ipr) ;
arp_m_byte_cnt <= 4 ;
end
default
/*
//0:arp_data <= 'h08;
//1:arp_data <= 'h06 ;//0806 arp
2-2:arp_data <= 'h00 ;
3-2:arp_data <= 'h01 ;//via ether
4-2:arp_data <='h08 ;
5-2:arp_data <='h00 ;//ipv4 0800
6-2:arp_data <= 'h06 ;// hardware size 6
7-2:arp_data <= 'h04 ;//protocol size 4
8-2:arp_data <= 'h00 ;
9-2:arp_data <= (req0_rep1r==0)?'h01:'h02 ;// arp reply 2
*/
if (arp_m_valid==0)begin
arp_m_data[0*8 +: 8] <= 'h00 ;
arp_m_data[1*8 +: 8] <= 'h01 ;
arp_m_data[2*8 +: 8] <= 'h08 ;
arp_m_data[3*8 +: 8] <= 'h00 ;
arp_m_data[4*8 +: 8] <= 'h06 ;
arp_m_data[5*8 +: 8] <= 'h04 ;
arp_m_data[6*8 +: 8] <= 'h00 ;
arp_m_data[7*8 +: 8] <= (req0_rep1r==0)?'h01:'h02 ;
arp_m_byte_cnt <= 8 ;
end else begin
/*
10-2:arp_data <= get_byte5 (my_macr);
11-2:arp_data <= get_byte4 (my_macr) ;
12-2:arp_data <= get_byte3 (my_macr) ;
13-2:arp_data <= get_byte2 (my_macr) ;
14-2:arp_data <= get_byte1 (my_macr) ;
15-2:arp_data <= get_byte0 (my_macr) ;//source mac
16-2:arp_data <= get_byte3(my_ipr) ;
17-2:arp_data <= get_byte2(my_ipr) ;
*/
arp_m_data[0*8 +: 8] <=(req0_rep1r==0 )? 0: get_byte5 (my_macr) ;
arp_m_data[1*8 +: 8] <=(req0_rep1r==0 )? 0: get_byte4 (my_macr) ;
arp_m_data[2*8 +: 8] <=(req0_rep1r==0 )? 0: get_byte3 (my_macr) ;
arp_m_data[3*8 +: 8] <=(req0_rep1r==0 )? 0: get_byte2 (my_macr) ;
arp_m_data[4*8 +: 8] <=(req0_rep1r==0 )? 0: get_byte1 (my_macr) ;
arp_m_data[5*8 +: 8] <=(req0_rep1r==0 )? 0: get_byte0 (my_macr) ;
arp_m_data[6*8 +: 8] <=get_byte3 (my_ip) ;
arp_m_data[7*8 +: 8] <=get_byte2 (my_ip) ;
arp_m_byte_cnt <= 8 ;
end
endcase
always@(posedge clk) arp_m_last <= st==31 ;
endmodule
这里由于上一个BLOG写好专门的字节移动模块,这里直接将8字节对齐。(实际上这是在ARP层,下层就是给MAC层,直接输入对齐的8直接就好,不需要考虑字节对齐问题)。
仿真结果:
没有什么问题。这里的arp_m_byte_cnt只输出8和4对应下层就是axis总线的keep就是8'hff和8‘h0f这里我们不专门处理KEEP了,再以后组装在一起的时候可以加以转换。
--------------
下一步要做的是arp协议的解析。
1,解析arp协议找出mac地址和ip地址。之后在XILINX的板子上实现对ARP的相应。
2,通过上述成功的arp总结并确保数据字端和顺序列的规律。
3,写好IP层+UDP层的发送代码。
4,写好IP层+ICMP_REPLAY的代码。