Skip to content

feat: FPGA VANC timecode inserter for Ninja V recording trigger#607

Open
alfskaar wants to merge 2 commits intohd-zero:mainfrom
alfskaar:fpga-vanc-timecode-v2
Open

feat: FPGA VANC timecode inserter for Ninja V recording trigger#607
alfskaar wants to merge 2 commits intohd-zero:mainfrom
alfskaar:fpga-vanc-timecode-v2

Conversation

@alfskaar
Copy link
Copy Markdown

Summary

Sample Verilog module and documentation for injecting SMPTE 12M-2 timecode as VANC (Vertical Ancillary Data) packets into the HDMI video blanking interval.

Background

The Atomos Ninja V "HDMI Device" trigger modes (Canon EOS R, Sony ILCE-7SM3, etc.) use VANC timecode — not HDMI InfoFrames — to detect recording state.

HDfury captures of a real Canon EOS R confirmed all InfoFrames are byte-for-byte identical between REC ON and REC OFF. The trigger mechanism is SMPTE 12M-2 timecode embedded at the pixel level during vertical blanking.

The IT66121 HDMI transmitter cannot inject VANC — it only handles InfoFrames and audio. VANC must be injected by the FPGA before the video reaches the IT66121.

Files

File Description
fpga_vanc_timecode/vanc_timecode_inserter.v 8-bit DE-based Verilog module: line/pixel counters, SMPTE ST 291M packet builder with BCD timecode, timecode input latching, DE-guard abort, insertion state machine, video passthrough mux
fpga_vanc_timecode/README.md VANC packet format spec (SMPTE ST 291M / 12M-2), integration notes, blanking line selection, horizontal position guidance, CPU register interface

Integration

Camera RX → Frame Buffer → Scaler → [VANC Inserter] → IT66121 Parallel Input

CPU (ARM / Allwinner V536) controls timecode via FPGA registers:

  • TC_HOURS, TC_MINUTES, TC_SECONDS, TC_FRAMES, TC_ENABLE
  • ARM increments timecode once per second; FPGA inserts VANC packets every frame

Status

Sample/reference code for FPGA integration. Software-side Canon EOS R VSIF trigger code exists separately in the firmware (not included in this PR).

Copilot AI review requested due to automatic review settings April 14, 2026 20:49
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a reference FPGA implementation and accompanying documentation for injecting SMPTE 12M-2 timecode as SMPTE ST 291M VANC packets into the HDMI video vertical blanking interval, enabling Atomos Ninja V “HDMI Device” record trigger behavior.

Changes:

  • Introduces a Verilog VANC timecode inserter module for an 8-bit DE-based video interface (with packet builder + insertion FSM).
  • Documents the VANC packet structure, integration placement, and recommended blanking line / horizontal offset guidance.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
fpga_vanc_timecode/vanc_timecode_inserter.v Implements line/pixel counting, timecode latching, ST 291M packet construction, and blanking-safe insertion mux.
fpga_vanc_timecode/README.md Explains Ninja V trigger mechanism and provides packet format + integration notes for the sample module.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +56 to +58
reg [11:0] h_count; // Horizontal pixel counter
reg [11:0] v_count; // Vertical line counter
reg prev_hsync;
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h_count is only 12 bits, so it will wrap for video modes with >4096 pixel clocks per line (e.g., many 2160p/4K HDMI timings have Htotal≈4400). If it wraps while vid_de_in is low later in the same line, at_h_start can become true again and trigger an unintended extra packet insertion. Consider increasing the counter width (e.g., 13+ bits) or making it parameterizable / bounded by an H_TOTAL parameter to prevent wrap within a line.

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +24
// NOTE: VANC_H_START denotes the pixel cycle *before* ADF[0] appears
// on vid_data_out, due to the 1-cycle output register pipeline.
// Set VANC_H_START = (desired_ADF_pixel - 1).
//
// IMPORTANT: This is SAMPLE code — adapt to the actual FPGA video
// pipeline, clock domain, and register interface.
// ==========================================================================

module vanc_timecode_inserter #(
parameter VANC_LINE = 14, // Vertical blanking line for VANC insertion
parameter VANC_H_START = 15 // Pixel cycle before ADF[0] output (see note above)
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VANC_LINE/VANC_H_START are compared against v_count/h_count, but the counters are effectively 0-based (reset to 0 on vsync rise, then v_count increments on each hsync rise). This makes it easy to misconfigure insertion by one line/pixel compared to the line numbers described in the README. Please document the counter origin (0-based vs 1-based) and/or adjust the counter update so that VANC_LINE=1 corresponds to “line 1” as typically referenced in video timing docs.

Suggested change
// NOTE: VANC_H_START denotes the pixel cycle *before* ADF[0] appears
// on vid_data_out, due to the 1-cycle output register pipeline.
// Set VANC_H_START = (desired_ADF_pixel - 1).
//
// IMPORTANT: This is SAMPLE code — adapt to the actual FPGA video
// pipeline, clock domain, and register interface.
// ==========================================================================
module vanc_timecode_inserter #(
parameter VANC_LINE = 14, // Vertical blanking line for VANC insertion
parameter VANC_H_START = 15 // Pixel cycle before ADF[0] output (see note above)
// NOTE: VANC_LINE and VANC_H_START are compared directly against the
// internal v_count/h_count counters, which are 0-based. That means:
// - VANC_LINE = 0 selects the first counted line after v_count resets.
// - VANC_H_START = 0 selects the first counted pixel cycle after h_count resets.
// Additionally, VANC_H_START denotes the pixel cycle *before* ADF[0]
// appears on vid_data_out, due to the 1-cycle output register pipeline.
// So if video timing documentation refers to "line 14" / "pixel 16" in
// 1-based terms, the corresponding parameters here are typically
// VANC_LINE = 13 and VANC_H_START = 14.
//
// IMPORTANT: This is SAMPLE code — adapt to the actual FPGA video
// pipeline, clock domain, and register interface.
// ==========================================================================
module vanc_timecode_inserter #(
parameter VANC_LINE = 14, // 0-based v_count line number for VANC insertion
parameter VANC_H_START = 15 // 0-based h_count cycle before ADF[0] output (see note above)

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +24
parameter VANC_LINE = 14, // Vertical blanking line for VANC insertion
parameter VANC_H_START = 15 // Pixel cycle before ADF[0] output (see note above)
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VANC_LINE and VANC_H_START are currently unsized parameters, which makes them 32-bit signed values in Verilog and can lead to width/signedness warnings (and occasional surprising comparison behavior). Consider sizing them explicitly (e.g., parameter [11:0] VANC_LINE = 12'd14, parameter [11:0] VANC_H_START = 12'd15) to match v_count/h_count.

Suggested change
parameter VANC_LINE = 14, // Vertical blanking line for VANC insertion
parameter VANC_H_START = 15 // Pixel cycle before ADF[0] output (see note above)
parameter [11:0] VANC_LINE = 12'd14, // Vertical blanking line for VANC insertion
parameter [11:0] VANC_H_START = 12'd15 // Pixel cycle before ADF[0] output (see note above)

Copilot uses AI. Check for mistakes.
Comment thread fpga_vanc_timecode/README.md
@alfskaar alfskaar force-pushed the fpga-vanc-timecode-v2 branch from edf9f98 to d92df36 Compare April 14, 2026 21:01
SMPTE ST 291M / 12M-2 ancillary data packet inserter for
DE-based parallel video interfaces. Intended as a starting
point for Atomos Ninja V record-trigger via VANC timecode.
@alfskaar alfskaar force-pushed the fpga-vanc-timecode-v2 branch from d92df36 to f493500 Compare April 14, 2026 21:07
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants