pcie2fifos.v#
Module Overview#
Purpose and Role in Stack#
The pcie2fifos module serves as the PCIe AXI4 to FIFO bridge, providing the critical interface between the host computer and the FPGA neuromorphic hardware. This module:
Converts AXI4 memory-mapped transactions (from PCIe controller) into simple FIFO operations
Implements AXI4 slave interface for both read and write transactions
Manages bidirectional data flow: Host→FPGA (writes) and FPGA→Host (reads)
Operates at 512-bit data width for high-bandwidth communication
Provides flow control through FIFO full/empty signals
In the software/hardware stack:
Host PC (Python) → PCIe DMA Driver → PCIe Controller (Xilinx IP)
↓ AXI4 512-bit
┌──────────────┐
│ pcie2fifos │
└──────┬───────┘
↓ FIFO Interface
┌────────────┴─────────────┐
│ │
Input FIFO Output FIFO
(Host→FPGA) (FPGA→Host)
│ │
▼ ▼
command_interpreter command_interpreter
This module abstracts away AXI4 protocol complexity, allowing the rest of the design to work with simple FIFO interfaces.
Module Architecture#
High-Level Block Diagram#
pcie2fifos
┌───────────────────────────────────────────────────────┐
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ AXI4 Write Channel State Machine │ │
│ │ (Host → FPGA Data Path) │ │
│ │ │ │
│ │ RX_RESET → RX_DATA → RX_DONE → RX_RESET │ │
│ │ │ ▲ │ │ │
│ │ │ │ │ │ │
AXI4 │ │ AW ready W data B response │ │
Write│ └────────┬──────┼─────────┼──────────────────┘ │
─────┼───────────┘ │ │ │
│ │ │ │
s_axi│ ┌───────────────▼─────────┴───────────────────┐ │
_awaddr AXI4 Write Logic │ │
_awvalid - Address channel (AW) │ │
_awready - Data channel (W) │ │ Input FIFO
_wdata │ - Response channel (B) │───▶│ (512-bit)
_wvalid │ - Flow control via inpFIFO_full │ │ PC → FPGA
_wready │ - Write enable: wready & wvalid │ │
_wlast │ └────────────────────────────────────┘ │
_bvalid │ │
_bready │ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ AXI4 Read Channel State Machine │ │
│ │ (FPGA → Host Data Path) │ │
│ │ │ │
│ │ TX_RESET → TX_DATA → TX_RESET │ │
│ │ │ ▲ │ │
│ │ │ │ │ │
AXI4 │ │ AR ready R data (multi-beat) │ │
Read │ └────────┬──────┼───────────────────────────┘ │
────────┼───────────┘ │ │
│ │ │
s_axi │ ┌───────────────▼─────────────────────────┐ │
_araddr │ │ AXI4 Read Logic │ │ Output FIFO
_arvalid│ │ - Address channel (AR) │◄───│ (512-bit)
_arready│ │ - Data channel (R) │ │ FPGA → PC
_rdata │ │ - Beat counter (arlen) │ │ (FWFT mode)
_rvalid │ │ - Auto-pop on rvalid & rready │ │
_rready │ │ - rlast generation │ │
_rlast │ │ └──────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Mandatory AXI4 Signal Assignments │ │
│ │ - bid = 4'd0 │ │
│ │ - rid = 4'd0 │ │
│ │ - rresp = 2'd0 (OKAY) │ │
│ │ - bresp = 2'd0 (OKAY) │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
Interface Specification#
Clock and Reset#
Signal |
Direction |
Width |
Description |
|---|---|---|---|
|
Input |
1 |
225 MHz AXI4 clock |
|
Input |
1 |
Active-low asynchronous reset |
AXI4 Read Address Channel#
Signal |
Direction |
Width |
Description |
|---|---|---|---|
|
Input |
64 |
Read address (unused in this design) |
|
Input |
2 |
Burst type (unused) |
|
Input |
4 |
Cache type (unused) |
|
Input |
4 |
Transaction ID (unused, returns 0) |
|
Input |
8 |
Burst length (beats - 1) |
|
Input |
1 |
Lock type (unused) |
|
Input |
3 |
Protection type (unused) |
|
Output (reg) |
1 |
Read address ready |
|
Input |
3 |
Burst size (unused) |
|
Input |
1 |
Read address valid |
Note: Address and metadata signals are ignored; this module simply pops data from output FIFO regardless of address.
AXI4 Write Address Channel#
Signal |
Direction |
Width |
Description |
|---|---|---|---|
|
Input |
64 |
Write address (unused) |
|
Input |
2 |
Burst type (unused) |
|
Input |
4 |
Cache type (unused) |
|
Input |
4 |
Transaction ID (unused, returns 0) |
|
Input |
8 |
Burst length (unused, single-beat assumed) |
|
Input |
1 |
Lock type (unused) |
|
Input |
3 |
Protection type (unused) |
|
Output (reg) |
1 |
Write address ready |
|
Input |
3 |
Burst size (unused) |
|
Input |
1 |
Write address valid |
AXI4 Write Data Channel#
Signal |
Direction |
Width |
Description |
|---|---|---|---|
|
Input |
512 |
Write data (directly connected to inpFIFO_din) |
|
Input |
1 |
Last beat of write burst |
|
Output (reg) |
1 |
Write data ready |
|
Input |
64 |
Write strobes (unused, all bytes written) |
|
Input |
1 |
Write data valid |
AXI4 Write Response Channel#
Signal |
Direction |
Width |
Description |
|---|---|---|---|
|
Output |
4 |
Response transaction ID (always 4’d0) |
|
Input |
1 |
Response ready (from master) |
|
Output |
2 |
Write response (always 2’d0 = OKAY) |
|
Output (reg) |
1 |
Write response valid |
AXI4 Read Data Channel#
Signal |
Direction |
Width |
Description |
|---|---|---|---|
|
Output |
512 |
Read data (from outFIFO_dout or default pattern) |
|
Output |
4 |
Read transaction ID (always 4’d0) |
|
Output |
1 |
Last beat of read burst |
|
Input |
1 |
Read data ready (from master) |
|
Output |
2 |
Read response (always 2’d0 = OKAY) |
|
Output (reg) |
1 |
Read data valid |
Input FIFO Interface (PC → FPGA)#
Signal |
Direction |
Width |
Description |
|---|---|---|---|
|
Input |
1 |
FIFO full flag (backpressure) |
|
Output |
512 |
FIFO data input |
|
Output |
1 |
FIFO write enable |
Connection:
assign inpFIFO_din = s_axi_wdata;
assign inpFIFO_wren = s_axi_wready & s_axi_wvalid;
Output FIFO Interface (FPGA → PC)#
Signal |
Direction |
Width |
Description |
|---|---|---|---|
|
Input |
1 |
FIFO empty flag |
|
Input |
512 |
FIFO data output |
|
Output |
1 |
FIFO read enable |
Connection (FWFT FIFO assumed):
assign s_axi_rdata = ~outFIFO_empty ? outFIFO_dout : {16{32'h89ABCDEF}};
assign outFIFO_rden = ~outFIFO_empty & s_axi_rvalid & s_axi_rready;
Note: FWFT (First-Word Fall-Through) mode means data appears on dout one cycle after rden assertion is not required; data is valid when empty is deasserted.
Detailed Logic Description#
Mandatory Signal Assignments#
assign s_axi_bid = 4'd0; // Transaction ID always 0
assign s_axi_rid = 4'd0; // Transaction ID always 0
assign s_axi_rresp = 2'd0; // OKAY response
assign s_axi_bresp = 2'd0; // OKAY response
These signals are required by AXI4 protocol but carry no information in this simple bridge design.
Input Data Path (Write Logic)#
Direct Assignments:
assign inpFIFO_din = s_axi_wdata; // 512-bit data passthrough
assign inpFIFO_wren = s_axi_wready & s_axi_wvalid; // Write when handshake occurs
Write State Machine States:
localparam [1:0] STATE_RX_RESET = 2'd0;
localparam [1:0] STATE_RX_DATA = 2'd1;
localparam [1:0] STATE_RX_DONE = 2'd3; // Note: 2'd2 skipped
State Transition Diagram:
┌──────────────┐
│ RX_RESET │
└──────┬───────┘
│ aresetn
▼
┌──────────────┐
┌──▶│ RX_DATA │
│ │ Wait for │
│ │ awvalid │──awvalid──┐
│ └──────────────┘ │
│ │
│ ▼
│ ┌──────────────┐
│ │ RX_DATA │
│ │ Push FIFO │
│ │ (if !full) │
│ └──────┬───────┘
│ │
│ wvalid & wlast
│ │
│ ▼
│ ┌──────────────┐
│ │ RX_DONE │
│ │ Send bresp │
│ └──────┬───────┘
│ │
│ bready
│ │
│ ├─ awvalid ──┐
│ │ │
│ ▼ ▼
└──────────────────────────────┘ (back to RX_DATA)
Detailed State Behavior:
STATE_RX_RESET:
s_axi_awready = 1'b1; // Ready to accept address
if (s_axi_awvalid)
rx_next_state = STATE_RX_DATA;
STATE_RX_DATA:
if (!inpFIFO_full) begin
s_axi_wready = 1'b1; // Ready to accept data
if (s_axi_wvalid & s_axi_wlast)
rx_next_state = STATE_RX_DONE;
end
// Note: Backpressure applied when FIFO full
STATE_RX_DONE:
s_axi_bvalid = 1'b1; // Assert write response valid
if (s_axi_bready) begin
s_axi_awready = 1'b1; // Ready for next transaction
if (s_axi_awvalid)
rx_next_state = STATE_RX_DATA;
else
rx_next_state = STATE_RX_RESET;
end
Output Data Path (Read Logic)#
Direct Assignments:
assign s_axi_rdata = ~outFIFO_empty ? outFIFO_dout : {16{32'h89ABCDEF}};
assign outFIFO_rden = ~outFIFO_empty & s_axi_rvalid & s_axi_rready;
Default Pattern: 0x89ABCDEF repeated 16 times (512 bits) when FIFO empty
Read State Machine States:
localparam STATE_TX_RESET = 1'b0;
localparam STATE_TX_DATA = 1'b1;
Read Length Tracking:
reg [7:0] s_axi_arlen_reg; // Capture burst length
reg [7:0] tx_ctr; // Beat counter
// Capture burst length
always @(posedge aclk)
if (!aresetn)
s_axi_arlen_reg <= 8'b0;
else if (s_axi_arready & s_axi_arvalid)
s_axi_arlen_reg <= s_axi_arlen;
// Increment beat counter
always @(posedge aclk)
if (!aresetn | (s_axi_arready & s_axi_arvalid))
tx_ctr <= 8'd0;
else if (s_axi_rready & s_axi_rvalid)
tx_ctr <= tx_ctr + 1'b1;
// Generate last signal
assign s_axi_rlast = (tx_ctr == s_axi_arlen_reg);
State Transition Diagram:
┌──────────────┐
│ TX_RESET │
└──────┬───────┘
│ aresetn
▼
┌──────────────┐
┌──▶│ TX_RESET │
│ │ Wait for │
│ │ arvalid │──arvalid──┐
│ └──────────────┘ │
│ │
│ ▼
│ ┌──────────────┐
│ │ TX_DATA │
│ │ Stream data │
│ │ (multi-beat)│
│ └──────┬───────┘
│ │
│ rready & rlast
│ │
│ ├─ arvalid ──┐
│ │ │
│ ▼ ▼
└──────────────────────────────┘ (stay in TX_DATA)
Detailed State Behavior:
STATE_TX_RESET:
s_axi_arready = 1'b1; // Ready to accept read address
if (s_axi_arvalid)
tx_next_state = STATE_TX_DATA;
STATE_TX_DATA:
s_axi_rvalid = 1'b1; // Data always valid (even if FIFO empty)
if (s_axi_rready & (tx_ctr==s_axi_arlen_reg)) begin
s_axi_arready = 1'b1; // Ready for next transaction
if (!s_axi_arvalid)
tx_next_state = STATE_TX_RESET;
// else stay in TX_DATA for back-to-back bursts
end
FWFT FIFO Behavior:
Data valid on
outFIFO_doutwhenoutFIFO_empty==0No read latency:
rdenpulse pops current data and advances to nextSimplifies
rdenlogic: just AND ofrvalidandrready
Timing Diagrams#
Write Transaction (Single Beat)#
Cycle: 0 1 2 3 4 5 6 7
│ │ │ │ │ │ │ │
aclk ──┘▔▔▔▔▔▔└┐ ┌▔┐ ┌▔┐ ┌▔┐ ┌▔┐ ┌▔┐ ┌▔
│ │▔▔▔▔▔▔│▔│▔▔▔▔│▔│▔▔▔▔│▔│▔▔▔▔│▔│▔▔▔▔│▔│▔▔▔▔│
RX State RESET │DATA │DATA │DATA │DONE │RESET │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔│
awvalid │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▔▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│
awready │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
wvalid │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
wready │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
wlast │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ XXXXXX │XXXXXX│XXXXXX│WDATA │WDATA │XXXXXX│XXXXXX│
wdata │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
inpFIFO_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
wren │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁
bvalid │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁
bready │ │ │ │ │ │ │ │
Notes:
Cycle 0: RESET state,
awreadyassertedCycle 1:
awvalidhandshake, transition to DATA stateCycle 2: Wait for
wvalid(FIFO not full assumed)Cycle 3:
wvalid&wreadyhandshake,wlastasserted, data written to FIFOCycle 4: DONE state,
bvalidasserted for write responseCycle 5:
breadyhandshake, return to RESET
Write Transaction with Backpressure#
Cycle: 0 1 2 3 4 5 6 7
│ │ │ │ │ │ │ │
RX State DATA │DATA │DATA │DATA │DATA │DONE │RESET │
│ │ │ │ │ │ │ │
inpFIFO_ ▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
full │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▔▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁
wvalid │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
wready │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
inpFIFO_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
wren │ │ │ │ │ │ │ │
Notes:
Cycles 1-3: FIFO full,
wreadydeasserted (backpressure)Cycle 4: FIFO no longer full,
wreadyasserted, handshake occursMaster must hold
wvalidandwdatastable during backpressure
Read Transaction (4-Beat Burst, arlen=3)#
Cycle: 0 1 2 3 4 5 6 7
│ │ │ │ │ │ │ │
TX State RESET │DATA │DATA │DATA │DATA │RESET │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
arvalid │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▔▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│
arready │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ 8'hXX │8'h03 │8'h03 │8'h03 │8'h03 │8'h03 │8'h00 │
arlen │ │ │(=3) │ │ │ │ │
│ │ │ │ │ │ │ │
arlen_reg 8'h00 │8'h00 │8'h03 │8'h03 │8'h03 │8'h03 │8'h03 │
│ │ │ │ │ │ │ │
tx_ctr 0 │0 │0 │1 │2 │3 │0
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁
rvalid │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁
rready │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ XXXXXX │XXXXXX│DATA0 │DATA1 │DATA2 │DATA3 │XXXXXX│
rdata │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
s_axi_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔▁▁▁▁▁▁▁▁
rlast │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
outFIFO_ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔│▔▔▔▔▔▔▁▁▁▁▁▁▁▁
rden │ │ │ │ │ │ │ │
Notes:
Cycle 0: RESET state,
arreadyassertedCycle 1:
arvalidhandshake,arlen=3(4 beats total)Cycle 2: First beat,
arlenregistered,tx_ctr=0,rlast=0Cycle 3-5: Beats 2-4,
tx_ctrincrementsCycle 5: Last beat,
tx_ctr=3,rlast=1Cycle 6: Return to RESET, counter resets
Memory Map#
This module does not implement a true memory map. All address signals (s_axi_araddr, s_axi_awaddr) are ignored. The module operates as a streaming interface:
Write Operations: Data pushed to input FIFO regardless of address
Read Operations: Data popped from output FIFO regardless of address
The actual memory mapping and addressing is handled by:
Host software: Determines which FIFO queue to use (via PCIe BAR mapping)
command_interpreter: Interprets commands from input FIFO and routes to appropriate modules
Protocol Details#
AXI4 Burst Types#
Supported: INCR (incrementing burst) - assumed by design Unsupported: FIXED, WRAP bursts - ignored, module treats all as streaming
Burst Length:
Write: Assumed single-beat (though
wlastdetection allows multi-beat)Read: Supports multi-beat bursts via
arlenand beat counter
AXI4 Response Codes#
Write Response (bresp): Always 2'b00 (OKAY)
Read Response (rresp): Always 2'b00 (OKAY)
No error conditions reported; module assumes all transactions succeed.
FIFO Assumptions#
Input FIFO (Standard FIFO):
wrenpulse writes data on same cyclefullflag provides backpressureDepth sufficient to absorb PCIe burst traffic
Output FIFO (FWFT Mode):
Data appears on
doutwhenemptydeassertedrdenpulse pops data and advances to nextZero read latency (data valid same cycle as
empty=0)
Typical FIFO Depths:
Input: 512 entries (256 KB) - handles large DMA transfers
Output: 512 entries (256 KB) - buffers spike/response data
Performance Characteristics#
Bandwidth#
Theoretical Maximum:
512 bits @ 225 MHz = 115.2 Gb/s = 14.4 GB/s per direction
Practical Bandwidth:
Write: Limited by FIFO full condition and PCIe overhead
Read: Limited by FIFO empty condition and burst efficiency
Expected: 8-12 GB/s (accounting for protocol overhead and command processing)
Latency#
Write Transaction:
Address handshake: 1 cycle
Data handshake: 1 cycle (if FIFO not full)
Response handshake: 1 cycle
Total: 3 cycles minimum (13.3 ns @ 225 MHz)
Read Transaction:
Address handshake: 1 cycle
Data valid: Immediate (FWFT FIFO)
Per-beat: 1 cycle (if master ready)
Total: 1 cycle address + N cycles data (N = burst length)
Flow Control#
Backpressure Mechanisms:
Write Path:
inpFIFO_full → s_axi_wready deasserted → PCIe master stalls
Read Path:
outFIFO_empty → s_axi_rdata = default pattern → PCIe master receives dummy data
Note: Read path does NOT stall when FIFO empty; returns default pattern instead. Software must track expected response count.
Cross-References#
Software Integration#
DMA Driver (C++ wrapper: adxdma_dmadump.cpp):
DMA_Write()→ Triggers AXI4 write transactions →inpFIFODMA_Read()→ Triggers AXI4 read transactions →outFIFO
Python (hs_bridge):
fpga_controller.send_command()→ Formats PCIe packet → DMA writefpga_controller.receive_response()→ DMA read → Parse packet
Key Terms and Definitions#
Term |
Definition |
|---|---|
AXI4 |
ARM Advanced eXtensible Interface version 4 - High-performance memory-mapped protocol |
AXI4 Slave |
Device that responds to read/write requests (this module) |
AXI4 Master |
Device that initiates transactions (PCIe controller) |
Handshake |
Valid/ready protocol: transaction occurs when both asserted |
Burst |
Multi-beat transaction transferring multiple data words |
Beat |
Single data transfer within a burst |
FWFT |
First-Word Fall-Through - FIFO mode with zero read latency |
Backpressure |
Flow control mechanism to pause upstream when buffer full |
Transaction ID |
|
Response Code |
|
INCR Burst |
Incrementing address burst type (addresses increment by size) |
wlast |
Indicates last beat of write burst |
rlast |
Indicates last beat of read burst |
arlen |
Read burst length in beats (0 = 1 beat, 1 = 2 beats, etc.) |
Design Simplifications#
This module makes several simplifying assumptions compared to full AXI4 protocol:
No Address Decoding: All addresses ignored; operates as pure FIFO bridge
No Transaction IDs: All IDs hardcoded to 0; no out-of-order support
No Error Reporting: All responses OKAY; no SLVERR or DECERR
Single Outstanding Transaction: State machines handle one transaction at a time
No Write Strobes:
wstrbignored; all bytes writtenNo Burst Optimization: Treats each burst independently
Read Returns Dummy Data When Empty: Does not stall; software must manage
These simplifications are valid for this use case:
Single master (PCIe controller)
Software controls transaction ordering
Command-response pattern ensures data availability
High-level protocol (in command_interpreter) handles errors
Common Issues and Debugging#
Problem: Data Lost on Write#
Symptoms: Host sends data but FPGA doesn’t receive it
Debug Steps:
Check
inpFIFO_full- if stuck high, downstream not consumingCheck
s_axi_wready- should pulse when not fullCheck
inpFIFO_wren- should pulse onwready & wvalidVerify
wlastassertion - module expects it to transition to DONE state
Common Cause: Input FIFO overflow due to command_interpreter stalled
Problem: Read Returns Garbage#
Symptoms: Host reads unexpected data
Debug Steps:
Check
outFIFO_empty- if high, FIFO has no dataCheck
s_axi_rdata- should be0x89ABCDEFpattern when emptyVerify command_interpreter has written response to
outFIFOCheck beat counter
tx_ctrvsarlen_reg- ensure correct burst length
Common Cause: Reading before response ready, or incorrect burst length
Problem: Write Transaction Hangs#
Symptoms: s_axi_wvalid stuck high, no progress
Debug Steps:
Check
s_axi_wready- if stuck low, likelyinpFIFO_fullCheck
rx_curr_state- should be DATA stateVerify
aresetn- ensure not in resetCheck for missing
s_axi_wlast- module waits for it
Common Cause: FIFO backpressure or missing wlast signal
VIO/ILA Probes (Recommended)#
// State machines
(*mark_debug = "true"*) reg [1:0] rx_curr_state;
(*mark_debug = "true"*) reg tx_curr_state;
// Handshakes
(*mark_debug = "true"*) wire aw_hs = s_axi_awvalid & s_axi_awready;
(*mark_debug = "true"*) wire w_hs = s_axi_wvalid & s_axi_wready;
(*mark_debug = "true"*) wire b_hs = s_axi_bvalid & s_axi_bready;
(*mark_debug = "true"*) wire ar_hs = s_axi_arvalid & s_axi_arready;
(*mark_debug = "true"*) wire r_hs = s_axi_rvalid & s_axi_rready;
// FIFO status
(*mark_debug = "true"*) wire inpFIFO_full;
(*mark_debug = "true"*) wire outFIFO_empty;
Potential Enhancements#
Address-Based Routing: Use addresses to multiplex between multiple logical FIFOs
Error Detection: Monitor for protocol violations (e.g.,
wvalidwithout priorawvalid)Performance Counters: Track transactions, stall cycles, bandwidth utilization
Configurable Data Width: Parameterize for 256-bit or 1024-bit data paths
Timeout Detection: Abort transactions stuck waiting for handshakes
Out-of-Order Support: Use transaction IDs for pipelined operation
Read Stalling: Deassert
rvalidwhen output FIFO empty instead of returning dummy data
Safety and Reset Behavior#
Reset Assertions#
On aresetn deassertion (active-low reset):
All state machines → RESET state
All
readysignals → 1 (accepting transactions)All
validoutputs → 0 (no data/responses)Beat counter
tx_ctr→ 0Burst length register
s_axi_arlen_reg→ 0
FIFO Reset Synchronization#
FIFOs must be reset consistently with this module:
Use same
aresetnor synchronized versionEnsure FIFOs clear before module exits reset
First transaction after reset should not assume FIFO state
Document Version: 1.0
Last Updated: December 2025
Module File: pcie2fifos.v
Module Location: CRI_proj/cri_fpga/code/new/hyddenn2/vivado/single_core.srcs/sources_1/new/
Protocol: AXI4 (slave interface)
Data Width: 512 bits
Clock Frequency: 225 MHz (aclk)