1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-30 08:32:52 +08:00

Rework ARP subsystem

This commit is contained in:
Alex Forencich 2018-06-18 13:59:58 -07:00
parent 25d1b373cc
commit 5b7646ccda
23 changed files with 857 additions and 656 deletions

255
rtl/arp.v
View File

@ -30,7 +30,7 @@ THE SOFTWARE.
* ARP block for IPv4, ethernet frame interface
*/
module arp #(
parameter CACHE_ADDR_WIDTH = 2,
parameter CACHE_ADDR_WIDTH = 9,
parameter REQUEST_RETRY_COUNT = 4,
parameter REQUEST_RETRY_INTERVAL = 125000000*2,
parameter REQUEST_TIMEOUT = 125000000*30
@ -71,8 +71,10 @@ module arp #(
* ARP requests
*/
input wire arp_request_valid,
output wire arp_request_ready,
input wire [31:0] arp_request_ip,
output wire arp_response_valid,
input wire arp_response_ready,
output wire arp_response_error,
output wire [47:0] arp_response_mac,
@ -93,7 +95,7 @@ localparam [15:0]
ARP_OPER_INARP_REPLY = 16'h0009;
wire incoming_frame_valid;
wire incoming_frame_ready;
reg incoming_frame_ready;
wire [47:0] incoming_eth_dest_mac;
wire [47:0] incoming_eth_src_mac;
wire [15:0] incoming_eth_type;
@ -107,19 +109,6 @@ wire [31:0] incoming_arp_spa;
wire [47:0] incoming_arp_tha;
wire [31:0] incoming_arp_tpa;
reg outgoing_frame_valid_reg = 1'b0, outgoing_frame_valid_next;
wire outgoing_frame_ready;
reg [47:0] outgoing_eth_dest_mac_reg = 48'd0, outgoing_eth_dest_mac_next;
reg [15:0] outgoing_arp_oper_reg = 16'd0, outgoing_arp_oper_next;
reg [47:0] outgoing_arp_tha_reg = 48'd0, outgoing_arp_tha_next;
reg [31:0] outgoing_arp_tpa_reg = 32'd0, outgoing_arp_tpa_next;
// drop frame
reg drop_incoming_frame_reg = 1'b0, drop_incoming_frame_next;
// wait on incoming frames until we can reply
assign incoming_frame_ready = outgoing_frame_ready | drop_incoming_frame_reg;
/*
* ARP frame processing
*/
@ -159,6 +148,13 @@ arp_eth_rx_inst (
.error_invalid_header()
);
reg outgoing_frame_valid_reg = 1'b0, outgoing_frame_valid_next;
wire outgoing_frame_ready;
reg [47:0] outgoing_eth_dest_mac_reg = 48'd0, outgoing_eth_dest_mac_next;
reg [15:0] outgoing_arp_oper_reg = 16'd0, outgoing_arp_oper_next;
reg [47:0] outgoing_arp_tha_reg = 48'd0, outgoing_arp_tha_next;
reg [31:0] outgoing_arp_tpa_reg = 32'd0, outgoing_arp_tpa_next;
arp_eth_tx
arp_eth_tx_inst (
.clk(clk),
@ -191,27 +187,8 @@ arp_eth_tx_inst (
.busy()
);
wire incoming_eth_type_valid = (incoming_eth_type == 16'h0806);
wire incoming_arp_htype_valid = (incoming_arp_htype == 16'h0001);
wire incoming_arp_ptype_valid = (incoming_arp_ptype == 16'h0800);
wire incoming_arp_oper_arp_request = (incoming_arp_oper == ARP_OPER_ARP_REQUEST);
wire incoming_arp_oper_arp_reply = (incoming_arp_oper == ARP_OPER_ARP_REPLY);
wire incoming_arp_oper_inarp_request = (incoming_arp_oper == ARP_OPER_INARP_REQUEST);
wire incoming_arp_oper_inarp_reply = (incoming_arp_oper == ARP_OPER_INARP_REPLY);
wire filtered_incoming_frame_valid = incoming_frame_valid &
incoming_eth_type_valid &
incoming_arp_htype_valid &
incoming_arp_ptype_valid;
wire filtered_incoming_arp_oper_arp_request = filtered_incoming_frame_valid & incoming_arp_oper_arp_request;
wire filtered_incoming_arp_oper_arp_reply = filtered_incoming_frame_valid & incoming_arp_oper_arp_reply;
wire filtered_incoming_arp_oper_inarp_request = filtered_incoming_frame_valid & incoming_arp_oper_inarp_request;
wire filtered_incoming_arp_oper_inarp_reply = filtered_incoming_frame_valid & incoming_arp_oper_inarp_reply;
wire cache_query_request_valid;
wire [31:0] cache_query_request_ip;
reg cache_query_request_valid_reg = 1'b0, cache_query_request_valid_next;
reg [31:0] cache_query_request_ip_reg = 32'd0, cache_query_request_ip_next;
wire cache_query_response_valid;
wire cache_query_response_error;
wire [47:0] cache_query_response_mac;
@ -219,8 +196,6 @@ wire [47:0] cache_query_response_mac;
reg cache_write_request_valid_reg = 1'b0, cache_write_request_valid_next;
reg [31:0] cache_write_request_ip_reg = 32'd0, cache_write_request_ip_next;
reg [47:0] cache_write_request_mac_reg = 48'd0, cache_write_request_mac_next;
wire cache_write_in_progress;
wire cache_write_complete;
/*
* ARP cache
@ -232,134 +207,109 @@ arp_cache_inst (
.clk(clk),
.rst(rst),
// Query cache
.query_request_valid(cache_query_request_valid),
.query_request_ip(cache_query_request_ip),
.query_request_valid(cache_query_request_valid_reg),
.query_request_ready(),
.query_request_ip(cache_query_request_ip_reg),
.query_response_valid(cache_query_response_valid),
.query_response_ready(1'b1),
.query_response_error(cache_query_response_error),
.query_response_mac(cache_query_response_mac),
// Write cache
.write_request_valid(cache_write_request_valid_reg),
.write_request_ready(),
.write_request_ip(cache_write_request_ip_reg),
.write_request_mac(cache_write_request_mac_reg),
.write_in_progress(cache_write_in_progress),
.write_complete(cache_write_complete),
// Configuration
.clear_cache(clear_cache)
);
reg arp_request_operation_reg = 1'b0, arp_request_operation_next;
reg arp_request_valid_reg = 1'b0, arp_request_valid_next;
reg arp_request_ready_reg = 1'b0, arp_request_ready_next;
reg [31:0] arp_request_ip_reg = 32'd0, arp_request_ip_next;
reg arp_response_valid_reg = 1'b0, arp_response_valid_next;
reg arp_response_error_reg = 1'b0, arp_response_error_next;
reg arp_response_broadcast_reg = 1'b0, arp_response_broadcast_next;
reg [47:0] arp_response_mac_reg = 48'd0, arp_response_mac_next;
reg [5:0] arp_request_retry_cnt_reg = 6'd0, arp_request_retry_cnt_next;
reg [35:0] arp_request_timer_reg = 36'd0, arp_request_timer_next;
assign cache_query_request_valid = ~arp_request_operation_reg ? arp_request_valid_reg : 1'b1;
assign cache_query_request_ip = arp_request_ip_reg;
assign arp_request_ready = arp_request_ready_reg;
assign arp_response_valid = arp_response_error_reg | (cache_query_response_valid & ~cache_query_response_error & ~arp_request_operation_reg) | arp_response_broadcast_reg;
assign arp_response_valid = arp_response_valid_reg;
assign arp_response_error = arp_response_error_reg;
assign arp_response_mac = arp_response_broadcast_reg ? 48'hffffffffffff : cache_query_response_mac;
assign arp_response_mac = arp_response_mac_reg;
always @* begin
incoming_frame_ready = 1'b0;
outgoing_frame_valid_next = outgoing_frame_valid_reg & ~outgoing_frame_ready;
outgoing_eth_dest_mac_next = outgoing_eth_dest_mac_reg;
outgoing_arp_oper_next = outgoing_arp_oper_reg;
outgoing_arp_tha_next = outgoing_arp_tha_reg;
outgoing_arp_tpa_next = outgoing_arp_tpa_reg;
cache_write_request_valid_next = 1'b0;
cache_write_request_mac_next = 48'd0;
cache_write_request_ip_next = 32'd0;
cache_query_request_valid_next = 1'b0;
cache_query_request_ip_next = cache_query_request_ip_reg;
arp_request_valid_next = 1'b0;
cache_write_request_valid_next = 1'b0;
cache_write_request_mac_next = cache_write_request_mac_reg;
cache_write_request_ip_next = cache_write_request_ip_reg;
arp_request_ready_next = 1'b0;
arp_request_ip_next = arp_request_ip_reg;
arp_request_operation_next = arp_request_operation_reg;
arp_request_retry_cnt_next = arp_request_retry_cnt_reg;
arp_request_timer_next = arp_request_timer_reg;
arp_response_valid_next = arp_response_valid_reg & ~arp_response_ready;
arp_response_error_next = 1'b0;
arp_response_broadcast_next = 1'b0;
drop_incoming_frame_next = 1'b0;
arp_response_mac_next = 48'd0;
// manage incoming frames
if (filtered_incoming_frame_valid & ~(outgoing_frame_valid_reg & ~outgoing_frame_ready)) begin
// store sender addresses in cache
cache_write_request_valid_next = 1'b1;
cache_write_request_ip_next = incoming_arp_spa;
cache_write_request_mac_next = incoming_arp_sha;
if (incoming_arp_oper_arp_request) begin
if (incoming_arp_tpa == local_ip) begin
// send reply frame to valid incoming request
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = incoming_eth_src_mac;
outgoing_arp_oper_next = ARP_OPER_ARP_REPLY;
outgoing_arp_tha_next = incoming_arp_sha;
outgoing_arp_tpa_next = incoming_arp_spa;
end else begin
// does not match -> drop it
drop_incoming_frame_next = 1'b1;
incoming_frame_ready = outgoing_frame_ready;
if (incoming_frame_valid & incoming_frame_ready) begin
if (incoming_eth_type == 16'h0806 && incoming_arp_htype == 16'h0001 && incoming_arp_ptype == 16'h0800) begin
// store sender addresses in cache
cache_write_request_valid_next = 1'b1;
cache_write_request_ip_next = incoming_arp_spa;
cache_write_request_mac_next = incoming_arp_sha;
if (incoming_arp_oper == ARP_OPER_ARP_REQUEST) begin
// ARP request
if (incoming_arp_tpa == local_ip) begin
// send reply frame to valid incoming request
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = incoming_eth_src_mac;
outgoing_arp_oper_next = ARP_OPER_ARP_REPLY;
outgoing_arp_tha_next = incoming_arp_sha;
outgoing_arp_tpa_next = incoming_arp_spa;
end
end else if (incoming_arp_oper == ARP_OPER_INARP_REPLY) begin
// INARP request
if (incoming_arp_tha == local_mac) begin
// send reply frame to valid incoming request
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = incoming_eth_src_mac;
outgoing_arp_oper_next = ARP_OPER_INARP_REPLY;
outgoing_arp_tha_next = incoming_arp_sha;
outgoing_arp_tpa_next = incoming_arp_spa;
end
end
end else if (incoming_arp_oper_inarp_request) begin
if (incoming_arp_tha == local_mac) begin
// send reply frame to valid incoming request
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = incoming_eth_src_mac;
outgoing_arp_oper_next = ARP_OPER_INARP_REPLY;
outgoing_arp_tha_next = incoming_arp_sha;
outgoing_arp_tpa_next = incoming_arp_spa;
end else begin
// does not match -> drop it
drop_incoming_frame_next = 1'b1;
end
end else begin
// does not match -> drop it
drop_incoming_frame_next = 1'b1;
end
end else if (incoming_frame_valid & ~filtered_incoming_frame_valid) begin
// incoming invalid frame -> drop it
drop_incoming_frame_next = 1'b1;
end
// manage ARP lookup requests
if (~arp_request_operation_reg & ~arp_response_valid) begin
if (arp_request_valid) begin
if (~(arp_request_ip | subnet_mask) == 0) begin
// broadcast address
// (all bits in request IP set where subnet mask is clear)
arp_request_valid_next = 1'b0;
arp_response_broadcast_next = 1'b1;
end else if (((arp_request_ip ^ gateway_ip) & subnet_mask) == 0) begin
// within subnet, look up IP directly
// (no bits differ between request IP and gateway IP where subnet mask is set)
arp_request_valid_next = 1'b1;
arp_request_ip_next = arp_request_ip;
end else begin
// outside of subnet, so look up gateway address
arp_request_valid_next = 1'b1;
arp_request_ip_next = gateway_ip;
end
end
if (cache_query_response_error & ~arp_response_error) begin
arp_request_operation_next = 1'b1;
// send ARP request frame
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = 48'hFF_FF_FF_FF_FF_FF;
outgoing_arp_oper_next = ARP_OPER_ARP_REQUEST;
outgoing_arp_tha_next = 48'h00_00_00_00_00_00;
outgoing_arp_tpa_next = arp_request_ip_reg;
arp_request_retry_cnt_next = REQUEST_RETRY_COUNT-1;
arp_request_timer_next = REQUEST_RETRY_INTERVAL;
end
end else if (arp_request_operation_reg) begin
if (arp_request_operation_reg) begin
arp_request_ready_next = 1'b0;
cache_query_request_valid_next = 1'b1;
arp_request_timer_next = arp_request_timer_reg - 1;
// if we got a response, it will go in the cache, so when the query succeds, we're done
if (cache_query_response_valid & ~cache_query_response_error) begin
if (cache_query_response_valid & ~cache_query_response_error) begin
arp_request_operation_next = 1'b0;
cache_query_request_valid_next = 1'b0;
arp_response_valid_next = 1'b1;
arp_response_error_next = 1'b0;
arp_response_mac_next = cache_query_response_mac;
end
// timer timeout
if (arp_request_timer_reg == 0) begin
@ -367,9 +317,9 @@ always @* begin
// have more retries
// send ARP request frame
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = 48'hFF_FF_FF_FF_FF_FF;
outgoing_eth_dest_mac_next = 48'hffffffffffff;
outgoing_arp_oper_next = ARP_OPER_ARP_REQUEST;
outgoing_arp_tha_next = 48'h00_00_00_00_00_00;
outgoing_arp_tha_next = 48'h000000000000;
outgoing_arp_tpa_next = arp_request_ip_reg;
arp_request_retry_cnt_next = arp_request_retry_cnt_reg - 1;
if (arp_request_retry_cnt_reg > 1) begin
@ -380,7 +330,51 @@ always @* begin
end else begin
// out of retries
arp_request_operation_next = 1'b0;
arp_response_valid_next = 1'b1;
arp_response_error_next = 1'b1;
cache_query_request_valid_next = 1'b0;
end
end
end else begin
arp_request_ready_next = ~arp_response_valid_next;
if (cache_query_request_valid_reg) begin
cache_query_request_valid_next = 1'b1;
if (cache_query_response_valid) begin
if (cache_query_response_error) begin
arp_request_operation_next = 1'b1;
// send ARP request frame
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = 48'hffffffffffff;
outgoing_arp_oper_next = ARP_OPER_ARP_REQUEST;
outgoing_arp_tha_next = 48'h000000000000;
outgoing_arp_tpa_next = arp_request_ip_reg;
arp_request_retry_cnt_next = REQUEST_RETRY_COUNT-1;
arp_request_timer_next = REQUEST_RETRY_INTERVAL;
end else begin
cache_query_request_valid_next = 1'b0;
arp_response_valid_next = 1'b1;
arp_response_error_next = 1'b0;
arp_response_mac_next = cache_query_response_mac;
end
end
end else if (arp_request_valid & arp_request_ready) begin
if (~(arp_request_ip | subnet_mask) == 0) begin
// broadcast address
// (all bits in request IP set where subnet mask is clear)
arp_response_valid_next = 1'b1;
arp_response_error_next = 1'b0;
arp_response_mac_next = 48'hffffffffffff;
end else if (((arp_request_ip ^ gateway_ip) & subnet_mask) == 0) begin
// within subnet, look up IP directly
// (no bits differ between request IP and gateway IP where subnet mask is set)
cache_query_request_valid_next = 1'b1;
cache_query_request_ip_next = arp_request_ip;
arp_request_ip_next = arp_request_ip;
end else begin
// outside of subnet, so look up gateway address
cache_query_request_valid_next = 1'b1;
cache_query_request_ip_next = gateway_ip;
arp_request_ip_next = gateway_ip;
end
end
end
@ -389,26 +383,25 @@ end
always @(posedge clk) begin
if (rst) begin
outgoing_frame_valid_reg <= 1'b0;
cache_query_request_valid_reg <= 1'b0;
cache_write_request_valid_reg <= 1'b0;
arp_request_valid_reg <= 1'b0;
arp_request_ready_reg <= 1'b0;
arp_request_operation_reg <= 1'b0;
arp_request_retry_cnt_reg <= 6'd0;
arp_request_timer_reg <= 36'd0;
arp_response_error_reg <= 1'b0;
arp_response_broadcast_reg <= 1'b0;
drop_incoming_frame_reg <= 1'b0;
arp_response_valid_reg <= 1'b0;
end else begin
outgoing_frame_valid_reg <= outgoing_frame_valid_next;
cache_query_request_valid_reg <= cache_query_request_valid_next;
cache_write_request_valid_reg <= cache_write_request_valid_next;
arp_request_valid_reg <= arp_request_valid_next;
arp_request_ready_reg <= arp_request_ready_next;
arp_request_operation_reg <= arp_request_operation_next;
arp_request_retry_cnt_reg <= arp_request_retry_cnt_next;
arp_request_timer_reg <= arp_request_timer_next;
arp_response_error_reg <= arp_response_error_next;
arp_response_broadcast_reg <= arp_response_broadcast_next;
drop_incoming_frame_reg <= drop_incoming_frame_next;
arp_response_valid_reg <= arp_response_valid_next;
end
cache_query_request_ip_reg <= cache_query_request_ip_next;
outgoing_eth_dest_mac_reg <= outgoing_eth_dest_mac_next;
outgoing_arp_oper_reg <= outgoing_arp_oper_next;
outgoing_arp_tha_reg <= outgoing_arp_tha_next;
@ -416,6 +409,8 @@ always @(posedge clk) begin
cache_write_request_mac_reg <= cache_write_request_mac_next;
cache_write_request_ip_reg <= cache_write_request_ip_next;
arp_request_ip_reg <= arp_request_ip_next;
arp_response_error_reg <= arp_response_error_next;
arp_response_mac_reg <= arp_response_mac_next;
end
endmodule

View File

@ -30,10 +30,10 @@ THE SOFTWARE.
* ARP block for IPv4, ethernet frame interface (64 bit datapath)
*/
module arp_64 #(
parameter CACHE_ADDR_WIDTH = 2,
parameter CACHE_ADDR_WIDTH = 9,
parameter REQUEST_RETRY_COUNT = 4,
parameter REQUEST_RETRY_INTERVAL = 125000000*2,
parameter REQUEST_TIMEOUT = 125000000*30
parameter REQUEST_RETRY_INTERVAL = 156250000*2,
parameter REQUEST_TIMEOUT = 156250000*30
)
(
input wire clk,
@ -73,8 +73,10 @@ module arp_64 #(
* ARP requests
*/
input wire arp_request_valid,
output wire arp_request_ready,
input wire [31:0] arp_request_ip,
output wire arp_response_valid,
input wire arp_response_ready,
output wire arp_response_error,
output wire [47:0] arp_response_mac,
@ -95,7 +97,7 @@ localparam [15:0]
ARP_OPER_INARP_REPLY = 16'h0009;
wire incoming_frame_valid;
wire incoming_frame_ready;
reg incoming_frame_ready;
wire [47:0] incoming_eth_dest_mac;
wire [47:0] incoming_eth_src_mac;
wire [15:0] incoming_eth_type;
@ -109,19 +111,6 @@ wire [31:0] incoming_arp_spa;
wire [47:0] incoming_arp_tha;
wire [31:0] incoming_arp_tpa;
reg outgoing_frame_valid_reg = 1'b0, outgoing_frame_valid_next;
wire outgoing_frame_ready;
reg [47:0] outgoing_eth_dest_mac_reg = 48'd0, outgoing_eth_dest_mac_next;
reg [15:0] outgoing_arp_oper_reg = 16'd0, outgoing_arp_oper_next;
reg [47:0] outgoing_arp_tha_reg = 48'd0, outgoing_arp_tha_next;
reg [31:0] outgoing_arp_tpa_reg = 32'd0, outgoing_arp_tpa_next;
// drop frame
reg drop_incoming_frame_reg = 1'b0, drop_incoming_frame_next;
// wait on incoming frames until we can reply
assign incoming_frame_ready = outgoing_frame_ready | drop_incoming_frame_reg;
/*
* ARP frame processing
*/
@ -162,6 +151,13 @@ arp_eth_rx_inst (
.error_invalid_header()
);
reg outgoing_frame_valid_reg = 1'b0, outgoing_frame_valid_next;
wire outgoing_frame_ready;
reg [47:0] outgoing_eth_dest_mac_reg = 48'd0, outgoing_eth_dest_mac_next;
reg [15:0] outgoing_arp_oper_reg = 16'd0, outgoing_arp_oper_next;
reg [47:0] outgoing_arp_tha_reg = 48'd0, outgoing_arp_tha_next;
reg [31:0] outgoing_arp_tpa_reg = 32'd0, outgoing_arp_tpa_next;
arp_eth_tx_64
arp_eth_tx_inst (
.clk(clk),
@ -195,27 +191,8 @@ arp_eth_tx_inst (
.busy()
);
wire incoming_eth_type_valid = (incoming_eth_type == 16'h0806);
wire incoming_arp_htype_valid = (incoming_arp_htype == 16'h0001);
wire incoming_arp_ptype_valid = (incoming_arp_ptype == 16'h0800);
wire incoming_arp_oper_arp_request = (incoming_arp_oper == ARP_OPER_ARP_REQUEST);
wire incoming_arp_oper_arp_reply = (incoming_arp_oper == ARP_OPER_ARP_REPLY);
wire incoming_arp_oper_inarp_request = (incoming_arp_oper == ARP_OPER_INARP_REQUEST);
wire incoming_arp_oper_inarp_reply = (incoming_arp_oper == ARP_OPER_INARP_REPLY);
wire filtered_incoming_frame_valid = incoming_frame_valid &
incoming_eth_type_valid &
incoming_arp_htype_valid &
incoming_arp_ptype_valid;
wire filtered_incoming_arp_oper_arp_request = filtered_incoming_frame_valid & incoming_arp_oper_arp_request;
wire filtered_incoming_arp_oper_arp_reply = filtered_incoming_frame_valid & incoming_arp_oper_arp_reply;
wire filtered_incoming_arp_oper_inarp_request = filtered_incoming_frame_valid & incoming_arp_oper_inarp_request;
wire filtered_incoming_arp_oper_inarp_reply = filtered_incoming_frame_valid & incoming_arp_oper_inarp_reply;
wire cache_query_request_valid;
wire [31:0] cache_query_request_ip;
reg cache_query_request_valid_reg = 1'b0, cache_query_request_valid_next;
reg [31:0] cache_query_request_ip_reg = 32'd0, cache_query_request_ip_next;
wire cache_query_response_valid;
wire cache_query_response_error;
wire [47:0] cache_query_response_mac;
@ -223,8 +200,6 @@ wire [47:0] cache_query_response_mac;
reg cache_write_request_valid_reg = 1'b0, cache_write_request_valid_next;
reg [31:0] cache_write_request_ip_reg = 32'd0, cache_write_request_ip_next;
reg [47:0] cache_write_request_mac_reg = 48'd0, cache_write_request_mac_next;
wire cache_write_in_progress;
wire cache_write_complete;
/*
* ARP cache
@ -236,134 +211,109 @@ arp_cache_inst (
.clk(clk),
.rst(rst),
// Query cache
.query_request_valid(cache_query_request_valid),
.query_request_ip(cache_query_request_ip),
.query_request_valid(cache_query_request_valid_reg),
.query_request_ready(),
.query_request_ip(cache_query_request_ip_reg),
.query_response_valid(cache_query_response_valid),
.query_response_ready(1'b1),
.query_response_error(cache_query_response_error),
.query_response_mac(cache_query_response_mac),
// Write cache
.write_request_valid(cache_write_request_valid_reg),
.write_request_ready(),
.write_request_ip(cache_write_request_ip_reg),
.write_request_mac(cache_write_request_mac_reg),
.write_in_progress(cache_write_in_progress),
.write_complete(cache_write_complete),
// Configuration
.clear_cache(clear_cache)
);
reg arp_request_operation_reg = 1'b0, arp_request_operation_next;
reg arp_request_valid_reg = 1'b0, arp_request_valid_next;
reg arp_request_ready_reg = 1'b0, arp_request_ready_next;
reg [31:0] arp_request_ip_reg = 32'd0, arp_request_ip_next;
reg arp_response_valid_reg = 1'b0, arp_response_valid_next;
reg arp_response_error_reg = 1'b0, arp_response_error_next;
reg arp_response_broadcast_reg = 1'b0, arp_response_broadcast_next;
reg [47:0] arp_response_mac_reg = 48'd0, arp_response_mac_next;
reg [5:0] arp_request_retry_cnt_reg = 6'd0, arp_request_retry_cnt_next;
reg [35:0] arp_request_timer_reg = 36'd0, arp_request_timer_next;
assign cache_query_request_valid = ~arp_request_operation_reg ? arp_request_valid_reg : 1'b1;
assign cache_query_request_ip = arp_request_ip_reg;
assign arp_request_ready = arp_request_ready_reg;
assign arp_response_valid = arp_response_error_reg | (cache_query_response_valid & ~cache_query_response_error & ~arp_request_operation_reg) | arp_response_broadcast_reg;
assign arp_response_valid = arp_response_valid_reg;
assign arp_response_error = arp_response_error_reg;
assign arp_response_mac = arp_response_broadcast_reg ? 48'hffffffffffff : cache_query_response_mac;
assign arp_response_mac = arp_response_mac_reg;
always @* begin
incoming_frame_ready = 1'b0;
outgoing_frame_valid_next = outgoing_frame_valid_reg & ~outgoing_frame_ready;
outgoing_eth_dest_mac_next = outgoing_eth_dest_mac_reg;
outgoing_arp_oper_next = outgoing_arp_oper_reg;
outgoing_arp_tha_next = outgoing_arp_tha_reg;
outgoing_arp_tpa_next = outgoing_arp_tpa_reg;
cache_write_request_valid_next = 1'b0;
cache_write_request_mac_next = 48'd0;
cache_write_request_ip_next = 32'd0;
cache_query_request_valid_next = 1'b0;
cache_query_request_ip_next = cache_query_request_ip_reg;
arp_request_valid_next = 1'b0;
cache_write_request_valid_next = 1'b0;
cache_write_request_mac_next = cache_write_request_mac_reg;
cache_write_request_ip_next = cache_write_request_ip_reg;
arp_request_ready_next = 1'b0;
arp_request_ip_next = arp_request_ip_reg;
arp_request_operation_next = arp_request_operation_reg;
arp_request_retry_cnt_next = arp_request_retry_cnt_reg;
arp_request_timer_next = arp_request_timer_reg;
arp_response_valid_next = arp_response_valid_reg & ~arp_response_ready;
arp_response_error_next = 1'b0;
arp_response_broadcast_next = 1'b0;
drop_incoming_frame_next = 1'b0;
arp_response_mac_next = 48'd0;
// manage incoming frames
if (filtered_incoming_frame_valid & ~(outgoing_frame_valid_reg & ~outgoing_frame_ready)) begin
// store sender addresses in cache
cache_write_request_valid_next = 1'b1;
cache_write_request_ip_next = incoming_arp_spa;
cache_write_request_mac_next = incoming_arp_sha;
if (incoming_arp_oper_arp_request) begin
if (incoming_arp_tpa == local_ip) begin
// send reply frame to valid incoming request
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = incoming_eth_src_mac;
outgoing_arp_oper_next = ARP_OPER_ARP_REPLY;
outgoing_arp_tha_next = incoming_arp_sha;
outgoing_arp_tpa_next = incoming_arp_spa;
end else begin
// does not match -> drop it
drop_incoming_frame_next = 1'b1;
incoming_frame_ready = outgoing_frame_ready;
if (incoming_frame_valid & incoming_frame_ready) begin
if (incoming_eth_type == 16'h0806 && incoming_arp_htype == 16'h0001 && incoming_arp_ptype == 16'h0800) begin
// store sender addresses in cache
cache_write_request_valid_next = 1'b1;
cache_write_request_ip_next = incoming_arp_spa;
cache_write_request_mac_next = incoming_arp_sha;
if (incoming_arp_oper == ARP_OPER_ARP_REQUEST) begin
// ARP request
if (incoming_arp_tpa == local_ip) begin
// send reply frame to valid incoming request
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = incoming_eth_src_mac;
outgoing_arp_oper_next = ARP_OPER_ARP_REPLY;
outgoing_arp_tha_next = incoming_arp_sha;
outgoing_arp_tpa_next = incoming_arp_spa;
end
end else if (incoming_arp_oper == ARP_OPER_INARP_REPLY) begin
// INARP request
if (incoming_arp_tha == local_mac) begin
// send reply frame to valid incoming request
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = incoming_eth_src_mac;
outgoing_arp_oper_next = ARP_OPER_INARP_REPLY;
outgoing_arp_tha_next = incoming_arp_sha;
outgoing_arp_tpa_next = incoming_arp_spa;
end
end
end else if (incoming_arp_oper_inarp_request) begin
if (incoming_arp_tha == local_mac) begin
// send reply frame to valid incoming request
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = incoming_eth_src_mac;
outgoing_arp_oper_next = ARP_OPER_INARP_REPLY;
outgoing_arp_tha_next = incoming_arp_sha;
outgoing_arp_tpa_next = incoming_arp_spa;
end else begin
// does not match -> drop it
drop_incoming_frame_next = 1'b1;
end
end else begin
// does not match -> drop it
drop_incoming_frame_next = 1'b1;
end
end else if (incoming_frame_valid & ~filtered_incoming_frame_valid) begin
// incoming invalid frame -> drop it
drop_incoming_frame_next = 1'b1;
end
// manage ARP lookup requests
if (~arp_request_operation_reg & ~arp_response_valid) begin
if (arp_request_valid) begin
if (~(arp_request_ip | subnet_mask) == 0) begin
// broadcast address
// (all bits in request IP set where subnet mask is clear)
arp_request_valid_next = 1'b0;
arp_response_broadcast_next = 1'b1;
end else if (((arp_request_ip ^ gateway_ip) & subnet_mask) == 0) begin
// within subnet, look up IP directly
// (no bits differ between request IP and gateway IP where subnet mask is set)
arp_request_valid_next = 1'b1;
arp_request_ip_next = arp_request_ip;
end else begin
// outside of subnet, so look up gateway address
arp_request_valid_next = 1'b1;
arp_request_ip_next = gateway_ip;
end
end
if (cache_query_response_error & ~arp_response_error) begin
arp_request_operation_next = 1'b1;
// send ARP request frame
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = 48'hFF_FF_FF_FF_FF_FF;
outgoing_arp_oper_next = ARP_OPER_ARP_REQUEST;
outgoing_arp_tha_next = 48'h00_00_00_00_00_00;
outgoing_arp_tpa_next = arp_request_ip_reg;
arp_request_retry_cnt_next = REQUEST_RETRY_COUNT-1;
arp_request_timer_next = REQUEST_RETRY_INTERVAL;
end
end else if (arp_request_operation_reg) begin
if (arp_request_operation_reg) begin
arp_request_ready_next = 1'b0;
cache_query_request_valid_next = 1'b1;
arp_request_timer_next = arp_request_timer_reg - 1;
// if we got a response, it will go in the cache, so when the query succeds, we're done
if (cache_query_response_valid & ~cache_query_response_error) begin
if (cache_query_response_valid & ~cache_query_response_error) begin
arp_request_operation_next = 1'b0;
cache_query_request_valid_next = 1'b0;
arp_response_valid_next = 1'b1;
arp_response_error_next = 1'b0;
arp_response_mac_next = cache_query_response_mac;
end
// timer timeout
if (arp_request_timer_reg == 0) begin
@ -371,9 +321,9 @@ always @* begin
// have more retries
// send ARP request frame
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = 48'hFF_FF_FF_FF_FF_FF;
outgoing_eth_dest_mac_next = 48'hffffffffffff;
outgoing_arp_oper_next = ARP_OPER_ARP_REQUEST;
outgoing_arp_tha_next = 48'h00_00_00_00_00_00;
outgoing_arp_tha_next = 48'h000000000000;
outgoing_arp_tpa_next = arp_request_ip_reg;
arp_request_retry_cnt_next = arp_request_retry_cnt_reg - 1;
if (arp_request_retry_cnt_reg > 1) begin
@ -384,7 +334,51 @@ always @* begin
end else begin
// out of retries
arp_request_operation_next = 1'b0;
arp_response_valid_next = 1'b1;
arp_response_error_next = 1'b1;
cache_query_request_valid_next = 1'b0;
end
end
end else begin
arp_request_ready_next = ~arp_response_valid_next;
if (cache_query_request_valid_reg) begin
cache_query_request_valid_next = 1'b1;
if (cache_query_response_valid) begin
if (cache_query_response_error) begin
arp_request_operation_next = 1'b1;
// send ARP request frame
outgoing_frame_valid_next = 1'b1;
outgoing_eth_dest_mac_next = 48'hffffffffffff;
outgoing_arp_oper_next = ARP_OPER_ARP_REQUEST;
outgoing_arp_tha_next = 48'h000000000000;
outgoing_arp_tpa_next = arp_request_ip_reg;
arp_request_retry_cnt_next = REQUEST_RETRY_COUNT-1;
arp_request_timer_next = REQUEST_RETRY_INTERVAL;
end else begin
cache_query_request_valid_next = 1'b0;
arp_response_valid_next = 1'b1;
arp_response_error_next = 1'b0;
arp_response_mac_next = cache_query_response_mac;
end
end
end else if (arp_request_valid & arp_request_ready) begin
if (~(arp_request_ip | subnet_mask) == 0) begin
// broadcast address
// (all bits in request IP set where subnet mask is clear)
arp_response_valid_next = 1'b1;
arp_response_error_next = 1'b0;
arp_response_mac_next = 48'hffffffffffff;
end else if (((arp_request_ip ^ gateway_ip) & subnet_mask) == 0) begin
// within subnet, look up IP directly
// (no bits differ between request IP and gateway IP where subnet mask is set)
cache_query_request_valid_next = 1'b1;
cache_query_request_ip_next = arp_request_ip;
arp_request_ip_next = arp_request_ip;
end else begin
// outside of subnet, so look up gateway address
cache_query_request_valid_next = 1'b1;
cache_query_request_ip_next = gateway_ip;
arp_request_ip_next = gateway_ip;
end
end
end
@ -393,26 +387,25 @@ end
always @(posedge clk) begin
if (rst) begin
outgoing_frame_valid_reg <= 1'b0;
cache_query_request_valid_reg <= 1'b0;
cache_write_request_valid_reg <= 1'b0;
arp_request_valid_reg <= 1'b0;
arp_request_ready_reg <= 1'b0;
arp_request_operation_reg <= 1'b0;
arp_request_retry_cnt_reg <= 6'd0;
arp_request_timer_reg <= 36'd0;
arp_response_error_reg <= 1'b0;
arp_response_broadcast_reg <= 1'b0;
drop_incoming_frame_reg <= 1'b0;
arp_response_valid_reg <= 1'b0;
end else begin
outgoing_frame_valid_reg <= outgoing_frame_valid_next;
cache_query_request_valid_reg <= cache_query_request_valid_next;
cache_write_request_valid_reg <= cache_write_request_valid_next;
arp_request_valid_reg <= arp_request_valid_next;
arp_request_ready_reg <= arp_request_ready_next;
arp_request_operation_reg <= arp_request_operation_next;
arp_request_retry_cnt_reg <= arp_request_retry_cnt_next;
arp_request_timer_reg <= arp_request_timer_next;
arp_response_error_reg <= arp_response_error_next;
arp_response_broadcast_reg <= arp_response_broadcast_next;
drop_incoming_frame_reg <= drop_incoming_frame_next;
arp_response_valid_reg <= arp_response_valid_next;
end
cache_query_request_ip_reg <= cache_query_request_ip_next;
outgoing_eth_dest_mac_reg <= outgoing_eth_dest_mac_next;
outgoing_arp_oper_reg <= outgoing_arp_oper_next;
outgoing_arp_tha_reg <= outgoing_arp_tha_next;
@ -420,6 +413,8 @@ always @(posedge clk) begin
cache_write_request_mac_reg <= cache_write_request_mac_next;
cache_write_request_ip_reg <= cache_write_request_ip_next;
arp_request_ip_reg <= arp_request_ip_next;
arp_response_error_reg <= arp_response_error_next;
arp_response_mac_reg <= arp_response_mac_next;
end
endmodule

View File

@ -27,32 +27,34 @@ THE SOFTWARE.
`timescale 1ns / 1ps
/*
* ARP cache block
* ARP cache
*/
module arp_cache #(
parameter CACHE_ADDR_WIDTH = 2
parameter CACHE_ADDR_WIDTH = 9
)
(
input wire clk,
input wire rst,
/*
* Query cache
* Cache query
*/
input wire query_request_valid,
output wire query_request_ready,
input wire [31:0] query_request_ip,
output wire query_response_valid,
input wire query_response_ready,
output wire query_response_error,
output wire [47:0] query_response_mac,
/*
* Write cache
* Cache write
*/
input wire write_request_valid,
output wire write_request_ready,
input wire [31:0] write_request_ip,
input wire [47:0] write_request_mac,
output wire write_in_progress,
output wire write_complete,
/*
* Configuration
@ -60,118 +62,156 @@ module arp_cache #(
input wire clear_cache
);
// bit LRU cache
reg mem_write = 0;
reg store_query = 0;
reg store_write = 0;
reg [31:0] ip_addr_mem[(2**CACHE_ADDR_WIDTH)-1:0];
reg [47:0] mac_addr_mem[(2**CACHE_ADDR_WIDTH)-1:0];
reg [(2**CACHE_ADDR_WIDTH)-1:0] lru_bit = 0;
reg query_response_valid_reg = 0;
reg query_response_error_reg = 0;
reg [47:0] query_response_mac_reg = 0;
reg write_complete_reg = 0;
localparam [2:0]
WRITE_STATE_IDLE = 0,
WRITE_STATE_SEARCH = 1,
WRITE_STATE_NOTFOUND = 2;
reg [2:0] write_state = WRITE_STATE_IDLE;
reg query_ip_valid_reg = 0, query_ip_valid_next;
reg [31:0] query_ip_reg = 0;
reg write_ip_valid_reg = 0, write_ip_valid_next;
reg [31:0] write_ip_reg = 0;
reg [47:0] write_mac_reg = 0;
reg [CACHE_ADDR_WIDTH-1:0] write_addr = 0;
reg [CACHE_ADDR_WIDTH-1:0] write_ptr = 0;
wire write_state_idle = (write_state == WRITE_STATE_IDLE);
wire write_state_search = (write_state == WRITE_STATE_SEARCH);
wire write_state_notfound = (write_state == WRITE_STATE_NOTFOUND);
reg [CACHE_ADDR_WIDTH-1:0] wr_ptr_reg = {CACHE_ADDR_WIDTH{1'b0}}, wr_ptr_next;
reg [CACHE_ADDR_WIDTH-1:0] rd_ptr_reg = {CACHE_ADDR_WIDTH{1'b0}}, rd_ptr_next;
reg clear_cache_operation = 0;
reg valid_mem[(2**CACHE_ADDR_WIDTH)-1:0];
reg [31:0] ip_addr_mem[(2**CACHE_ADDR_WIDTH)-1:0];
reg [47:0] mac_addr_mem[(2**CACHE_ADDR_WIDTH)-1:0];
reg query_request_ready_reg = 0, query_request_ready_next;
reg query_response_valid_reg = 0, query_response_valid_next;
reg query_response_error_reg = 0, query_response_error_next;
reg [47:0] query_response_mac_reg = 0;
reg write_request_ready_reg = 0, write_request_ready_next;
wire [31:0] query_request_hash;
wire [31:0] write_request_hash;
assign query_request_ready = query_request_ready_reg;
assign query_response_valid = query_response_valid_reg;
assign query_response_error = query_response_error_reg;
assign query_response_mac = query_response_mac_reg;
assign write_in_progress = ~write_state_idle;
assign write_complete = write_complete_reg;
assign write_request_ready = write_request_ready_reg;
wire lru_full = &lru_bit;
lfsr #(
.LFSR_WIDTH(32),
.LFSR_POLY(32'h4c11db7),
.LFSR_CONFIG("GALOIS"),
.LFSR_FEED_FORWARD(0),
.REVERSE(1),
.DATA_WIDTH(32),
.STYLE("AUTO")
)
rd_hash (
.data_in(query_request_ip),
.state_in(32'hffffffff),
.data_out(),
.state_out(query_request_hash)
);
integer i;
lfsr #(
.LFSR_WIDTH(32),
.LFSR_POLY(32'h4c11db7),
.LFSR_CONFIG("GALOIS"),
.LFSR_FEED_FORWARD(0),
.REVERSE(1),
.DATA_WIDTH(32),
.STYLE("AUTO")
)
wr_hash (
.data_in(write_request_ip),
.state_in(32'hffffffff),
.data_out(),
.state_out(write_request_hash)
);
always @* begin
mem_write = 1'b0;
store_query = 1'b0;
store_write = 1'b0;
wr_ptr_next = wr_ptr_reg;
rd_ptr_next = rd_ptr_reg;
query_ip_valid_next = query_ip_valid_reg;
query_request_ready_next = ~query_ip_valid_reg || ~query_request_valid || query_response_ready;
query_response_valid_next = query_response_valid_reg & ~query_response_ready;
query_response_error_next = query_response_error_reg;
if (query_ip_valid_reg && (~query_request_valid || query_response_ready)) begin
query_response_valid_next = 1;
query_ip_valid_next = 0;
if (valid_mem[rd_ptr_reg] && ip_addr_mem[rd_ptr_reg] == query_ip_reg) begin
query_response_error_next = 0;
end else begin
query_response_error_next = 1;
end
end
if (query_request_valid && query_request_ready && (~query_ip_valid_reg || ~query_request_valid || query_response_ready)) begin
store_query = 1;
query_ip_valid_next = 1;
rd_ptr_next = query_request_hash[CACHE_ADDR_WIDTH-1:0];
end
write_ip_valid_next = write_ip_valid_reg;
write_request_ready_next = 1'b1;
if (write_ip_valid_reg) begin
write_ip_valid_next = 0;
mem_write = 1;
end
if (write_request_valid && write_request_ready) begin
store_write = 1;
write_ip_valid_next = 1;
wr_ptr_next = write_request_hash[CACHE_ADDR_WIDTH-1:0];
end
end
always @(posedge clk) begin
if (rst) begin
query_response_valid_reg <= 0;
query_response_error_reg <= 0;
write_complete_reg <= 0;
write_state <= WRITE_STATE_IDLE;
write_addr <= 0;
write_ptr <= 0;
clear_cache_operation <= 1;
lru_bit <= 0;
query_ip_valid_reg <= 1'b0;
query_request_ready_reg <= 1'b0;
query_response_valid_reg <= 1'b0;
write_ip_valid_reg <= 1'b0;
write_request_ready_reg <= 1'b0;
end else begin
write_complete_reg <= 0;
query_response_valid_reg <= 0;
query_response_error_reg <= 0;
query_ip_valid_reg <= query_ip_valid_next;
query_request_ready_reg <= query_request_ready_next;
query_response_valid_reg <= query_response_valid_next;
write_ip_valid_reg <= write_ip_valid_next;
write_request_ready_reg <= write_request_ready_next;
end
// clear LRU bits when full
if (lru_full) begin
lru_bit <= 0;
end
query_response_error_reg <= query_response_error_next;
// fast IP match and readout
if (query_request_valid) begin
query_response_valid_reg <= 1;
query_response_error_reg <= 1;
for (i = 0; i < 2**CACHE_ADDR_WIDTH; i = i + 1) begin
if (ip_addr_mem[i] == query_request_ip) begin
query_response_error_reg <= 0;
query_response_mac_reg <= mac_addr_mem[i];
lru_bit[i] <= 1'b1;
end
end
end
if (store_query) begin
query_ip_reg <= query_request_ip;
end
// manage writes
if (write_state_idle) begin
if (write_request_valid) begin
write_state <= WRITE_STATE_SEARCH;
write_ip_reg <= write_request_ip;
write_mac_reg <= write_request_mac;
end
write_addr <= 0;
end else if (write_state_search) begin
write_addr <= write_addr + 1;
if (&write_addr) begin
write_state <= WRITE_STATE_NOTFOUND;
end
if (ip_addr_mem[write_addr] == write_ip_reg) begin
write_state <= WRITE_STATE_IDLE;
mac_addr_mem[write_addr] <= write_mac_reg;
write_complete_reg <= 1;
end
end else if (write_state_notfound) begin
write_ptr <= write_ptr + 1;
if (~lru_bit[write_ptr]) begin
ip_addr_mem[write_ptr] <= write_ip_reg;
mac_addr_mem[write_ptr] <= write_mac_reg;
write_state <= WRITE_STATE_IDLE;
write_complete_reg <= 1;
end
end
if (store_write) begin
write_ip_reg <= write_request_ip;
write_mac_reg <= write_request_mac;
end
// clear cache
if (clear_cache & ~clear_cache_operation) begin
clear_cache_operation <= 1;
write_addr <= 0;
end
if (clear_cache_operation) begin
write_addr <= write_addr + 1;
ip_addr_mem[write_addr] <= 0;
mac_addr_mem[write_addr] <= 0;
clear_cache_operation <= ~&write_addr;
end
wr_ptr_reg <= wr_ptr_next;
rd_ptr_reg <= rd_ptr_next;
query_response_mac_reg <= mac_addr_mem[rd_ptr_reg];
if (mem_write) begin
valid_mem[wr_ptr_reg] <= 1'b1;
ip_addr_mem[wr_ptr_reg] <= write_ip_reg;
mac_addr_mem[wr_ptr_reg] <= write_mac_reg;
end
end

View File

@ -66,8 +66,10 @@ module ip
* ARP requests
*/
output wire arp_request_valid,
input wire arp_request_ready,
output wire [31:0] arp_request_ip,
input wire arp_response_valid,
output wire arp_response_ready,
input wire arp_response_error,
input wire [47:0] arp_response_mac,
@ -242,20 +244,24 @@ reg input_ip_hdr_ready_reg = 1'b0, input_ip_hdr_ready_next;
reg arp_request_valid_reg = 1'b0, arp_request_valid_next;
reg arp_response_ready_reg = 1'b0, arp_response_ready_next;
reg drop_packet_reg = 1'b0, drop_packet_next;
assign input_ip_hdr_ready = input_ip_hdr_ready_reg;
assign input_ip_payload_tready = outgoing_ip_payload_tready | drop_packet_reg;
assign arp_request_valid = arp_request_valid_reg | (input_ip_hdr_valid & ~input_ip_hdr_ready_reg);
assign arp_request_valid = arp_request_valid_reg;
assign arp_request_ip = input_ip_dest_ip;
assign arp_response_ready = arp_response_ready_reg;
assign tx_error_arp_failed = arp_response_error;
always @* begin
state_next = STATE_IDLE;
arp_request_valid_next = 1'b0;
arp_request_valid_next = arp_request_valid_reg & ~arp_request_ready;
arp_response_ready_next = 1'b0;
drop_packet_next = 1'b0;
input_ip_hdr_ready_next = 1'b0;
@ -269,26 +275,25 @@ always @* begin
if (input_ip_hdr_valid) begin
// initiate ARP request
arp_request_valid_next = 1'b1;
arp_response_ready_next = 1'b1;
state_next = STATE_ARP_QUERY;
end else begin
state_next = STATE_IDLE;
end
end
STATE_ARP_QUERY: begin
arp_request_valid_next = 1;
arp_response_ready_next = 1'b1;
if (arp_response_valid) begin
// wait for ARP reponse
if (arp_response_error) begin
// did not get MAC address; drop packet
input_ip_hdr_ready_next = 1'b1;
arp_request_valid_next = 1'b0;
drop_packet_next = 1'b1;
state_next = STATE_WAIT_PACKET;
end else begin
// got MAC address; send packet
input_ip_hdr_ready_next = 1'b1;
arp_request_valid_next = 1'b0;
outgoing_ip_hdr_valid_next = 1'b1;
outgoing_eth_dest_mac_next = arp_response_mac;
state_next = STATE_WAIT_PACKET;
@ -314,6 +319,7 @@ always @(posedge clk) begin
if (rst) begin
state_reg <= STATE_IDLE;
arp_request_valid_reg <= 1'b0;
arp_response_ready_reg <= 1'b0;
drop_packet_reg <= 1'b0;
input_ip_hdr_ready_reg <= 1'b0;
outgoing_ip_hdr_valid_reg <= 1'b0;
@ -321,6 +327,7 @@ always @(posedge clk) begin
state_reg <= state_next;
arp_request_valid_reg <= arp_request_valid_next;
arp_response_ready_reg <= arp_response_ready_next;
drop_packet_reg <= drop_packet_next;
input_ip_hdr_ready_reg <= input_ip_hdr_ready_next;

View File

@ -68,8 +68,10 @@ module ip_64
* ARP requests
*/
output wire arp_request_valid,
input wire arp_request_ready,
output wire [31:0] arp_request_ip,
input wire arp_response_valid,
output wire arp_response_ready,
input wire arp_response_error,
input wire [47:0] arp_response_mac,
@ -246,25 +248,28 @@ ip_eth_tx_64_inst (
.error_payload_early_termination(tx_error_payload_early_termination)
);
reg input_ip_hdr_ready_reg = 1'b0, input_ip_hdr_ready_next;
reg arp_request_valid_reg = 1'b0, arp_request_valid_next;
reg arp_response_ready_reg = 1'b0, arp_response_ready_next;
reg drop_packet_reg = 1'b0, drop_packet_next;
assign input_ip_hdr_ready = input_ip_hdr_ready_reg;
assign input_ip_payload_tready = outgoing_ip_payload_tready | drop_packet_reg;
assign arp_request_valid = arp_request_valid_reg | (input_ip_hdr_valid & ~input_ip_hdr_ready_reg);
assign arp_request_valid = arp_request_valid_reg;
assign arp_request_ip = input_ip_dest_ip;
assign arp_response_ready = arp_response_ready_reg;
assign tx_error_arp_failed = arp_response_error;
always @* begin
state_next = STATE_IDLE;
arp_request_valid_next = 1'b0;
arp_request_valid_next = arp_request_valid_reg & ~arp_request_ready;
arp_response_ready_next = 1'b0;
drop_packet_next = 1'b0;
input_ip_hdr_ready_next = 1'b0;
@ -278,26 +283,25 @@ always @* begin
if (input_ip_hdr_valid) begin
// initiate ARP request
arp_request_valid_next = 1'b1;
arp_response_ready_next = 1'b1;
state_next = STATE_ARP_QUERY;
end else begin
state_next = STATE_IDLE;
end
end
STATE_ARP_QUERY: begin
arp_request_valid_next = 1'b1;
arp_response_ready_next = 1'b1;
if (arp_response_valid) begin
// wait for ARP reponse
if (arp_response_error) begin
// did not get MAC address; drop packet
input_ip_hdr_ready_next = 1'b1;
arp_request_valid_next = 1'b0;
drop_packet_next = 1'b1;
state_next = STATE_WAIT_PACKET;
end else begin
// got MAC address; send packet
input_ip_hdr_ready_next = 1'b1;
arp_request_valid_next = 1'b0;
outgoing_ip_hdr_valid_next = 1'b1;
outgoing_eth_dest_mac_next = arp_response_mac;
state_next = STATE_WAIT_PACKET;
@ -323,6 +327,7 @@ always @(posedge clk) begin
if (rst) begin
state_reg <= STATE_IDLE;
arp_request_valid_reg <= 1'b0;
arp_response_ready_reg <= 1'b0;
drop_packet_reg <= 1'b0;
input_ip_hdr_ready_reg <= 1'b0;
outgoing_ip_hdr_valid_reg <= 1'b0;
@ -330,6 +335,7 @@ always @(posedge clk) begin
state_reg <= state_next;
arp_request_valid_reg <= arp_request_valid_next;
arp_response_ready_reg <= arp_response_ready_next;
drop_packet_reg <= drop_packet_next;
input_ip_hdr_ready_reg <= input_ip_hdr_ready_next;

View File

@ -30,7 +30,7 @@ THE SOFTWARE.
* IPv4 and ARP block, ethernet frame interface
*/
module ip_complete #(
parameter ARP_CACHE_ADDR_WIDTH = 2,
parameter ARP_CACHE_ADDR_WIDTH = 9,
parameter ARP_REQUEST_RETRY_COUNT = 4,
parameter ARP_REQUEST_RETRY_INTERVAL = 125000000*2,
parameter ARP_REQUEST_TIMEOUT = 125000000*30
@ -141,8 +141,10 @@ This module integrates the IP and ARP modules for a complete IP stack
*/
wire arp_request_valid;
wire arp_request_ready;
wire [31:0] arp_request_ip;
wire arp_response_valid;
wire arp_response_ready;
wire arp_response_error;
wire [47:0] arp_response_mac;
@ -361,8 +363,10 @@ ip_inst (
.input_ip_payload_tuser(input_ip_payload_tuser),
// ARP requests
.arp_request_valid(arp_request_valid),
.arp_request_ready(arp_request_ready),
.arp_request_ip(arp_request_ip),
.arp_response_valid(arp_response_valid),
.arp_response_ready(arp_response_ready),
.arp_response_error(arp_response_error),
.arp_response_mac(arp_response_mac),
// Status
@ -415,8 +419,10 @@ arp_inst (
.output_eth_payload_tuser(arp_tx_eth_payload_tuser),
// ARP requests
.arp_request_valid(arp_request_valid),
.arp_request_ready(arp_request_ready),
.arp_request_ip(arp_request_ip),
.arp_response_valid(arp_response_valid),
.arp_response_ready(arp_response_ready),
.arp_response_error(arp_response_error),
.arp_response_mac(arp_response_mac),
// Configuration

View File

@ -30,7 +30,7 @@ THE SOFTWARE.
* IPv4 and ARP block, ethernet frame interface (64 bit datapath)
*/
module ip_complete_64 #(
parameter ARP_CACHE_ADDR_WIDTH = 2,
parameter ARP_CACHE_ADDR_WIDTH = 9,
parameter ARP_REQUEST_RETRY_COUNT = 4,
parameter ARP_REQUEST_RETRY_INTERVAL = 156250000*2,
parameter ARP_REQUEST_TIMEOUT = 156250000*30
@ -145,8 +145,10 @@ This module integrates the IP and ARP modules for a complete IP stack
*/
wire arp_request_valid;
wire arp_request_ready;
wire [31:0] arp_request_ip;
wire arp_response_valid;
wire arp_response_ready;
wire arp_response_error;
wire [47:0] arp_response_mac;
@ -378,8 +380,10 @@ ip_inst (
.input_ip_payload_tuser(input_ip_payload_tuser),
// ARP requests
.arp_request_valid(arp_request_valid),
.arp_request_ready(arp_request_ready),
.arp_request_ip(arp_request_ip),
.arp_response_valid(arp_response_valid),
.arp_response_ready(arp_response_ready),
.arp_response_error(arp_response_error),
.arp_response_mac(arp_response_mac),
// Status
@ -434,8 +438,10 @@ arp_inst (
.output_eth_payload_tuser(arp_tx_eth_payload_tuser),
// ARP requests
.arp_request_valid(arp_request_valid),
.arp_request_ready(arp_request_ready),
.arp_request_ip(arp_request_ip),
.arp_response_valid(arp_response_valid),
.arp_response_ready(arp_response_ready),
.arp_response_error(arp_response_error),
.arp_response_mac(arp_response_mac),
// Configuration

View File

@ -30,7 +30,7 @@ THE SOFTWARE.
* IPv4 and ARP block with UDP support, ethernet frame interface
*/
module udp_complete #(
parameter ARP_CACHE_ADDR_WIDTH = 2,
parameter ARP_CACHE_ADDR_WIDTH = 9,
parameter ARP_REQUEST_RETRY_COUNT = 4,
parameter ARP_REQUEST_RETRY_INTERVAL = 125000000*2,
parameter ARP_REQUEST_TIMEOUT = 125000000*30,

View File

@ -30,7 +30,7 @@ THE SOFTWARE.
* IPv4 and ARP block with UDP support, ethernet frame interface (64 bit datapath)
*/
module udp_complete_64 #(
parameter ARP_CACHE_ADDR_WIDTH = 2,
parameter ARP_CACHE_ADDR_WIDTH = 9,
parameter ARP_REQUEST_RETRY_COUNT = 4,
parameter ARP_REQUEST_RETRY_INTERVAL = 125000000*2,
parameter ARP_REQUEST_TIMEOUT = 125000000*30,

View File

@ -26,6 +26,7 @@ THE SOFTWARE.
from myhdl import *
import os
import axis_ep
import eth_ep
import arp_ep
@ -35,6 +36,7 @@ testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("../rtl/arp_cache.v")
srcs.append("../rtl/arp_eth_rx.v")
srcs.append("../rtl/arp_eth_tx.v")
@ -65,6 +67,7 @@ def bench():
arp_request_valid = Signal(bool(0))
arp_request_ip = Signal(intbv(0)[32:])
arp_response_ready = Signal(bool(0))
local_mac = Signal(intbv(0)[48:])
local_ip = Signal(intbv(0)[32:])
@ -85,17 +88,18 @@ def bench():
output_eth_payload_tlast = Signal(bool(0))
output_eth_payload_tuser = Signal(bool(0))
arp_request_ready = Signal(bool(0))
arp_response_valid = Signal(bool(0))
arp_response_error = Signal(bool(0))
arp_response_mac = Signal(intbv(0)[48:])
# sources and sinks
source_pause = Signal(bool(0))
sink_pause = Signal(bool(0))
eth_source_pause = Signal(bool(0))
eth_sink_pause = Signal(bool(0))
source = eth_ep.EthFrameSource()
eth_source = eth_ep.EthFrameSource()
source_logic = source.create_logic(
eth_source_logic = eth_source.create_logic(
clk,
rst,
eth_hdr_ready=input_eth_hdr_ready,
@ -108,13 +112,13 @@ def bench():
eth_payload_tready=input_eth_payload_tready,
eth_payload_tlast=input_eth_payload_tlast,
eth_payload_tuser=input_eth_payload_tuser,
pause=source_pause,
name='source'
pause=eth_source_pause,
name='eth_source'
)
sink = eth_ep.EthFrameSink()
eth_sink = eth_ep.EthFrameSink()
sink_logic = sink.create_logic(
eth_sink_logic = eth_sink.create_logic(
clk,
rst,
eth_hdr_ready=output_eth_hdr_ready,
@ -127,8 +131,30 @@ def bench():
eth_payload_tready=output_eth_payload_tready,
eth_payload_tlast=output_eth_payload_tlast,
eth_payload_tuser=output_eth_payload_tuser,
pause=sink_pause,
name='sink'
pause=eth_sink_pause,
name='eth_sink'
)
arp_request_source = axis_ep.AXIStreamSource()
arp_request_source_logic = arp_request_source.create_logic(
clk,
rst,
tdata=(arp_request_ip,),
tvalid=arp_request_valid,
tready=arp_request_ready,
name='arp_request_source'
)
arp_response_sink = axis_ep.AXIStreamSink()
arp_response_sink_logic = arp_response_sink.create_logic(
clk,
rst,
tdata=(arp_response_error, arp_response_mac),
tvalid=arp_response_valid,
tready=arp_response_ready,
name='arp_response_sink'
)
# DUT
@ -164,8 +190,10 @@ def bench():
output_eth_payload_tuser=output_eth_payload_tuser,
arp_request_valid=arp_request_valid,
arp_request_ready=arp_request_ready,
arp_request_ip=arp_request_ip,
arp_response_valid=arp_response_valid,
arp_response_ready=arp_response_ready,
arp_response_error=arp_response_error,
arp_response_mac=arp_response_mac,
@ -214,14 +242,13 @@ def bench():
test_frame.arp_spa = 0xc0a80164
test_frame.arp_tha = 0x000000000000
test_frame.arp_tpa = 0xc0a80165
source.send(test_frame.build_eth())
eth_source.send(test_frame.build_eth())
yield clk.posedge
yield output_eth_payload_tlast.posedge
yield clk.posedge
yield clk.posedge
while eth_sink.empty():
yield clk.posedge
rx_frame = sink.recv()
rx_frame = eth_sink.recv()
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(rx_frame)
@ -244,15 +271,15 @@ def bench():
print("test 2: Cached read")
current_test.next = 2
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xc0a80164
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xc0a80164,)])
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0x5A5152535455
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0x5A5152535455
yield delay(100)
@ -260,18 +287,13 @@ def bench():
print("test 3: Unached read")
current_test.next = 3
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xc0a80166
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xc0a80166,)])
# wait for ARP request packet
yield output_eth_payload_tlast.posedge
yield clk.posedge
yield clk.posedge
while eth_sink.empty():
yield clk.posedge
rx_frame = sink.recv()
rx_frame = eth_sink.recv()
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(rx_frame)
@ -302,13 +324,17 @@ def bench():
test_frame.arp_spa = 0xc0a80166
test_frame.arp_tha = 0xDAD1D2D3D4D5
test_frame.arp_tpa = 0xc0a80165
source.send(test_frame.build_eth())
eth_source.send(test_frame.build_eth())
yield clk.posedge
# wait for lookup
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0x6A6162636465
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0x6A6162636465
yield delay(100)
@ -316,18 +342,13 @@ def bench():
print("test 4: Unached read, outside of subnet")
current_test.next = 4
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0x08080808
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0x08080808,)])
# wait for ARP request packet
yield output_eth_payload_tlast.posedge
yield clk.posedge
yield clk.posedge
while eth_sink.empty():
yield clk.posedge
rx_frame = sink.recv()
rx_frame = eth_sink.recv()
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(rx_frame)
@ -358,13 +379,17 @@ def bench():
test_frame.arp_spa = 0xc0a80101
test_frame.arp_tha = 0xDAD1D2D3D4D5
test_frame.arp_tpa = 0xc0a80165
source.send(test_frame.build_eth())
eth_source.send(test_frame.build_eth())
yield clk.posedge
# wait for lookup
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0xAABBCCDDEEFF
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0xAABBCCDDEEFF
yield delay(100)
@ -372,20 +397,20 @@ def bench():
print("test 5: Unached read, timeout")
current_test.next = 5
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xc0a80167
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xc0a80167,)])
yield arp_response_valid.posedge
assert bool(arp_response_error)
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert err
# check for 4 ARP requests
assert sink.count() == 4
assert eth_sink.count() == 4
while not sink.empty():
rx_frame = sink.recv()
while not eth_sink.empty():
rx_frame = eth_sink.recv()
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(rx_frame)
@ -410,26 +435,26 @@ def bench():
current_test.next = 6
# subnet broadcast
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xc0a801FF
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xc0a801ff,)])
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0xFFFFFFFFFFFF
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0xffffffffffff
# general broadcast
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xFFFFFFFF
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xffffffff,)])
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0xFFFFFFFFFFFF
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0xffffffffffff
yield delay(100)

View File

@ -50,6 +50,7 @@ reg output_eth_payload_tready = 0;
reg arp_request_valid = 0;
reg [31:0] arp_request_ip = 0;
reg arp_response_ready = 0;
reg [47:0] local_mac = 0;
reg [31:0] local_ip = 0;
@ -70,6 +71,7 @@ wire output_eth_payload_tvalid;
wire output_eth_payload_tlast;
wire output_eth_payload_tuser;
wire arp_request_ready;
wire arp_response_valid;
wire arp_response_error;
wire [47:0] arp_response_mac;
@ -92,6 +94,7 @@ initial begin
output_eth_payload_tready,
arp_request_valid,
arp_request_ip,
arp_response_ready,
local_mac,
local_ip,
gateway_ip,
@ -109,6 +112,7 @@ initial begin
output_eth_payload_tvalid,
output_eth_payload_tlast,
output_eth_payload_tuser,
arp_request_ready,
arp_response_valid,
arp_response_error,
arp_response_mac
@ -152,8 +156,10 @@ UUT (
.output_eth_payload_tuser(output_eth_payload_tuser),
// ARP requests
.arp_request_valid(arp_request_valid),
.arp_request_ready(arp_request_ready),
.arp_request_ip(arp_request_ip),
.arp_response_valid(arp_response_valid),
.arp_response_ready(arp_response_ready),
.arp_response_error(arp_response_error),
.arp_response_mac(arp_response_mac),
// Configuration

View File

@ -26,6 +26,7 @@ THE SOFTWARE.
from myhdl import *
import os
import axis_ep
import eth_ep
import arp_ep
@ -35,6 +36,7 @@ testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("../rtl/arp_cache.v")
srcs.append("../rtl/arp_eth_rx_64.v")
srcs.append("../rtl/arp_eth_tx_64.v")
@ -66,6 +68,7 @@ def bench():
arp_request_valid = Signal(bool(0))
arp_request_ip = Signal(intbv(0)[32:])
arp_response_ready = Signal(bool(0))
local_mac = Signal(intbv(0)[48:])
local_ip = Signal(intbv(0)[32:])
@ -87,17 +90,18 @@ def bench():
output_eth_payload_tlast = Signal(bool(0))
output_eth_payload_tuser = Signal(bool(0))
arp_request_ready = Signal(bool(0))
arp_response_valid = Signal(bool(0))
arp_response_error = Signal(bool(0))
arp_response_mac = Signal(intbv(0)[48:])
# sources and sinks
source_pause = Signal(bool(0))
sink_pause = Signal(bool(0))
eth_source_pause = Signal(bool(0))
eth_sink_pause = Signal(bool(0))
source = eth_ep.EthFrameSource()
eth_source = eth_ep.EthFrameSource()
source_logic = source.create_logic(
eth_source_logic = eth_source.create_logic(
clk,
rst,
eth_hdr_ready=input_eth_hdr_ready,
@ -111,13 +115,13 @@ def bench():
eth_payload_tready=input_eth_payload_tready,
eth_payload_tlast=input_eth_payload_tlast,
eth_payload_tuser=input_eth_payload_tuser,
pause=source_pause,
name='source'
pause=eth_source_pause,
name='eth_source'
)
sink = eth_ep.EthFrameSink()
eth_sink = eth_ep.EthFrameSink()
sink_logic = sink.create_logic(
eth_sink_logic = eth_sink.create_logic(
clk,
rst,
eth_hdr_ready=output_eth_hdr_ready,
@ -131,8 +135,30 @@ def bench():
eth_payload_tready=output_eth_payload_tready,
eth_payload_tlast=output_eth_payload_tlast,
eth_payload_tuser=output_eth_payload_tuser,
pause=sink_pause,
name='sink'
pause=eth_sink_pause,
name='eth_sink'
)
arp_request_source = axis_ep.AXIStreamSource()
arp_request_source_logic = arp_request_source.create_logic(
clk,
rst,
tdata=(arp_request_ip,),
tvalid=arp_request_valid,
tready=arp_request_ready,
name='arp_request_source'
)
arp_response_sink = axis_ep.AXIStreamSink()
arp_response_sink_logic = arp_response_sink.create_logic(
clk,
rst,
tdata=(arp_response_error, arp_response_mac),
tvalid=arp_response_valid,
tready=arp_response_ready,
name='arp_response_sink'
)
# DUT
@ -170,8 +196,10 @@ def bench():
output_eth_payload_tuser=output_eth_payload_tuser,
arp_request_valid=arp_request_valid,
arp_request_ready=arp_request_ready,
arp_request_ip=arp_request_ip,
arp_response_valid=arp_response_valid,
arp_response_ready=arp_response_ready,
arp_response_error=arp_response_error,
arp_response_mac=arp_response_mac,
@ -220,14 +248,13 @@ def bench():
test_frame.arp_spa = 0xc0a80164
test_frame.arp_tha = 0x000000000000
test_frame.arp_tpa = 0xc0a80165
source.send(test_frame.build_eth())
eth_source.send(test_frame.build_eth())
yield clk.posedge
yield output_eth_payload_tlast.posedge
yield clk.posedge
yield clk.posedge
while eth_sink.empty():
yield clk.posedge
rx_frame = sink.recv()
rx_frame = eth_sink.recv()
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(rx_frame)
@ -250,15 +277,15 @@ def bench():
print("test 2: Cached read")
current_test.next = 2
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xc0a80164
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xc0a80164,)])
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0x5A5152535455
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0x5A5152535455
yield delay(100)
@ -266,18 +293,13 @@ def bench():
print("test 3: Unached read")
current_test.next = 3
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xc0a80166
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xc0a80166,)])
# wait for ARP request packet
yield output_eth_payload_tlast.posedge
yield clk.posedge
yield clk.posedge
while eth_sink.empty():
yield clk.posedge
rx_frame = sink.recv()
rx_frame = eth_sink.recv()
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(rx_frame)
@ -308,13 +330,17 @@ def bench():
test_frame.arp_spa = 0xc0a80166
test_frame.arp_tha = 0xDAD1D2D3D4D5
test_frame.arp_tpa = 0xc0a80165
source.send(test_frame.build_eth())
eth_source.send(test_frame.build_eth())
yield clk.posedge
# wait for lookup
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0x6A6162636465
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0x6A6162636465
yield delay(100)
@ -322,18 +348,13 @@ def bench():
print("test 4: Unached read, outside of subnet")
current_test.next = 4
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0x08080808
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0x08080808,)])
# wait for ARP request packet
yield output_eth_payload_tlast.posedge
yield clk.posedge
yield clk.posedge
while eth_sink.empty():
yield clk.posedge
rx_frame = sink.recv()
rx_frame = eth_sink.recv()
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(rx_frame)
@ -364,13 +385,17 @@ def bench():
test_frame.arp_spa = 0xc0a80101
test_frame.arp_tha = 0xDAD1D2D3D4D5
test_frame.arp_tpa = 0xc0a80165
source.send(test_frame.build_eth())
eth_source.send(test_frame.build_eth())
yield clk.posedge
# wait for lookup
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0xAABBCCDDEEFF
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0xAABBCCDDEEFF
yield delay(100)
@ -378,20 +403,20 @@ def bench():
print("test 5: Unached read, timeout")
current_test.next = 5
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xc0a80167
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xc0a80167,)])
yield arp_response_valid.posedge
assert bool(arp_response_error)
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert err
# check for 4 ARP requests
assert sink.count() == 4
assert eth_sink.count() == 4
while not sink.empty():
rx_frame = sink.recv()
while not eth_sink.empty():
rx_frame = eth_sink.recv()
check_frame = arp_ep.ARPFrame()
check_frame.parse_eth(rx_frame)
@ -416,26 +441,26 @@ def bench():
current_test.next = 6
# subnet broadcast
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xc0a801FF
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xc0a801ff,)])
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0xFFFFFFFFFFFF
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0xffffffffffff
# general broadcast
yield clk.posedge
arp_request_valid.next = True
arp_request_ip.next = 0xFFFFFFFF
yield clk.posedge
arp_request_valid.next = False
arp_request_source.send([(0xffffffff,)])
yield arp_response_valid.posedge
assert not bool(arp_response_error)
assert int(arp_response_mac) == 0xFFFFFFFFFFFF
while arp_response_sink.empty():
yield clk.posedge
err, mac = arp_response_sink.recv().data[0]
assert not err
assert mac == 0xffffffffffff
yield delay(100)

View File

@ -51,6 +51,7 @@ reg output_eth_payload_tready = 0;
reg arp_request_valid = 0;
reg [31:0] arp_request_ip = 0;
reg arp_response_ready = 0;
reg [47:0] local_mac = 0;
reg [31:0] local_ip = 0;
@ -72,6 +73,7 @@ wire output_eth_payload_tvalid;
wire output_eth_payload_tlast;
wire output_eth_payload_tuser;
wire arp_request_ready;
wire arp_response_valid;
wire arp_response_error;
wire [47:0] arp_response_mac;
@ -95,6 +97,7 @@ initial begin
output_eth_payload_tready,
arp_request_valid,
arp_request_ip,
arp_response_ready,
local_mac,
local_ip,
gateway_ip,
@ -113,6 +116,7 @@ initial begin
output_eth_payload_tvalid,
output_eth_payload_tlast,
output_eth_payload_tuser,
arp_request_ready,
arp_response_valid,
arp_response_error,
arp_response_mac
@ -158,8 +162,10 @@ UUT (
.output_eth_payload_tuser(output_eth_payload_tuser),
// ARP requests
.arp_request_valid(arp_request_valid),
.arp_request_ready(arp_request_ready),
.arp_request_ip(arp_request_ip),
.arp_response_valid(arp_response_valid),
.arp_response_ready(arp_response_ready),
.arp_response_error(arp_response_error),
.arp_response_mac(arp_response_mac),
// Configuration

View File

@ -26,12 +26,15 @@ THE SOFTWARE.
from myhdl import *
import os
import axis_ep
module = 'arp_cache'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
@ -48,6 +51,8 @@ def bench():
query_request_valid = Signal(bool(0))
query_request_ip = Signal(intbv(0)[32:])
query_response_ready = Signal(bool(0))
write_request_valid = Signal(bool(0))
write_request_ip = Signal(intbv(0)[32:])
write_request_mac = Signal(intbv(0)[48:])
@ -55,12 +60,55 @@ def bench():
clear_cache = Signal(bool(0))
# Outputs
query_request_ready = Signal(bool(0))
query_response_valid = Signal(bool(0))
query_response_error = Signal(bool(0))
query_response_mac = Signal(intbv(0)[48:])
write_in_progress = Signal(bool(0))
write_complete = Signal(bool(0))
write_request_ready = Signal(bool(0))
# sources and sinks
query_request_source_pause = Signal(bool(0))
query_response_sink_pause = Signal(bool(0))
write_request_source_pause = Signal(bool(0))
query_request_source = axis_ep.AXIStreamSource()
query_request_source_logic = query_request_source.create_logic(
clk,
rst,
tdata=(query_request_ip,),
tvalid=query_request_valid,
tready=query_request_ready,
pause=query_request_source_pause,
name='query_request_source'
)
query_response_sink = axis_ep.AXIStreamSink()
query_response_sink_logic = query_response_sink.create_logic(
clk,
rst,
tdata=(query_response_mac,),
tvalid=query_response_valid,
tready=query_response_ready,
tuser=query_response_error,
pause=query_response_sink_pause,
name='query_response_sink'
)
write_request_source = axis_ep.AXIStreamSource()
write_request_source_logic = write_request_source.create_logic(
clk,
rst,
tdata=(write_request_ip, write_request_mac),
tvalid=write_request_valid,
tready=write_request_ready,
pause=write_request_source_pause,
name='write_request_source'
)
# DUT
if os.system(build_cmd):
@ -73,16 +121,18 @@ def bench():
current_test=current_test,
query_request_valid=query_request_valid,
query_request_ready=query_request_ready,
query_request_ip=query_request_ip,
query_response_valid=query_response_valid,
query_response_ready=query_response_ready,
query_response_error=query_response_error,
query_response_mac=query_response_mac,
write_request_valid=write_request_valid,
write_request_ready=write_request_ready,
write_request_ip=write_request_ip,
write_request_mac=write_request_mac,
write_in_progress=write_in_progress,
write_complete=write_complete,
clear_cache=clear_cache
)
@ -107,24 +157,13 @@ def bench():
current_test.next = 1
yield clk.posedge
write_request_valid.next = True
write_request_ip.next = 0xc0a80111
write_request_mac.next = 0x0000c0a80111
yield clk.posedge
write_request_valid.next = False
write_request_source.send([(0xc0a80111, 0x0000c0a80111)])
write_request_source.send([(0xc0a80112, 0x0000c0a80112)])
yield write_complete.posedge
yield clk.posedge
yield delay(100)
yield clk.posedge
write_request_valid.next = True
write_request_ip.next = 0xc0a80112
write_request_mac.next = 0x0000c0a80112
yield clk.posedge
write_request_valid.next = False
yield write_complete.posedge
yield clk.posedge
while not write_request_source.empty():
yield clk.posedge
yield delay(100)
@ -133,71 +172,47 @@ def bench():
current_test.next = 2
yield clk.posedge
query_request_valid.next = True
query_request_ip.next = 0xc0a80111
yield clk.posedge
query_request_valid.next = False
query_request_source.send([(0xc0a80111, )])
query_request_source.send([(0xc0a80112, )])
query_request_source.send([(0xc0a80113, )])
yield query_response_valid.posedge
assert not bool(query_response_error)
assert int(query_response_mac) == 0x0000c0a80111
while query_response_sink.empty():
yield clk.posedge
yield clk.posedge
query_request_valid.next = True
query_request_ip.next = 0xc0a80112
yield clk.posedge
query_request_valid.next = False
resp = query_response_sink.recv()
assert resp.data[0][0] == 0x0000c0a80111
assert not resp.user[0]
yield query_response_valid.posedge
assert not bool(query_response_error)
assert int(query_response_mac) == 0x0000c0a80112
while query_response_sink.empty():
yield clk.posedge
resp = query_response_sink.recv()
assert resp.data[0][0] == 0x0000c0a80112
assert not resp.user[0]
# not in cache; was not written
yield clk.posedge
query_request_valid.next = True
query_request_ip.next = 0xc0a80113
yield clk.posedge
query_request_valid.next = False
while query_response_sink.empty():
yield clk.posedge
yield query_response_valid.posedge
assert bool(query_response_error)
resp = query_response_sink.recv()
assert resp.user[0]
yield delay(100)
raise StopSimulation
yield clk.posedge
print("test 3: write more")
current_test.next = 3
yield clk.posedge
write_request_valid.next = True
write_request_ip.next = 0xc0a80121
write_request_mac.next = 0x0000c0a80121
yield clk.posedge
write_request_valid.next = False
yield write_complete.posedge
yield clk.posedge
yield clk.posedge
write_request_valid.next = True
write_request_ip.next = 0xc0a80122
write_request_mac.next = 0x0000c0a80122
yield clk.posedge
write_request_valid.next = False
yield write_complete.posedge
yield clk.posedge
write_request_source.send([(0xc0a80121, 0x0000c0a80121)])
write_request_source.send([(0xc0a80122, 0x0000c0a80122)])
# overwrites 0xc0a80121 due to LRU
yield clk.posedge
write_request_valid.next = True
write_request_ip.next = 0xc0a80123
write_request_mac.next = 0x0000c0a80123
yield clk.posedge
write_request_valid.next = False
write_request_source.send([(0xc0a80123, 0x0000c0a80123)])
yield write_complete.posedge
yield clk.posedge
while not write_request_source.empty():
yield clk.posedge
yield delay(100)
@ -206,59 +221,61 @@ def bench():
current_test.next = 4
yield clk.posedge
query_request_valid.next = True
query_request_ip.next = 0xc0a80111
yield clk.posedge
query_request_valid.next = False
query_request_source.send([(0xc0a80111, )])
yield query_response_valid.posedge
assert not bool(query_response_error)
assert int(query_response_mac) == 0x0000c0a80111
while query_response_sink.empty():
yield clk.posedge
resp = query_response_sink.recv()
assert resp.data[0][0] == 0x0000c0a80111
assert not resp.user[0]
yield clk.posedge
query_request_valid.next = True
query_request_ip.next = 0xc0a80112
yield clk.posedge
query_request_valid.next = False
query_request_source.send([(0xc0a80112, )])
yield query_response_valid.posedge
assert not bool(query_response_error)
assert int(query_response_mac) == 0x0000c0a80112
while query_response_sink.empty():
yield clk.posedge
resp = query_response_sink.recv()
assert resp.data[0][0] == 0x0000c0a80112
assert not resp.user[0]
# not in cache; was overwritten
yield clk.posedge
query_request_valid.next = True
query_request_ip.next = 0xc0a80121
yield clk.posedge
query_request_valid.next = False
query_request_source.send([(0xc0a80121, )])
yield query_response_valid.posedge
assert bool(query_response_error)
while query_response_sink.empty():
yield clk.posedge
resp = query_response_sink.recv()
assert resp.user[0]
yield clk.posedge
query_request_valid.next = True
query_request_ip.next = 0xc0a80122
yield clk.posedge
query_request_valid.next = False
query_request_source.send([(0xc0a80122, )])
yield query_response_valid.posedge
assert not bool(query_response_error)
assert int(query_response_mac) == 0x0000c0a80122
while query_response_sink.empty():
yield clk.posedge
resp = query_response_sink.recv()
assert resp.data[0][0] == 0x0000c0a80122
assert not resp.user[0]
yield clk.posedge
query_request_valid.next = True
query_request_ip.next = 0xc0a80123
yield clk.posedge
query_request_valid.next = False
query_request_source.send([(0xc0a80123, )])
yield query_response_valid.posedge
assert not bool(query_response_error)
assert int(query_response_mac) == 0x0000c0a80123
while query_response_sink.empty():
yield clk.posedge
resp = query_response_sink.recv()
assert resp.data[0][0] == 0x0000c0a80123
assert not resp.user[0]
# LRU reset by previous operation
yield delay(100)
raise StopSimulation
yield clk.posedge
print("test 5: LRU test")
current_test.next = 5

View File

@ -39,6 +39,8 @@ reg [7:0] current_test = 0;
reg query_request_valid = 0;
reg [31:0] query_request_ip = 0;
reg query_response_ready = 0;
reg write_request_valid = 0;
reg [31:0] write_request_ip = 0;
reg [47:0] write_request_mac = 0;
@ -46,12 +48,13 @@ reg [47:0] write_request_mac = 0;
reg clear_cache = 0;
// Outputs
wire query_request_ready;
wire query_response_valid;
wire query_response_error;
wire [47:0] query_response_mac;
wire write_in_progress;
wire write_complete;
wire write_request_ready;
initial begin
// myhdl integration
@ -61,17 +64,18 @@ initial begin
current_test,
query_request_valid,
query_request_ip,
query_response_ready,
write_request_valid,
write_request_ip,
write_request_mac,
clear_cache
);
$to_myhdl(
query_request_ready,
query_response_valid,
query_response_error,
query_response_mac,
write_in_progress,
write_complete
write_request_ready
);
// dump file
@ -87,16 +91,17 @@ UUT (
.rst(rst),
// Query cache
.query_request_valid(query_request_valid),
.query_request_ready(query_request_ready),
.query_request_ip(query_request_ip),
.query_response_valid(query_response_valid),
.query_response_ready(query_response_ready),
.query_response_error(query_response_error),
.query_response_mac(query_response_mac),
// Write cache
.write_request_valid(write_request_valid),
.write_request_ready(write_request_ready),
.write_request_ip(write_request_ip),
.write_request_mac(write_request_mac),
.write_in_progress(write_in_progress),
.write_complete(write_complete),
// Configuration
.clear_cache(clear_cache)
);

View File

@ -26,6 +26,7 @@ THE SOFTWARE.
from myhdl import *
import os
import axis_ep
import eth_ep
import ip_ep
@ -58,6 +59,7 @@ def bench():
input_eth_payload_tvalid = Signal(bool(0))
input_eth_payload_tlast = Signal(bool(0))
input_eth_payload_tuser = Signal(bool(0))
arp_request_ready = Signal(bool(0))
arp_response_valid = Signal(bool(0))
arp_response_error = Signal(bool(0))
arp_response_mac = Signal(intbv(0)[48:])
@ -93,6 +95,7 @@ def bench():
output_eth_payload_tuser = Signal(bool(0))
arp_request_valid = Signal(bool(0))
arp_request_ip = Signal(intbv(0)[32:])
arp_response_ready = Signal(bool(0))
output_ip_hdr_valid = Signal(bool(0))
output_ip_eth_dest_mac = Signal(intbv(0)[48:])
output_ip_eth_src_mac = Signal(intbv(0)[48:])
@ -224,6 +227,28 @@ def bench():
name='ip_sink'
)
arp_request_sink = axis_ep.AXIStreamSink()
arp_request_sink_logic = arp_request_sink.create_logic(
clk,
rst,
tdata=(arp_request_ip,),
tvalid=arp_request_valid,
tready=arp_request_ready,
name='arp_request_sink'
)
arp_response_source = axis_ep.AXIStreamSource()
arp_response_source_logic = arp_response_source.create_logic(
clk,
rst,
tdata=(arp_response_error, arp_response_mac),
tvalid=arp_response_valid,
tready=arp_response_ready,
name='arp_response_source'
)
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
@ -257,8 +282,10 @@ def bench():
output_eth_payload_tuser=output_eth_payload_tuser,
arp_request_valid=arp_request_valid,
arp_request_ready=arp_request_ready,
arp_request_ip=arp_request_ip,
arp_response_valid=arp_response_valid,
arp_response_ready=arp_response_ready,
arp_response_error=arp_response_error,
arp_response_mac=arp_response_mac,
@ -325,17 +352,13 @@ def bench():
while True:
yield clk.posedge
arp_response_valid.next = 0
arp_response_error.next = 0
arp_response_mac.next = 0
if not arp_request_sink.empty():
req_ip = arp_request_sink.recv().data[0][0]
if arp_request_valid:
if int(arp_request_ip) in arp_table:
arp_response_valid.next = 1
arp_response_mac.next = arp_table[int(arp_request_ip)]
if req_ip in arp_table:
arp_response_source.send([(0, arp_table[req_ip])])
else:
arp_response_valid.next = 1
arp_response_error.next = 1
arp_response_source.send([(1, 0)])
rx_error_header_early_termination_asserted = Signal(bool(0))
rx_error_payload_early_termination_asserted = Signal(bool(0))

View File

@ -44,6 +44,7 @@ reg [7:0] input_eth_payload_tdata = 0;
reg input_eth_payload_tvalid = 0;
reg input_eth_payload_tlast = 0;
reg input_eth_payload_tuser = 0;
reg arp_request_ready = 0;
reg arp_response_valid = 0;
reg arp_response_error = 0;
reg [47:0] arp_response_mac = 0;
@ -81,6 +82,7 @@ wire output_eth_payload_tlast;
wire output_eth_payload_tuser;
wire arp_request_valid;
wire [31:0] arp_request_ip;
wire arp_response_ready;
wire output_ip_hdr_valid;
wire [47:0] output_ip_eth_dest_mac;
wire [47:0] output_ip_eth_src_mac;
@ -125,6 +127,7 @@ initial begin
input_eth_payload_tvalid,
input_eth_payload_tlast,
input_eth_payload_tuser,
arp_request_ready,
arp_response_valid,
arp_response_error,
arp_response_mac,
@ -162,6 +165,7 @@ initial begin
output_eth_payload_tuser,
arp_request_valid,
arp_request_ip,
arp_response_ready,
output_ip_hdr_valid,
output_ip_eth_dest_mac,
output_ip_eth_src_mac,
@ -226,8 +230,10 @@ UUT (
.output_eth_payload_tuser(output_eth_payload_tuser),
// ARP requests
.arp_request_valid(arp_request_valid),
.arp_request_ready(arp_request_ready),
.arp_request_ip(arp_request_ip),
.arp_response_valid(arp_response_valid),
.arp_response_ready(arp_response_ready),
.arp_response_error(arp_response_error),
.arp_response_mac(arp_response_mac),
// IP frame input

View File

@ -26,6 +26,7 @@ THE SOFTWARE.
from myhdl import *
import os
import axis_ep
import eth_ep
import ip_ep
@ -59,6 +60,7 @@ def bench():
input_eth_payload_tvalid = Signal(bool(0))
input_eth_payload_tlast = Signal(bool(0))
input_eth_payload_tuser = Signal(bool(0))
arp_request_ready = Signal(bool(0))
arp_response_valid = Signal(bool(0))
arp_response_error = Signal(bool(0))
arp_response_mac = Signal(intbv(0)[48:])
@ -96,6 +98,7 @@ def bench():
output_eth_payload_tuser = Signal(bool(0))
arp_request_valid = Signal(bool(0))
arp_request_ip = Signal(intbv(0)[32:])
arp_response_ready = Signal(bool(0))
output_ip_hdr_valid = Signal(bool(0))
output_ip_eth_dest_mac = Signal(intbv(0)[48:])
output_ip_eth_src_mac = Signal(intbv(0)[48:])
@ -232,6 +235,28 @@ def bench():
name='ip_sink'
)
arp_request_sink = axis_ep.AXIStreamSink()
arp_request_sink_logic = arp_request_sink.create_logic(
clk,
rst,
tdata=(arp_request_ip,),
tvalid=arp_request_valid,
tready=arp_request_ready,
name='arp_request_sink'
)
arp_response_source = axis_ep.AXIStreamSource()
arp_response_source_logic = arp_response_source.create_logic(
clk,
rst,
tdata=(arp_response_error, arp_response_mac),
tvalid=arp_response_valid,
tready=arp_response_ready,
name='arp_response_source'
)
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
@ -267,8 +292,10 @@ def bench():
output_eth_payload_tuser=output_eth_payload_tuser,
arp_request_valid=arp_request_valid,
arp_request_ready=arp_request_ready,
arp_request_ip=arp_request_ip,
arp_response_valid=arp_response_valid,
arp_response_ready=arp_response_ready,
arp_response_error=arp_response_error,
arp_response_mac=arp_response_mac,
@ -337,17 +364,13 @@ def bench():
while True:
yield clk.posedge
arp_response_valid.next = 0
arp_response_error.next = 0
arp_response_mac.next = 0
if not arp_request_sink.empty():
req_ip = arp_request_sink.recv().data[0][0]
if arp_request_valid:
if int(arp_request_ip) in arp_table:
arp_response_valid.next = 1
arp_response_mac.next = arp_table[int(arp_request_ip)]
if req_ip in arp_table:
arp_response_source.send([(0, arp_table[req_ip])])
else:
arp_response_valid.next = 1
arp_response_error.next = 1
arp_response_source.send([(1, 0)])
rx_error_header_early_termination_asserted = Signal(bool(0))
rx_error_payload_early_termination_asserted = Signal(bool(0))

View File

@ -44,6 +44,7 @@ reg [7:0] input_eth_payload_tkeep = 0;
reg input_eth_payload_tvalid = 0;
reg input_eth_payload_tlast = 0;
reg input_eth_payload_tuser = 0;
reg arp_request_ready = 0;
reg arp_response_valid = 0;
reg arp_response_error = 0;
reg [47:0] arp_response_mac = 0;
@ -83,6 +84,7 @@ wire output_eth_payload_tlast;
wire output_eth_payload_tuser;
wire arp_request_valid;
wire [31:0] arp_request_ip;
wire arp_response_ready;
wire output_ip_hdr_valid;
wire [47:0] output_ip_eth_dest_mac;
wire [47:0] output_ip_eth_src_mac;
@ -129,6 +131,7 @@ initial begin
input_eth_payload_tvalid,
input_eth_payload_tlast,
input_eth_payload_tuser,
arp_request_ready,
arp_response_valid,
arp_response_error,
arp_response_mac,
@ -168,6 +171,7 @@ initial begin
output_eth_payload_tuser,
arp_request_valid,
arp_request_ip,
arp_response_ready,
output_ip_hdr_valid,
output_ip_eth_dest_mac,
output_ip_eth_src_mac,
@ -235,8 +239,10 @@ UUT (
.output_eth_payload_tuser(output_eth_payload_tuser),
// ARP requests
.arp_request_valid(arp_request_valid),
.arp_request_ready(arp_request_ready),
.arp_request_ip(arp_request_ip),
.arp_response_valid(arp_response_valid),
.arp_response_ready(arp_response_ready),
.arp_response_error(arp_response_error),
.arp_response_mac(arp_response_mac),
// IP frame input

View File

@ -45,6 +45,7 @@ srcs.append("../rtl/arp_eth_rx.v")
srcs.append("../rtl/arp_eth_tx.v")
srcs.append("../rtl/eth_arb_mux_2.v")
srcs.append("../rtl/eth_mux_2.v")
srcs.append("../rtl/lfsr.v")
srcs.append("../lib/axis/rtl/arbiter.v")
srcs.append("../lib/axis/rtl/priority_encoder.v")
srcs.append("%s.v" % testbench)

View File

@ -45,6 +45,7 @@ srcs.append("../rtl/arp_eth_rx_64.v")
srcs.append("../rtl/arp_eth_tx_64.v")
srcs.append("../rtl/eth_arb_mux_64_2.v")
srcs.append("../rtl/eth_mux_64_2.v")
srcs.append("../rtl/lfsr.v")
srcs.append("../lib/axis/rtl/arbiter.v")
srcs.append("../lib/axis/rtl/priority_encoder.v")
srcs.append("%s.v" % testbench)

View File

@ -53,6 +53,7 @@ srcs.append("../rtl/arp_eth_rx.v")
srcs.append("../rtl/arp_eth_tx.v")
srcs.append("../rtl/eth_arb_mux_2.v")
srcs.append("../rtl/eth_mux_2.v")
srcs.append("../rtl/lfsr.v")
srcs.append("../lib/axis/rtl/arbiter.v")
srcs.append("../lib/axis/rtl/priority_encoder.v")
srcs.append("../lib/axis/rtl/axis_fifo.v")
@ -525,13 +526,13 @@ def bench():
udp_tx_error_payload_early_termination_asserted.next = 1
def wait_normal():
i = 16
i = 20
while i > 0:
i = max(0, i-1)
if (input_eth_payload_tvalid or input_ip_payload_tvalid or input_udp_payload_tvalid or
output_eth_payload_tvalid or output_ip_payload_tvalid or output_udp_payload_tvalid or
input_eth_hdr_valid or input_ip_hdr_valid or input_udp_hdr_valid):
i = 16
i = 20
yield clk.posedge
@instance

View File

@ -53,6 +53,7 @@ srcs.append("../rtl/arp_eth_rx_64.v")
srcs.append("../rtl/arp_eth_tx_64.v")
srcs.append("../rtl/eth_arb_mux_64_2.v")
srcs.append("../rtl/eth_mux_64_2.v")
srcs.append("../rtl/lfsr.v")
srcs.append("../lib/axis/rtl/arbiter.v")
srcs.append("../lib/axis/rtl/priority_encoder.v")
srcs.append("../lib/axis/rtl/axis_fifo.v")
@ -543,13 +544,13 @@ def bench():
udp_tx_error_payload_early_termination_asserted.next = 1
def wait_normal():
i = 16
i = 20
while i > 0:
i = max(0, i-1)
if (input_eth_payload_tvalid or input_ip_payload_tvalid or input_udp_payload_tvalid or
output_eth_payload_tvalid or output_ip_payload_tvalid or output_udp_payload_tvalid or
input_eth_hdr_valid or input_ip_hdr_valid or input_udp_hdr_valid):
i = 16
i = 20
yield clk.posedge
@instance