Skip to content

scale-lab/NEWCAS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 

Repository files navigation

NEWCAS Tutorial: Leveraging LLMs in Hardware Design

Welcome to the NEWCAS tutorial on integrating Large Language Models (LLMs) into the hardware design, synthesis, and verification lifecycle. In this tutorial, we will use an LLM to design an integer square root module, simulate it, optimize its area, and verify its coverage using industry-standard open-source tools.

1. Environment Setup

Before we begin, ensure your system has the required open-source hardware tools installed: Yosys (synthesis), Icarus Verilog & Verilator (simulation), and Cocotb (Python-based verification).

macOS

Open your terminal and run:

# Install hardware tools via Homebrew
brew install yosys icarus-verilog verilator

# Install Python verification libraries
pip install pytest cocotb

Ubuntu / Windows Subsystem for Linux (WSL)

Open your terminal and run:

# Install hardware tools via APT
sudo apt update
sudo apt install yosys icarus-verilog verilator gtkwave

# Install Python verification libraries
pip install pytest cocotb

2. Preparing for Synthesis

To synthesize our hardware design and calculate its physical area, we need a standard cell library.

  1. Download the gscl45nm.lib (Generic Standard Cell Library, 45nm).
  2. Download the baseline testbench provided for this tutorial: problem1_tb.v.
  3. Place both files in your working directory.

3. Hardware Design Generation

We will start by asking an LLM (like Gemini) to generate our baseline Verilog module. First you need to select an LLM.Find your match based on the first letter of your name!

First Letter Assigned AI Platform
A, B, C, F, G OpenAI
D, E, H, I, J, K Anthropic
L, M, N, O, P, Q, R DeepSeek
S, T, U, V, W, X, Y, Z Google

As you progress in your design, make sure to track your metrics using this form

After logging into your selected LLM, Copy and paste the following prompt into the LLM:

Prompt for LLM: Write a combinational Verilog module named signed_isqrt to compute the integer square root of $x$, where $x$ is an input signed 16-bit integer and the output $y$ is an unsigned 8-bit integer. Specifications:

  • x: Signed 16-bit input representing the value for integer square root computation (operational range: -32,768 to +32,767). Negative values should be handled as special cases and output 0.
  • y: Unsigned 8-bit output containing the computed integer square root value (operational range: 0 to 181 for valid positive inputs, 0 for negative inputs).

You can experiment with Chain-of-Thought (CoT) techniques here. For example, you can modify your prompt to be as follows.

Prompt for LLM: You are an expert digital IC design engineer. Your task is to design a Verilog module for [INSERT SPECIFICATION from earlier].

To ensure the design is synthesizable and bug-free, you must think step-by-step. Do not output the final Verilog code until you have completed the following steps:

  1. Signal Analysis: List all I/O ports with names, directions, and bit-widths.
  2. Block Diagram & Architecture: Describe the internal registers, counters, and data paths needed.
  3. FSM Breakdown (if applicable): Define the states, next-state logic conditions, and output logic.
  4. Timing & Edge Considerations: Explicitly state how reset (sync vs async) and clock edges are handled.
  5. Before Verilog Generation List assumptions, invariants, safety properties, reset behavior, and List clock-domain assumptions.
  6. Verilog Generation: Finally, provide the complete, well-commented Verilog code based only on the steps above.

Next Steps:

  1. Save the generated Verilog code into a file named signed_isqrt.v.

4. Initial Simulation & Debugging (Verilator)

Before synthesizing, we must ensure the LLM's design is functionally correct. We will use Verilator to compile and run the provided testbench against the generated design.

Run the following commands in your terminal:

# Compile the design and testbench
verilator -Wno-LATCH -Wno-WIDTH --binary --top-module signed_isqrt_tb problem1_tb.v signed_isqrt.v

# Execute the compiled simulation
./obj_dir/Vsigned_isqrt_tb

Inspect the out, and make sure everything is marked "SUCCESS".

Iterative Debugging (manual Agentic flow for generation):

If the testbench reports failures, copy the terminal errors and paste them back into the LLM. Ask it to analyze the failure and provide a corrected signed_isqrt.v file. Repeat this until the testbench prints SUCCESS.


5. Synthesis and Area Optimization

Once the design is functionally correct, we will synthesize it using Yosys to map the behavioral Verilog to actual logic gates and measure its silicon area.

  1. Create a script file named synth.ys and add the following Yosys commands:
# Read the design file
read_verilog signed_isqrt.v

# Check design hierarchy
hierarchy -check -top signed_isqrt

# Generic synthesis and optimization
proc; opt; opt; techmap; opt

# Map flip-flops and logic to the 45nm library
dfflibmap -liberty gscl45nm.lib
abc -liberty gscl45nm.lib

# Generate statistics (Area)
stat -liberty gscl45nm.lib

# Write out the synthesized netlist
write_verilog signed_isqrt_syn.v
  1. Run the script:
yosys -s synth.ys
  1. Look at the terminal output for the Chip area statistic.

LLM Optimization terative Debugging (manual Agentic flow for area optimization):

  1. Go back to your LLM and prompt:

Here is my working Verilog code and design area. Optimize the algorithm to use fewer hardware resources (smaller area) while maintaining functional correctness"

  1. Replace your code, re-verify with Verilator (Step 4), and re-run Yosys to see how much the LLM reduced your design area!
  2. Try various prompting and CoT strategies to further reduce the area, until you cannot get further improvements. For example, try

You are a hardware synthesis and optimization expert. Your goal is to optimize the provided Verilog code to minimize design area (LUTs, registers, and gate count) without changing its functional behavior.

Follow these steps strictly before writing any modified code:

  1. Resource Identification: Analyze the current code and list every hardware resource it will infer (e.g., how many adders, multipliers, comparators, and registers of what bit-widths).
  2. Resource Sharing Analysis: Identify operations that do not happen simultaneously. Can we reuse a single adder or multiplier across different FSM states using a multiplexer?
  3. Bit-Width Pruning: Look at every register, counter, and wire. Are there variables where the maximum possible value is smaller than the allocated bit-width?
  4. Logic Simplification: Identify redundant states in the FSM, unused default branches, or mathematical expressions that can be simplified using boolean algebra.
  5. Optimized Verilog: Rewrite the Verilog code incorporating all the area-saving strategies identified above. Include comments explaining where resources were shared.
  1. Replace your code, re-verify with Verilator (Part 4 in this tutorial), and re-run Yosys to see how much the LLM reduced your design area!

6. Design Verification & Coverage

Testbenches rarely test every possible edge case on the first try. We will use Verilator's coverage tools to see what lines of code the testbench missed.

  1. Run Verilator with coverage flags enabled:
verilator -Wno-LATCH -Wno-WIDTH --binary -j 0 --coverage --coverage-line --coverage-toggle --top-module signed_isqrt_tb problem1_tb.v signed_isqrt.v

./obj_dir/Vsigned_isqrt_tb

verilator_coverage --annotate report coverage.dat
  1. Check the generated report/ directory to see which lines of Verilog were not triggered. LLM Prompt (manual Agentic flow for coverage improvement):
  2. Ask the LLM to write additional Verilog test cases targeting the uncovered lines, append them to problem1_tb.v, and re-test to achieve 100% coverage.

7. Advanced Verification: Python & Cocotb

Writing testbenches in pure Verilog can be tedious. Cocotb allows us to write hardware testbenches using Python, taking advantage of Python's math libraries for reference models.

Ask the LLM to generate the Python environment:

Prompt for LLM: Write a Python testbench using cocotb for a combinational Verilog module named signed_isqrt to compute the integer square root of $x$, where $x$ is an input signed 16-bit integer and the output $y$ is an unsigned 8-bit integer. Include directed edge cases and randomized testing. Also, create the standard cocotb Makefile for the Icarus Verilog simulator.

Execution:

  1. Save the Python code to test_signed_isqrt.py.
  2. Save the Makefile code to Makefile. (Ensure the MODULE and TOPLEVEL variables in the Makefile correctly match your filenames).
  3. Run the simulation using Icarus Verilog:
make SIM=icarus
  1. If there are any 0.00ns ERROR gpi failures, copy the traceback to the LLM and ask it to fix any port naming mismatches!

About

NEWCAS tutorial

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors