← All engineering notes
ENGINEERING NOTE · STORAGE CONTROLLER

An NVMe SSD front end,
built in 7 days.

Directed by one designer, Melten's design-agent system built the Host-facing front end of an NVMe SSD controller on an AMD Versal FPGA in 7 days.1 Ubuntu's standard NVMe driver runs it like any SSD. Over PCIe Gen4 x8, it moved 13.9 GB/s each way, 88–89% of the link's raw rate, and 3.3 million 4 KiB I/Os per second.2

Host NVMe queuesStorage back end
An SSD controller's front end turns the Host's NVMe commands into PCIe data transfers, completions, and interrupts. This one is hardware on one AMD Versal FPGA, with a DRAM disk standing in for the flash back end.
7 days
From specification to Gen4 x8 board results1
13.9 GB/s
Sequential reads and writes, each, through PCIe Gen4 x82
3.3M IOPS
4 KiB random reads (3.27M) and writes (3.30M)2
8 / 8
Data-integrity checks passed, including after controller reset, reboot, and power-on5
WHY IT MATTERS

Why it matters

Specification in. Working NVMe drive out.

Directed by one designer, agents produced the architecture, RTL, firmware, verification, FPGA builds, board bring-up, and performance tuning.

Standard to the Host.

Ubuntu's own NVMe driver finds the drive, creates eight I/O queues, and runs I/O. BIOS boot, shutdown, reboot, and controller reset work too.

Near the link limit.

13.9 GB/s each way and 3.3M random IOPS. Packet headers take most of what remains of the Gen4 x8 link's raw rate.

Built for a flash back end.

Every I/O step runs in hardware. A DRAM disk stands in for the FTL and NAND, behind a back-end interface designed for them.

AMD VERSAL VMK180 BOARD · AS THE HOST SEES IT
Ubuntu 26.04 · lspci -nnvv
# lspci -nnvv (excerpt)
01:00.0 Non-Volatile memory controller [0108]: Melten NVMe DRAM Disk [fb38:eb80] (rev 01) (prog-if 02 [NVM Express])
        Capabilities: [60] MSI-X: Enable+ Count=16 Masked-
                        MaxPayload 256 bytes, MaxReadReq 512 bytes
                LnkCap: Port #0, Speed 16GT/s, Width x8, ASPM not supported
                LnkSta: Speed 16GT/s, Width x8
        Kernel driver in use: nvme
An excerpt of the Host's own view of the board during the final verification run: an NVMe controller on a 16 GT/s x8 link (PCIe Gen4 x8), with MSI-X interrupts, bound to Ubuntu's standard nvme driver. Lines are copied from the run's log; other lines are omitted.
WHY THIS IS HARD

Millions of commands a second,
all in hardware.

An NVMe front end must follow the specification closely enough for an unmodified Host driver, and keep enough commands and data in flight to fill a Gen4 x8 link whose Host-memory reads take on the order of a microsecond.

RequirementWhat it takesHow this front end does it
Host compatibilityStandard driver, full lifecycle: NVMe registers, Admin and I/O queues, PRP data pointers, MSI and MSI-X, plus BIOS boot, shutdown, reboot, and controller reset.Registers and queues in hardware; Admin commands and controller lifecycle in Arm Cortex-R5F firmware; all checked with Ubuntu's driver on the board.
Command rateA command every 306 ns: at 3.3M IOPS, fetch, decode, data pointers, transfer, completion, and interrupt must overlap.A hardware pipeline with no processor in the I/O path. Each measured command-path stage serves at least 15M commands/s in simulation.6
BandwidthMicrosecond-scale Host reads: filling 15.75 GB/s takes many transfers in flight at once.A 512-bit datapath at 250 MHz (16 GB/s), with 16 transfer slots and 12 outstanding Host reads, sized from latencies measured on the board.
Vendor IPA vendor path that stalled: with AMD's CPM4 PCIe AXI bridge, Host-memory reads cross the on-chip network (NoC). On Gen4 x4, NVMe writes, where the device reads Host memory, reached only 1.9 GB/s, while NVMe reads reached 6.9 GB/s.Agents wrote Melten's own PCIe AXI Bridge on the CPM4's native packet interface. It bypasses the on-chip network for Host-memory access and puts packet packing and buffering under their control.
Vendor bridge replaced

Overcoming IP bottlenecks with the Melten PCIe AXI bridge.

With AMD's CPM4 PCIe AXI bridge, the on-chip network's 2 KiB read reorder buffer was a likely bottleneck, given the long Host-read latency; a trial that gave NVMe writes a second network port nearly doubled them. Agents specified a replacement bridge and finished validating it with NVMe traffic on the board 21 hours later. With outstanding requests tuned to board-measured Host-read latency, the final Gen4 x8 image reached 13.94 GB/s for NVMe writes, the Host-memory-read direction, and 13.90 GB/s for NVMe reads.4

HOW IT WORKS

One PCIe link,
every I/O in hardware.

The Host posts commands to queues in its own memory and rings a doorbell. The front end fetches each command, resolves its data pointers, moves the data between Host memory and on-board DRAM buffers, writes the completion entry, and raises the interrupt, all in hardware. Firmware on one Arm Cortex-R5F handles Admin commands; a second runs the DRAM back end.

Written by agents: the NVMe front end (51 SystemVerilog files, about 10,100 lines), the PCIe AXI Bridge (35 files, about 7,600 lines), firmware for both cores (about 1,400 lines of C, plus shared utilities), FPGA integration, and board test tooling.

From AMD: the CPM4 PCIe controller, the Versal on-chip network and DDR4 memory controller, and the Arm Cortex-R5F cores.

NVMe front-end architecture. The Host connects over PCIe Gen4 x8 to the AMD CPM4 PCIe controller, then to Melten's PCIe AXI Bridge and the NVMe Front End, which contains registers and queues, the command pipeline, data movers, and completion and interrupts. A back-end interface connects the front end to a DRAM back end on an Arm Cortex-R5F, a stand-in for a future FTL and NAND back end. Data buffers and the DRAM disk live in DDR4 behind the Versal on-chip network. A second Arm Cortex-R5F runs Admin firmware.
Architecture overview. Every I/O command passes through the hardware front end; the Arm cores handle Admin commands and the DRAM back end. In a production SSD, the FTL and NAND would replace the DRAM back end behind the same interface.
MEASURED RESULTS

Near the link limit,
reads and writes.

fio on the Ubuntu Host in performance mode: data crosses PCIe to and from on-board DRAM buffers, and the back end skips only the DRAM-disk copy.2

PCIe Gen4 x8 raw rate vs. measured through the front end

Sequential read
Link raw · 15.75 GB/s13.90 GB/s (88%)
Sequential write
Link raw · 15.75 GB/s13.94 GB/s (89%)
4 KiB random read
Link raw · 15.75 GB/s3.27M IOPS (85%)
4 KiB random write
Link raw · 15.75 GB/s3.30M IOPS (86%)

The link carries at most 15.75 GB/s each way after encoding. Most of the rest is packet overhead: at the 256-byte payload size the Host set, headers and framing take 8.6% of the raw rate.3

Small blocks

3.3 million commands a second, at 96% of large-block bandwidth.

Each 4 KiB random read is a full NVMe command: queue fetch, data pointers, transfer, completion, and interrupt. At 3.27M per second, one finishes every 306 ns on average, and the link still carries 13.4 GB/s.

CORRECTNESS

Every data check passed.

On the same FPGA image in normal storage mode, the Host wrote and verified the whole 1 GiB namespace, then checked it again after a controller reset, a reboot, and a shutdown and power-on.5

8 / 8Data-integrity checks passed, with no NVMe or PCIe errors in the Host kernel log.
Write/read comparisons: CRC32C, SHA-256, and byte checks
5 / 5
Data intact after reset, reboot, and power-on
3 / 3
Namespace verified end to end
1 GiB

Performance mode. Throughput runs skip only the DRAM-disk copy; Host data still crosses PCIe into on-board DRAM buffers.

Scope. Graceful Host transitions only; no power-loss or error-recovery claim.

HOW THE AGENT SYSTEM WORKED

Specification to 13.9 GB/s,
in 7 days.

Agents carried the work from requirements to board tuning, one campaign at a time.

Function first, then speed.

The first image ran Ubuntu I/O with a simple data mover on Day 1.7. Later campaigns raised the clock to 250 MHz, the link to x8, and throughput to 13.9 GB/s, rechecking data correctness each time.

Measured latency, not assumptions.

On-chip logic analyzers measured Host- and DRAM-read latency on the board. Agents replayed those delays against the RTL in simulation to size queues and outstanding requests.

Bottlenecks measured, then removed.

Board trials, including a second write engine on its own network port, showed AMD's CPM4 PCIe AXI bridge limiting the Host-memory read path. Agents replaced the bridge rather than accept the limit.

7 DAYS · SPECIFICATION TO GEN4 X8 RESULTS
  1. Day 0
    SpecificationNVMe requirements and architecture.
  2. Day 1.7
    Ubuntu ran I/OGen4 x4 with the standard driver; data checks passed.
  3. Day 2.5
    250 MHz on the boardTiming closed; AMD's CPM4 PCIe AXI bridge held NVMe writes to about 1.9 GB/s on x4.
  4. Day 3.2
    Boot, shutdown, rebootController lifecycle with the Host's BIOS and Ubuntu.
  5. Day 3.6
    Gen4 x8 link512-bit datapath on a Gen4 x8 link.
  6. Day 4.6
    Melten bridge on the boardNVMe traffic through the new PCIe AXI Bridge.
  7. Day 5.1
    Timing-closed x8 imageNew bridge at 250 MHz; lifecycle and data checks passed.
  8. Day 7
    13.9 GB/s, 3.3M IOPSTuned final image; all data checks passed.

Day counts run from the first repository commit; no time is excluded.1

FOR ENGINEERS

Engineering details.

The front-end specification, final board measurements, and internal service rates, without interrupting the main story.

Open the specification and full results

Front-end specification

Hardware
AMD Versal VMK180 evaluation board (XCVM1802), PCIe Gen4 x8 to an Ubuntu 26.04 Host.
NVMe
NVMe 1.4c subset: one 1 GiB namespace with 4 KiB blocks; up to eight I/O queue pairs of 256 entries; PRP lists up to 256 KiB; volatile write cache with FUA and Flush.
Admin commands
Identify, Create/Delete I/O queues, Get/Set Features (Number of Queues), Get Features (Volatile Write Cache), and Get Log Page (SMART, zero-filled).
Interrupts
MSI and MSI-X, 16 vectors each; legacy INTx is not supported.
Datapath
512-bit AXI at 250 MHz; 16 transfer slots, 12 outstanding Host reads, 6 outstanding DRAM reads, 8 write credits.
PCIe
AMD CPM4 in native-stream mode with Melten's PCIe AXI Bridge; 512-byte payload capability, 256-byte payloads and 512-byte read requests as set by the Host.
Processors
Two Arm Cortex-R5F cores in split mode: one for Admin commands and controller lifecycle, one for the DRAM back end.
Implementation
Timing closed at 250 MHz (setup 0.000 ns, hold +0.006 ns); 153,948 LUTs, 126,276 flip-flops, 130 block RAMs; no DSPs or UltraRAM.
Verification
Verilator module and integration regressions with the production firmware, AMD interconnect simulation, on-board logic-analyzer captures, and Host-side fio and data checks.

Final board measurements

WorkloadThroughputIOPSShare of raw link rate
Sequential read13.90 GB/s12.94 GiB/s53.0K88.2%
Sequential write13.94 GB/s12.99 GiB/s53.0K88.5%
4 KiB random read13.38 GB/s12.46 GiB/s3.27M85.0%
4 KiB random write13.53 GB/s12.60 GiB/s3.30M85.9%

One 60-second run per workload on the final image. Three further 10-second runs of each workload, on the same image and Host settings, agreed within 0.2%. GB/s is decimal (109 bytes per second); GiB/s is binary.2

Internal service rates (RTL simulation)

Module and caseService intervalRate
Host-to-buffer data, aligned 4 KiB64 cycles14.901 GiB/s (16.000 GB/s)
Buffer-to-Host data, aligned 4 KiB64 cycles14.901 GiB/s (16.000 GB/s)
Either direction, unaligned 4 KiB65 cycles14.672 GiB/s (15.754 GB/s)
Command fetch, immediate responses3 cycles/command83.333M commands/s
Command fetch, 256-cycle response latency16.649 cycles/command; peak 16 outstanding15.016M commands/s
PRP processing, 4 KiB command9 cycles/command27.778M commands/s
Command decode through context lookup6 cycles/command41.667M commands/s
Completion entry through context lookup9 cycles/command27.778M commands/s

Actual RTL with finite resources and checked data, against peers that respond without delay, at 250 MHz. These cover the payload and command-path modules named here, not every stage of the controller.6

NOTES AND METHODOLOGY
  1. Elapsed time runs from the first commit in the design repository to the commit that recorded the final board results: 7.2 days, with no time excluded. The work ran as a sequence of campaigns: a functional Gen4 x4 drive, 250 MHz timing, Host lifecycle, Gen4 x8, the PCIe AXI Bridge, x8 timing closure with the new bridge, and final tuning.
  2. Measured with fio 3.41 on an Ubuntu 26.04.1 Host (Linux 7.0, Intel Core i5-11400): io_uring with direct I/O, fixed buffers, and registered files. Sequential cases use 256 KiB transfers, one job, and queue depth 16; random cases use 4 KiB transfers, eight jobs, and queue depth 16 per job. Performance mode replaces the back-end firmware with a hardware responder that skips the DRAM-disk copy; commands, PRP processing, data transfers between the Host and on-board DRAM buffers, completions, and MSI-X interrupts all run normally. The Host's IOMMU (VT-d) was disabled in BIOS and its CPU governor set to performance.
  3. Agents measured Host-memory read latency of ~1.7 μs directly on the physical board. At this latency, NVMe writes through AMD's CPM4 PCIe AXI bridge and NoC achieved only 1.9 GB/s on Gen4 x4.
  4. Normal storage mode runs the back-end firmware that copies data to and from the DRAM disk. With the whole 1 GiB namespace overwritten, the checks were: sequential and random 4 KiB writes with CRC32C read-back; Flush and FUA write/read byte comparisons; eight concurrent mixed readers and writers; a full per-chunk SHA-256 comparison; and the same pattern read back after an NVMe controller reset, a Host reboot, and a Host shutdown and power-on, without reprogramming the FPGA. One Host power-on needed a retry; the cause of the first failure is undetermined, and the data matched afterward. The checks do not establish behavior under power loss, abrupt reset during I/O, or error recovery.
  5. Service rates come from the actual RTL in simulation, with finite transfer slots and credits and with data and ordering checked, against peers that respond without delay. A 512-bit path at 250 MHz moves at most 16 GB/s. With injected peer latency, the rates fall, as shown in the project's reports. Stages not listed, such as queue arbitration, tag allocation, and the interrupt path, were verified for correctness on the board but not measured in isolation.
PROJECT INQUIRIES

Your next chip
starts here.

Tell us what you want your next chip to do.

contact@melten.ai