This repository is the main implementation tree for a full RTL AV1 encoder. The sibling ../SVT-AV1/ repository is reference-only and is used to validate feature behavior against a mature software encoder.
The goal is a full end-to-end AV1 encoder whose final output is:
- generated by the RTL encoder byte path itself
- decodable in FFmpeg or another standards-compliant AV1 decoder
- visually verified against the source
- delivered as playable outputs for representative proofs derived from the RTL-generated AV1 stream
Proof target:
- Big Buck Bunny at
1280x720 @ 24 fpsis a useful natural-video reference source, not a mandatory fixed-duration milestone - normally use the smallest clip that proves the behavior, even 1 frame for intra/residual or 2 frames when a KEY→INTER transition is enough
- use more frames only when the feature itself needs reference/GOP/quality behavior; longer runs such as 240 frames / 10 seconds are optional soak/regression evidence, not the required proof size
- AV1 bitstream generated by RTL, not software fallback assembly
- remove/archive generated or garbled artifacts that slow ASIC progress without adding proof
This README.md is a living status document and must be updated continuously while the encoder is being implemented.
Official external debug references pulled from the web are tracked in av1-reference-docs/external/README.md.
- Do not wait until project completion to refresh this file.
- Update it after meaningful implementation, simulation, decode, or verification changes.
- Update it for milestones, discoveries, blocker changes, ownership changes, validation results, and any feature movement worth preserving.
- Keep it aligned with
AGENTS.mdandav1-reference-docs/svt-av1-feature-inventory.md. - It must reflect the current supported feature subset, current verification status, known gaps, active blockers, and the currently recommended run flow.
- Important findings must not live only in terminal output, replies, or commit messages. If they affect what is true about the encoder, record them here.
The active program goal is full feature-complete RTL AV1.
- The reduced pre-ASIC freeze on canonical
mainat8994490d209a745fb157e999af616b49de2c6ce1is a historical checkpoint, not project completion. - The exact active source of truth is
FULL_RTL_SCOPE.md. - The exact matrix is derived from
av1-reference-docs/svt-av1-feature-inventory.mdplus the prior gap audit. - Historical checkpoint details live in
PRE_ASIC_HANDOFF.mdandP7_REFERENCE_BOUNDARY.md.
This is the README-level feature inventory for reaching a real full RTL AV1 encoder and then an ASIC-ready implementation. A green smoke test, a reduced checkpoint, or a software-writer-matching debug run is not completion unless the item is owned by the RTL path and independently decoded/verified.
- Bitstream ownership and headers: complete OBU, sequence header, frame header, tile group, metadata, packetization, and final IVF/container wrapping from RTL-owned bytes; remove dependency on the C++ debug writer for finished syntax.
- Entropy and CDF state: complete symbol/CDF coverage, adaptive CDF update and refresh semantics, frame-context carryover, and context reset rules across key/inter frames and GOP boundaries.
- Input/output surfaces: raw YUV and Y4M input, 8-bit and 10-bit 4:2:0,
Main/High/Professional profile signaling, automatic/explicit level signaling,
reconstructed-frame output, PSNR/SSIM reporting, still-picture/AVIF-style
support, and representative
1280x720 @ 24 fpsoutputs. - Partitioning and transforms: full recursive partition coverage, square and
non-square block sizes, transform-size/type selection, lossless
qindex=0/TX_4X4, delta-q, and reconstruction parity for every enabled transform. - Intra tools: complete luma/chroma intra prediction, CfL, filter intra, palette/screen-content decisions if kept in scope, and natural-keyframe proof cases beyond the current reduced probes.
- Coefficient syntax: full luma and chroma coefficient syntax across EOB ranges, coefficient magnitudes, transform sizes, transform types, qindex ranges, and dense/high-energy natural-content distributions.
- Chroma tools: non-flat Cb/Cr residual coding, chroma intra-neighbor ownership, chroma inter prediction/residual integration, and decoder-to-recon parity on natural chroma clips.
- Inter prediction and motion: multi-reference frames beyond LAST-only, complete MV predictor/context classes, fractional/subpel coverage, compound references, global/warped motion, OBMC, inter-intra, wedge/compound modes, MFMV/order-hint behavior, and broader natural-motion validation.
- Reference/GOP control: full reference-frame lifecycle, refresh-map management, random access, open/closed GOP behavior, overlays/show-existing frame handling if enabled, hierarchical layers, and long-sequence stability.
- Post-reconstruction filters: loop filter, CDEF, restoration, superres/film grain policy, and filtered-reference writeback before any filtered tool is advertised in the bitstream.
- Rate/quality control: CQP/CRF/VBR/CBR-style control as scoped, AQ/ROI, mode-decision/RD search, recode loops as needed, and quality/bitrate regression evidence against representative clips.
- Advanced/deferred AV1 tools: screen-content tools, segmentation, global metadata/signaling, and any remaining advanced AV1 tool that is not explicitly de-scoped in a future standards-backed decision.
- lint-clean synthesizable RTL with simulation-only code guarded or removed;
- explicit SRAM/DRAM/frame-buffer interfaces instead of testbench-owned memory assumptions;
- hierarchy-preserving synthesis scripts, constraints, and module-level gates;
- clock/reset strategy, CDC review if multiple clocks are introduced, and scan / DFT planning;
- timing, area, power, and gate-level simulation evidence on the chosen ASIC flow; and
- repo hygiene suitable for handoff: no generated build trees, stale worktrees, debug dumps, or software-authored final-bitstream shortcuts in the source tree.
The RTL must own the final AV1 syntax generation needed for completion. The testbench may feed raw YUV, capture RTL bytes, decode output, compute metrics, and package a playable container, but it must not author the final AV1 syntax on behalf of the RTL for project completion.
Historical reduced-freeze note: the checkpoint below intentionally disabled post-reconstruction AV1 filters; that is not the active program goal. Sequence headers signal enable_cdef=0 and enable_restoration=0, and every supported frame header keeps loop_filter_level[0..1]=0. With loop filter, CDEF, restoration, superres, and film grain disabled, the post-filter reference frame is identical to the unfiltered RTL reconstruction, so the harness may promote reconstructed luma/chroma buffers directly as LAST references.
This contract is tracked in P9_DISABLED_FILTER_POLICY.md and guarded by make bitstream-check, which parses sequence/key/inter headers and includes negative filter-enabled guard cases. If a future lane enables any of those filters, add real RTL post-recon filter/restoration writeback before dumping recon.yuv or promoting reference buffers; do not repair filtered references in the C++ testbench.
Validation record: the post-merge proof was rechecked on canonical commit 55850d927f4f6018bcc00d7556fef2029d2404c7 from origin/main in a clean detached worktree at /tmp/t_3754b875_clean. Local main is currently 11021fac2ca7644e3acda4e38931663bea4cb49a and is ahead of origin/main by 1 commit. Under THREADS=1 BUILD_JOBS=1, make -C tb bitstream-check, make -C tb top-public-matrix-check (FFmpeg/libdav1d and aomdec both matched recon.yuv on the 32x32 natural-ish fractional NEWMV proof), and make -C tb standalone-matrix-check all passed.
Simulation and Verilator builds should use the right thread count for the task at hand.
- For historical pre-ASIC AV1 Kanban validation matrix reruns and any doc/handoff checks, default to
THREADS=1 BUILD_JOBS=1. - For routine smoke/debug work on this host, use the host's detected thread count unless a task says otherwise.
- Do not force
THREADSabove the host's real thread count; Verilator 5.020 aborts at runtime if the model is built for more threads than theVerilatedContextcan create.
Routine smoke/debug commands on this machine:
THREADS=16 BUILD_JOBS=16 bash docker_run.shTHREADS=16 BUILD_JOBS=16 bash run.shcd tb
make THREADS=16 BUILD_JOBS=16Historical pre-ASIC validation matrix: see PRE_ASIC_HANDOFF.md for the canonical single-thread command and gate list; see FULL_RTL_SCOPE.md for the active scope.
Always use primary references before making codec decisions.
av1-reference-docs/av1-spec.pdfFULL_RTL_SCOPE.mdASIC_READINESS.md../SVT-AV1/- local or mirrored
libaomsources underav1-reference-docs/external/ - official blocker notes in
av1-reference-docs/external/README.md
Download and keep needed spec sheets and reference material locally. Prefer primary references over memory and verify temporary inferences quickly.
The repo-local test assets are stored under data/:
bigbuckbunny.mp4raw_frames.yuvffmpeg_reference.ivf
These are used for RTL encode, decode, and comparison against an ffmpeg AV1 reference encode.
Inventory of the current repo state:
- Implemented:
- 8-bit 4:2:0 low-delay bring-up flow
- fixed
8x8luma blocks inside64x64superblocks - luma intra search across
DC, directional,SMOOTH, andPAETH - luma transform, quantization, coefficient coding, inverse transform, and reconstruction
- reduced single-reference inter decision capture with integer-pel MVs
- ME candidate SAD accumulation fixed to include the final sample before best-match update
- bounded ME candidate raster seeded from
(0,0)before the valid search window - software-side debug writer for AV1 headers, tiles, and reduced block syntax
- testbench-side preservation of the raw RTL byte stream into per-frame
rtl_frames/*.obufiles plus a concatenated*_rtl_raw.obu - testbench-side direct capture of the RTL byte-valid path into
*_rtl_raw.obuand*_rtl.ivfownership artifacts, instead of relying only on the debug memory-write side effects - RTL reduced still-picture sequence header and keyframe header emission now matches the software writer's header prefix on the fast all-key debug case
- RTL raw frame OBU size byte is now back-patched to the actual emitted raw payload length at frame completion
- Chud PC 2 generated
16x16smoke ownership is back in sync on the RTL byte path:rtl/av1_encoder_top.vnow uses the append address (bs_wr_addr) rather than the drift-prone debug total when back-patching the frame OBU size and reportingbs_bytes_written- the testbench defaults to static-CDF /
disable_cdf_update=1, matching the current RTL entropy subset that does not yet own adaptive CDF updates - the sequence writer no longer forces the first IP-frame bootstrap packet through a software-only
INTRA_ONLY_FRAMEheader that the RTL header generator does not emit
rtl/av1_entropy.vnow uses a real AV1-style range coder for the existing bool, literal, and generic symbol interface instead of the old debug bit-packer- standalone entropy reference-check harness in
tb/test_entropy.cppandmake entropy-check - RTL top-level now tracks writer-style 8x8 neighborhood syntax state (
part_ctx,skip,mode) as groundwork for tile ownership - RTL raw payload now emits a real AV1 skip symbol per block before the older placeholder coefficient-bool stream
- RTL raw payload now also emits intra-block
y_mode, zeroangle_delta, and deterministicUV_DC_PREDsyntax for keyframe and intra-only blocks before the placeholder coefficient stream - RTL raw payload now emits the luma
txb_skip=0entry symbol and the deterministic zero-chromatxb_skip=1symbols before reconstruction, while still using the older placeholder luma coefficient-presence stream behind them - RTL raw payload now emits a first real luma coefficient syntax slice for intra DC-only 8x8 blocks with
eob=1and|qcoeff[0]| <= 14: intratx_type,eob,coeff_base_eob, boundedcoeff_br, and neighbor-aware DC sign - RTL raw payload now emits the first verified sparse low-order AC luma slice for intra 8x8 blocks where only
qcoeff[0]andqcoeff[1]are nonzero,qcoeff[8] == 0,|qcoeff[0]| <= 2, and|qcoeff[1]| == 1: fulleob_multi64symbol2,eob_extra=0,coeff_base_eobat scanc=2, zero base at scanc=1, DC base, DC sign, and AC sign - RTL raw payload now also emits the first verified dense low-order AC luma slice for intra 8x8 blocks where only flat indices
0,8,1, and10are nonzero with magnitudes1,1,2, and1: fulleob_multi64symbol4foreob=9,eob_extra=0including the trailing direct bits, zero bases through scan positions7..3, the context-2 bases at scan2and1, the DC base, and all three AC signs - software-writer coefficient scan order now matches the official libaom
default_scan_8x8table - RTL luma reconstruction now transposes the dequantized 8x8 coefficient matrix into the decoder-consistent flat-index orientation before the inverse 2D transform
- non-directional intra prediction now matches AV1's one-sided edge fallback rules for left-only and top-only blocks instead of forcing both missing sides to
128 - directional intra prediction now has a real top-right extension path for the current
8x8raster-order subset instead of always repeating the last top sample - RTL raw block syntax on non-key frames now emits the real
intra_intersymbol before block-mode syntax instead of falling straight fromskipto keyframe-styley_mode rtl/av1_bitstream.vno longer emits a placeholder non-key frame header; it now writes a reduced videoINTER_FRAMEheader matching the current software reference subset- the raw-path reduced inter subset now owns real single-reference LAST-frame motion syntax instead of only the earlier zero-motion scaffold:
- the ME decision is no longer clamped to zero-MV matches on the RTL-owned path
- the top-level now derives a reduced LAST-ref MV candidate stack from neighboring blocks, stores per-block integer MVs, and emits the real
newmv,zeromv,refmv,drl,mv_joint, sign, class, class0, and class-bit syntax on the RTL byte path - coefficient-bearing inter blocks continue through the real generic coefficient syntax path and use the inter
DCT_DCTtx_typeCDF on the RTL path instead of falling back to the old placeholder / intra-coded entry
rtl/av1_me.vnow preserves the already-tested zero MV when it is also the final legal raster-search candidate:- the old helper always skipped zero after the dedicated zero-MV probe, which pushed bottom-right blocks past the legal search window and could leave
TS_WAIT_MEspinning on longer clips - the scan now skips zero only when another in-range candidate still follows it
- the old helper always skipped zero after the dedicated zero-MV probe, which pushed bottom-right blocks past the legal search window and could leave
- standalone
rtl/av1_bitstream.vregression harness intb/test_rtl_bitstream.cppandmake bitstream-check - the P7 reference boundary checkpoint is a historical reduced LAST-only boundary documented in
P7_REFERENCE_BOUNDARY.mdand frozen on canonicalmainat8994490d209a745fb157e999af616b49de2c6ce1(already pushed toorigin/main); compound / multi-ref tools were disabled for that checkpoint, andFULL_RTL_SCOPE.mddefines the active program scope
- Validated:
- small still-picture and selected small video-path debug cases decode successfully
- official external debug references have been pulled into
av1-reference-docs/external/ - Chud PC 2 generated
16x16all-key and 2-frame IP smoke cases now pass the full ownership/decode gate withTHREADS=16 BUILD_JOBS=16:encoded.obu == encoded_rtl_raw.obuencoded.ivf == encoded_rtl.ivfffmpeg/libdav1d andaomdecdecoded output both matchrecon.yuv
16x162-frame IP output decodes in bothffmpeg/libdav1dandaomdec- decoded output matches
recon.yuvexactly on that16x16inter case - the pre-ASIC freeze on canonical
mainat8994490d209a745fb157e999af616b49de2c6ce1passed the single-threaded current matrix on Chud PC 2 withTHREADS=1 BUILD_JOBS=1: 21/21 gates, raw RTL OBU/IVF equality, FFmpeg/libdav1d parity, andaomdecparity all held, and no testbench or packaging repair masked RTL bugs - the strict
16x162-frame zero-motion IP ownership repro is now exact on the raw RTL path, not just decoder-clean:encoded.obuandencoded_rtl_raw.obunow match byte-for-byteencoded.ivfandencoded_rtl.ivfnow match byte-for-byte- the decoded raw RTL IVF now matches both
recon.yuvand the flat repeated-frame source exactly - the last frame-1 tile-data drift was the reduced single-ref
cmp_ctx=2/ branch-0 CDF entry on the RTL path; it now matches the software reference at3024
make entropy-check THREADS=$(nproc) BUILD_JOBS=$(nproc)passes in WSL and matches the C++AV1RangeCoderbyte-for-byte for bool, literal, and symbol casesmake bitstream-check THREADS=$(nproc) BUILD_JOBS=$(nproc) WIDTH=16 HEIGHT=16now passes in WSL:- sequence header bytes match the reduced reference model exactly
- video keyframe header bytes match the reduced reference model exactly
- the new video inter-frame header bytes match the reduced reference model exactly
- after adding non-key
intra_inter, reduced inter-header ownership, and zero-motion inter scaffolding, the16x16top-level build still advances cleanly on the small all-key smoke path - the
16x161-frame all-key top-level smoke still decodes and matchesrecon.yuvexactly after the entropy-core upgrade - the same
16x16smoke still decodes and matchesrecon.yuvafter moving the skip symbol onto the RTL raw path - the same
16x16smoke still decodes and matchesrecon.yuvafter moving intray_mode, zeroangle_delta, anduv_mode=DCsymbols onto the RTL raw path - the preserved RTL raw payload on that smoke case increased from
52to53bytes after the intra-mode syntax move, confirming the raw path changed while the software decode path stayed stable - the same
16x16smoke still decodes and matchesrecon.yuvafter moving luma/chromatxb_skipentry symbols onto the RTL raw path - the preserved RTL raw payload on that smoke case increased again from
53to56bytes after thetxb_skipmove, confirming the clean rebuild picked up the new raw syntax - a
16x161-frame all-key smoke atqindex=255still decodes and matchesrecon.yuvafter moving the first real DC-only luma coefficient syntax slice onto the RTL raw path - on that
qindex=255smoke, the preserved RTL raw payload dropped from28bytes to20, which is consistent with replacing the old placeholder coefficient-presence stream for the lone non-skip block - a
16x161-frame all-key smoke atqindex=128still decodes and matchesrecon.yuvafter extending that DC-only slice through the boundedcoeff_brpath - on that
qindex=128smoke, the preserved RTL raw payload dropped from48bytes to28, which indicates all four current DC-only luma blocks moved off the placeholder coefficient stream and onto the real DC-only coefficient path - the focused
16x16data/ac_probe_16x16_1f.yuvstill-picture check atqindex=240now decodes and matchesrecon.yuvexactly after:- correcting
tb/av1_bitstream_writer.hto libaom's realdefault_scan_8x8 - transposing the RTL inverse-path 8x8 coefficient matrix before IDCT
- fixing left-only / top-only non-directional intra edge fallback in
rtl/av1_intra_pred.v
- correcting
- the same focused
16x16data/ac_probe_16x16_1f.yuvcheck atqindex=240still decodes and matchesrecon.yuvexactly after moving the first sparse low-order AC subset onto the RTL raw path - on that sparse-AC check, the preserved RTL raw payload is now
35bytes and bothaomdecandffmpegdecode outputs matchrecon.yuvbit-for-bit - the same focused
16x16data/ac_probe_16x16_1f.yuvcheck atqindex=240still decodes and matchesrecon.yuvexactly after moving the first dense low-ordereob=9subset onto the RTL raw path - on that exact-match probe, the preserved RTL raw payload dropped again from
35bytes to29, which indicates the last remaining dense luma block on that clip moved off the placeholder coefficient bool stream and onto the real coefficient path - after the current mux fix, the isolated
highdc_16x16_1fownership repro no longer corrupts the raw RTL byte stream:encoded.obuandencoded_rtl_raw.obumatch byte-for-byte again- the written entropy byte sequence now matches the shadow
AV1RangeCoderoutput exactly on the same run
- the current
qindex=1failing repros are shared bugs, not writer-vs-RTL drift:output/highdc_q1/encoded.obuandoutput/highdc_q1/encoded_rtl_raw.obumatch byte-for-byteoutput/crop560_q1/encoded.obuandoutput/crop560_q1/encoded_rtl_raw.obumatch byte-for-byte
- a local upstream AOM reference decoder build with
CONFIG_ACCOUNTING=1andCONFIG_INSPECTION=1is now available for stricter syntax validation alongside ffmpeg/libdav1d - the video-keyframe path on that same
16x16data/ac_probe_16x16_1f.yuvprobe is now exact again, not just the reduced still-picture path:- the missing
refresh_frame_contextbit in the non-still frame header was restored beforetile_info - the remaining
22-byte luma drift was traced to a predictor/config mismatch, not coefficients: the sequence header advertisesenable_intra_edge_filter=0, so libaom disables both directional edge filtering and directional edge upsampling - the RTL directional predictor now keeps edge upsampling disabled on the current bitstream configuration, which restores bit-exact decoded-vs-
recon.yuvmatching on both the still-picture and video-keyframe outputs of the focused AC probe
- the missing
- the current
16x16data/tmp_probe_16x16_1f.yuvlocal fallback still packages the captured RTL byte path directly intoencoded_rtl.ivf - on that local fallback, software-owned and RTL-owned outputs still decode cleanly to
recon.yuv, but they are not byte-exact in this checkout:encoded.obuvsencoded_rtl_raw.obufirst differ at byte14- a temporary
rtl/av1_encoder_top.vrevert shows the same34vs35byte drift, so do not treat that clip as a regression caused by the new inter-path change
- the strict
16x16single-frame q sweeps remain exact on the natural DC-only crop, while the originaldata/ac_probe_16x16_1f.yuvexact-match gate is currently unavailable in this checkout:output/natural_focus_x640_y360_q128/input.yuvnow matches byte-for-byte betweenencoded.obuandencoded_rtl_raw.obufromqindex=1throughqindex=240- decoded output matches
recon.yuvon representative low and high q cases for that crop after the DC-base fix
- the raw RTL path now follows the same partition-tree leaf order as the software writer inside each superblock:
rtl/av1_encoder_top.vadvances blocks in Morton / recursive split order instead of plain raster order- this cleared the first larger-frame ownership drift that appeared after the
16x16fixes
- single-frame natural-content ownership now scales beyond the
16x16probes:- a
32x32qindex=128Big Buck Bunny crop now matches byte-for-byte betweenencoded.obuandencoded_rtl_raw.obu - a
64x64qindex=128Big Buck Bunny crop now matches byte-for-byte betweenencoded.obuandencoded_rtl_raw.obu - on both of those larger single-frame checks, software-owned and RTL-owned IVF outputs decode back to
recon.yuvexactly
- a
- the first larger natural-content repeated-frame zero-motion inter checkpoint is now exact on the RTL byte path:
data/natural_repeat64_x640_y360_2f.yuvis a64x64repeated-frame crop built from frame 0 ofdata/raw_frames.yuvat(640,360)- at
qindex=128,encoded.obuandencoded_rtl_raw.obunow match byte-for-byte - at that same checkpoint,
encoded.ivfandencoded_rtl.ivfnow match byte-for-byte and the decoded RTL IVF matchesrecon.yuv - the last drift on that clip was zero-motion inter blocks still taking the placeholder coefficient path and the intra
tx_typeCDF;rtl/av1_encoder_top.vnow routes them through the real generic coefficient path and the interDCT_DCTCDF
- reduced single-reference natural-motion ownership now extends beyond the repeated-frame zero-motion cases:
data/natural_motion64_x640_y360_2f.yuvat64x64,qindex=128, and2frames is byte-exact between software-owned and RTL-owned OBU/IVF outputs, and the decoded RTL IVF matchesrecon.yuvdata/natural_motion64_x640_y360_3f.yuvat64x64,qindex=128, and3frames is byte-exact between software-owned and RTL-owned OBU/IVF outputs, and the decoded RTL IVF matchesrecon.yuvdata/natural_motion32_x640_y360_3f.yuvat32x32,qindex=128, and3frames is byte-exact between software-owned and RTL-owned OBU/IVF outputs, and the decoded RTL IVF matchesrecon.yuv- the first motion-path drift on that bring-up was not MV payload packing; it was mis-ported raw
refmv/drlprobabilities instead of the actual AV1 ICDF entries, and correcting those ICDF values restored exactness on the motion clips
- the longer-motion exactness guards now extend past the earlier
3-frame limit after the ME bottom-right zero-skip fix:output/natural_motion32_x640_y360_5f_fix1/:32x32,5frames,qindex=128, byte-exact between software-owned and RTL-owned OBU/IVF outputs, decoded RTL IVF matchesrecon.yuvoutput/natural_motion64_x640_y360_5f_fix1/:64x64,5frames,qindex=128, byte-exact between software-owned and RTL-owned OBU/IVF outputs, decoded RTL IVF matchesrecon.yuvoutput/natural_motion64_x640_y360_6f_fix1/:64x64,6frames,qindex=128, byte-exact between software-owned and RTL-owned OBU/IVF outputs, decoded RTL IVF matchesrecon.yuvoutput/natural_motion64_x640_y360_7f_fixmvref64/:64x64,7frames,qindex=128, byte-exact between software-owned and RTL-owned OBU/IVF outputs, strictaomdecoutput matchesrecon.yuvoutput/natural_motion64_x640_y360_10f_progress70m/:64x64,10frames,qindex=128, byte-exact between software-owned and RTL-owned OBU/IVF outputs, strictaomdecoutput matchesrecon.yuv- the first longer-sequence drift was not MV payload packing; the reduced ref-MV stack was reaching one row and one column farther than AOM's
MVREF_ROW_COLS == 3scan and was overweighting a later NEWMV candidate by+4
- earlier
64x64repeated-frame anddebug_64x64_2fdecoder-corruption cases were cleared on the reduced video path before the ME core update - the first real non-zero fractional-pel translational checkpoint on the reduced single-reference LAST path is now exact:
make THREADS=1 BUILD_JOBS=1 me-checkpasses and confirms the half-pel refine search is activemake THREADS=1 BUILD_JOBS=1 WIDTH=32 HEIGHT=32 natural32-ip-fractional-syntax-check natural32-ip-newmv-syntax-check natural32-ip-syntax-checkpasses withencoded.obu == encoded_rtl_raw.obu,encoded.ivf == encoded_rtl.ivf, and FFmpeg/libdav1d plusaomdecdecode-vs-recon.yuvparity on the named 32x32 fixturesmake THREADS=1 BUILD_JOBS=1 natural32-chroma-syntax-check nonzero-chroma16-syntax-check nonzero-chroma-syntax-checkpasses with the same raw-byte and public-decoder parity on the named chroma fixturesmake THREADS=1 BUILD_JOBS=1 natural64-ip-fractional-syntax-checkpasses withencoded.obu == encoded_rtl_raw.obu,encoded.ivf == encoded_rtl.ivf, and FFmpeg/libdav1d plusaomdecparity on the 64x64 natural-motion guard- this is the first real non-zero fractional-pel translational motion on the reduced single-reference LAST path; it does not yet prove full AV1, multi-reference inter, arbitrary natural-motion coverage, or final 1280x720@24fps Big Buck Bunny validation, and the software writer/testbench still serves as the oracle where applicable
- Broken:
- decoded output is not yet verified as coming from a fully RTL-owned final AV1 syntax path
- Placeholder or debug-only:
- the current AV1 writer in
tb/is still being used as a software debug assembly path - chroma handling is still simplified relative to full AV1 completion
- the current AV1 writer in
- Missing:
- full RTL-owned AV1 byte generation for completion
- remaining roadmap items from
av1-reference-docs/svt-av1-feature-inventory.md - final target clip validation at
1280x720 @ 24 fps
- Not RTL-owned yet:
- final sequence header / frame header / tile / block syntax generation is still not fully emitted by the RTL byte path in the completion-ready form required by this project
- Added a public-decoder proof for the fixed large-DC lossy path at
qindex=1:make THREADS=1 BUILD_JOBS=1 p5-highdc-q1-public-checkbuilds a 16x16 all-key probe, prints a per-block coefficient summary, and requires RTL raw OBU equality, RTL IVF equality, FFmpeg/libdav1d decode-to-recon.yuv, andaomdecparity.
- Scope note: broader multi-block / wider-geometry coefficient diversity remains future work.
-
Added the next dynamic public-decoder proof for RTL-owned multi-block non-zero Cb/Cr coefficient syntax:
make THREADS=16 BUILD_JOBS=16 nonzero-chroma16-syntax-checkbuilds a 16x16 all-key frame with flat luma and non-neutral chroma, forcing multiple 4x4 chroma transform blocks.- The gate verifies RTL raw OBU equals the software oracle OBU, then verifies FFmpeg/libdav1d and
aomdecdecode the RTL IVF back to RTLrecon.yuv.
-
Root-cause fixes from this checkpoint:
- Top-level intra chroma prediction now reads already-reconstructed current-frame Cb/Cr neighbors, matching the luma
ref_rd_is_neighpattern instead of falling back to constant 128 for every block. - The testbench chroma reference read mux now selects current-frame reconstructed chroma memory for neighbor reads and previous-frame chroma memory for inter prediction reads.
- RTL now mirrors the oracle's Cb/Cr entropy context state for chroma
txb_skipand DC-sign contexts across neighboring blocks. - New chroma-neighbor fetch states use unique state encodings so they do not collide with the chroma-only TX-type states.
- Top-level intra chroma prediction now reads already-reconstructed current-frame Cb/Cr neighbors, matching the luma
-
The earlier one-block
nonzero-chroma-syntax-checkremains as the isolated 8x8 syntax gate; the new 16x16 gate closes the first multi-block non-flat chroma blocker. -
Added the next 32x32 natural-ish all-key gate:
make THREADS=16 BUILD_JOBS=16 natural32-chroma-syntax-checkbuilds a 32x32 deterministic gradient probe with non-flat luma and chroma.- Root cause fixed here:
TS_TXB_SKIP_CB/TS_TXB_SKIP_CRselectedcur_txb_chr_icdfwhile updatingchr_syntax_planein the same cycle, so multi-block frames could swap Cb/Cr txb contexts. Those states now select the Cb/Cr plane explicitly. - The 32x32 gate verifies RTL raw OBU equality plus FFmpeg/libdav1d and
aomdecdecode-vs-recon.yuvparity.
-
Added a 32x32 two-frame zero-MV inter residual gate:
make THREADS=16 BUILD_JOBS=16 natural32-ip-syntax-checkbuilds two repeated natural-ish 32x32 frames with+all_key=0and RTLme_zero_mv_only_inenabled.- This proves the reduced LAST-frame inter path can emit RTL-owned P-frame bytes with natural-ish non-zero residuals while keeping motion-vector syntax deterministic.
- The gate verifies concatenated RTL raw OBU equality plus FFmpeg/libdav1d and
aomdecdecode-vs-recon.yuvparity across both frames. - Parallel scouting found unconstrained 32x32 non-zero-MV natural IP still exposes a public-decoder/recon mismatch; that remains the next motion-specific blocker rather than mixing it into this zero-MV residual checkpoint.
-
Added the first top-level chroma residual plumbing slice after the TX_4X4 table checkpoint:
av1_encoder_topnow instantiatesav1_chroma_residualand runs it for each 4x4 Cb/Cr block before chroma reference write-back.- The top-level stores public Verilator-visible
chr_cb_qcoeff[],chr_cr_qcoeff[],chr_cb_has_coeff, andchr_cr_has_coefffor the software oracle / ownership path. tb/av1_bitstream_writer.hBlockInfoandtb/tb_av1_encoder.cppnow carry/capture those Cb/Cr qcoeff fields.tb/test_top_chroma_integration.pyplusmake top-chroma-integration-checkguard that the top-level does not regress to predictor-only chroma.
-
Important fix from this slice: raw chroma fetch and chroma inter prediction complete on different cycles, so
TS_CHR_WAITlatches their done pulses (chr_fetch_seen/chr_pred_seen) instead of requiring same-cycle completion. The old same-cycle wait caused the 16x16 2-frame IP smoke to hang in state 30. -
Verified after the fix: generated 16x16 all-key and 2-frame IP smoke still pass raw OBU exactness, IVF exactness, FFmpeg/libdav1d decode-vs-
recon.yuv, andaomdecdecode-vs-recon.yuv. -
The first constrained non-zero Cb/Cr TX_4X4 syntax proof is now in place for a one-block 8x8 all-key probe; broader 16x16+ non-flat chroma proof still needs decoder-matching chroma intra-neighbor prediction.
- The final AV1 bitstream is not yet fully generated by the RTL byte path.
- The current
tb/writer remains a debug and bring-up tool, not the acceptable final ownership model. - The preserved
*_rtl_raw.obuartifacts and the new*_rtl.ivfpackaging are ownership checkpoints only; they are not yet completion-ready AV1 streams. - The current generated
16x16all-key and 2-frame IP Chud PC 2 smoke cases are byte-exact between software-owned and RTL-owned raw/IVF artifacts and decode torecon.yuv; larger final-target/full-syntax ownership is still incomplete. - The entropy foundation is no longer the active blocker for tile ownership:
av1_entropy.vcan now encode reference-matching bools, literals, and generic CDF symbols- the raw RTL path now also owns the block skip symbol
- the raw RTL path now also owns the non-key
intra_interblock symbol - the raw RTL path now also owns keyframe and intra-only
y_mode, zeroangle_delta, and deterministicuv_mode - the raw RTL path now also owns luma/chroma
txb_skipentry symbols for the current reduced 8x8/4x4 transform subset - the raw RTL path now also owns a real DC-only luma coefficient slice for intra blocks with
eob=1, boundedcoeff_br, and neighbor-conditioned DC-sign context - the raw RTL path now also owns the first sparse low-order AC subset for the exact-match
qindex=240still-picture probe:eob=3,eob_extra=0, EOB coeff at flat index1, zero base at flat index8, and the corresponding DC/AC signs - the raw RTL path now also owns the first dense low-order AC subset on that same probe:
eob=9,eob_extra=0, nonzeros at flat indices0,8,1, and10, the intervening zero bases, and the corresponding DC/AC signs - the current software-owned exact-match path now also has its video-keyframe header and directional predictor configuration back in sync with the decoder on the verified
qindex=240probe:- non-still frame headers now emit
refresh_frame_contextbeforetile_info - the predictor no longer applies directional edge upsampling while the bitstream still advertises
enable_intra_edge_filter=0
- non-still frame headers now emit
- the direct RTL-owned byte capture path is now aligned with the software-owned payload on the focused
16x16ownership probe:tb/tb_av1_encoder.cppnow recordsbs_byte_valid,ec_byte_valid, and explicitmanual_bs_wrback-patches directly from the RTL top-level mux when buildingencoded_rtl_raw.obu/encoded_rtl.ivf- on the current
16x16probe, that direct capture matches the software-ownedencoded.obupayload byte-for-byte and decodes successfully once wrapped in IVF
- the larger single-frame ownership drift is now fixed through the first natural-content
32x32and64x64cases:- the raw RTL path now advances blocks in the same recursive partition-tree / Morton order that the writer and decoder expect inside each superblock
- this removed the first
32x32payload divergence that appeared once the frame needed more than the original16x16exact-match traversal
- the remaining ownership gap is extending that reduced non-DC path and matching syntax ownership beyond the current single-frame keyframe subset:
- full multi-frame / non-key ownership beyond the current reduced non-key header and the verified reduced LAST-ref motion checkpoints
- full inter syntax and motion signaling on the RTL path beyond the current reduced single-reference LAST
GLOBALMV/NEARESTMV/NEWMVownership subset with integer MV payloads - less constrained dense and higher-energy coefficient shapes beyond the current regression clips
- The current active exactness regression is now reference-decoder-backed:
- the strict
output/highdc_q1/first-block bug is now fixed:- the software debug writer and the RTL-owned raw path now both select the correct official TX_8X8 qctx tables from
qindex - AOM inspection now parses all four intended large-DC blocks at
qindex=1astx_size=1,eob=1, with the expected Golomb tail - ffmpeg now decodes
output/highdc_q1/encoded.ivf, anddecoded.yuvmatchesrecon.yuvbit-for-bit on that repro
- the software debug writer and the RTL-owned raw path now both select the correct official TX_8X8 qctx tables from
- the current P5 reduced-subset coefficient probes now have decoder-backed guards:
make p5-highdc-q1-public-checkproves the high-DC / non-zero-ACqindex=1lane through raw OBU equality, IVF equality, andffmpeg/aomdecdecode-to-recon parity
qindex=0remains a deferred lossless /TX_4X4feature, not part of the current supported reduced subset:- AOM reference inspection shows the decoder entering the lossless
TX_4X4path (tx_size=0) whenbase_q_idx=0 - until that separate lossless path is implemented, the testbench and RTL clamp requested
qindex=0runs to effectiveqindex=1so the current subset does not emit invalid streams
- AOM reference inspection shows the decoder entering the lossless
- the strict
- Full P-frame/inter-frame AV1 syntax support is still incomplete.
- The current raw-path inter subset now covers reduced single-reference LAST
GLOBALMV,NEARESTMV, andNEWMVwith reduced neighboring ref-MV stack derivation plus the first syntax-only subpel ownership slice:- the reduced inter frame header now signals
force_integer_mv=0andallow_high_precision_mv=1 - reduced
NEWMVcomponents now emit the realmv_frandmv_hpsymbols on both the software debug writer path and the RTL-owned syntax path
- the reduced inter frame header now signals
- The strict raw-path inter checkpoints are now cleared on both the zero-motion repeated-frame cases and the first natural-motion cases:
- the
16x162-frame flat repeated-frame IP repro is byte-exact between software-owned and RTL-owned OBU/IVF outputs - the
64x642-framedata/natural_repeat64_x640_y360_2f.yuvcrop is byte-exact between software-owned and RTL-owned OBU/IVF outputs, and the decoded RTL IVF matchesrecon.yuv - the
64x642-frame and3-framedata/natural_motion64_x640_y360_*f.yuvcrops are byte-exact between software-owned and RTL-owned OBU/IVF outputs, and the decoded RTL IVF matchesrecon.yuv - the
32x323-framedata/natural_motion32_x640_y360_3f.yuvcrop is byte-exact between software-owned and RTL-owned OBU/IVF outputs, and the decoded RTL IVF matchesrecon.yuv output/natural_motion32_x640_y360_5f_fix1/andoutput/natural_motion64_x640_y360_5f_fix1/are byte-exact at5frames,output/natural_motion64_x640_y360_6f_fix1/is byte-exact at6frames,output/natural_motion64_x640_y360_7f_fixmvref64/is byte-exact at7frames, andoutput/natural_motion64_x640_y360_10f_progress70m/is byte-exact at10framesoutput/natural_motion64_x640_y360_2f_subpel2/,output/natural_motion64_x640_y360_7f_subpel2/, andoutput/natural_motion64_x640_y360_10f_subpel2/now keep that same exactness after the syntax-only subpel header / payload move, and strictaomdecoutput still matchesrecon.yuv- the
64x64full-coeff low-delay LAST gradient gate is currently public-decoder clean through the first40requested non-zero integer motion blocks under the reduced cap (39NEWMVpayload blocks plus one stack-hitNEARESTMVblock): RTL raw OBU and IVF match the software oracle, and FFmpeg/libdav1d plusaomdecdecode back torecon.yuv - the repaired longer-motion root cause was the reduced ref-MV stack reach, not the MV payload encoder itself: matching AOM's
MVREF_ROW_COLS == 3scan removed the extra far-neighbor weight that had been flipping later NEWMV references - the first strict decoder corruption after enabling subpel syntax was shared writer/RTL syntax, not ownership drift:
mv_hpwas missing aftermv_fron reducedNEWMVcomponentsallow_high_precision_mvwas missing in the reduced inter frame header afterforce_integer_mv=0
- the next remaining inter ownership work is widening beyond the current reduced single-reference LAST syntax-only subpel subset into broader natural-motion clips and reference-MV-context debugging
- the
- Real chroma residual coding and fuller chroma tool coverage remain incomplete.
- The old
17/18-blockNEWMVthreshold is no longer the active blocker. - The current active blockers are:
- unrestricted
64x64+full-coeffNEWMV/ reference-stack / MV-prediction parity beyond the current reduced cap; do not treat cap raises as final completion - moving final AV1 syntax ownership out of
tb/av1_bitstream_writer.hand onto the RTL byte path - extending the verified
qindex=1+reduced subset beyond the current single-frame coefficient, partition, and syntax checkpoints - implementing the separate deferred
qindex=0/ losslessTX_4X4path instead of clamping it to the supported floor - widening beyond the current reduced single-reference LAST motion subset into multi-reference/reference-MV-context coverage on broader natural clips
- restoring the original
data/ac_probe_16x16_1f.yuvlocal asset in this checkout, becausedata/tmp_probe_16x16_1f.yuvis decode-clean but not a byte-exact substitute ownership gate
- unrestricted
- A lightweight debug probe now exists in the testbench:
+dump_inter_summary=1prints captured inter blocks, MVs, and nonzero counts after each frame+dump_blocks=1onoutput/highdc_q1/and the local AOMinspectbuild are now the fastest strict large-DC regression guard for the fixed qctx-selectedTX_8X8pathdata/ac_probe_16x16_1f.yuvremains the first exact-match regression gate at the verifiedqindex=240subset
- Larger roadmap phases in
av1-reference-docs/svt-av1-feature-inventory.mdare still open:- stronger inter syntax and motion signaling
- better partitioning and mode decision
- rate control beyond fixed QP
- deblock, CDEF, restoration, and later quality tools
- advanced deferred AV1 tools
- The final target clip has not been completed from the RTL-generated AV1 path.
Do not treat this project as complete until all of the following are true:
- the AV1 stream is produced by the RTL byte path
- the stream decodes correctly end to end
- the decoded output has been visually verified against the source
- the final target clip has been produced at
1280x720 @ 24 fps - the remaining major gaps against full AV1 standard support are closed, or the repo clearly and honestly documents any still-open non-completion blockers
Use the repo scripts for broad runs, and use a small 64x64 focused check when validating bitstream, syntax, and reconstruction changes quickly.
Broad run (use the live CPU count; on Chud PC 2 this is currently 16):
THREADS=$(nproc) BUILD_JOBS=$(nproc) bash run.shFocused verification flow on Chud PC 2:
cd tb
make THREADS=16 BUILD_JOBS=16 WIDTH=64 HEIGHT=64
./Vav1_encoder_top +frames=1 +qindex=128 +dc_only=0 +ownership_strict=1 +input=../data/raw_frames.yuv +output=../output/encoded.obu
python3 test_rtl_obu_ivf_integrity.py --output-dir ../output --frames 1Fast header regression:
cd tb
make THREADS=16 BUILD_JOBS=16 WIDTH=16 HEIGHT=16 bitstream-checkStandalone entropy verification:
cd tb
make entropy-check THREADS=16 BUILD_JOBS=16Strict bitstream ownership gate:
cd tb
make THREADS=16 BUILD_JOBS=16 bitstream-ownership-checkFor exact reconstruction checks, decode the generated RTL IVF (encoded_rtl.ivf) and compare it against output/recon.yuv.
For RTL ownership debug, inspect rtl_frames/frame_XXXX_rtl_raw.obu and the concatenated *_rtl_raw.obu written beside the software-oracle encoded.obu / encoded.ivf outputs. In +ownership_strict=1, the testbench also writes *_sw_oracle.obu / *_sw_oracle.ivf aliases and refuses byte-count mismatches or writer-only repair knobs.
For inter bring-up, use the repeated-frame 64x64 clip first to clear the zero-motion gate, then move to data/natural_motion64_x640_y360_2f.yuv or data/natural_motion64_x640_y360_3f.yuv for the reduced motion subset.
If a syntax blocker appears, check av1-reference-docs/external/README.md first and refresh that folder from official sources before guessing.
For ref-MV / NEWMV bring-up, use +dump_inter_summary=1 together with RTL-owned controls such as +me_newmv_limit= so the first decoder-failing MV threshold can be isolated quickly. Do not use writer-only reducers such as +limit_newmv_blocks= in ownership gates.
The reduced motion guards now extend cleanly through the repaired 64x64 7-frame and 10-frame natural-motion cases.
Use output/natural_motion64_x640_y360_10f_progress70m/ as the long exact guard and budget +timeout=70000000 or higher when rerunning it.
For raw-path syntax moves, keep a 16x16 1-frame all-key smoke in the loop first so decoded output vs recon.yuv can be rechecked quickly after each block-syntax change.
For sparse AC bring-up, keep data/ac_probe_16x16_1f.yuv in the loop as the first exact-match regression check at the verified qindex=240 subset. Use output/highdc_q1/ plus make p5-highdc-q1-public-check as the strict large-DC regression guard for the fixed qctx-selected TX_8X8 path, and treat requested qindex=0 runs as a deferred lossless / TX_4X4 task that currently clamps to effective qindex=1.
Verified directly on Chud PC 2 (chudpc2-MS-7C91, Verilator 5.020, nproc=16):
make THREADS=16 BUILD_JOBS=16 entropy-checkpasses.make THREADS=16 BUILD_JOBS=16 WIDTH=16 HEIGHT=16 bitstream-checkpasses.make THREADS=16 BUILD_JOBS=16 inv-xform-checkpasses.- The top-level
16x16Verilator build now compiles on Chud PC 2 after removing function-call result slicing that Verilator 5.020 rejects and avoiding mixed blocking/nonblocking assignments tointra_cand_sad. - A generated
16x16flat all-key RTL IVF decodes in both FFmpeg/libdav1d andaomdec, and decoded output matchesrecon.yuv.
Current Chud PC 2 ownership status:
- The earlier generated non-flat
16x16all-key and flat16x162-frame IP raw-stream drift has been fixed in the RTL byte path. - Keep
THREADS=16 BUILD_JOBS=16on Chud PC 2 and runmake bitstream-ownership-checkfor the strict no-repair gate. The gate requires raw RTL OBU equality against the software oracle, RTL IVF payload equality against raw RTL OBU bytes, FFmpeg/libdav1d decode-vs-recon.yuv, andaomdecdecode-vs-recon.yuv. - The current operating point remains static CDF /
disable_cdf_update=1; do not claim adaptive CDF ownership until RTL owns CDF update state and a dedicated gate covers it.
- The RTL-generated stream must decode successfully.
- Visual verification matters, not just parser acceptance.
- Compare decoded RTL output against the source clip.
- Use PSNR / SSIM where useful, but do not treat metrics alone as completion.
- Preserve simulator logs and cycle counts for repeatable validation runs.
- Always sanity-check behavior against a software AV1 encode of the same source.
- Keep the decoded output on a valid path toward the final RTL-generated bitstream requirement.