136 Timing-Prediction Test Vehicle

136 : Timing-Prediction Test Vehicle

Design render

Submitted normal operation: 10 MHz, 50% duty (100 ns period). The 10–50 MHz research sweep deliberately exceeds that timing-safe specification. The design is verified: local hardening, RTL, GL and precheck pass, and canonical CI is all green (GDS run 35034979531); verification is tracked in the attempt log. Earlier physical results below remain historical evidence; fresh results are in data/safe10/.

How it works

A timing-prediction test vehicle for the IHP SG13G2 open PDK. It contains:

  • DUT: a 16-bit ripple-carry adder split into four 4-bit segments. The carry between segments (and the final carry-out) passes through configurable inverter-pair delay banks (taps at 0/16/32/48 pairs), giving programmable critical-path lengths for a rising-launch/falling-capture timing experiment. Worst-case carry propagation is operand dependent, so the first-failure frequency depends on the applied pattern.
  • Oracle: an independent combinational reference adder recomputes the expected result. It is compared at the next frame boundary, after operands have been held for 19 cycles; the deliberately delayed DUT is captured much earlier.
  • Canaries: two ring-oscillator delay proxies - a generic inverter-line RO and a structure-matched RO (looping through delay-bank + full-adder segments like the DUT) - each with a 16-bit ripple edge counter over a configurable window (2^8..2^14 cycles). The window is one-shot per reset: win_done is cleared only by rst_n, so the ring stops when the window closes and the counter holds its value until the next reset. Take one canary sample per reset rather than treating the count as continuous telemetry. The effective gate-open interval is (window cycles - 3) external clock periods - the three boot cycles before the configuration commits do not count - i.e. 25.3 us at 10 MHz and 5.06 us at 50 MHz for the 2^8 window.
  • Measurement: one timed operation per 19-cycle frame, 16-bit error and op counters (both saturating), first-error DUT byte capture, serial byte readout with an auto-incrementing pointer, a freeze input, and FORCE_ERR/FORCE_CAN DFT bits that make the error-accounting path itself testable before tapeout.

Config word (16-bit, driven during reset and held through the third rising edge after reset release, when it is committed): [1:0]/[3:2]/[5:4]/[7:6] = delay bank taps per segment, [9:8] = pattern (0=PRBS, 1=worst-case carry, 2=carry-free alternating, 3=static hold), [11:10] = canary select, [13:12] = window select, [14] = force canary mask, [15] = force DUT error.

The DUT launches operands on a rising edge and samples exactly once on the immediately following falling edge. Clock HIGH time is the measurement aperture: 10 ns at 50 MHz/50% duty, not the full 20 ns period. A failed first sample holds until comparison. Frequency sweeps must record actual high time and duty cycle.

FREEZE blocks new launches. An already launched operation completes its pending falling-edge capture even if FREEZE rises during the high phase. Keep clocking for two complete cycles after asserting FREEZE before reading. Resume never repeats a capture. Maintain the normal clock waveform through the pending falling edge.

ui[7] has no on-chip synchronizer, so the host must transition it as if it were synchronous: assert or release FREEZE during the clock HIGH phase. That leaves between half and one full clock period of settling ahead of the edge that samples it - 50-100 ns at 10 MHz, 10-20 ns at 50 MHz - comfortably beyond the 4 ns input-path budget src/pnr.sdc already assumes with set_input_delay 4.0000 on ui_in[7]. A host that can only act in the LOW phase must still land the transition at least 20 ns (10 MHz) or 10 ns (50 MHz) before the next rising edge, and prove it on a scope. FREEZE must be generated in the chip's clock domain (host FPGA register, PIO, or equivalent hardware); an OS-scheduled software GPIO write does not bound its own jitter to that window and is not an acceptable source. A transition landing inside the setup/hold aperture of a rising edge can make update_en resolve differently per register, which corrupts the 19-cycle frame alignment and can count a fabricated error. The normative rule, its scope check, and the exclusion policy are in the post-silicon protocol.

How to test

  1. Hold rst_n low and drive the config word on ui[7:0] (LSB) and uio[7:0] (MSB). Release rst_n during the clock LOW phase before the first counted rising edge. Keep the config word stable through the third rising edge after releasing rst_n (the on-chip boot counter commits it at that edge), then set ui[7] low - obeying the FREEZE transition rule above - and release your uio drivers within the following clock period. The chip takes over the uio bus on the fourth rising edge; holding your drivers past it makes both sides drive the pads, causing bus contention. Configuration is already latched at that point; subsequent uio values do not update it.
  2. Run the experiment at the target clock frequency/voltage/temperature for a known number of operations (19 cycles each). Start at 1.20 V/ambient and a low clock frequency. Record the clock high time as well as frequency.
  3. Set ui[7] high during the clock HIGH phase (the FREEZE transition rule above), allow two complete clocks for pending capture and ripple settling, then read the 16 status bytes: uio[7:0] is the data byte selected by uo[3:0] (auto-incrementing pointer). Byte map: 0-1 = DUT error count (saturating), 2-3/4-5 = generic/matched RO edge counts (16-bit, wrap mod 65536 -- telemetry, not saturating), 6-7 = operation count (saturating; it counts launches, so completed comparisons are max(ops_cnt - 1, 0) and using the raw count as the denominator biases every error rate low; once saturated, the true count is >= 65535 and no longer recoverable from this byte), 8 = segment-tap echo {seg3, seg2, seg1, seg0}; 9 = status flags {1, mat_ro_dead, gen_ro_dead, err_seen, can_sel[1:0], win_sel[1:0]} (can_sel is bits 3:2, win_sel is bits 1:0, and bit 7 is 1); 10 = low 8 bits of the first failed DUT result capture; 11-15 = 0. While frozen, uo[7:4] = {frame_strobe, mat_ro_dead, gen_ro_dead, dut_err}.
  4. Repeat across frequency/voltage/temperature; compare f(error) contours against the RO telemetry and static timing analysis.

External hardware

A controller that can drive the clock from ~1-50 MHz, hold/step the config pins, and read the status pins (e.g. the Tiny Tapeout demo board or an FPGA host). For the PVT sweep: a variable core-voltage supply (verified accessible per Tiny Tapeout IHP powering rules) and a temperature chamber or controlled hot/cold plate. An external low-jitter clock source with characterized duty cycle is recommended near the timing boundary. Elevated temperature is optional and subject to fixture/assembly limits; 125 °C is a library corner, not a required test condition or a certified board rating.

IO

#InputOutputBidirectional
0cfg_seg0[0] (reset) / unused (run)ro_ptr[0]cfg[8] (reset in) / status[0] (run out)
1cfg_seg0[1] (reset) / unused (run)ro_ptr[1]cfg[9] (reset in) / status[1] (run out)
2cfg_seg1[0] (reset) / unused (run)ro_ptr[2]cfg[10] (reset in) / status[2] (run out)
3cfg_seg1[1] (reset) / unused (run)ro_ptr[3]cfg[11] (reset in) / status[3] (run out)
4cfg_seg2[0] (reset) / unused (run)dut_err (live)cfg[12] (reset in) / status[4] (run out)
5cfg_seg2[1] (reset) / unused (run)gen_ro_deadcfg[13] (reset in) / status[5] (run out)
6cfg_seg3[0] (reset) / unused (run)mat_ro_deadcfg[14] (reset in) / status[6] (run out)
7cfg_seg3[1] (reset) / FREEZE (run, active high)frame_strobecfg[15] (reset in) / status[7] (run out)

Chip location

Controller Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Analog Mux Mux Mux Mux Mux Mux Mux Mux tt_um_chip_rom (Chip ROM) tt_um_factory_test (Tiny Tapeout Factory Test) tt_um_ieee_LDO (LDO) tt_um_chip_ieee_analog (IEEE Bandgap Reference) tt_um_snn_voice_calculator_mauro_ciccone (snn-voice-calculator) tt_um_hx2003_delay (4 Channel - 32 Tap Programmable Delay with Delay Locked Loop Calibration) tt_um_adxl362_test (tt_um_adxl362_test) tt_um_larsnit_cfar (1D CA/GO/SO CFAR radar detector) tt_um_abeccari_swsynth (Sine Wave Synthesizer) tt_um_dpi_adexp (AdExp DPI Neuron ) tt_um_140oo041_fpu130 (FPU-130) tt_um_blonghi_uart (uart) tt_um_directsgg_mini_proceo_8bit (Mini 8-bit Processor) tt_um_umaece1982_lfsr (Low-Power LFSR-Based Test Pattern Generator) tt_um_deploy_timer (launch deployment timer) tt_um_urish_simon (Simon Says memory game) tt_um_nimelli_kinematic_wave_engine (Kinematic Wave Engine) tt_um_multi_seg_monitor (Multi Segment Monitor) tt_um_UART_TX (project) tt_um_crc8_lfsr (CRC-8 Serial LFSR) tt_um_tinynpu4 (TinyNPU4) tt_um_alu_bns (6-bit multi function ALU ( eldawly_V2) ) tt_um_echoworld424_tpv (Timing-Prediction Test Vehicle) tt_um_gyro_lockin (Laser Gyro Lock-in Readout Core) tt_um_josue_olivos_sar_adc (4-Bit Charge-Redistribution SAR ADC Controller) tt_um_flower (VGA Flower) tt_um_vperumal_l1_fabric (Scalable Banked L1 Memory Fabric for Edge AI) tt_um_preinception_top (Preinception: Simple Compute Accelerator) tt_um_italu (iTALU: Interactive Testable Arithmetic Logic Unit) tt_um_neuron (4-Input Signed Neuron / Perceptron) tt_um_4tap_mac (4-Tap Signed MAC Unit) tt_um_mac_engine (DSP MAC Engine) tt_um_crypto_led_demo (QAMER CryptoUART: Encrypted UART with LED Status) tt_um_layernorm (LayerNorm) tt_um_ez130_8t_mystery (EZ130 8T Mystery Circuit) tt_um_sent2spi (SENT Receiver with SPI Interface) tt_um_llr_hepiarisc (Hepiarisc with SPI flash) tt_um_rebeccargb_vga_pride (VGA Pride) tt_um_hasi_ising (Oscillator Ising Machine) tt_um_c061618g2 (Circuitli C061618G2) tt_um_tiny_dram_pim (Tiny Dual-Channel DRAM-PIM Controller + PU) tt_um_Tbilisi_CORDIC_Engine (Tbilisi CORDIC Engine) tt_um_rahulmascarenhas_folded_nn (Frozen ternary backbone + loadable head) tt_um_miniMAC (miniMAC_IHP26b) tt_um_rumcajs (IEEE DOORSH) tt_um_sg13g2_mystery (SG13G2 Mystery Circuit) tt_um_ULSR88 (ULSR demo) tt_um_ez130_7t_mystery (EZ130 7T Mystery Circuit) tt_um_tinyopt4 (ieee_tt_tinyopt4) tt_um_vga_example (IEEE VGA Animated Beach) tt_um_hyphen133_drone_detection (IEEE Acoustic Drone Detector) tt_um_nuatlabs_fifo_pwm (Async FIFO with CDC + PWM Peripheral) tt_um_nuatlabs_uart (8N1 UART Transceiver) tt_um_eeg_threshold_detector (IEEE Digital EEG Threshold Event Detector) tt_um_smart_traffic (Smart Traffic Light Controller) tt_um_94442024_mini_cpu (Mini 8-bit Accumulator CPU) tt_um_wokwi_475369131246576641 (IEEE_UPB_TT_1) tt_um_aion (AION) tt_um_rebeccargb_hardware_utf8 (Hardware UTF Encoder/Decoder) tt_um_rebeccargb_universal_decoder (Universal Binary to Segment Decoder) tt_um_rebeccargb_intercal_alu (INTERCAL ALU) tt_um_flappy_bird (IEEE Flappy Bird VGA Game) tt_um_oryan01_alu (ALU CASS PUCV) tt_um_S4xU4 (S4xU4) tt_um_vga_ca (Space CA) tt_um_llr_simplenpu (simple SPI flash streaming NPU) tt_um_pucv_pspwm (3LFCC PS-PWM Modulator) tt_um_yuri_fpga (Tiny FPGA) tt_um_mikailgedik_inverted_inverters (Inverted inverters) tt_um_esauqch_hamming74 (Hamming(7,4) encoder/decoder (IEEE)) tt_um_hackin7_analog_experiments (TinyAnalogExperiments) tt_um_snake (snake game) tt_um_mini_kraken (Kraken IO Subprocessor) tt_um_fabien_pio (AstraPIO) tt_um_chiplab (ChipLab) tt_um_wokwi_475490677474407425 (Tiny_Divider) tt_um_c061618g2tr (Circuitli C061618G2TR) tt_um_catalinlazar_nanopio (nanoPIO) tt_um_catalinlazar_uart_spi_i2c_bridge (UART-SPI-I2C Bridge) tt_um_enzonappi_sent_i2c (SENT to I2C bridge) tt_um_kush1434_proof (Proof) tt_um_schwallsunk_signal_discriminator (Highspeed voltage discriminator) tt_um_tiarinix_ttihp_verilog_template (8-bit educational SAP-style CPU) tt_um_vga_glyph_mode (BOOTCAMP) tt_um_GiulioGirelli_packet_processor (Configurable Low-Latency Match-Action Packet Processor) tt_um_vga_tictactoe (Tic Tac Toe) tt_um_vga_dvd_player (DVD player) tt_um_clea_katseye_rain (KATSEYE) tt_um_romd_uart_hello (UART Hello World) tt_um_vga_snake (CDM PYTHON GAME) tt_um_vga_slot_machine (tt_um_vga_slot_machine) tt_um_jet_seq8b (SEQ8 Programmable Sequencer) tt_um_kibo_leak_inspect (KIBO Leak-Inspection Target Controller (VGA)) tt_um_endless_runner (Endless Runner) tt_um_omega_infinity_kaoru (OMEGA INFINITY KAORU 3D Metal Grid Processor) tt_um_nikleberg_mixer (Mixer) tt_um_lahnb_sgdma (TinyDMA: A Descriptor-Based Dual-PSRAM Memory Mover) tt_um_gstj_lockin (Digital IQ Lock-in (IEEE)) tt_um_benpayne_ps2_decoder (PS/2 Keyboard Decoder for 68k) tt_um_cass_s_ui_neuron_lif (Neurona LIF con Aprendizaje STDP Dinamico (IEEE)) tt_um_vga_glyph_mode_CDM_Matrix (CDM Matrix) tt_um_qd39l_xor_stream (Fixed-ROM XOR Stream Engine) tt_um_conv3x3 (3x3 Clock Rate Streaming Input Convolution Engine) tt_um_mc14500b_soc_extended (MC14500B Extended 1-bit Microcontroller SoC) tt_um_vga_hypno_spiral (tt_um_vga_hypno_spiral) tt_um_mattizen_morse_tree (Morse Tree LED Decoder) tt_um_CDM (Colegio de Muntinlupa DVD-like Display) tt_um_romd_uart_loader (UART SPI RAM Loader) tt_um_TscherterJunior_stapel_geraet (stapel gerät) tt_um_das2225_dna_accel (DNA_Accel) tt_um_tinysoc (TinySoC) tt_um_barrel_shifter (Barrel Shifter) tt_um_approx_mac_coprocessor (Approximate DSP: Time-Multiplexed MAC Coprocessor) tt_um_joesagents_market_split_oracle (Market-split oracle) tt_um_mgpauly1458_ringmeter (Ring oscillator frequency meter) tt_um_pettit_prism_lite (PRISM with Risc-V (TinyQV) SoC) tt_um_workshop_cpu (IEEE Workshop Simple CPU) tt_um_algofoogle_analog_junk (Simple comparator + 2 DACs analog layout in a 1x1 tile) tt_um_lkhanh_cordic (TinyQV SoC (Dual Memory Backend)) tt_um_4x4npu (4x4NPU: Dual-Lane INT4 Neural Accelerator) tt_um_abiaselli_izh_bridge_3x2 (Izhikevich event bridge (4 contexts)) tt_um_fabulous_ihp_26b (Tiny FABulous FPGA) tt_um_zanderivo_voronoi (Four-Metric VGA Nearest-Prototype Visualizer)