Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions docs/designs/command_processor.md
Original file line number Diff line number Diff line change
Expand Up @@ -672,13 +672,14 @@ host-side instead. They become usable once queues get independent rings.
ap_ctrl stub + SCOPE; `0x1000–0x1FFF` → the CP regfile. The legacy
launch FSM, DCR path, and dev-caps were **removed**; CP is the sole
launch/DCR path (`vx_start = cp_gpu_if.start`). A dedicated
`m_axi_host` port carries the ring
([`:299-320`](../../hw/rtl/afu/xrt/VX_afu_wrap.sv#L299)); `axi_dev`
shares Vortex's memory bank 0 through a 2-master `VX_mm_axi_arb`
([`:533`](../../hw/rtl/afu/xrt/VX_afu_wrap.sv#L533)), which holds a
sticky owner per channel. The CP's narrower TID is zero-padded up to the
platform ID width, and `PLATFORM_MEMORY_OFFSET` is subtracted from its
addresses before the arbiter.
`m_axi_host` port carries the ring. With one memory port, `axi_dev`
shares it with Vortex through a 2-master `VX_mm_axi_arb`, which holds a
sticky owner per channel. With several, `axi_dev` is bridged to the
memory bus by `VX_membus_from_axi` and enters the bank adapter
(`VX_mem_to_axi`) as its own input port, upstream of bank selection, so
the CP reaches every memory bank. The CP's device addresses are
offset-relative like Vortex's own, and `PLATFORM_MEMORY_OFFSET` is added
once, at the bank port, for both masters.
- **OPAE** ([`hw/rtl/afu/opae/vortex_afu.sv`](../../hw/rtl/afu/opae/vortex_afu.sv)) —
`VX_cp_core` instantiated at [`:325`](../../hw/rtl/afu/opae/vortex_afu.sv#L325).
MMIO uses a word-address bit-10 demux (the 0x1000 byte boundary) to the
Expand Down
41 changes: 24 additions & 17 deletions docs/designs/fpga_afu_shell.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ DMA-command engine have been removed.
|---|---|
| [`vortex_afu.v`](../../hw/rtl/afu/xrt/vortex_afu.v) | Vitis RTL-kernel top — thin wrapper instantiating `VX_afu_wrap`. |
| [`vortex_afu.vh`](../../hw/rtl/afu/xrt/vortex_afu.vh) | Defines/macros (`GEN_AXI_MEM`, `GEN_AXI_HOST`, the bit-12 window). |
| [`VX_afu_wrap.sv`](../../hw/rtl/afu/xrt/VX_afu_wrap.sv) | The real shell (~696 LOC): AXI-Lite bit-12 demux, `VX_cp_core`, `m_axi_host`, bank-0 `VX_axi_arb2`, the `Vortex_axi` instance. |
| [`VX_afu_wrap.sv`](../../hw/rtl/afu/common/VX_afu_wrap.sv) | The real shell (~1,200 LOC): AXI-Lite bit-12 demux, `VX_cp_core`, `m_axi_host`, the Vortex instance and the device-memory path shared with the CP. |
| [`VX_afu_ctrl.sv`](../../hw/rtl/afu/xrt/VX_afu_ctrl.sv) | Slimmed AXI-Lite slave (~322 LOC): `ap_ctrl` stub at 0x00 + a SCOPE serial register pair + SCOPE watchdog. |
| [`VX_afu_axil_demux.sv`](../../hw/rtl/afu/common/VX_afu_axil_demux.sv) | AXI-Lite demux splitting the control space on `addr[12]`, one outstanding transaction per direction. |
| [`VX_afu_axi_drain.sv`](../../hw/rtl/afu/common/VX_afu_axi_drain.sv) | Outstanding-transaction tracker per AXI master; reports when a port owes the interconnect nothing. |
| [`VX_afu_axi_limit.sv`](../../hw/rtl/afu/common/VX_afu_axi_limit.sv) | Holds an AXI master to one read and one write in flight; applied to port 0 of the multi-port shell. |
| [`VX_afu_reset_seq.sv`](../../hw/rtl/afu/common/VX_afu_reset_seq.sv) | Quiesce-before-reset sequencer for the soft reset; refuses rather than resetting a master that will not drain. |

- **Control.** Host AXI-Lite `addr[12]` splits the slave: `addr[12]=0` →
Expand All @@ -39,12 +40,16 @@ DMA-command engine have been removed.
with its address, and routing W by a register that only updates at the AW
handshake sent AW and W to different slaves and deadlocked the interface.
Covered by `hw/unittest/afu_axil_demux`.
- **Memory.** Vortex banks 1..N pass straight to platform AXI; bank 0
shares with CP `axi_dev` via `VX_axi_arb2`
([`:506-558`](../../hw/rtl/afu/xrt/VX_afu_wrap.sv#L506)); CP `axi_host`
drives a **dedicated `m_axi_host` AXI master** for the command ring +
host DMA ([`:302-326`](../../hw/rtl/afu/xrt/VX_afu_wrap.sv#L302)).
`PLATFORM_MEMORY_OFFSET` is applied per bank.
- **Memory.** Two structures, selected by the number of memory ports.
*One port* (the merged platforms): `Vortex_axi` and the CP's `axi_dev`
share the port through a 2:1 `VX_mm_axi_arb`, and CP bursts reach the
platform as bursts. *Several ports*: Vortex's memory ports and `axi_dev`
(bridged by `VX_membus_from_axi`) are the inputs of one bank adapter,
`VX_mem_to_axi`, so the CP is merged **upstream** of bank selection and
reaches every bank. In both, port 0 carries one read and one write in
flight (`VX_afu_axi_limit` in the second case). CP `axi_host` drives a
**dedicated `m_axi_host` AXI master** for the command ring + host DMA.
`PLATFORM_MEMORY_OFFSET` is applied per bank, at the port.
- **Interrupt.** The AFU `interrupt` pin is driven from `cp_interrupt`
([`:335`](../../hw/rtl/afu/xrt/VX_afu_wrap.sv#L335)).

Expand Down Expand Up @@ -78,20 +83,22 @@ DMA-command engine have been removed.
## 3. Shared components and asymmetries

Reused from the common libraries (not under `afu/`):
[`VX_axi_arb2.sv`](../../hw/rtl/libs/VX_axi_arb2.sv) (XRT bank-0 arbiter),
[`VX_mem_arb.sv`](../../hw/rtl/mem/VX_mem_arb.sv) (OPAE bank-0 arbiter),
[`VX_mm_axi_arb.sv`](../../hw/rtl/libs/VX_mm_axi_arb.sv) (XRT single-port arbiter),
[`VX_mem_to_axi.sv`](../../hw/rtl/libs/VX_mem_to_axi.sv) (XRT multi-port bank adapter),
[`VX_mem_bus_arb.sv`](../../hw/rtl/mem/VX_mem_bus_arb.sv) (OPAE port-0 arbiter),
[`VX_avs_adapter.sv`](../../hw/rtl/libs/VX_avs_adapter.sv) /
`VX_mem_data_adapter.sv` (OPAE Avalon), and
[`VX_cp_axi_to_membus.sv`](../../hw/rtl/cp/VX_cp_axi_to_membus.sv) (AXI→
membus bridge, both OPAE bridges). The top-level cores are
[`Vortex.sv`](../../hw/rtl/Vortex.sv) (OPAE, membus ports) and
[`Vortex_axi.sv`](../../hw/rtl/Vortex_axi.sv) (XRT, AXI ports), each
keeping direct `start`/`busy`/`dcr_*` ports.
[`VX_membus_from_axi.sv`](../../hw/rtl/mem/VX_membus_from_axi.sv) (AXI→
membus bridge: both OPAE bridges and the XRT multi-port device bridge). The
top-level cores are [`Vortex.sv`](../../hw/rtl/Vortex.sv) (OPAE and XRT
multi-port, membus ports) and [`Vortex_axi.sv`](../../hw/rtl/Vortex_axi.sv)
(XRT single-port, AXI ports), each keeping direct `start`/`busy`/`dcr_*` ports.

**Key XRT↔OPAE asymmetries:** dedicated host-AXI master (`m_axi_host`) vs.
a CCI-P host-DMA state machine; an interrupt pin vs. none; `VX_axi_arb2`
vs. `VX_mem_arb` for bank-0 sharing; AXI-Lite `addr[12]` vs. CCI-P MMIO
word-address bit 10 for the control demux. Both expose SCOPE over a serial
a CCI-P host-DMA state machine; an interrupt pin vs. none; with several
memory ports, the CP as its own bank-adapter input vs. a `VX_mem_bus_arb` on
Vortex's port 0 (both upstream of bank selection); AXI-Lite `addr[12]` vs.
CCI-P MMIO word-address bit 10 for the control demux. Both expose SCOPE over a serial
sideband.

The XRT shell's reset-delay shift register is reloaded either by the platform
Expand Down
99 changes: 99 additions & 0 deletions hw/rtl/afu/common/VX_afu_axi_limit.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

`include "VX_platform.vh"

// ============================================================================
// VX_afu_axi_limit — holds an AXI master to one read and one write in flight.
//
// A new AR is withheld until the previous read's last beat, and a new AW until
// the previous write's B. The limits only ever tighten on a handshake, so an
// offer already made to the slave is never withdrawn.
//
// AW and W of one write may fire in either order. W is let through whenever
// its AW has already gone, and AW whenever its W has, whatever the limit says
// by then: withholding half of an accepted write would hang it.
// ============================================================================

`TRACING_OFF
module VX_afu_axi_limit (
input wire clk,
input wire reset,

input wire in_awvalid,
output wire in_awready,
input wire in_wvalid,
output wire in_wready,
input wire in_wlast,
input wire in_arvalid,
output wire in_arready,

output wire out_awvalid,
input wire out_awready,
output wire out_wvalid,
input wire out_wready,
output wire out_arvalid,
input wire out_arready,

input wire b_fire,
input wire r_fire_last
);
reg rd_busy;
reg wr_busy;
reg w_owed; // AW sent, its W still to come
reg aw_owed; // W sent, its AW still to come

wire aw_allow = aw_owed || ~wr_busy;
wire w_allow = w_owed || (~wr_busy && ~aw_owed);
wire ar_allow = ~rd_busy;

assign out_awvalid = in_awvalid && aw_allow;
assign in_awready = out_awready && aw_allow;
assign out_wvalid = in_wvalid && w_allow;
assign in_wready = out_wready && w_allow;
assign out_arvalid = in_arvalid && ar_allow;
assign in_arready = out_arready && ar_allow;

wire aw_fire = out_awvalid && out_awready;
wire w_fire_last = out_wvalid && out_wready && in_wlast;
wire ar_fire = out_arvalid && out_arready;

always @(posedge clk) begin
if (reset) begin
rd_busy <= 1'b0;
wr_busy <= 1'b0;
w_owed <= 1'b0;
aw_owed <= 1'b0;
end else begin
if (ar_fire) begin
rd_busy <= 1'b1;
end else if (r_fire_last) begin
rd_busy <= 1'b0;
end
if (aw_fire) begin
wr_busy <= 1'b1;
end else if (b_fire) begin
wr_busy <= 1'b0;
end
if (aw_fire && ~w_fire_last) begin
aw_owed <= 1'b0;
w_owed <= ~aw_owed;
end else if (w_fire_last && ~aw_fire) begin
w_owed <= 1'b0;
aw_owed <= ~w_owed;
end
end
end

endmodule
`TRACING_ON
Loading
Loading