软件版本:Anlogic -TD5.9.1-DR1_ES1.1 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板 3.4 ARP层该层具有接收ARP请求、发送ARP回复,和发送ARP请求、接收ARP回复的功能,并将接收到的对端的地址信息存入cache中。 3.4.1 ARP接收模块该模块通过计数器接收28字节ARP信息字段。信息接收完成后,通过接收到的操作码判断接收到的数据包是ARP请求包还是ARP应答包。如果是应答包,将接收到的地址信息写入cache中;如果是请求包,判断目的IP地址与本地IP地址是否一致,若一致,将地址信息写入cache中,且发送至uiarp_rx模块,若不一致,则过滤该包。 - if(OPER == ARP_REQUEST) begin//如果是ARP请求 ARP_REQUEST = 16'h0001(16’h01 ARP请求包 ; 16’h02 ARP应答)
- if(TPA == I_ip_local_addr) begin //比较接收到的ARP包里面的IP地址是否和本地IP地址一致
- O_arp_req_ip_addr <= SPA; //发送IP(远端源IP地址)
- O_arp_req_mac_addr <= SHA; //发送方MAC(远端源地址MAC)
- O_arp_req_valid <= 1'b1; //设置ARP请求有效(通知发送ARP发送模块发送一个ARP应答给远端主机),保存远端主机的IP地址和MAC地址到cache
- O_arp_reply_done <= 1'b0;
- end
- else begin
- O_arp_req_ip_addr <= 32'd0;
- O_arp_req_mac_addr <= 48'd0;
- O_arp_req_valid <= 1'b0;
- O_arp_reply_done <= 1'b0;
- end
- end
复制代码 3.4.2 ARP发送模块该模块对ARP应答和ARP请求同时进行处理,首先对这两种逻辑进行仲裁,以避免发送冲突。如果既没有ARP应答也没有ARP请求,且内部ARP包发送逻辑非忙,则处理缓存的有效信号;如果只有ARP应答,没有ARP请求,且发送逻辑非忙,则请求发送ARP应答包,若发送逻辑忙,则将发送ARP应答包的请求缓存至reply_buffer_valid中,等待非忙时发出;如果只有ARP请求,没有ARP应答,且发送逻辑非忙,则请求发送ARP请求包,若发送逻辑忙,则将发送ARP请求包的请求缓存至request_buffer_valid中,等待非忙时发出;若ARP应答和ARP请求同时为高,则优先发送ARP请求,缓存ARP应答。 - case({I_arp_treq_en, I_arp_rreply_en})//本状态机实现了即便是同时有ARP应答或者ARP请求,都能确保完成发送
- 2'b00:begin
- if((!O_arp_treq) && (!O_arp_tvalid)) begin//没有arp_treq请求,并且arp_tvalid为0 代表没有要发送的ARP数据
- if(request_buffer_valid) begin//如果有未发送完的ARP请求,则继续发送
- OPER <= ARP_REQUEST;
- TPA <= ip_request_buffer;
- THA <= 48'd0;
- request_buffer_valid <= 1'b0;//清除request_buffer_valid
- O_arp_treq <= 1'b1;
- end
- else if(reply_buffer_valid) begin//如果有未发送完的ARP应答,则继续发送
- OPER <= ARP_REPLY;
- TPA <= ip_reply_buffer;
- THA <= mac_reply_buffer;
- reply_buffer_valid <= 1'b0;//清除request_buffer_valid
- O_arp_treq <= 1'b1;
- end
- end
- end
- 2'b01:begin//发送ARP应答
- if((!O_arp_treq) && (!O_arp_tvalid)) begin
- OPER <= ARP_REPLY;
- TPA <= I_arp_rreply_ip_addr;
- THA <= I_arp_rreply_mac_addr;
- O_arp_treq <= 1'b1;
- end
- else begin//需要arp应答
- ip_reply_buffer <= I_arp_rreply_ip_addr;//寄存目的地址IP
- mac_reply_buffer <= I_arp_rreply_mac_addr;//寄存目的地址MAC
- reply_buffer_valid <= 1'b1;//需要发送ARP应答
- end
- end
- 2'b10:begin//发送ARP请求,当ip_arp_tx发送IP包查询MAC没有查询到,执行ARP请求,请求远程主机提供MAC
- if((!O_arp_treq) && (!O_arp_tvalid)) begin
- OPER <= ARP_REQUEST;
- TPA <= I_arp_tip_addr;
- THA <= 48'd0;
- O_arp_treq <= 1'b1;//ARP 发送
- end
- else begin//arp请求包
- ip_request_buffer <= I_arp_tip_addr;
- request_buffer_valid <= 1'b1;//ARP 请求有效标志
- end
- end
- 2'b11:begin//既有ARP请求,又有ARP应答
- if((!O_arp_treq) && (!O_arp_tvalid)) begin
- OPER <= ARP_REQUEST;
- TPA <= I_arp_tip_addr;
- THA <= 48'd0;
- O_arp_treq <= 1'b1;//ARP 发送
- end
- else begin
- ip_request_buffer <= I_arp_tip_addr;
- request_buffer_valid <= 1'b1;//ARP请求有效
- end
- ip_reply_buffer <= I_arp_rreply_ip_addr;
- mac_reply_buffer <= I_arp_rreply_mac_addr;
- reply_buffer_valid <= 1'b1; //ARP应答有效
- end
- endcase
复制代码若O_arp_treq和uiip_arp_tx模块发送的I_arp_tbusy完成握手,则开始发送ARP包,并且通过判断ARP包的类型来确定发送的目的地址。通过计数器cnt发送28字节有效数据,再通过计数器pad_cnt在末尾补18个字节的0,即完成发送,开始等待下一次握手。 - case(STATE)
- WAIT_BUFFER_READY:begin
- if(O_arp_treq && I_arp_tbusy) begin
- O_arp_tdata <= HTYPE[15:8]; //硬件类型-以太网类型
- O_arp_tvalid <= 1'b1; //ARP数据有效
- cnt <= cnt + 1'b1;
- if(OPER == ARP_REQUEST) begin //如果是ARP请求
- O_arp_tdest_mac_addr <= 48'hff_ff_ff_ff_ff_ff; //ARP目的地址为广播地址
- O_arp_ttype <= 1'b1; //通知ip_arp_tx ARP类型为ARP请求
- end
- else begin
- O_arp_tdest_mac_addr <= THA;
- O_arp_ttype <= 1'b0; //通知ip_arp_tx ARP类型为ARP应答
- end
- O_arp_treq <= 1'b0;
- STATE <= SEND_ARP_PACKET;
- end
- else
- STATE <= WAIT_BUFFER_READY;
- end
- SEND_ARP_PACKET:begin
- case(cnt)
- 1: begin O_arp_tdata <= HTYPE[7:0]; cnt <= cnt + 1'b1;end
- 2: begin O_arp_tdata <= PTYPE[15:8]; cnt <= cnt + 1'b1;end
- 3: begin O_arp_tdata <= PTYPE[7:0]; cnt <= cnt + 1'b1;end
- 4: begin O_arp_tdata <= HLEN; cnt <= cnt + 1'b1;end
- 5: begin O_arp_tdata <= PLEN; cnt <= cnt + 1'b1;end
- 6: begin O_arp_tdata <= OPER[15:8]; cnt <= cnt + 1'b1;end
- 7: begin O_arp_tdata <= OPER[7:0]; cnt <= cnt + 1'b1;end
- 8: begin O_arp_tdata <= I_mac_local_addr[47:40]; cnt <= cnt + 1'b1;end
- 9: begin O_arp_tdata <= I_mac_local_addr[39:32]; cnt <= cnt + 1'b1;end
- 10: begin O_arp_tdata <= I_mac_local_addr[31:24]; cnt <= cnt + 1'b1;end
- 11: begin O_arp_tdata <= I_mac_local_addr[23:16]; cnt <= cnt + 1'b1;end
- 12: begin O_arp_tdata <= I_mac_local_addr[15:8]; cnt <= cnt + 1'b1;end
- 13: begin O_arp_tdata <= I_mac_local_addr[7:0]; cnt <= cnt + 1'b1;end
- 14: begin O_arp_tdata <= I_ip_local_addr[31:24]; cnt <= cnt + 1'b1;end
- 15: begin O_arp_tdata <= I_ip_local_addr[23:16]; cnt <= cnt + 1'b1;end
- 16: begin O_arp_tdata <= I_ip_local_addr[15:8]; cnt <= cnt + 1'b1;end
- 17: begin O_arp_tdata <= I_ip_local_addr[7:0]; cnt <= cnt + 1'b1;end
- 18: begin O_arp_tdata <= THA[47:40]; cnt <= cnt + 1'b1;end
- 19: begin O_arp_tdata <= THA[39:32]; cnt <= cnt + 1'b1;end
- 20: begin O_arp_tdata <= THA[31:24]; cnt <= cnt + 1'b1;end
- 21: begin O_arp_tdata <= THA[23:16]; cnt <= cnt + 1'b1;end
- 22: begin O_arp_tdata <= THA[15:8]; cnt <= cnt + 1'b1;end
- 23: begin O_arp_tdata <= THA[7:0]; cnt <= cnt + 1'b1;end
- 24: begin O_arp_tdata <= TPA[31:24]; cnt <= cnt + 1'b1;end
- 25: begin O_arp_tdata <= TPA[23:16]; cnt <= cnt + 1'b1;end
- 26: begin O_arp_tdata <= TPA[15:8]; cnt <= cnt + 1'b1;end
- 27: begin O_arp_tdata <= TPA[7:0]; cnt <= cnt + 1'b1;end
- 28: begin
- O_arp_tdata <= 8'd0;
- if(pad_cnt == 5'd17) begin //通过在末尾添加0以确保数据长度为46
- cnt <= cnt + 1'b1;
- pad_cnt <= 5'd0;
- end
- else begin
- cnt <= cnt;
- pad_cnt <= pad_cnt + 1'b1;
- end
- end
- 29: begin
- O_arp_tdata <= 8'd0;
- O_arp_tvalid <= 1'b0;
- O_arp_tdest_mac_addr <= 48'd0;
- O_arp_ttype <= 1'b0;
- cnt <= 5'd0;
- STATE <= WAIT_BUFFER_READY;
- end
- default:begin
- O_arp_tdata <= 8'd0;
- O_arp_tvalid <= 1'b0;
- cnt <= 5'd0;
- STATE <= WAIT_BUFFER_READY;
- end
- endcase
- end
- endcase
- end
- end
复制代码 3.4.3 CACHE模块mac_cache模块相当于一个RAM,通过IP作为地址,写入或读出MAC地址。写入mac_cache模块的地址信息远程主机发送的ARP应答包或ARP请求包中的地址,在IP层发送UDP数据报文时,需要在mac_cache中读出和IP地址对应的MAC地址。 - `timescale 1ns/1ps
- module mac_cache
- (
- input wire I_wclk,
- input wire I_reset,
- input wire I_wen,
- input wire [31:0] I_wip_addr,
- input wire [47:0] I_wmac_addr,
- input wire I_rclk,
- input wire I_ren,
- input wire [31:0] I_rip_addr,
- output reg [47:0] O_rmac_addr,
- output reg O_rmac_done
- );
- reg mac_cache_flag [0:3];
- reg [31:0] ip_address_cache [0:3];
- reg [47:0] mac_address_cache [0:3];
- reg [1:0] index;
- always@(posedge I_wclk or posedge I_reset) begin
- if(I_reset) begin
- mac_cache_flag[0] <= 1'b0;
- ip_address_cache[0] <= 32'd0;
- mac_address_cache[0] <= 48'd0;
- mac_cache_flag[1] <= 1'b0;
- ip_address_cache[1] <= 32'd0;
- mac_address_cache[1] <= 48'd0;
- mac_cache_flag[2] <= 1'b0;
- ip_address_cache[2] <= 32'd0;
- mac_address_cache[2] <= 48'd0;
- mac_cache_flag[3] <= 1'b0;
- ip_address_cache[3] <= 32'd0;
- mac_address_cache[3] <= 48'd0;
- index <= 2'd0;
- end
- else begin
- if(I_wen) begin
- if(mac_cache_flag[0] && ip_address_cache[0] == I_wip_addr)
- mac_address_cache[0] <= I_wmac_addr;
- else if(mac_cache_flag[1] && ip_address_cache[1] == I_wip_addr)
- mac_address_cache[1] <= I_wmac_addr;
- else if(mac_cache_flag[2] && ip_address_cache[2] == I_wip_addr)
- mac_address_cache[2] <= I_wmac_addr;
- else if(mac_cache_flag[3] && ip_address_cache[3] == I_wip_addr)
- mac_address_cache[3] <= I_wmac_addr;
- else begin
- mac_cache_flag[index] <= 1'b1;
- ip_address_cache[index] <= I_wip_addr;
- mac_address_cache[index] <= I_wmac_addr;
- index <= index + 1'b1;
- end
- end
- else begin
- mac_cache_flag[0] <= mac_cache_flag[0];
- ip_address_cache[0] <= ip_address_cache[0];
- mac_address_cache[0] <= mac_address_cache[0];
- mac_cache_flag[1] <= mac_cache_flag[1];
- ip_address_cache[1] <= ip_address_cache[1];
- mac_address_cache[1] <= mac_address_cache[1];
- mac_cache_flag[2] <= mac_cache_flag[2];
- ip_address_cache[2] <= ip_address_cache[2];
- mac_address_cache[2] <= mac_address_cache[2];
- mac_cache_flag[3] <= mac_cache_flag[3];
- ip_address_cache[3] <= ip_address_cache[3];
- mac_address_cache[3] <= mac_address_cache[3];
- end
- end
- end
- always@(posedge I_rclk or posedge I_reset) begin
- if(I_reset) begin
- O_rmac_addr <= 48'd0;
- O_rmac_done <= 1'b0;
- end
- else begin
- if(I_ren) begin
- O_rmac_done <= 1'b1;
- if(mac_cache_flag[0] && I_rip_addr == ip_address_cache[0])
- O_rmac_addr <= mac_address_cache[0];
- else if(mac_cache_flag[1] && I_rip_addr == ip_address_cache[1])
- O_rmac_addr <= mac_address_cache[1];
- else if(mac_cache_flag[2] && I_rip_addr == ip_address_cache[2])
- O_rmac_addr <= mac_address_cache[2];
- else if(mac_cache_flag[3] && I_rip_addr == ip_address_cache[3])
- O_rmac_addr <= mac_address_cache[3];
- else
- O_rmac_addr <= 48'd0;
- end
- else begin
- O_rmac_addr <= O_rmac_addr;
- O_rmac_done <= 1'b0;
- end
- end
- end
- endmodule
复制代码 |