Skip to content

Latch

A D-type latch captures a snapshot of a running counter when a button is held. When the button is released, the latch holds its last captured value and the LEDs freeze.

Modules

latch_test

The module takes a clock, power-on reset, active-low reset button, a latch-enable button (btn), and outputs 6 LEDs.

The ASYNCHRONOUS block does three things:

  1. Combines por and rst_n into an active-low reset wire.
  2. Drives the D-latch: display_buffer <= btn : ~counter[26:21]. The enable : data syntax means btn is the gate — when high, the inverted upper counter bits flow through; when low, the latch holds.
  3. Outputs leds <= { btn, display_buffer[4:0] } — the MSB LED shows the button state, the lower 5 LEDs show the latched value.

The SYNCHRONOUS block increments a 27-bit counter on every clock cycle, identical to the counter example.

The key declaration is LATCH display_buffer [6] D — an explicitly declared 6-bit D-type latch. The width and type are part of the declaration, not inferred from context.

Project Files

Two project files target the Tang Nano 20K and 9K. Both map two buttons — one for reset, one for latch enable — and six LEDs. Button polarity is inverted between boards.

jz
@project(CHIP="GW2AR-18-QN88-C8-I7") LATCH_EXAMPLE
    @import "latch.jz"

    CLOCKS {
        SCLK = { period=37.04 }; // 27MHz clock
    }

    IN_PINS {
        SCLK   = { standard=LVCMOS33 };
        DONE   = { standard=LVCMOS33 };
        KEY[2] = { standard=LVCMOS33 };
    }

    OUT_PINS {
        LED[6] = { standard=LVCMOS33, drive=8 };
    }

    MAP {
        // System Clock
        // 27MHz
        SCLK = 4;

        // 2 BUttons
        // High = Closed
        // Low = Open
        KEY[0] = 87;
        KEY[1] = 88;

        // 6 LEDs
        // High = OFF
        // Low = ON
        LED[0] = 15;
        LED[1] = 16;
        LED[2] = 17;
        LED[3] = 18;
        LED[4] = 19;
        LED[5] = 20;

        // DONE can be used as a POR signal
        // Low = programming ongoing
        // High = programming successfully
        DONE    = IOR32B; 
    }

    @top latch_test {
        IN  [1] clk   = SCLK;
        IN  [1] por   = DONE;
        IN  [1] rst_n = ~KEY[0];
        IN  [1] btn   = KEY[1];
        OUT [6] leds  = LED;
    }
@endproj
jz
// Latch example — demonstrates a D latch.
//
// A 27-bit counter free-runs at the clock rate. Six LEDs show the
// D latch output:
//
//   leds[5]   — raw btn state (direct passthrough).
//   leds[4:0] — D latch (display_buffer[4:0]). While btn is held,
//               the latch is transparent and the LEDs follow
//               ~counter[26:22] (inverted upper counter bits).
//               Releasing btn freezes the pattern.
//
// Button behavior:
//   Hold    — latch is transparent, LEDs track counter.
//   Release — latch holds its last value, LEDs freeze.

@module latch_test
    PORT {
        IN  [1] clk;
        IN  [1] por;
        IN  [1] rst_n;
        IN  [1] btn;
        OUT [6] leds;
    }

    WIRE {
        reset [1];
    }

    REGISTER {
        counter [27] = 27'b1;
    }

    LATCH {
        // Explicit storage for the 6-bit LED pattern
        display_buffer [6] D;
    }

    ASYNCHRONOUS {
        reset = por & rst_n;

        display_buffer <= btn : ~counter[26:21];
        leds <= { btn, display_buffer[4:0] };
    }

    SYNCHRONOUS(CLK=clk RESET=reset RESET_ACTIVE=Low) {
        counter <= counter + 27'b1;
    }
@endmod

JZ-HDL Language Features

Explicit latch declaration. In Verilog, latches appear silently whenever an always @(*) block has an incomplete if or case — the designer never asked for a latch, but one appears in the netlist. These accidental latches are a top source of synthesis bugs, and tools may only flag them as warnings.

JZ-HDL requires latches to be declared in a LATCH block with a name, width, and type. The gated assignment syntax (enable : data) makes the enable condition visible at the point of use. If no latch is declared, the compiler will not infer one — incomplete assignments in ASYNCHRONOUS blocks are compile errors. Every latch in a JZ-HDL design exists because the designer put it there intentionally.