162 Fuzzy Search Engine

162 : Fuzzy Search Engine

Design render

How it works

sky25a-levenshtein is a fuzzy search engine which can find the best matching word in a dictionary based on levenshtein distance.

Fundamentally its an implementation of the bit-vector levenshtein algorithm from Heikki Hyyrö's 2003 paper with the title A Bit-Vector Algorithm for Computing Levenshtein and Damerau Edit Distances.

Architecture

The overall architecture is a Wishbone Classic system with two masters (The levenshtein engine and an SPI controlled master) and two slaves (The levenshtein engine and a QSPI SRAM controller).

Using the SPI interface, you store a dictionary and some bitvectors representing a search word in SRAM and then configures and activates the engine. The engine will then read the dictionary and bitvectors from the SRAM and, ultimately store the index and distance of the word in the dictionary with the lowest levenshtein distance in registers which can be read by the user.

image

SPI

The device is organized as a wishbone bus which is accessed through commands on an SPI bus.

The maximum SPI frequency is 25% of the master clock (12.5MHz when the chip is running at 50MHz).

The bus uses SPI mode 3 (CPOL=1, CPHA=1)

Input bytes:

Byte Bit Description
0 7 READ=0 WRITE=1
0 6-0 Address bit 22-16
1 7-0 Address bit 15-8
2 7-0 Address bit 7-0
3 7-0 Byte to write if WRITE, otherwise ignored

Output bytes:

Byte Bit Description
0 7-0 Byte read if READ, otherwise just 0x00

Since the SPI bridges to a wishbone bus which is shared by another master and because register and SRAM have different latencies, the response time is variable.

While the bus is working, the output bits will be zero. The final output byte will be preceeded by a one-bit.

Note that this means that the value 0x5A can appear 8 different ways on the SPI bus:

01 5A   0000000 1 01011010
02 B4   000000 1 01011010 0
05 68   00000 1 01011010 00
0A D0   0000 1 01011010 000
15 A0   000 1 01011010 0000
2B 40   00 1 01011010 00000
56 80   0 1 01011010 000000
AD 00   1 01011010 00000000

Memory Layout

The address space is 23 bits and is organized as follows:

Address Size Access Identifier
0x000000 1 R/W CTRL
0x000001 1 R/W SRAM_CTRL
0x000002 1 R/W LENGTH
0x000003 1 R/O MAX_LENGTH
0x000004 2 R/O INDEX
0x000006 1 R/O DISTANCE
0x000200 512 R/W VECTORMAP
0x000400 8M R/W DICT

CTRL

The control register is used to start the engine and see when it has completed.

The layout is as follows:

Bits Size Access Description
0 1 R/W Enable flag
1-7 7 R/O Not used

Set the enable flag to start the engine. When the engine is finished, the enable flag is changed to 0

SRAM_CTRL

Controls the SRAM

Bits Size Access Description
0-1 2 R/W Chip select
2-7 6 R/O Not used

The chip select flag controls which chip select is used on the PMOD when accessing SRAM

Value Pin Notes
0 None Default value
1 CS Uses the default CS on the PMOD (Pin 1). Compatible with Machdyne's QQSPI PSRAM
2 CS2 Uses CS2 on the PMOD (pin 6). Compatible with mole99's QSPI Flash/(P)SRAM
3 CS3 Uses CS3 on the PMOD (pin 7). Compatible with mole99's QSPI Flash/(P)SRAM

LENGTH

Bits Size Access Description
0-7 8 R/W Word length minus 1

Used to indicate the length of the search word. Note that the word cannot be empty and it cannot exceed the maximum length as indicated by the MAX_LENGTH field.

MAX_LENGTH

Bits Size Access Description
0-7 8 R/O Max word length supported minus 1

This field indicates the maximum supported length of the engine.

DISTANCE

When the engine has finished executing, this address contains the levenshtein distance of the best match.

INDEX

When the engine has finished executing, this address contains the index of the best word from the dictionary in big endian byte order.

VECTORMAP

The vector map must contain the corresponding bitvector for each input byte in the alphabet.

If the search word is application, the bit vectors will look as follows:

Letter Index Bit vector
a 0x61 16'b00000000_01000001 (a_____a____)
p 0x70 16'b00000000_00000110 (_pp________)
l 0x6C 16'b00000000_00001000 (___l_______)
i 0x69 16'b00000001_00010000 (____i___i__)
c 0x63 16'b00000000_00100000 (_____c_____)
t 0x74 16'b00000000_10000000 (_______t___)
o 0x6F 16'b00000010_00000000 (_________o_)
n 0x6E 16'b00000100_00000000 (__________n)
* * 16'b00000000_00000000 (___________)

The size of the vectors is MAX_LENGTH bits rounded up to the nearest 8. The vectors are stored in big endian order.

The vector map is stored in SRAM so the values are indetermined at power up and must be cleared.

DICT

The word list.

The word list is stored of a sequence of words, each encoded as a sequence of 8-bit characters and terminated by the byte value 0x00. The list itself is terminated with the byte value 0x01.

Note that the algorithm doesn't care about the particular characters. It only cares if they are identical or not, so even though the algorithm doesn't support UTF-8 and is limited to a character set of 254 characters, ignoring Asian alphabets, a list of words usually don't contain more than 254 distinct characters, so you can practially just map lettters to a value between 2 and 255.

Levenshtein module

The levenshtein module is a state machine with 8 states:

image

STATE_READ_DICT_BASE + n

At these states, four dictionary bytes are read from the PMOD PSRAM via the wishbone bus as indicated by dict_address.

The bytes are stored in a symbols buffer.

STATE_PROCESS

At this state each symbol in the symbols buffer is processed one byte per cycle. The symbol being processed is indicated by symbol_idx.

If the symbol processed is WORD_TERMINATOR (0x00) the best_idx and best_distance variables are updated and the bitvector engine is reset. If it was the last symbol, state changes to STATE_READ_DICT_BASE + 0.

If the symbol processed is DICT_TERMINATOR (0x01), the engine disables itself.

If the symbol is neigher WORD_TERMINATOR or DICT_TERMINATOR, the state changes to STATE_READ_VECTOR_BASE + 0.

STATE_READ_VECTOR_BASE + n

At these states a 16-bit vector is read from the PMOD SRAM in 8-bit chunks, representing the symbol being processed.

When both bytes has been read, state changes to STATE_LEVENSHTEIN

STATE_LEVENSHTEIN

At this state, the bitvector based levenshtein algorithm is run.

If it was the last symbol in the symbol buffer, state changes to STATE_READ_DICT_BASE + 0 - otherwise, state changes to STATE_PROCESS.

Summary

Unless the terminator symbols are reached, the states are:

  • STATE_READ_DICT_BASE + 0
  • STATE_READ_DICT_BASE + 1
  • STATE_READ_DICT_BASE + 2
  • STATE_READ_DICT_BASE + 3
  • STATE_PROCESS, symbol_idx=0
  • STATE_READ_VECTOR_BASE + 0
  • STATE_READ_VECTOR_BASE + 1
  • STATE_LEVENSHTEIN
  • STATE_PROCESS, symbol_idx=1
  • STATE_READ_VECTOR_BASE + 0
  • STATE_READ_VECTOR_BASE + 1
  • STATE_LEVENSHTEIN
  • STATE_PROCESS, symbol_idx=2
  • STATE_READ_VECTOR_BASE + 0
  • STATE_READ_VECTOR_BASE + 1
  • STATE_LEVENSHTEIN
  • STATE_PROCESS, symbol_idx=3
  • STATE_READ_VECTOR_BASE + 0
  • STATE_READ_VECTOR_BASE + 1
  • STATE_LEVENSHTEIN
  • STATE_READ_DICT_BASE + 0
  • ...

Reading from the PMOD PSRAM is done at half the frequency in 1S-4S-4S mode with 6 wait cycles, so going from STATE_READ_x_BASE + 0 to STATE_READ_x_BASE + 1 takes 44 cycles ((8 + 24/4 + 6 + 8/4) * 2 = 44) and the remaining states takes 4 cycles ((8 / 4) * 2 = 4). So processing 4 bytes of dictionary symbols takes 256 cycles (44 + 4 + 4 + 4 + (1 + 44 + 4 + 1) * 4 = 256) or 64 cycles/symbol.

Assuming a 512KiB dictionary and 50MHz clock, searching takes up to 671ms.

How to test

You can compile the client as follows:

mkdir -p build
cmake -G Ninja -B build .
cmake --build build

Next, you can run the test tool:

# Machdyne QQSPI PSRAM
./build/client/client --interface tt --test --verify-dictionary --verify-search

# mole99 PSRAM
./build/client/client --interface tt --cs cs2 --test --verify-dictionary --verify-search

This will load 1024 words of random length and characters into the SRAM and then perform a bunch of searches, verifying that the returned result is correct.

External hardware

To operate, the device needs a QSPI PSRAM PMOD. The design is tested with the QQSPI PSRAM PMOD from Machdyne, but any memory PMOD will work as long as it supports:

  • WRITE QUAD with the command 0x38 in 1S-4S-4S mode and no latency
  • FAST READ QUAD with the command 0xE8 in 1S-4S-4S mode and 6 wait cycles
  • 24-bit addresses
  • Uses pin 0, 6, or 7 for SS#.
  • Must be able to run at half the clock speed of the TT chip.

Note that this makes it incompatible with the spi-ram-emu project for the RP2040.

IO

#InputOutputBidirectional
0SRAM QSPI CS
1SRAM QSPI SIO0/MOSI
2SRAM QSPI SIO1/MISO
3SRAM QSPI SCK
4SPI SS#SRAM QSPI SIO2
5SPI SCKSRAM QSPI SIO3
6SPI MOSISRAM QSPI CS2
7SPI MISOSRAM QSPI CS3

Chip location

Controller Mux Mux Mux Mux Mux Mux Mux Mux Mux Analog Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Analog Mux Mux Mux Mux Analog Mux Mux Mux Mux Mux Mux tt_um_chip_rom (Chip ROM) tt_um_factory_test (Tiny Tapeout Factory Test) tt_um_oscillating_bones (Oscillating Bones) tt_um_rebelmike_incrementer (Incrementer) tt_um_rebeccargb_tt09ball_gdsart (TT09Ball GDS Art) tt_um_tt_tinyQV (TinyQV 'Asteroids' - Crowdsourced Risc-V SoC) tt_um_DalinEM_asic_1 (ASIC) tt_um_urish_simon (Simon Says memory game) tt_um_rburt16_bias_generator (Bias Generator) tt_um_librelane3_test (Tiny Tapeout LibreLane 3 Test) tt_um_10_vga_crossyroad (Crossyroad) tt_um_rebeccargb_universal_decoder (Universal Binary to Segment Decoder) tt_um_rebeccargb_hardware_utf8 (Hardware UTF Encoder/Decoder) tt_um_rebeccargb_intercal_alu (INTERCAL ALU) tt_um_rebeccargb_dipped (Densely Packed Decimal) tt_um_rebeccargb_styler (Styler) tt_um_rebeccargb_vga_timing_experiments (VGA Timing Experiments) tt_um_rebeccargb_colorbars (Color Bars) tt_um_rebeccargb_vga_pride (VGA Pride) tt_um_cw_vref (Current-Mode Bandgap Reference) tt_um_tinytapeout_logo_screensaver (VGA Screensaver with Tiny Tapeout Logo) tt_um_rburt16_opamp_3stage (OpAmp 3stage) tt_um_gamepad_pmod_demo (Gamepad Pmod Demo) tt_um_micro_tiles_container (Micro tile container) tt_um_virantha_enigma (Enigma - 52-bit Key Length) tt_um_jamesrosssharp_1bitam (1bit_am_sdr) tt_um_jamesrosssharp_tiny1bitam (Tiny 1-bit AM Radio) tt_um_MichaelBell_rle_vga (RLE Video Player) tt_um_MichaelBell_mandelbrot (VGA Mandelbrot) tt_um_murmann_group (Decimation Filter for Incremental and Regular Delta-Sigma Modulators) tt_um_betz_morse_keyer (Morse Code Keyer) tt_um_urish_giant_ringosc (Giant Ring Oscillator (3853 inverters)) tt_um_tiny_pll (Tiny PLL) tt_um_tc503_countdown_timer (Countdown Timer) tt_um_richardgonzalez_ped_traff_light (Pedestrian Traffic Light) tt_um_analog_factory_test (TT08 Analog Factory Test) tt_um_alexandercoabad_mixedsignal (mixedsignal) tt_um_tgrillz_sixSidedDie (Six Sided Die) tt_um_mattvenn_analog_ring_osc (Ring Oscillators) tt_um_vga_clock (VGA clock) tt_um_mattvenn_r2r_dac_3v3 (Analog 8 bit 3.3v R2R DAC) tt_um_mattvenn_spi_test (SPI test) tt_um_quarren42_demoscene_top (asic design is my passion) tt_um_micro_tiles_container_group2 (Micro tile container (group 2)) tt_um_z2a_rgb_mixer (RGB Mixer demo) tt_um_frequency_counter (Frequency counter) tt_um_urish_sic1 (SIC-1 8-bit SUBLEQ Single Instruction Computer) tt_um_tobi_mckellar_top (Capacitive Touch Sensor) tt_um_log_afpm (16-bit Logarithmic Approximate Floating Point Multiplier) tt_um_uwasic_dinogame (UW ASIC - Optimized Dino) tt_um_ece298a_8_bit_cpu_top (8-Bit CPU) tt_um_tqv_peripheral_harness (Rotary Encoder Peripheral) tt_um_led_matrix_driver (SPI LED Matrix Driver) tt_um_2048_vga_game (2048 sliding tile puzzle game (VGA)) tt_um_mac (MAC) tt_um_dpmunit (DPM_Unit) tt_um_nitelich_riscyjr (RISCY Jr.) tt_um_nitelich_conway (Conway's GoL) tt_um_pwen (Pulse Width Encoder) tt_um_mcs4_cpu (MCS-4 4004 CPU) tt_um_mbist (Design of SRAM BIST) tt_um_weighted_majority (Weighted Majority Voter / Trend Detector) tt_um_brandonramos_VGA_Pong_with_NES_Controllers (VGA Pong with NES Controllers) tt_um_brandonramos_opamp_ladder (2-bit Flash ADC) tt_um_NE567Mixer28 (OTA folded cascode) tt_um_acidonitroso_programmable_threshold_voltage_sensor (Programmable threshold voltage sensor) tt_um_DAC1 (tt_um_DAC1) tt_um_trivium_stream_processor (Trivium Stream Cipher) tt_um_analog_example (Digital OTA) tt_um_sortaALUAriaMitra (Sorta 4-Bit ALU) tt_um_RoyTr16 (Connect Four VGA) tt_um_jnw_wulffern (JNW-TEMP) tt_um_serdes (Secure SERDES with Integrated FIR Filtering) tt_um_limpix31_r0 (VGA Human Reaction Meter) tt_um_torurstrom_async_lock (Asynchronous Locking Unit) tt_um_galaguna_PostSys (Post's Machine CPU Based) tt_um_edwintorok (Rounding error) tt_um_td4 (tt-td04) tt_um_snn (Reward implemented Spiking Neural Network) tt_um_matrag_chirp_top (Tiny Tapeout Chirp Modulator) tt_um_sha256_processor_dvirdc (SHA-256 Processor) tt_um_pchri03_levenshtein (Fuzzy Search Engine) tt_um_AriaMitraClock (12 Hour Clock (with AM and PM)) tt_um_swangust (posit8_add) tt_um_DelosReyesJordan_HDL (Reaction Time Test) tt_um_upalermo_simple_analog_circuit (Simple Analog Circuit) tt_um_swangust2 (posit8_mul) tt_um_thexeno_rgbw_controller (RGBW Color Processor) tt_um_top_layer (Spike Detection and Classification System) tt_um_Alida_DutyCycleMeter (Duty Cycle Meter) tt_um_dco (Digitally Controlled Oscillator) tt_um_8bitalu (8-bit Pipelined ALU) tt_um_resfuzzy (resfuzzy) tt_um_javibajocero_top (MarcoPolo) tt_um_Scimia_oscillator_tester (Oscillator tester) tt_um_ag_priority_encoder_parity_checker (Priority Encoder with Parity Checker) tt_um_tnt_mosbius (tnt's variant of SKY130 mini-MOSbius) tt_um_program_counter_top_level (Test Design 1) tt_um_subdiduntil2_mixed_signal_classifier (Mixed-signal Classifier) tt_um_dac_test3v3 (Analog 8 bit 3.3v R2R DAC) tt_um_LPCAS_TP1 ( LPCAS_TP1 ) tt_um_regfield (Register Field) tt_um_delaychain (Delay Chain) tt_um_tdctest_container (Micro tile container) tt_um_spacewar (Spacewar) tt_um_Enhanced_pll (Enhance PLL) tt_um_romless_cordic_engine (ROM-less Cordic Engine) tt_um_ev_motor_control (PLC Based Electric Vehicle Motor Control System) tt_um_plc_prg (PLC-PRG) tt_um_kishorenetheti_tt16_mips (8-bit MIPS Single Cycle Processor) tt_um_snn_core (Adaptive Leaky Integrate-and-Fire spiking neuron core for edge AI) tt_um_myprocessor (8-bit Custom Processor) tt_um_sjsu (SJSU vga demo) tt_um_vedic_4x4 (Vedic 4x4 Multiplier) tt_um_braun_mult (8x8 Braun Array Multiplier) tt_um_r2r_dac (4-bit R2R DAC) tt_um_stochastic_integrator_tt9_CL123abc (Stochastic Integrator) tt_um_uart (UART Controller with FIFO and Interrupts) tt_um_lfsr_stevej (Linear Feedback Shift Register) tt_um_FFT_engine (FFT Engine) tt_um_tpu (Tiny Tapeout Tensor Processing Unit) tt_um_tt_tinyQVb (TinyQV 'Berzerk' - Crowdsourced Risc-V SoC) tt_um_IZ_RG_22 (IZ_RG_22) tt_um_32_bit_fp_ALU_S_M (32-bit floating point ALU) tt_um_AriaMitraGames (Games (Tic Tac Toe and Rock Paper Scissors)) tt_um_sc_bipolar_qif_neuron (Stochastic Computing based QIF model neuron) tt_um_mac_spst_tiny (Low Power and Enhanced Speed Multiplier, Accumulator with SPST Adder) tt_um_kb2ghz_xalu (4-bit minicomputer ALU) tt_um_emmersonv_tiq_adc (3 Bit TIQ ADC) tt_um_simonsays (Simon Says) tt_um_BNN (8-bit Binary Neural Network) tt_um_anweiteck_2stageCMOSOpAmp (2 Stage CMOS Op Amp) tt_um_6502 (Simplified 6502 Processor) tt_um_swangust3 (posit8_div) tt_um_jonathan_thing_vga (VGA-Video-Player) tt_um_wokwi_412635532198550529 (ttsky-pettit-wokproc-trainer) tt_um_vga_hello_world (VGA HELLO WORLD) tt_um_jyblue1001_pll (Analog PLL) tt_um_BryanKuang_mac_peripheral (8-bit Multiply-Accumulate (MAC) with 2-Cycle Serial Interface) tt_um_rebeccargb_tt09ball_screensaver (TT09Ball VGA Screensaver) tt_um_openfpga22 (Open FGPA 2x2 design) tt_um_andyshor_demux (Demux) tt_um_flash_raid_controller (SPI flash raid controller) tt_um_jonnor_pdm_microphone (PDM microphone) tt_um_digital_playground (Sky130 Digital Playground) tt_um_mod6_counter (Mod-6 Counter) tt_um_BMSCE_T2 (Choreo8) tt_um_Richard28277 (4-bit ALU) tt_um_shuangyu_top (Calculator) tt_um_wokwi_441382314812372993 (Sumador/restador de 4 bits) tt_um_TensorFlowE (TensorFlowE) tt_um_wokwi_441378095886546945 (7SDSC) tt_um_wokwi_440004235377529857 (Latched 4-bits adder) tt_um_dlmiles_tqvph_i2c (TinyQV I2C Controller Device) tt_um_markgarnold_pdp8 (Serial PDP8) tt_um_wokwi_441564414591667201 (tt-parity-detector) tt_um_vga_glyph_mode (VGA Glyph Mode) tt_um_toivoh_pwl_synth (PiecewiseOrionSynth Deluxe) tt_um_minirisc (MiniRISC-FSM) tt_um_wokwi_438920793944579073 (Multiple digital design structures) tt_um_sleepwell (Sleep Well) tt_um_lcd_controller_Andres078 (LCD_controller) tt_um_SummerTT_HDL (SJSU Summer Project: Game of Life) tt_um_chrishtet_LIF (Leaky Integrate and Fire Neuron) tt_um_diff (ttsky25_EpitaXC) tt_um_htfab_split_flops (Split Flops) tt_um_alu_4bit_wrapper (4-bit ALU with Flags) tt_um_tnt_rf_test (TTSKY25A Register File Test) tt_um_mosbius (mini mosbius) tt_um_robot_controller_top_module (AR Chip) tt_um_flummer_ltc (Linear Timecode (LTC) generator) tt_um_stress_sensor (Tiny_Tapeout_2025_three_sensors) tt_um_krisjdev_manchester_baby (Manchester Baby) tt_um_mbikovitsky_audio_player (Simple audio player) tt_um_wokwi_414123795172381697 (TinySnake) tt_um_vga_example (Jabulani Ball VGA Demo ) tt_um_stochastic_addmultiply_CL123abc (Stochastic Multiplier, Adder and Self-Multiplier) tt_um_nvious_graphics (nVious Graphics) tt_um_pe_simonbju (pe) tt_um_mikael (TinyTestOut) tt_um_brent_kung (brent-kung_4) tt_um_7FM_ShadyPong (ShadyPong) tt_um_algofoogle_vga_matrix_dac (Analog VGA CSDAC experiments) tt_um_tv_b_gone (TV-B-Gone) tt_um_sjsu_vga_music (SJSU Fight Song) tt_um_fsm_haz (FSM based RISC-V Pipeline Hazard Resolver) tt_um_dma (DMA controller) tt_um_3v_inverter_SiliconeGuide (Analog Double Inverter) tt_um_rejunity_lgn_mnist (LGN hand-written digit classifier (MNIST, 16x16 pixels)) tt_um_gray_sobel (Gray scale and Sobel filter for Edge Detection) tt_um_Xgamer1999_LIF (Demonstration of Leaky integrate and Fire neuron SJSU) tt_um_dac12 (12 bit DAC) tt_um_voting_machine (Digital Voting Machine) tt_um_updown_counter (8bit_up-down_counter) tt_um_openram_top (Single Port OpenRAM Testchip) tt_um_customalu (Custom ALU) tt_um_assaify_mssf_pll (24 MHz MSSF PLL) tt_um_Maj_opamp (2-Stage OpAmp Design) tt_um_wokwi_442131619043064833 (Encoder 7 segments display) tt_um_wokwi_441835796137492481 (TESVG Binary Counter and shif register ) tt_um_combo_haz (Combinational Logic Based RISC-V Pipeline Hazard Resolver) tt_um_tx_fsm (Design and Functional Verification of Error-Correcting FIFO Buffer with SECDED and ARQ ) tt_um_will_keen_solitaire (solitaire) tt_um_rom_vga_screensaver (VGA Screensaver with embedded bitmap ROM) tt_um_13hihi31_tdc (Time to Digital Converter) tt_um_dteal_awg (Arbitrary Waveform Generator) tt_um_LIF_neuron (AFM_LIF) tt_um_rebelmike_register (Circulating register test) tt_um_MichaelBell_hs_mul (8b10b decoder and multiplier) tt_um_SNPU (random_latch) tt_um_rejunity_atari2600 (Atari 2600) tt_um_bit_serial_cpu_top (16-bit bit-serial CPU) tt_um_semaforo (semaforo) tt_um_bleeptrack_cc1 (Cross stitch Creatures #1) tt_um_bleeptrack_cc2 (Cross stitch Creatures #2) tt_um_bleeptrack_cc3 (Cross stitch Creatures #3) tt_um_bleeptrack_cc4 (Cross stitch Creatures #4) tt_um_bitty (Bitty) tt_um_spi2ws2811x16 (spi2ws2811x8) tt_um_uart_spi (UART and SPI Communication blocks with loopback) tt_um_urish_charge_pump (Dickson Charge Pump) tt_um_adc_dac_tern_alu (adc_dac_BCT_addr_ALU_STI) tt_um_sky1 (GD Sky Processor) tt_um_fifo (ASYNCHRONOUS FIFO) tt_um_TT16 (Asynchronous FIFO) tt_um_axi4lite_top (Axi4_Lite) tt_um_TT06_pwm (PWM Generator) tt_um_hack_cpu (HACK CPU) tt_um_marxkar_jtag (JTAG CONTROLLER) tt_um_cache_controller (Simple Cache Controller) tt_um_stopwatchtop (Stopwatch with 7-seg Display) tt_um_adpll (all-digital pll) tt_um_tnt_rom_test (TT09 SKY130 ROM Test) tt_um_tnt_rom_nolvt_test (TT09 SKY130 ROM Test (no LVT variant)) tt_um_wokwi_414120207283716097 (fulladder) tt_um_kianV_rv32ima_uLinux_SoC (KianV uLinux SoC) tt_um_tv_b_gone_rom (TV-B-Gone-EU) Available Available Available Available Available Available Available Available Available Available Available Available Available