Lab 3 AI Prototype

Modularity Experiment: Debounce + Keypad FSM

Learning Goals

The goal of this prototype is to explore how AI handles design modularity when implementing digital systems. By the end of this experiment you should be able to:

  • Demonstrate how an LLM can be used as a coding partner for modular designs.
  • Compare a monolithic prompt versus decomposed prompts on quality and correctness.
  • Document specific tips on how to prompt an LLM effectively for FSM-based designs.

Build both of the prototypes below and compare their performance in your reflection.

Prototype A: Monolithic Prompt (All-at-once)

Fire up your favorite LLM. ChatGPT is a good place to start, but you may consider using other LLMs as well like Claude or Gemini. Enter the prompt below.

NoteLLM Prompt: Whole Lab (Monolithic)

Target device: Lattice iCE40 UP5K FPGA with internal high-speed oscillator (~20 MHz).

Write synthesizable SystemVerilog to scan a 4x4 matrix keypad and display the last two hex keys pressed on a dual 7‑segment display. Implement:

  • A clock divider that derives a scan clock on the order of 100–200 Hz from the internal oscillator.
  • A keypad scanning controller that iterates one active‑low column at a time and samples active‑low rows, registering at most one key per press (debounce‑by‑design), ignoring additional presses while any key is held, and allowing a new registration only after release.
  • A top level that updates two hex digits (older and most recent) when a new key is registered and drives a time‑multiplexed two‑digit 7‑segment display without visible flicker and with balanced brightness.

Use idiomatic SystemVerilog (e.g., logic, always_ff, enumerated states for FSMs). Provide clean module boundaries and keep all state synchronous. Include brief comments explaining the design choices.

Create a new Radiant project, type the code generated by the LLM in and analyze the results. If the synthesis fails, type the error message back into the LLM to see what suggestions it generates.

Prototype B: Modular Prompts (Decompose into FSMs)

In this variant, you will prompt the LLM for the two main FSMs separately: (1) the one‑shot registration (debounce‑by‑design) behavior and (2) the keypad scanning controller. After generating those, you will request a top‑level integration and display logic.

NoteLLM Prompt 1: One‑shot Registration (Debounce‑by‑design)

Target device: Lattice iCE40 UP5K FPGA.

Overall Goal: Write SystemVerilog to scan a 4x4 matrix keypad and display the last two hex keys pressed on a dual 7 segment display.

Current Goal: Write a synthesizable SystemVerilog module that produces a one‑shot registration signal for the keypad system. Behavior:

  • When a key press is first detected, capture the current key code and assert a single‑cycle “new key” pulse.
  • While any key remains pressed, do not accept additional keys.
  • Only after keys are released should a subsequent press be recognized.
  • This should handle debouncing of the keys.

Implement as a small synchronous FSM with enumerated states and glitch‑free outputs. Keep names and interfaces reasonable; do not assume any hidden modules beyond what you define here.

Run this prompt within the same session to maintain the context of the above FSM.

NoteLLM Prompt 2: Keypad Scanner Controller

Target device: Lattice iCE40 UP5K FPGA.

Write a synthesizable SystemVerilog module that cycles through keypad columns (active‑low, one at a time) and samples rows (active‑low) to detect a single key at a time. Behavior:

  • Iterate columns at a suitable scan rate derived from the divided clock and sample rows.
  • When a key is detected, report a stable key code consistent with a standard 4x4 keypad layout and maintain it while the key remains pressed.
  • Provide a boolean signal indicating whether any key is currently pressed.

Use clean state encoding and synchronous logic; avoid combinational feedback and latches.

NoteLLM Prompt 3: Integrate and Display

Target device: Lattice iCE40 UP5K FPGA with internal oscillator as the root clock source.

Write a top‑level SystemVerilog module that instantiates the scanner and one‑shot modules, shifts the last two keys (older ← most recent; most recent ← new), and drives a multiplexed two‑digit seven‑segment display. Requirements:

  • Update the displayed digits only when a new key is registered.
  • Ensure equal apparent brightness and no visible flicker.
  • Keep all logic synthesizable and synchronous; use idiomatic SystemVerilog constructs.

Provide any small clock‑enable or divider logic you need. You can also assume that a sevenSegment module exists that takes a 4 bit input and outputs the 7 segments.

Reference Material

  • Use the Lab 3 specifications for exact behavior and constraints: lab/lab3/specs.qmd.

Reflect

Write up a few paragraphs reflecting on your experience using the LLM in both styles (monolithic vs modular). Include screenshots, code snippets, and other media as needed.

Consider discussing:

  • How did the monolithic prompt perform versus the decomposed prompts?
  • Did modularizing the prompts improve correctness, synthesis success, or readability?
  • Did Prototype A modularize the design in the way you expected without explicit instruction?
  • What FSM structures and SystemVerilog idioms did the LLM use that were helpful or surprising?
  • What issues did you encounter (e.g., keypad code mapping, active‑low row/col logic, debounce‑by‑design), and how did the LLM handle them?
  • What would you do differently the next time you use an LLM in your workflow?