Amaranth HDL Documentation

repository·main·Indexed 24 days ago

https://github.com/amaranth-lang/amaranth

An open-source hardware description language (HDL) and toolchain for designing synchronous digital logic using Python. Amaranth supports a full FPGA/ASIC workflow, targeting any process that accepts behavioral Verilog-2001, with specific support for Lattice, AMD, and Altera families. It includes a standard library for clock domain crossing (CDC), CRC generation, and data layouts, as well as a CLI for RTL generation and simulation.

Tokens
40.1K
Snippets
81
Records
218
Agent score
85%

What's inside Amaranth

  1. Overview of the Amaranth toolchain

    main

    Amaranth is an open-source toolchain for developing hardware based on synchronous digital logic using Python. It provides a complete FPGA development workflow including:

    • Amaranth language: A Python library for register transfer level (RTL) modeling of synchronous logic.
    • Standard library: A collection of essential digital design components (FIFOs, CDC primitives, I/O buffers).
    • Simulator: An event-driven Python-based simulator for testing designs using Python generator functions.
    • Build system: An integration layer for FPGA toolchains and development board definitions.

    The toolchain is designed to be interoperable with industry-standard (System)Verilog and VHDL code.

  2. Overview of Amaranth HDL

    main

    Amaranth is an open-source toolchain for developing hardware based on synchronous digital logic using Python. It provides a hardware definition language, a standard library, a simulator, and a build system to cover the typical FPGA development workflow.

    Key features include:

    • Python-based hardware design: Use Python to define complex hardware with reusable components.
    • Interoperability: Amaranth can integrate with existing (System)Verilog or VHDL code, and vice versa.
    • Ecosystem: Includes evaluation board definitions (amaranth-boards) and a System on Chip toolkit (amaranth-soc).
  3. Overview of the Amaranth Standard Library (amaranth.lib)

    main

    The Amaranth standard library, located in the amaranth.lib module, provides essential building blocks for hardware design. It is organized into three functional categories:

    1. Core Idiomatic Modules: Modules used in almost all idiomatic Amaranth code or required for interoperability. These include:
      • amaranth.lib.enum: Enumerations.
      • amaranth.lib.data: Data structures.
      • amaranth.lib.wiring: Interfaces and components.
      • amaranth.lib.meta: Interface metadata.
      • amaranth.lib.stream: Data streams.
    2. Platform Abstraction Modules: Modules that abstract common functionality that varies between different hardware platforms, such as:
      • amaranth.lib.memory
      • amaranth.lib.cdc (Clock Domain Crossing)
    3. Utility Modules: Modules with standard implementations for common digital design tasks, including:
      • amaranth.lib.fifo
      • amaranth.lib.crc

    Note that the standard library is technically separate from the Amaranth language itself; these modules are provided as a library that could be implemented by third parties.

  4. Use amaranth.lib.wiring for interfaces and connections

    main
    The amaranth.lib.wiring module is used to declare interfaces between different design components and establish reliable connections between them. This module provides abstractions to manage ports and signal routing more effectively than manual signal wiring.
  5. Transfer data between clock domains with amaranth.lib.cdc

    main

    The amaranth.lib.cdc module provides specialized building blocks designed to safely handle Clock Domain Crossing (CDC). These components prevent metastability and data corruption when signals move between asynchronous clock domains.

    Available synchronizer components include:

    • FFSynchronizer: Standard flip-flop based synchronizer.
    • AsyncFFSynchronizer: Asynchronous flip-flop synchronizer.
    • ResetSynchronizer: Synchronizer specifically for reset signals.
    • PulseSynchronizer: Synchronizer for transferring single-cycle pulses.
  6. What is a Signal in Amaranth

    main
    A Signal is a value representing a (potentially) varying number. Signals are the fundamental building blocks for data flow in Amaranth. Depending on how they are assigned, they are generated as either wires (in a combinational domain) or registers (in a synchronous domain). Signals always have a well-defined value and cannot be uninitialized or undefined.
  7. What is a Module in Amaranth

    main

    A module is the fundamental unit of an Amaranth design hierarchy. It is the smallest collection of logic that can be independently simulated, synthesized, or processed.

    Modules are responsible for:

    • Associating signals with control domains.
    • Providing control flow syntax.
    • Managing clock domains.
    • Aggregating submodules.

    Every design begins with a fresh module instance.

    m = Module()
  8. Use the Amaranth standard library

    main

    The Amaranth standard library provides reliable, reusable building blocks for digital design. While optional, it is recommended for:

    • Clock Domain Crossing (CDC): Provides primitives that can be specialized by platform integrations to follow vendor recommendations.
    • I/O Buffers: Provides a common interface for high-speed designs requiring registered or geared I/O buffers.
    • Common Components: Includes synchronous and asynchronous FIFOs and flexible I/O buffer interfaces.

    Using the standard library reduces the amount of code required when migrating between different FPGA families.

  9. Simulate designs with the Amaranth simulator

    main

    The Amaranth simulator is an event-driven, pure-Python implementation that requires no system dependencies.

    • Test Benches: Written as Python generator functions.
    • Capabilities: Supports designs with multiple clocks and asynchronous resets.
    • Performance: Compiles the netlist to Python code ahead of time for high performance (especially when running on PyPy).
    • Alternative: You can also convert Amaranth designs to Verilog to use with external simulators like Icarus Verilog or Verilator.
  10. Use IntEnum and IntFlag for transparent (unwrapped) signals

    main
    Similar to standard Python, IntEnum and IntFlag in amaranth.lib.enum are loosely typed. When a Signal is initialized with an IntEnum or IntFlag, it is NOT wrapped in a view class; instead, the signal remains a standard Signal object. This is useful when you want the enumeration to behave like a raw integer in hardware.
  11. Replace circuits with Python processes

    main

    For advanced simulation performance or to avoid reimplementing complex algorithms in Amaranth, you can replace an Amaranth circuit with an async Python function called a process.

    A process runs simultaneously with the Design Under Test (DUT) and communicates with the design via Signal objects.

    Key differences between a process and a testbench:

    • Execution Order: Testbenches run in a well-defined order (first to last as added), whereas processes run in an undefined order while the design is converging.
    • Observability: Processes cannot use ctx.get() to inspect signal values; this prevents processes from observing inconsistent intermediate states. Instead, they must react to changes or clock edges.

    To add a process, use Simulator.add_process(async_function).