Specification
Specification is the first and most consequential stage in the VLSI design flow: it defines what the chip is supposed to do before any architecture or RTL work begins. A complete specification covers functional requirements, performance targets (speed, throughput, latency), a power budget, area/cost targets, the target process node/foundry, and memory and I/O requirements. Every later stage — RTL, verification, synthesis, physical design — is ultimately judged against this document, which is why ambiguity or missing requirements here are the most expensive kind of mistake to make: a gap discovered after RTL is written costs far more to fix than a gap caught on paper.
Each layer narrows the previous one: product requirements say what the chip must achieve; the architecture spec decides the technical approach; the microarchitecture spec defines components, datapaths, and control logic; RTL is the first stage where any of this becomes actual code.
What a complete spec covers
| Document | Defines |
|---|---|
| Product / market requirements | Target application, competitive positioning, high-level functional and cost goals |
| Architecture spec | The technical approach chosen to meet those goals — instruction set, bus protocols, memory hierarchy, major functional blocks |
| Microarchitecture spec | Internal structure of each block: datapaths, control logic, pipeline stages, and how modules interact — this is the document RTL engineers actually implement against |
| Design / IP spec | Per-block interface definitions, register maps, timing requirements, and verification requirements for individual RTL units |
Best practices & pitfalls
The further a requirements gap travels before it's caught, the more it costs to fix — a change that's a text edit at the spec stage can mean re-writing RTL, re-running verification, and re-synthesizing if it's caught after logic synthesis. Specs should be unambiguous enough that two independent engineers implementing against them would produce interoperable results, and should explicitly separate "must have" requirements from "nice to have" ones so trade-offs during implementation have a clear priority order.
RTL Design
Register-Transfer Level (RTL) design describes a synchronous digital circuit's behavior in terms of how data moves between hardware registers each clock cycle, and what logic operates on it in transit — without describing the transistor-level implementation of that logic. It's written in a hardware description language (Verilog, VHDL, or SystemVerilog) and is synthesizable: an RTL description can be mechanically converted into a gate-level netlist by the tools in Stage 04.
The core RTL idea: on every active clock edge, REG B captures the combinational function of REG A's previous value. RTL code describes exactly this — what moves between registers and when — leaving the gate-level "how" to logic synthesis.
Coding guidelines that matter for synthesizable RTL
| Guideline | Why it matters |
|---|---|
| Non-blocking assignment (<=) for sequential logic | Evaluates all right-hand sides first, then updates all left-hand sides at the end of the time step — models real flip-flop behavior correctly and avoids simulation/synthesis mismatches |
| Synchronous reset preferred for ASIC | Sampled on the clock edge like any other data path, so static timing analysis can check it normally; asynchronous resets need extra reset-recovery/removal timing checks and dedicated reset-tree handling |
| Complete combinational sensitivity / assignments | An incomplete if/case statement in combinational logic infers an unintended latch instead of the intended pure logic — a classic and hard-to-spot bug |
| One clear clocking scheme per block | Mixing clock edges or clock domains inside a single always block makes both synthesis and timing closure far harder; cross-domain signals need explicit synchronizers |
| Parameterize widths and depths | Makes the same RTL block reusable across configurations without hand-editing bit widths, reducing copy-paste bugs |
Best practices & pitfalls
RTL sits in the middle of the design abstraction stack — more concrete than a behavioral/architectural model, more abstract than a gate netlist — and the whole point of writing good RTL is that it should simulate correctly and synthesize into exactly the hardware the designer intended, with no surprises. Static lint checks (Stage 03) catch most of the classic mistakes above automatically and should run continuously during RTL development, not just once at the end.
Functional Verification
Functional verification confirms that the RTL actually implements the specification's intended behavior before it's committed to synthesis and physical design — and it's routinely the most resource-intensive phase of modern chip development, often consuming more engineering effort than RTL design itself. Two broad methodologies are used together: simulation-based (dynamic) verification, which exercises the RTL with stimulus and checks the results, and formal verification (static), which mathematically proves properties about the RTL without needing any stimulus at all.
Stimulus flows in from the left (sequencer → driver → DUT); results flow out to the right (DUT → monitor → scoreboard / coverage). The scoreboard checks DUT output against a reference model; the coverage collector tracks how much of the intended behavior has actually been exercised.
Verification techniques
| Technique | What it does |
|---|---|
| Constrained-random verification (CRV) | Generates randomized-but-legal stimulus to reach scenarios a human wouldn't think to write directed tests for |
| Coverage-driven verification (CDV) | Uses functional coverage (covergroups) and code coverage (line/toggle/branch/FSM) to measure what's actually been exercised, closing the loop between "tests ran" and "behavior was verified" |
| SystemVerilog Assertions (SVA) | Checks temporal properties ("if A happens, B must follow within N cycles") continuously during simulation, catching bugs far closer to their root cause than a scoreboard mismatch would |
| Formal / property checking | Mathematically proves (or disproves) a property against all possible input sequences — no vectors needed — strongest for control logic, protocol compliance, and hard-to-reach corner cases |
| Linting | Static analysis of the RTL itself (before simulation) catching unintended latches, incomplete case statements, and other structural issues early and cheaply |
| CDC / RDC checks | Clock-domain-crossing and reset-domain-crossing analysis catch synchronization bugs that are typically invisible to ordinary functional simulation |
Best practices & pitfalls
Coverage closure is a loop, not a milestone: run tests, measure coverage, analyze the holes, add or adjust tests or constraints, and repeat until both code and functional coverage reach their sign-off targets (with any waivers explicitly justified). Formal and simulation are complementary, not competing — formal is exhaustive but works best on bounded, control-heavy logic, while simulation scales to full-chip, data-heavy scenarios formal can't practically cover.
Logic Synthesis
Logic synthesis translates verified RTL into a gate-level netlist built from real cells in a target standard-cell library, optimized for power, performance, and area (PPA) under the constraints the designer provides. A single RTL design can map to many functionally equivalent but structurally different netlists, each with different PPA characteristics — the constraints given to the synthesis tool are what steer it toward the netlist that's actually wanted, which is why an incomplete or wrong constraint set is one of the most common sources of a bad synthesis result.
Synthesis flows through translation into generic technology-independent gates, mapping onto the actual standard-cell library, and a final timing-driven optimization pass — all steered by the SDC constraints supplied alongside the RTL.
Common SDC constraint types
| Constraint | Purpose |
|---|---|
| create_clock | Defines a clock's period and waveform — the single most important constraint, since nearly everything else is measured relative to it |
| set_input_delay / set_output_delay | Models the timing budget consumed outside the block being synthesized, at its inputs and outputs |
| set_max_transition / set_max_capacitance | Bounds signal slew and load so the mapped gates stay within the cell library's characterized operating range |
| set_false_path | Tells the tool a timing path is functionally never exercised, so it isn't wastefully optimized |
| set_multicycle_path | Tells the tool a path is allowed more than one clock cycle to settle, relaxing an otherwise-unreachable timing requirement |
| set_case_analysis | Fixes a signal to a constant value for optimization purposes, letting the tool simplify logic that's only reachable in one configuration |
Best practices & pitfalls
Unconstrained paths are the classic synthesis trap: if a path isn't covered by any timing constraint, the tool has no reason to optimize it at all, and it can silently become the worst path in the design without ever showing up as a violation. Over-constraining has the opposite problem — asking for more margin than actually needed burns area and power chasing a target that was never real. Because synthesis and static timing analysis use closely related but not identical timing engines, correlating synthesis-reported timing against a signoff STA run early is standard practice rather than waiting until physical design to find a mismatch.
Sources
General industry research — this page is not sourced from vendor-specific internal documentation.
- VLSI specification, architecture, and microarchitecture design flow — general web research
- RTL design, synchronous design practice, and HDL coding guidelines — general web research
- An Introduction to Universal Verification Methodology for the Digital Design of ICs: A Review — IEEE Xplore
- A Proposed Methodology to Improve UVM-Based Test Generation and Coverage Closure — IEEE Xplore
- Efficient Methodology of Sampling UVM RAL During Simulation for SoC Functional Coverage — IEEE Xplore
- Logic Optimization and Synthesis: Trends and Directions in Industry — IEEE Xplore
- RTL Synthesis of Case Study Using Design Compiler — IEEE Xplore
- RTL Synthesis: From Logic Synthesis to Automatic Pipelining — IEEE Xplore