实现一个arp_cache实现对IP和MAC的对应存储。
多周期实现,有8个条目,没有使用刷新计时器。
/*
arp_cache arp_cache(
.clk ( ),
.rst ( ),
.ip_in( ),
.mac_in( ),
.wr_en( ),
.wr_busy ( ),
.req_en ( ),
.ip_req( ),
.mac_out( ),
.req_done( ),
.req_hit( )
);
*/
module arp_cache(
input clk , rst ,
input [31:0]ip_in,
input [47:0]mac_in,
input wr_en,
output reg wr_busy ,
input req_en ,
input [31:0] ip_req,
output reg [47:0] mac_out,
output reg req_done,req_hit
);
reg [31:0] ip_in_r; always @ (posedge clk) if (rst)ip_in_r<=0; else if (wr_en) ip_in_r<=ip_in;
reg [47:0] mac_in_r; always @ (posedge clk) if (rst)mac_in_r<=0; else if (wr_en) mac_in_r<=mac_in;
reg [31:0]ip_req_r ; always @ (posedge clk) if (rst)ip_req_r<=0; else if (req_en) ip_req_r<=ip_req;
reg [48+32-1:0] ram [0:7] ; integer i; initial for(i=0;i<7;i=i+1) ram[i]<=0;
reg [7:0] wr_st ;
always @ (posedge clk) if (rst) wr_busy<=1; else if (wr_en && wr_st==10) wr_busy <= 1; else if (wr_st == 80 ) wr_busy <=0;
always @ (posedge clk) if (rst) wr_st<=0 ;else case (wr_st)
0:wr_st<=10;
10:if ( wr_en ) wr_st<=20;
20 : if ( ram [0][31:0] ==ip_in_r ) wr_st<=80; else wr_st <= wr_st + 1; // if exist then exit
21 : if ( ram [1][31:0] ==ip_in_r ) wr_st<=80; else wr_st <= wr_st + 1;
22 : if ( ram [2][31:0] ==ip_in_r ) wr_st<=80; else wr_st <= wr_st + 1;
23 : if ( ram [3][31:0] ==ip_in_r ) wr_st<=80; else wr_st <= wr_st + 1;
24 : if ( ram [4][31:0] ==ip_in_r ) wr_st<=80; else wr_st <= wr_st + 1;
25 : if ( ram [5][31:0] ==ip_in_r ) wr_st<=80; else wr_st <= wr_st + 1;
26 : if ( ram [6][31:0] ==ip_in_r ) wr_st<=80; else wr_st <= wr_st + 1;
27 : if ( ram [7][31:0] ==ip_in_r ) wr_st<=80; else wr_st <= 64 ;
64:if ( ram [0][31:0] == 0 ) wr_st<=80; else wr_st <= wr_st + 1;// find a free space
65:if ( ram [1][31:0] == 0 ) wr_st<=80; else wr_st <= wr_st + 1;
66:if ( ram [2][31:0] == 0 ) wr_st<=80; else wr_st <= wr_st + 1;
67:if ( ram [3][31:0] == 0 ) wr_st<=80; else wr_st <= wr_st + 1;
68:if ( ram [4][31:0] == 0 ) wr_st<=80; else wr_st <= wr_st + 1;
69:if ( ram [5][31:0] == 0 ) wr_st<=80; else wr_st <= wr_st + 1;
70:if ( ram [6][31:0] == 0 ) wr_st<=80; else wr_st <= wr_st + 1;
71:if ( ram [7][31:0] == 0 ) wr_st<=80; else wr_st <= wr_st + 1;
80: wr_st<=10;
default wr_st<=0;
endcase
always @(posedge clk ) if (rst)ram [0]<=0; else if ( wr_st==(64+0) && ( ram [0][31:0] == 0 ) ) ram [0] <= {mac_in_r,ip_in_r}; //record it
always @(posedge clk ) if (rst)ram [1]<=0; else if ( wr_st==(64+1) && ( ram [1][31:0] == 0 ) ) ram [1] <= {mac_in_r,ip_in_r};
always @(posedge clk ) if (rst)ram [2]<=0; else if ( wr_st==(64+2) && ( ram [2][31:0] == 0 ) ) ram [2] <= {mac_in_r,ip_in_r};
always @(posedge clk ) if (rst)ram [3]<=0; else if ( wr_st==(64+3) && ( ram [3][31:0] == 0 ) ) ram [3] <= {mac_in_r,ip_in_r};
always @(posedge clk ) if (rst)ram [4]<=0; else if ( wr_st==(64+4) && ( ram [4][31:0] == 0 ) ) ram [4] <= {mac_in_r,ip_in_r};
always @(posedge clk ) if (rst)ram [5]<=0; else if ( wr_st==(64+5) && ( ram [5][31:0] == 0 ) ) ram [5] <= {mac_in_r,ip_in_r};
always @(posedge clk ) if (rst)ram [6]<=0; else if ( wr_st==(64+6) && ( ram [6][31:0] == 0 ) ) ram [6] <= {mac_in_r,ip_in_r};
always @(posedge clk ) if (rst)ram [7]<=0; else if ( wr_st==(64+7) && ( ram [7][31:0] == 0 ) ) ram [7] <= {mac_in_r,ip_in_r};
reg [7:0] rd_st ;
always @(posedge clk) if (rst) rd_st <=0 ; else case (rd_st)
0:rd_st <=0;
10:if (req_en)rd_st<=64;
64:if ( ram [0][31:0] == ip_req_r ) rd_st <=80;else rd_st <= rd_st + 1 ; // find the item by ip
65:if ( ram [1][31:0] == ip_req_r ) rd_st <=80;else rd_st <= rd_st + 1 ;
66:if ( ram [2][31:0] == ip_req_r ) rd_st <=80;else rd_st <= rd_st + 1 ;
67:if ( ram [3][31:0] == ip_req_r ) rd_st <=80;else rd_st <= rd_st + 1 ;
68:if ( ram [4][31:0] == ip_req_r ) rd_st <=80;else rd_st <= rd_st + 1 ;
69:if ( ram [5][31:0] == ip_req_r ) rd_st <=80;else rd_st <= rd_st + 1 ;
70:if ( ram [6][31:0] == ip_req_r ) rd_st <=80;else rd_st <= rd_st + 1 ;
71:if ( ram [7][31:0] == ip_req_r ) rd_st <=80;else rd_st <= rd_st + 1 ;
72: rd_st<=75;// hit = 0
75: rd_st<=10;
80 : rd_st<=100;// hit = 1
100: rd_st<=10;
default rd_st <=0;
endcase
always @(posedge clk) if (rst){req_hit,req_done}<=0; else case (rd_st)
72 :{req_hit,req_done}<=2'b01 ;
80 :{req_hit,req_done}<=2'b11;
default {req_hit,req_done}<=0;
endcase
always @(posedge clk) if (rst) mac_out <=0 ; else case (rd_st) //output the mac when poll
64: mac_out <= ram[0][64+32-1:32] ;
65: mac_out <= ram[1][64+32-1:32] ;
66: mac_out <= ram[2][64+32-1:32] ;
67: mac_out <= ram[3][64+32-1:32] ;
68: mac_out <= ram[4][64+32-1:32] ;
69: mac_out <= ram[5][64+32-1:32] ;
70: mac_out <= ram[6][64+32-1:32] ;
71: mac_out <= ram[7][64+32-1:32] ;
endcase
endmodule
代码没有调试也没有仿真,统调时进行。