Connect DVP to Tiny DMA2/request 11, IRQ15 and the camera pad/reset lifecycle. Harden shared capture CDC, frame statistics, per-row size validation and HAL cleanup while preserving the Mini DMA3 binding and existing register ABI. Add deterministic capture/recovery firmware, source-bound evidence tooling, focused RTL/host tests and compact netlist acceptance. Preserve SAFE24, 128 KiB main SRAM, private Crypto storage and the locked dependencies. Retained validation: focused RTL, host/policy checks, Mini firmware, and ICS55/IHP130 RECOVERY, QVGA, synthesis and boot/DVP netlist checks pass. Full-system VGA remains historical; long full Icarus and broad regressions remain deferred. Global publication/format gaps and negative observational STA are retained, not reported as passing qualification. Specification: docs/ip/tiny-soc.md, TINY-R2-P9. Evidence: docs/ip/tiny-soc-verification.md.
19 KiB
APB4 DVP
The DVP block captures an 8-bit parallel camera stream and presents the captured pixels through an AXI4-Stream source. APB4 is used for configuration, status, statistics, error reporting, and interrupts. The existing DMA engine can transfer the AXI4-Stream payload into AXI4 memory using DVP receive mode. The input path supports RGB565 and YUV422 byte formats, programmable VSYNC and HREF polarity, selectable PCLK sampling edge, snapshot and continuous capture, and rectangular cropping.
Integration
| Property | Value |
|---|---|
| APB4 base address | 0x1000E000 |
| APB4 interrupt group bit | 13 |
| Management-core interrupt | 15 |
| Input interface | 8-bit parallel data, PCLK, HREF, VSYNC |
| AXI4-Stream data width | 32 bits |
| AXI4-Stream frame markers | TUSER[0] SOF, TLAST EOL |
| DMA request selector | DVP_RX=11; Mini default bulk DMA channel 3 |
| ABI version | 0x00020000 |
The Tiny Gen1 R2 target reuses this IP specification and ABI
unchanged at the same base/core IRQ, with product-selected DMA channel 2,
PCLK host/stream, GPIO12-23 ALT1 camera routing and optional XPI NSS1 PSRAM
frame buffers. Camera and I2S profiles are mutually exclusive. Its
TINY-R2-P9 integration must validate exact transfer length, shared HAL
channel/burst binding and final-word drain without changing the DVP registers,
formats, FIFO or stream semantics. The product contract requires measuring
the existing 512-byte FIFO's stall budget and qualifying PSRAM transport in
TINY-R2-P8 before capture integration.
Tiny support remains a frozen target, not existing end-to-end or physical
evidence; Mini's channel-3 default remains unchanged.
The separately approved PPALite extension inserts an optional processing route after this existing CDC FIFO in the future standard Tiny product. RAW remains reset-default and preserves this DVP V2 stream/ABI. PROCESS performs pixel/line selection and row-aligned output packing before the same DVP_RX request11/DMA2 destination path. It adds no source format, Pad, FIFO depth, central-DMA request or private memory master to DVP. Mini retains RAW integration. No PPALite path is implemented by this freeze.
The pixel clock is buffered and can be inverted before the pixel-domain reset
synchronizer. Configuration and frame statistics cross between the system and
pixel domains through the common cdc_2phase primitive. Captured payloads use
the common cdc_fifo_warm_flush primitive and carry
{TUSER, TLAST, TKEEP, TSTRB, TDATA}. FIFO overflow drops the active frame,
sets an error flag, and requires software to discard the affected DMA buffer.
Register ABI
All registers are 32 bits and naturally aligned. Unmapped, unaligned, and
direction-invalid accesses complete with resp_err. Configuration writes are
rejected while capture is active. Frame dimensions must be non-zero; invalid
format or crop values set the configuration error path and do not start a
valid capture. RW registers support byte strobes.
| Offset | Name | Access | Description |
|---|---|---|---|
0x000 |
CTRL |
RW | Enable, snapshot, and crop-enable controls. |
0x004 |
RXDATA |
RO/pop | PIO receive word when AXI4-Stream output is disabled. |
0x008 |
STATUS |
RO | Active, FIFO, stream, and error state. |
0x00C |
STREAM_CTRL |
RW | Enable AXI4-Stream output. |
0x010 |
FORMAT |
RW | RGB565/YUV422 selection and byte/pixel swap controls. |
0x014 |
SYNC_CFG |
RW | VSYNC, HREF, and PCLK polarity controls. |
0x018 |
FRAME_SIZE |
RW | Frame width in bits 15:0 and height in bits 31:16. |
0x01C |
CROP_START |
RW | Crop X coordinate in bits 15:0 and Y coordinate in bits 31:16. |
0x020 |
CROP_SIZE |
RW | Crop width in bits 15:0 and height in bits 31:16. |
0x024 |
FRAME_COUNT |
RO | Completed frame count. |
0x028 |
LINE_COUNT |
RO | Completed line count from the last frame. |
0x02C |
PIXEL_COUNT |
RO | Captured pixel count from the last frame. |
0x030 |
WORD_COUNT |
RO | Full 32-bit AXI4-Stream word count from the last frame. |
0x034 |
DROP_COUNT |
RO | Number of dropped words caused by overflow. |
0x038 |
ERROR_STATUS |
RW1C | Sticky overflow, sync, size, partial, config, and abort errors. |
0x03C |
INTR_STATE |
RW1C | Sticky frame, line, overflow, configuration, and abort events. |
0x040 |
INTR_ENABLE |
RW | Interrupt enable mask. |
0x044 |
INTR_STATUS |
RO | INTR_STATE & INTR_ENABLE. |
0x048 |
INTR_TEST |
WO | Write-one software interrupt injection. |
0x04C |
COMMAND |
WO | Abort and FIFO flush commands. |
0x0F8 |
IP_VERSION |
RO | ABI version, currently 0x00020000 (2.0). |
0x0FC |
CAPABILITY |
RO | Implemented format, crop, statistics, interrupt, and stream features. |
CTRL bit 0 enables capture, bit 1 selects snapshot mode, and bit 2 enables
cropping. STREAM_CTRL bit 0 enables AXI4-Stream output; when it is clear,
software can consume captured words through RXDATA. FORMAT values 0 and
1 select RGB565 and YUV422 respectively. Values above 1 are invalid.
FORMAT bits 2 and 3 control byte and pixel ordering. SYNC_CFG bits 0, 1,
and 2 select active-low VSYNC, active-low HREF, and falling-edge PCLK.
The seven interrupt bits are frame start, line done, frame done, overflow,
synchronization error, configuration error, and aborted capture. Error and
interrupt state are write-one-to-clear. Hardware events have priority over a
simultaneous software clear so that an event cannot be lost. The external
interrupt is the reduction OR of INTR_STATE & INTR_ENABLE.
STATUS bit 0 is ENABLE, bit 1 is ACTIVE, bit 2 is FIFO_EMPTY and bit 5
is ERROR. ENABLE reports the configuration actually applied in the pixel
domain; CTRL continues to read back the requested control value. Software
can therefore acknowledge a disable/enable transition without a new register.
ACTIVE is delivered with a coherent pixel-domain status snapshot;
it is not an alias for ENABLE. An error W1C is retained until the pixel domain
applies its mask and returns a status packet with the matching clear epoch.
Old reports cannot acknowledge that operation. New source errors take priority
over a simultaneous clear. APB response timing and register offsets remain
unchanged; software must poll with a timeout. A stopped pixel clock cannot
complete a clear or recovery operation.
Configuration transfer is held behind pending error clears. A separate applied
pixel configuration is updated only when the core accepts the mailbox; the
mailbox's earlier data presentation cannot modify an active frame.
Configuration and command transactions carry internal epochs; lifecycle idle
stays low until the matching applied/drained status is returned. Waiting for
the first VSYNC is armed work, not idle. Local reset-ready requires a native
pixel-domain status after reset. Tiny global boot uses its existing internal
leaf/APB/AXI prerequisites independently of this local-reset readiness, so an
absent sensor clock does not become a global CPU boot dependency.
ABORT cancels older configuration requests still waiting in the APB register shell without changing requested-register readback. Its command mailbox also carries the last issued configuration epoch. If that configuration arrives or applies after ABORT, it completes the existing acknowledgement but cannot rearm the core. The cancellation record is retired by the next different applied configuration epoch, before the one-bit epoch can be reused. Repeated or coalesced ABORT commands do not advance configuration epochs. ABORT does not wait for configuration readiness, including when an active frame blocks configuration application. Later configuration writes remain eligible after the command drains; normal recovery still clears errors and acknowledges disable/enable before using a new frame. No register or FIFO ABI is added.
Error interrupt causes use a retained six-bit pending mask and an acknowledged mailbox, separate from the status snapshots. Repeated causes can coalesce while pending, but two events between status samples cannot cancel one another. New causes on mailbox acceptance remain pending for the next transfer. Clearing an interrupt does not repeatedly reassert it merely because ERROR_STATUS still holds an old error; a new occurrence does notify again.
The RTL ABI constants are maintained directly in
rtl/ip/multimedia/dvp_define.svh. Matching HAL offsets and masks are
maintained directly in crt/src/hal/dvp.c. Changes to either definition must
update the other definition, this document, and the RTL/software tests in the
same change.
AXI4-Stream and Capture Semantics
Two 16-bit pixels, each formed from two 8-bit sensor samples, are packed into
one 32-bit stream word. The first
pixel occupies TDATA[15:0] and the second pixel occupies TDATA[31:16].
TUSER[0] is asserted on the first word of a frame, and TLAST is asserted
on the last word of each line. TID and TDEST are tied to zero.
For an even number of pixels, TKEEP and TSTRB are 4'b1111. For an odd
number of pixels, the final word of each line uses 4'b0011 and the unused
upper half of TDATA is zero. AXI4-Stream TVALID remains asserted and the
payload remains stable while TREADY is low. The FIFO backpressures the pixel
domain; an inability to accept a word during an active frame records an
overflow and terminates that frame.
VSYNC rising after polarity normalization starts a frame. HREF qualifies
pixel sampling and its falling edge completes a line. Snapshot mode stops
after the next completed frame; continuous mode resets line and pixel counters
and captures the next frame. Crop coordinates are applied in the normalized
frame coordinate space, and a crop must fit within the configured frame size.
Snapshot completion remains stopped until a disabled configuration rearms it.
Source row width is checked against FRAME_SIZE, independently of crop
selection. The first complete pixel beyond the configured width reports
SIZE and ends the active frame before the column counter can wrap. HREF
falling with fewer complete pixels also reports SIZE. Compensating long and
short rows cannot form a valid frame merely because aggregate counts match.
Rows outside the crop are checked too. An incomplete final byte additionally
reports PARTIAL. These faults retain the existing sticky-error/event path;
they do not flush already accepted FIFO or DMA data. Software discards the
failed destination, drains/cancels DMA before source cleanup, and uses the
existing ABORT, W1C and acknowledged disable/enable rearm sequence.
An enabled source waiting for its first VSYNC does not treat the preceding
partial frame as captured data. ABORT/FLUSH execute only on an accepted
command handshake, not repeatedly from a retained CDC payload.
The PIO path and AXI4-Stream path are mutually exclusive at the output:
RXDATA pops a word only while stream output is disabled. The DMA HAL uses a
single-frame transfer length; descriptor rings, double buffering, and frame
metadata chaining are not part of the current ABI.
DMA and Software Contract
The DMA MVP treats each full AXI4-Stream word as one 32-bit memory write.
It accepts only TKEEP=4'hf; an odd-pixel DVP line produces a partial final
word and therefore requires PIO handling or a future narrow-transfer/DRE DMA
extension. Software should configure the frame and crop dimensions, clear
stale error and interrupt state, program the product-selected DVP_RX destination
and capacity, enable stream output, and then start DVP capture. A frame that
reports overflow, synchronization, partial, DMA, or abort errors must not be
consumed by software.
The existing convenience helper uses Mini's channel-3 binding; Tiny must
supply its product transport configuration as specified in its integration
contract before that helper is advertised as supported there.
The public HAL exposes structured configuration, bounded status polling,
command and interrupt control, capability discovery, and a convenience API
for one-frame DMA capture. Applications should use rs_dvp_configure(),
rs_dma_configure(), rs_dma_start(), rs_dvp_start(), and
rs_dvp_capture_dma() rather than
accessing the registers directly.
The snapshot helpers derive transfer length from the current frame/crop
geometry. word_capacity bounds the destination; it is not a request to fill
the entire allocation. DMA rejects odd active widths, insufficient capacity
and address overflow before starting. PIO uses ceil(width / 2) * height
storage words and preserves the zero-padded final halfword in each odd row.
Success requires a new completed frame, exact pixel/word and DMA counts, an
empty FIFO and all destination responses. The helper initializes CRC options
explicitly. Tiny uses channel 2/four-beat bursts; Mini retains channel 3 and
its existing maximum-burst default.
Each convenience capture rearms the existing snapshot configuration through
an acknowledged non-flushing disable/enable sequence; callers need not repeat
rs_dvp_configure() between successful captures. PIO refuses a busy or suspended
product-selected DMA consumer before changing stream mode, interrupts or FIFO
contents. The source must also be inactive with an empty FIFO before rearm.
Recovery drains/aborts DMA before issuing a source abort that clears FIFO
storage. A failed DMA drain is returned to the caller without clearing the
source tail. rs_dvp_abort() refuses a busy product-selected DMA channel and
waits for an acknowledged abort, FIFO empty and error clear. Recovery timeout
is an error, not permission to reuse the buffer or rearm capture.
Frozen PPALite Source and Route Contract
The PPALite contract owns the processed pixel formats, derived geometry, padded row pitch and buffer metadata. In PROCESS, DVP cropping stays here, BYTE_SWAP/PIXEL_SWAP are zero, and the processor interprets the explicit sensor byte order. Raw DVP still exposes two16-bit pixels per full stream word, or a final halfword for an odd-width row. A legal halfword row tail must not be confused with an invalid incomplete sensor pixel.
RAW DMA retains its even-active-width requirement. PROCESS may consume the
legal halfword tail and emit full padded words; that is a new downstream
operation, not a retroactive change to this source stream or a narrow-DMA mode.
Raw helpers on PPALite-capable Tiny must reject PROCESS before programming
capture, and the PPALite HAL must use its derived length rather than raw
2 * width * height. The unchanged Mini default channel3 is not copied to Tiny.
Route changes require stopped/acknowledged DVP configuration and cleanup, empty source/processor endpoints and the full central-DMA barrier defined by PPALite. The route is locked through capture/failed cleanup. Fixed PROCESS may be retained between frames without stopping unrelated DMA clients. The Tiny source guard freezes geometry/format/crop while owned, verifies actual configuration/command CDC completion, and admits only the ordered source start, non-flushing snapshot stop and isolated cleanup operations. Diagnostic reads and the DVP register map remain unchanged.
Before processed capture is qualified, PPALITE-P2 must close or reuse current R2 evidence for source correctness: real SYNC/SIZE/PARTIAL detection, exact statistics beyond65535 words, coherent host-side active/configuration/status, every repeated frame event, error epochs and snapshot stop/rearm behavior. The R2-P9 candidate implements SYNC/SIZE/PARTIAL detection and a 32-bit word counter transported through a 144-bit completed-frame mailbox. These source guarantees still require matching validation; a downstream image/checksum alone does not establish them. Minimal shared correctness fixes must retain register offsets/meanings, the512 B payload FIFO and Mini compatibility.
The internal statistics layout is {drop[31:0], words[31:0], pixels[31:0], lines[15:0], frames[31:0]}. The existing two-phase CDC carries the entire
144-bit snapshot; register offsets and the separate 128-bit configuration
channel are unchanged. VGA 640x480 at two bytes per pixel reports 153600
words rather than the former 16-bit wrapped value 22528. PIO counts one
additional halfword-bearing word at each odd-width row end.
Valid processed completion requires this source's full-frame/statistic/error verdict, a checked non-flushing stop, processor counts and exact DMA length including final memory write responses. PPALite PIPE_DONE or a last EOL is not source-frame validity. Continue monitoring late source faults until the capturing HAL finalizes its result; do not publish a plausible prefix.
The current ABORT command also requests source FIFO clearing. Failed processed capture therefore closes admission, drains/aborts its DMA, acknowledges old stream isolation, and only then issues source ABORT/FLUSH and processor cleanup. Ordinary stream VALID cannot be withdrawn while a live consumer still owns the beat. Missing PIXCLK or flush/reset acknowledgement retains failed-session ownership; no fabricated padding or common-DMA reset substitutes for recovery. The existing helper's early success-path abort must be corrected/avoided with shared checked lifecycle helpers before either route is advertised as complete.
The original FIFO still receives raw sensor bytes. Its overflow budget is not enlarged simply by dividing final image width or extracting Y. Preserve raw-rate occupancy/margin calculations and validate any extra downstream buffer credit explicitly. These new obligations have no passing evidence yet.
Verification and Current Scope
The self-checking RTL test covers the versioned ABI, invalid APB4 accesses, configuration writes, RGB565 packing, SOF/EOL framing, even and odd line widths, AXI4-Stream output, frame statistics, and interrupt state handling. The SBY target proves APB4 response behavior, request/response progress, interrupt composition, and normal/error coverage for the register shell. Host tests compile and execute the DVP directed test, while the IHP130 regression exercises behavior simulation, synthesis, netlist simulation, and STA integration.
The current ABI does not include a native DVP AXI4 memory master, outstanding AXI transactions, frame descriptor rings, line stride configuration, JPEG or other compressed formats, external sync metadata, or multiple camera clocks. Those features require a versioned ABI extension and explicit SoC routing; existing register fields must not be repurposed for them.
RTL Coding-Style Migration
The current DVP maintenance pass is limited to source organization and naming;
it does not change the register ABI, APB4 timing, AXI4-Stream framing, CDC
topology, pixel packing, interrupt behavior, or error semantics. Register
address macros retain their APB4_DVP_* names so the software HAL remains
compatible. Internal field macros use the APB4_DVP__* namespace, and local
parameters use UpperCamelCase. Internal configuration and command paths use
the project abbreviations cfg and cmd, while public APB4 and AXI4-Stream
interfaces remain unchanged.
Owned DVP modules use explicit named-port connections. Module ports and macro
definitions are manually column-aligned only inside narrow
verilog_format: off/on regions where Verible cannot preserve the alignment;
ordinary declarations, assignments, and instances remain formatter-managed.
The dvp_camera simulation model follows the same naming and named-port
rules. Its delayed falling-edge assignment is intentionally retained because
it models camera HREF timing and is not synthesizable IP behavior.
The local validation entry points are:
python3 -m pytest -q tests/test_dvp.py
make CONFIG=configs/ci/ihp130.mk formal-dvp
make format-check rtl-style-check-all rtl-readiness-check-all