Chapter 1 — Enhancements Implemented
Home / Book / Part I — Production Readiness / Chapter 1 — Enhancements Implemented
PART I — PRODUCTION READINESS PRODUCTION READINESS

Chapter 1 — Enhancements Implemented

Reaching Production Readiness as priority #1 — Enhancements to the FPGA DMA Engine Design Process Implemented.

Reaching Production Readiness as priority #1 — Enhancements to the FPGA DMA Engine Design Process Implemented

← Overview · Next → Component Library

Why safety and convenience matter here

In FPGA data paths, “mostly correct” is usually a bug waiting for a hard-to-debug failure. A single width mismatch, dropped last signal, or handshake corner case can silently corrupt payloads and only surface later as unstable behavior at system boundaries. That is why this chapter emphasizes safety first: the design should fail less by construction, not just by luck during a clean demo run.

The width_converter.v module is central to that safety posture. It provides explicit, buffered, handshake-aware width translation between PCIe- and DMA-facing paths instead of relying on implicit truncation/padding assumptions. Wrappers in width_adapters.v then package those conversions into repeatable integration units (pcie_dma_width_adapter and dma_pcie_width_adapter), reducing wiring entropy and making the safe path the default path.

Convenience is not a separate concern—it is a force multiplier for safety. When integration primitives are easy to use, teams are less likely to bypass them with one-off glue logic. The baseline tb_dma_engine.v testbench completes that loop by giving fast feedback on module behavior, reset handling, and timeout conditions, so correctness checks stay lightweight enough to run often. In practice, this combination helps keep development velocity high without normalizing risk.

1) Width Converter Module

Primary file: fpga/util/width_converter.v (View Module Details)

Implemented proper width conversion between PCIe (256-bit) and DMA (512-bit) data paths.

Key capabilities

  • Bidirectional conversion (upsizing and downsizing)
  • Buffering and flow-control support
  • last signal propagation
  • Parameterized power-of-two width ratios
  • Back-pressure support via ready/valid handshakes

Integration approach

  • Used via pcie_dma_width_adapter and dma_pcie_width_adapter
  • Replaces prior truncation/padding logic
  • Removes width-mismatch data loss risk

Width converter integration points in-project

  • Top-level boundary: instantiate at PCIe↔DMA boundaries in fpga_top.v (or equivalent integration module).
  • PCIe ingress path: between pcie_endpoint.v stream outputs and DMA input path.
  • PCIe egress path: between DMA output stream and PCIe transmit path.
  • Verification anchor: mirrored in testbench/tb_dma_engine.v for width-mismatch regression coverage.

Width converter code example

// 256-bit PCIe stream -> 512-bit DMA stream
width_converter #(
	.INPUT_WIDTH(256),
	.OUTPUT_WIDTH(512)
) u_width_converter (
	.clk(clk),
	.rst_n(rst_n),
	.s_data(pcie_data),
	.s_valid(pcie_valid),
	.s_last(pcie_last),
	.s_ready(pcie_ready),
	.m_data(dma_data),
	.m_valid(dma_valid),
	.m_last(dma_last),
	.m_ready(dma_ready)
);

2) Clock Domain Crossing (CDC) Modules

Primary file: fpga/util/cdc_modules.v (View Module Details)

Added safe synchronization patterns for production multi-clock deployments.

Included modules

  • cdc_sync: multi-stage synchronizer for control signals
  • cdc_pulse_sync: reliable single-cycle pulse transfer
  • cdc_handshake: request/ack protocol for data transfer safety

CDC integration points in-project

  • Reset/status controls: use cdc_sync for level/control signals crossing domains (e.g., enable/status flags).
  • Event signaling: use cdc_pulse_sync for interrupt-like one-shot events between pcie_clk and user_clk domains.
  • Control-plane payloads: use cdc_handshake for small config/status data transfers that must be acknowledged.
  • Placement guidance: keep CDC modules at explicit domain boundaries (not deep inside algorithmic logic) for easier timing/debug.

CDC module code examples

// 1) Multi-stage control-signal synchronizer
cdc_sync #(
	.WIDTH(1),
	.STAGES(2)
) u_cdc_sync (
	.dst_clk(user_clk),
	.dst_rst_n(user_rst_n),
	.src_data(ctrl_src),
	.dst_data(ctrl_dst)
);
// 2) Single-cycle pulse transfer between clock domains
cdc_pulse_sync u_cdc_pulse_sync (
	.src_clk(pcie_clk),
	.src_rst_n(pcie_rst_n),
	.src_pulse(pcie_irq_pulse),
	.dst_clk(user_clk),
	.dst_rst_n(user_rst_n),
	.dst_pulse(user_irq_pulse)
);
// 3) Full data handshake crossing
cdc_handshake #(
	.DATA_WIDTH(32)
) u_cdc_handshake (
	.src_clk(pcie_clk),
	.src_rst_n(pcie_rst_n),
	.src_data(cfg_data_src),
	.src_valid(cfg_valid_src),
	.src_ready(cfg_ready_src),
	.dst_clk(user_clk),
	.dst_rst_n(user_rst_n),
	.dst_data(cfg_data_dst),
	.dst_valid(cfg_valid_dst),
	.dst_ready(cfg_ready_dst)
);

3) Width Adapter Wrappers

Primary file: fpga/util/width_adapters.v (View Module Details)

Convenience wrappers for common conversion paths:

  • pcie_dma_width_adapter: 256-bit PCIe → 512-bit DMA
  • dma_pcie_width_adapter: 512-bit DMA → 256-bit PCIe

Benefits:

  • Faster integration
  • Consistent interfaces
  • Reduced wiring mistakes at boundaries

Wrapper code examples

// PCIe (256b) -> DMA (512b) wrapper usage
pcie_dma_width_adapter #(
	.PCIE_WIDTH(256),
	.DMA_WIDTH(512)
) u_pcie_dma_width_adapter (
	.clk(clk),
	.rst_n(rst_n),
	.pcie_data(pcie_data),
	.pcie_valid(pcie_valid),
	.pcie_last(pcie_last),
	.pcie_ready(pcie_ready),
	.dma_data(dma_data),
	.dma_valid(dma_valid),
	.dma_last(dma_last),
	.dma_ready(dma_ready)
);
// DMA (512b) -> PCIe (256b) wrapper usage
dma_pcie_width_adapter #(
	.DMA_WIDTH(512),
	.PCIE_WIDTH(256)
) u_dma_pcie_width_adapter (
	.clk(clk),
	.rst_n(rst_n),
	.dma_data(dma_data),
	.dma_valid(dma_valid),
	.dma_last(dma_last),
	.dma_ready(dma_ready),
	.pcie_data(pcie_data),
	.pcie_valid(pcie_valid),
	.pcie_last(pcie_last),
	.pcie_ready(pcie_ready)
);

4) Testbench Infrastructure

Primary file: fpga/testbench/tb_dma_engine.v (View Module Details)

Introduced baseline functional verification scaffolding.

Current coverage:

  • Module-presence checks
  • Clock/reset behavior
  • Test pass/fail reporting
  • Timeout protection
`timescale 1ns / 1ps

module tb_fpga_dma_engine;
	reg clk;
	reg rst_n;
	parameter CLK_PERIOD = 4; // 250 MHz

	initial begin
		clk = 0;
		forever #(CLK_PERIOD/2) clk = ~clk;
	end

	initial begin
		rst_n = 0;
		#(CLK_PERIOD * 10);
		rst_n = 1;
	end

	// Example DUT hook-up (excerpt)
	pcie_dma_width_adapter u_pcie_dma_width_adapter (
		.clk(clk),
		.rst_n(rst_n),
		.pcie_data(pcie_data),
		.pcie_valid(pcie_valid),
		.pcie_last(pcie_last),
		.pcie_ready(pcie_ready),
		.dma_data(dma_data),
		.dma_valid(dma_valid),
		.dma_last(dma_last),
		.dma_ready(dma_ready)
	);
endmodule

Copy-ready templates for your next phase

Template A — roadmap (phase-based)

## FPGA Infrastructure Roadmap

### Phase 1: Safety Baseline (Now)
- [ ] Width adapters inserted at every width boundary
- [ ] CDC modules inserted at every clock-domain boundary
- [ ] Baseline testbench passing smoke scenarios

### Phase 2: Functional Confidence
- [ ] Descriptor lifecycle tests (fetch → schedule → execute → complete)
- [ ] Back-pressure and burst edge-case coverage
- [ ] Interrupt/completion flow validation

### Phase 3: Hardware Bring-up
- [ ] PCIe link training + enumeration verified
- [ ] BAR read/write behavior verified
- [ ] End-to-end transfer integrity verified on board

### Phase 4: Production Hardening
- [ ] Error injection + recovery flows validated
- [ ] Timing closure achieved
- [ ] Performance baseline captured and documented

Next: Component Library →