4 min read
On this page

Hardware Description Languages

Hardware Description Languages (HDLs) describe digital circuits in text form, enabling simulation, synthesis, and verification of complex designs.

HDL Concepts

Hardware vs Software Mindset

| Software | Hardware (HDL) | |---|---| | Sequential execution | Concurrent execution (everything runs simultaneously) | | Variables hold values | Wires carry signals continuously | | Functions compute results | Modules describe circuits | | Memory is implicit | Every register must be explicit | | Timing is abstracted | Timing is fundamental |

Key Difference: Concurrency

In hardware, all signals update simultaneously. An HDL assignment A = B & C doesn't "execute" — it describes a permanent wire connection from an AND gate to signal A.

Levels of Abstraction

| Level | Description | Example | |---|---|---| | Behavioral | Algorithm, control flow | "Sort these numbers" | | RTL (Register Transfer Level) | Registers + combinational logic | "On clock edge, store A + B" | | Gate level | Logic gates and connections | "NAND2(a, b) → wire1" | | Transistor level | Individual transistors | SPICE netlists |

RTL is the sweet spot for design — high enough for productivity, low enough for synthesis tools to produce efficient circuits.

RTL Design

Combinational Logic in RTL

Described with continuous assignments or always blocks sensitive to all inputs:

// Continuous assignment (Verilog-like pseudocode)
assign y = a & b | c;

// Always block (combinational)
always @(*) begin
    case (sel)
        2'b00: y = a;
        2'b01: y = b;
        2'b10: y = c;
        2'b11: y = d;
    endcase
end

Rule: Combinational blocks must assign outputs for every possible input combination (no latches inferred).

Sequential Logic in RTL

Described with clocked always blocks:

// D flip-flop with synchronous reset
always @(posedge clk) begin
    if (reset)
        q <= 0;
    else
        q <= d;
end

The <= (non-blocking assignment) is used for sequential logic. = (blocking) for combinational.

Common RTL Patterns

Counter:

always @(posedge clk) begin
    if (reset)
        count <= 0;
    else if (enable)
        count <= count + 1;
end

Shift register:

always @(posedge clk) begin
    shift_reg <= {shift_reg[N-2:0], serial_in};
end

FSM:

// State register
always @(posedge clk) begin
    if (reset) state <= IDLE;
    else state <= next_state;
end

// Next-state logic (combinational)
always @(*) begin
    case (state)
        IDLE: next_state = start ? RUNNING : IDLE;
        RUNNING: next_state = done ? COMPLETE : RUNNING;
        COMPLETE: next_state = IDLE;
        default: next_state = IDLE;
    endcase
end

// Output logic (combinational)
assign busy = (state == RUNNING);

Simulation

Event-Driven Simulation

The simulator processes events (signal changes) and propagates their effects:

  1. Initialize all signals.
  2. Process events in time order.
  3. When a signal changes, schedule dependent events (after gate delays).
  4. Advance simulation time to next event.
  5. Repeat.

Zero-delay simulation: All combinational logic evaluates in zero time. Useful for functional verification.

Timing simulation: Includes gate delays. Checks for timing violations.

Testbenches

A testbench is a non-synthesizable HDL module that:

  1. Instantiates the design under test (DUT)
  2. Generates stimulus (clock, reset, input patterns)
  3. Checks outputs against expected values
  4. Reports pass/fail
// Testbench pseudocode
module tb;
    reg clk = 0;
    always #5 clk = ~clk;  // 10-unit period clock

    reg [7:0] a, b;
    wire [8:0] sum;

    adder DUT(.a(a), .b(b), .sum(sum));

    initial begin
        a = 8'd10; b = 8'd20;
        #10;
        assert(sum == 9'd30) else $error("Test failed!");
        $finish;
    end
endmodule

Waveform Viewing

Simulation results are visualized as waveforms — signal values over time. Tools: GTKWave, ModelSim, Vivado simulator.

Synthesis

Synthesis converts RTL to a gate-level netlist:

RTL code → Synthesis tool → Gate netlist → Place & Route → Physical layout

What is Synthesizable

| Synthesizable | Not Synthesizable | |---|---| | Combinational logic (assign, always @(*)) | Delays (#10) | | Sequential logic (always @(posedge clk)) | File I/O (fopen)if/else,case,?:,operatorsInitialblocks(forsimulationonly)ModuleinstantiationSystemtasks(fopen) | | if/else, case, ?:, operators | Initial blocks (for simulation only) | | Module instantiation | System tasks (display, $finish) | | Parameters, generate | Infinite loops |

Synthesis Constraints

  • Clock period: Target frequency
  • I/O timing: Input/output delays relative to clock
  • Area: Maximum gate count or utilization
  • Power: Maximum power budget

The synthesis tool optimizes the design to meet these constraints.

Timing Constraints

create_clock -period 10 [get_ports clk]    // 100 MHz clock
set_input_delay -clock clk 2 [get_ports data_in]
set_output_delay -clock clk 1 [get_ports data_out]

The tool reports timing slack = (required time) - (actual time). Positive slack: timing met. Negative slack: timing violation.

Modern HDL Landscape

Verilog / SystemVerilog

  • Most widely used in industry (especially US, Asia)
  • SystemVerilog adds verification features (classes, assertions, coverage)
  • UVM (Universal Verification Methodology) for testbench infrastructure

VHDL

  • Strongly typed, verbose
  • Popular in Europe, defense, aerospace
  • VHDL-2008 added modern features

Chisel (Scala-based)

  • Generates Verilog from Scala
  • Used by RISC-V projects (SiFive, BOOM)
  • Higher-level abstractions (parameterized generators)

SpinalHDL (Scala-based)

  • Similar to Chisel but different philosophy
  • Comprehensive type system, strong compile-time checks

Amaranth (Python-based)

  • Python library for digital design
  • Generates Verilog or directly targets FPGAs

Clash (Haskell-based)

  • Functional HDL
  • Strong type system catches many design errors

Rust-Based Hardware Simulation

While Rust is not an HDL, it excels at hardware simulation and verification:

// Simple D flip-flop simulation
STRUCTURE DFlipFlop
    q : boolean

FUNCTION NEW_DFLIPFLOP()
    ff ← new DFlipFlop
    ff.q ← false
    RETURN ff

PROCEDURE CLOCK_EDGE(ff, d)
    ff.q ← d

FUNCTION OUTPUT(ff)
    RETURN ff.q

// 4-bit counter simulation
STRUCTURE Counter
    value : integer
    max   : integer

FUNCTION NEW_COUNTER(max)
    ctr ← new Counter
    ctr.value ← 0
    ctr.max ← max
    RETURN ctr

PROCEDURE TICK(ctr, enable, reset)
    IF reset THEN
        ctr.value ← 0
    ELSE IF enable THEN
        IF ctr.value ≥ ctr.max THEN
            ctr.value ← 0
        ELSE
            ctr.value ← ctr.value + 1

Rust is used for:

  • Cycle-accurate simulators: Verilator generates C++/Rust from Verilog
  • Formal verification tools: SAT/SMT solvers in Rust
  • Hardware test frameworks: cocotb (Python) and Rust alternatives
  • FPGA toolchains: Parts of Yosys, nextpnr ecosystem

Verification

Simulation-Based

  • Directed tests: Manual test cases for specific scenarios
  • Random/constrained random: Generate random but legal inputs
  • Coverage-driven: Track which states/transitions have been tested

Formal Verification

  • Model checking: Exhaustively verify properties for all possible inputs
  • Equivalence checking: Prove two designs implement the same function
  • Property checking: Verify assertions hold for all reachable states

Assertion-Based Verification

// SystemVerilog assertion: FIFO should never be read when empty
assert property (@(posedge clk) (read_en |-> !empty));

// Cover: Make sure we actually test the full condition
cover property (@(posedge clk) (count == MAX_COUNT));

Applications in CS

  • Processor design: x86, ARM, RISC-V processors designed in HDLs. Millions of lines of RTL.
  • ASIC design: Custom chips for AI (TPU), networking, automotive. HDL → synthesis → fabrication.
  • FPGA development: HDL is the primary design entry for FPGAs. IP cores reuse HDL modules.
  • Hardware-software co-design: Simulate hardware + firmware together. Virtual platforms.
  • Education: Understanding HDLs deepens understanding of computer architecture.
  • Open-source hardware: RISC-V cores (Rocket, BOOM), OpenTitan, LibreCores — all in HDLs.