skip to content
back to learning-hdl

custom axi interconnect

custom axi interconnect

[!tip] goal

  • create an axi interconnect between an in-order processor and memory (memory controller?)
  • implement custom logic (hardware rtl) inside the axi interconnect to measure the average memory access times

todo

  • implement a simple axi interconnect in sv
  • simulate and test in sv and verilator
  • plan the custom logic for latency measurement
  • implement the logic separately and test
  • try to integrate axi interconnect and the custom logic

sort

  1. Start with a standard AXI interconnect structure
  2. Add latency measurement logic
  3. Implement a control signal interface
  4. Create a mechanism to provide the measured latency to the processor

Let’s break this down step by step:

  1. Standard AXI Interconnect:

    • Implement the basic AXI protocol handling for read and write channels
    • Ensure proper routing between the processor (master) and memory (slave)
  2. Latency Measurement Logic:

    • Add counters to track the time between request initiation and completion
    • Implement separate tracking for read and write transactions
    • Calculate running averages of latencies
  3. Control Signal Interface:

    • Add a dedicated input signal for triggering latency reporting
    • Implement a state machine to handle the control signal
  4. Latency Reporting Mechanism:

    • Design a method to transfer the latency data to the processor
    • This could be through a dedicated AXI-Lite interface or custom signals

Here’s a basic Verilog implementation outline for this enhanced AXI interconnect:

module axi_interconnect_with_latency (
input wire clk,
input wire rst_n,
// AXI slave interface (from processor)
input wire [31:0] s_axi_awaddr,
input wire s_axi_awvalid,
output wire s_axi_awready,
input wire [31:0] s_axi_wdata,
input wire s_axi_wvalid,
output wire s_axi_wready,
output wire [1:0] s_axi_bresp,
output wire s_axi_bvalid,
input wire s_axi_bready,
input wire [31:0] s_axi_araddr,
input wire s_axi_arvalid,
output wire s_axi_arready,
output wire [31:0] s_axi_rdata,
output wire [1:0] s_axi_rresp,
output wire s_axi_rvalid,
input wire s_axi_rready,
// AXI master interface (to memory)
output wire [31:0] m_axi_awaddr,
output wire m_axi_awvalid,
input wire m_axi_awready,
output wire [31:0] m_axi_wdata,
output wire m_axi_wvalid,
input wire m_axi_wready,
input wire [1:0] m_axi_bresp,
input wire m_axi_bvalid,
output wire m_axi_bready,
output wire [31:0] m_axi_araddr,
output wire m_axi_arvalid,
input wire m_axi_arready,
input wire [31:0] m_axi_rdata,
input wire [1:0] m_axi_rresp,
input wire m_axi_rvalid,
output wire m_axi_rready,
// Control and status signals
input wire measure_latency,
output reg [31:0] avg_read_latency,
output reg [31:0] avg_write_latency
);
// Latency measurement variables
reg [31:0] read_start_time, write_start_time;
reg [31:0] read_latency_sum, write_latency_sum;
reg [31:0] read_count, write_count;
// State machine states
localparam IDLE = 2'b00, MEASURE = 2'b01, REPORT = 2'b10;
reg [1:0] state;
// AXI interconnect logic (simplified for brevity)
assign m_axi_awaddr = s_axi_awaddr;
assign m_axi_awvalid = s_axi_awvalid;
assign s_axi_awready = m_axi_awready;
assign m_axi_wdata = s_axi_wdata;
assign m_axi_wvalid = s_axi_wvalid;
assign s_axi_wready = m_axi_wready;
assign s_axi_bresp = m_axi_bresp;
assign s_axi_bvalid = m_axi_bvalid;
assign m_axi_bready = s_axi_bready;
assign m_axi_araddr = s_axi_araddr;
assign m_axi_arvalid = s_axi_arvalid;
assign s_axi_arready = m_axi_arready;
assign s_axi_rdata = m_axi_rdata;
assign s_axi_rresp = m_axi_rresp;
assign s_axi_rvalid = m_axi_rvalid;
assign m_axi_rready = s_axi_rready;
// Latency measurement logic
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
read_latency_sum <= 0;
write_latency_sum <= 0;
read_count <= 0;
write_count <= 0;
avg_read_latency <= 0;
avg_write_latency <= 0;
end else begin
case (state)
IDLE: begin
if (measure_latency)
state <= MEASURE;
end
MEASURE: begin
// Start read transaction
if (s_axi_arvalid && s_axi_arready)
read_start_time <= $time;
// End read transaction
if (s_axi_rvalid && s_axi_rready) begin
read_latency_sum <= read_latency_sum + ($time - read_start_time);
read_count <= read_count + 1;
end
// Start write transaction
if (s_axi_awvalid && s_axi_awready)
write_start_time <= $time;
// End write transaction
if (s_axi_bvalid && s_axi_bready) begin
write_latency_sum <= write_latency_sum + ($time - write_start_time);
write_count <= write_count + 1;
end
// Transition to REPORT state when measurement period ends
if (!measure_latency)
state <= REPORT;
end
REPORT: begin
// Calculate average latencies
avg_read_latency <= (read_count > 0) ? read_latency_sum / read_count : 0;
avg_write_latency <= (write_count > 0) ? write_latency_sum / write_count : 0;
// Reset counters and return to IDLE
read_latency_sum <= 0;
write_latency_sum <= 0;
read_count <= 0;
write_count <= 0;
state <= IDLE;
end
endcase
end
end
endmodule

This implementation provides a basic framework for an AXI interconnect with latency measurement capabilities. Here’s a breakdown of its key components:

  1. AXI Interfaces: The module includes both slave (processor-facing) and master (memory-facing) AXI interfaces.

  2. Latency Measurement: The module tracks the start and end times of read and write transactions, accumulating the total latency and transaction count.

  3. Control Signal: The measure_latency input signal triggers the latency measurement period.

  4. State Machine: A simple state machine (IDLE, MEASURE, REPORT) controls the measurement and reporting process.

  5. Latency Reporting: The average read and write latencies are output as avg_read_latency and avg_write_latency.

To use this interconnect:

  1. Integrate it between your processor (AXI master) and memory (AXI slave).
  2. Connect the measure_latency signal to your processor’s control logic.
  3. When the processor needs latency information, it should: a. Assert the measure_latency signal for the desired measurement period. b. De-assert measure_latency to trigger the calculation of average latencies. c. Read the avg_read_latency and avg_write_latency outputs.

Note that this is a simplified implementation and may need additional features depending on your specific requirements, such as:

  • Support for multiple AXI slaves
  • More sophisticated latency calculations (e.g., min/max latencies, histograms)
  • AXI-Lite interface for configuration and status reporting
  • Clock domain crossing if the processor and memory operate at different frequencies

references

https://zipcpu.com/blog/2021/08/14/axiperf.html https://github.com/alexforencich/verilog-axi/tree/38915fb5330cb8270b454afc0140a94489dc56db/rtl