Skip to content

LATCH

Source: Verilog/Shared/ndlib/LATCH.v

Where it sits (Simulation): ND120_TOP > ND120_CORE > ND3202D > CPU_15 > CPU_PROC_32 > CPU_PROC_CGA_33 > CGA > CGA_MIC > CGA_MIC_CSEL > LATCH - instance path: CORE.CPU_BOARD.CPU.PROC.CGA.DELILAH.MIC.CSEL.CSEL_LATCH

Used in: CGA_MIC_CSEL (Simulation, Tang, Nexys, MEGA65 R6, MEGA65 R3, QMTECH, Basys3, Cmod)

Contains: no other modules.

Module hierarchy - All modules

LATCH symbol

Schematic

Drawn from the Verilog: the yosys netlist of the Simulation (Verilator) build, instance CORE.CPU_BOARD.CPU.PROC.CGA.DELILAH.MIC.CSEL.CSEL_LATCH. Sub-modules are boxes (click the picture to open it full size; there every sub-module box links to its page, and every wire shows its Verilog name).

LATCH schematic

Description

ND120 Shared Component LATCH Last reviewed: 24-NOV-2024 Ronny Hansen

Ports

Direction Width Name Description
input 1 sysclk FPGA system clock — same code path for sim and FPGA
input 1 D
input 1 ENABLE
output 1 Q
output 1 QN

Verilog source

Verilog/Shared/ndlib/LATCH.v on GitHub.

Show the Verilog of LATCH (77 lines)
/**************************************************************************
** ND120 Shared                                                          **
**                                                                       **
** Component LATCH                                                       **
**                                                                       **
** Last reviewed: 24-NOV-2024                                            **
** Ronny Hansen                                                          **
***************************************************************************/

// QUARTUS_LATCH_RENAME (31-AUG-2026, MiSTer build 2): Quartus Prime has a
// built-in WYSIWYG primitive named exactly "LATCH" (3-port: d/ena/q) that
// silently wins over a same-named user module - "Port ENABLE does not exist
// in primitive LATCH" is Quartus telling you it resolved the instance to ITS
// primitive, not this one. A PLAIN rename was tried first and reverted: it
// broke every -y library build under Verilator (CPU_PROC_32/sim and others)
// - that tool's -y module search requires the FILENAME to match the module
// name, and this file stays LATCH.v for every other toolchain, so renaming
// the module alone made it go looking for a nonexistent ND120_LATCH.v.
// Gated instead: LATCH everywhere except a Quartus build, which defines
// QUARTUS_LATCH_RENAME (nd120.qsf) and gets ND120_LATCH. Only one real
// instantiation exists in the whole repo (CGA_MIC_CSEL.v), gated the same way.
`ifdef QUARTUS_LATCH_RENAME
module ND120_LATCH (
`else
module LATCH (
`endif
    input  wire sysclk,    //! FPGA system clock — same code path for sim and FPGA
    input  wire D,
    input  wire ENABLE,
    output wire Q,
    output wire QN
);

  // Level-sensitive sysclk capture (matches L4.v / L8.v).
  //
  // Replaces the previous `always @(posedge ENABLE)` pattern which routed
  // ENABLE through fabric as a clock signal — unsafe on FPGA (no clock
  // network, glitch-prone, hold-time analysis incomplete).
  //
  // Semantics: while ENABLE is high, regD tracks D on every sysclk edge
  // (effectively transparent on a 1-sysclk grain). When ENABLE is low,
  // regD holds. This is the closest synchronous approximation to the
  // original 74xx transparent-latch behaviour.
  //
  // Edge-detect was tried first and broke LCS loading, because during
  // LCS load `s_aluclk_n` is held high constantly — no rising edge ever
  // appears, so an edge-detect FF never fires and CSEL_Q stayed at its
  // init value. Level-sensitive capture has no such failure mode: it
  // tracks D throughout the high window.

  reg regD = 1'b0;

`ifdef USE_TRANSPARENT_LATCHES
  // TRUE transparent latch (the original 74xx behaviour): while ENABLE high, Q
  // follows D combinationally; when ENABLE falls, Q holds. This is the correct
  // reference model with no sysclk-sampling race. FPGA path below keeps the
  // synchronous approximation.
  always @(*) begin
    if (ENABLE) regD = D;
  end
`else
  always @(posedge sysclk) begin
    if (ENABLE) regD <= D;
  end
`endif

`ifdef USE_TRANSPARENT_LATCHES
  assign Q  = regD;
  assign QN = ~regD;
`else
  // FPGA: synthesizable transparent latch = mux + FF (Q follows D while ENABLE high)
  wire q = ENABLE ? D : regD;
  assign Q  = q;
  assign QN = ~q;
`endif

endmodule