Rename nMigen to Amaranth HDL.

This commit is contained in:
whitequark 2021-12-10 05:39:50 +00:00
parent 0b28a97ca0
commit 909a3b8be7
200 changed files with 14493 additions and 14451 deletions

View file

@ -1,4 +1,4 @@
from nmigen import *
from amaranth import *
class LEDBlinker(Elaboratable):
@ -18,7 +18,7 @@ class LEDBlinker(Elaboratable):
return m
# --- BUILD ---
from nmigen_boards.icestick import *
from amaranth_boards.icestick import *
ICEStickPlatform().build(LEDBlinker(), do_program=True)

View file

@ -1,4 +1,4 @@
from nmigen import *
from amaranth import *
class UpCounter(Elaboratable):
@ -41,7 +41,7 @@ class UpCounter(Elaboratable):
return m
# --- TEST ---
from nmigen.sim import Simulator
from amaranth.sim import Simulator
dut = UpCounter(25)
@ -71,7 +71,7 @@ sim.add_sync_process(bench)
with sim.write_vcd("up_counter.vcd"):
sim.run()
# --- CONVERT ---
from nmigen.back import verilog
from amaranth.back import verilog
top = UpCounter(25)

View file

@ -1,8 +1,8 @@
(* generator = "nMigen" *)
(* generator = "Amaranth" *)
module top(clk, rst, en, ovf);
(* src = "<nmigen-root>/nmigen/hdl/ir.py:526" *)
(* src = "<amaranth-root>/amaranth/hdl/ir.py:526" *)
input clk;
(* src = "<nmigen-root>/nmigen/hdl/ir.py:526" *)
(* src = "<amaranth-root>/amaranth/hdl/ir.py:526" *)
input rst;
(* src = "up_counter.py:26" *)
input en;
@ -38,7 +38,7 @@ module top(clk, rst, en, ovf);
\count$next = \$3 [15:0];
endcase
endcase
(* src = "<nmigen-root>/nmigen/hdl/xfrm.py:518" *)
(* src = "<amaranth-root>/amaranth/hdl/xfrm.py:518" *)
casez (rst)
1'h1:
\count$next = 16'h0000;

View file

@ -1,167 +0,0 @@
Migen and nMigen compatibility summary
======================================
nMigen intends to provide as close to 100% compatibility to Migen as possible without compromising its other goals. However, Migen widely uses `*` imports, tends to expose implementation details, and in general does not have a well-defined interface. This document attempts to elucidate a well-defined Migen API surface (including, when necessary, private items that have been used downstream), and describes the intended nMigen replacements and their implementation status.
API change legend:
- *id*: identical
- *obs*: removed or incompatibly changed with compatibility stub provided
- *obs →n*: removed or incompatibly changed with compatibility stub provided, use *n* instead
- *brk*: removed or incompatibly changed with no replacement provided
- *brk →n*: removed or incompatibly changed with no replacement provided, use *n* instead
- *→n*: renamed to *n*
- *⇒m*: merged into *m*
- *a=→b=*: parameter *a* renamed to *b*
- *a=*: parameter *a* removed
- *.a=→.b*: attribute *a* renamed to *b*
- *.a=*: attribute *a* removed
- *?*: no decision made yet
When describing renames or replacements, `mod` refers to a 3rd-party package `mod` (no nMigen implementation provided), `.mod.item` refers to `nmigen.mod.item`, and "(import `.item`)" means that, while `item` is provided under `nmigen.mod.item`, it is aliased to, and should be imported from a shorter path for readability.
Status legend:
- () No decision yet, or no replacement implemented
- (+) Implemented replacement (the API and/or compatibility shim are provided)
- (⊕) Verified replacement and/or compatibility shim (the compatibility shim is manually reviewed and/or has 100% test coverage)
- (⊙) No direct replacement or compatibility shim is provided
Compatibility summary
---------------------
- () `fhdl``.hdl`
- (⊕) `bitcontainer``.tools`
- (⊕) `log2_int` id
- (⊕) `bits_for` id
- (⊕) `value_bits_sign``Value.shape`
- (⊕) `conv_output` **obs**
- (⊕) `decorators``.hdl.xfrm`
<br>Note: `transform_*` methods not considered part of public API.
- (⊙) `ModuleTransformer` **brk**
- (⊙) `ControlInserter` **brk**
- (⊕) `CEInserter``EnableInserter`
- (⊕) `ResetInserter` id
- (⊕) `ClockDomainsRenamer``DomainRenamer`, `cd_remapping=``domain_map=`
- (⊙) `edif` **brk**
- (⊕) `module` **obs**`.hdl.dsl`
<br>Note: any class inheriting from `Module` in oMigen should inherit from `Elaboratable` in nMigen and use an nMigen `Module` in its `.elaborate()` method.
- (⊕) `FinalizeError` **obs**
- (⊕) `Module` **obs**`.hdl.dsl.Module`
- (⊙) `namer` **brk**
- (⊙) `simplify` **brk**
- (⊕) `specials` **obs**
- (⊙) `Special` **brk**
- (⊕) `Tristate` **obs**
- (⊕) `TSTriple` **obs**`.lib.io.Pin`
- (⊕) `Instance``.hdl.ir.Instance`
- (⊕) `Memory` id
<br>Note: nMigen memories should not be added as submodules.
- (⊕) `.get_port` **obs**`.read_port()` + `.write_port()`
- (⊕) `_MemoryPort` **obs**`.hdl.mem.ReadPort` + `.hdl.mem.WritePort`
- (⊕) `READ_FIRST`/`WRITE_FIRST` **obs**
<br>Note: `READ_FIRST` corresponds to `mem.read_port(transparent=False)`, and `WRITE_FIRST` to `mem.read_port(transparent=True)`.
- (⊙) `NO_CHANGE` **brk**
<br>Note: in designs using `NO_CHANGE`, replace it with logic implementing required semantics explicitly, or with a different mode.
- (⊕) `structure``.hdl.ast`
- (⊕) `DUID` id
- (⊕) `_Value``Value`
<br>Note: values no longer valid as keys in `dict` and `set`; use `ValueDict` and `ValueSet` instead.
- (⊕) `wrap``Value.cast`
- (⊕) `_Operator``Operator`, `op=``operator=`, `.op``.operator`
- (⊕) `Mux` id
- (⊕) `_Slice``Slice` id
- (⊕) `_Part``Part` id
- (⊕) `Cat` id, `.l``.parts`
- (⊕) `Replicate``Repl`, `v=``value=`, `n=``count=`, `.v``.value`, `.n``.count`
- (⊕) `Constant``Const`, `bits_sign=``shape=`, `.nbits``.width`
- (⊕) `Signal` id, `bits_sign=``shape=`, `attr=``attrs=`, `name_override=`, `related=`, `variable=`, `.nbits``.width`
- (⊕) `ClockSignal` id, `cd=``domain=`, `.cd``.domain`
- (⊕) `ResetSignal` id, `cd=``domain=`, `.cd``.domain`
- (⊕) `_Statement``Statement`
- (⊕) `_Assign``Assign`, `l=``lhs=`, `r=``rhs=`
- (⊕) `_check_statement` **obs**`Statement.cast`
- (⊕) `If` **obs**`.hdl.dsl.Module.If`
- (⊕) `Case` **obs**`.hdl.dsl.Module.Switch`
- (⊕) `_ArrayProxy``.hdl.ast.ArrayProxy`, `choices=``elems=`, `key=``index=`
- (⊕) `Array` id
- (⊕) `ClockDomain``.hdl.cd.ClockDomain`
- (⊙) `_ClockDomainList` **brk**
- (⊙) `SPECIAL_INPUT`/`SPECIAL_OUTPUT`/`SPECIAL_INOUT` **brk**
- (⊙) `_Fragment` **brk**`.hdl.ir.Fragment`
- (⊙) `tools` **brk**
- (⊙) `insert_resets` **brk**`.hdl.xfrm.ResetInserter`
- (⊙) `rename_clock_domain` **brk**`.hdl.xfrm.DomainRenamer`
- (⊙) `tracer` **brk**
- (⊕) `get_var_name``.tracer.get_var_name`
- (⊙) `remove_underscore` **brk**
- (⊙) `get_obj_var_name` **brk**
- (⊙) `index_id` **brk**
- (⊙) `trace_back` **brk**
- (⊙) `verilog`
- (⊙) `DummyAttrTranslate` ?
- (⊕) `convert` **obs**`.back.verilog.convert`
- (⊙) `visit` **brk**`.hdl.xfrm`
- (⊙) `NodeVisitor` **brk**
- (⊙) `NodeTransformer` **brk**`.hdl.xfrm.ValueTransformer`/`.hdl.xfrm.StatementTransformer`
- () `genlib``.lib`
- () `cdc` ?
- (⊙) `MultiRegImpl` **brk**
- (⊕) `MultiReg``.lib.cdc.FFSynchronizer`
- () `PulseSynchronizer` ?
- () `BusSynchronizer` ?
- (⊕) `GrayCounter` **obs**`.lib.coding.GrayEncoder`
- (⊕) `GrayDecoder` **obs**`.lib.coding.GrayDecoder`
<br>Note: `.lib.coding.GrayEncoder` and `.lib.coding.GrayDecoder` are purely combinatorial.
- () `ElasticBuffer` ?
- () `lcm` ?
- () `Gearbox` ?
- (⊕) `coding` id
- (⊕) `Encoder` id
- (⊕) `PriorityEncoder` id
- (⊕) `Decoder` id
- (⊕) `PriorityDecoder` id
- () `divider` ?
- () `Divider` ?
- (⊕) `fifo``.lib.fifo`
- (⊕) `_FIFOInterface``FIFOInterface`
- (⊕) `SyncFIFO` id, `.replace=`
- (⊕) `SyncFIFOBuffered` id, `.fifo=`
- (⊕) `AsyncFIFO` ?
- (⊕) `AsyncFIFOBuffered`, `.fifo=`
- (⊕) `fsm` **obs**
<br>Note: FSMs are a part of core nMigen DSL; however, not all functionality is provided. The compatibility shim is a complete port of Migen FSM module.
- (⊙) `io` **brk**
<br>Note: all functionality in this module is a part of nMigen platform system.
- () `misc` ?
- () `split` ?
- () `displacer` ?
- () `chooser` ?
- () `timeline` ?
- () `WaitTimer` ?
- () `BitSlip` ?
- (⊕) `record` **obs**`.hdl.rec.Record`
<br>Note: nMigen uses a `Layout` object to represent record layouts.
- (⊕) `DIR_NONE` id
- (⊕) `DIR_M_TO_S``DIR_FANOUT`
- (⊕) `DIR_S_TO_M``DIR_FANIN`
- (⊕) `Record` id
- (⊙) `set_layout_parameters` **brk**
- (⊙) `layout_len` **brk**
- (⊙) `layout_get` **brk**
- (⊙) `layout_partial` **brk**
- (⊕) `resetsync` **obs**
- (⊕) `AsyncResetSynchronizer` **obs**`.lib.cdc.ResetSynchronizer`
- () `roundrobin` ?
- () `SP_WITHDRAW`/`SP_CE` ?
- () `RoundRobin` ?
- () `sort` ?
- () `BitonicSort` ?
- (⊕) `sim` **obs**`.back.pysim`
<br>Note: only items directly under `nmigen.compat.sim`, not submodules, are provided.
- (⊙) `core` **brk**
- (⊙) `vcd` **brk**`vcd`
- (⊙) `Simulator` **brk**
- (⊕) `run_simulation` **obs**`.back.pysim.Simulator`
- (⊕) `passive` **obs**`.hdl.ast.Passive`
- (⊙) `build` **brk**
<br>Note: the build system has been completely redesigned in nMigen.
- (⊙) `util` **brk**

View file

@ -1,241 +0,0 @@
*The text below is the original nMigen implementation proposal. It is provided for illustrative and historical purposes only.*
This repository contains a proposal for the design of nMigen in form of an implementation. This implementation deviates from the existing design of Migen by making several observations of its drawbacks:
* Migen is strongly tailored towards Verilog, yet translation of Migen to Verilog is not straightforward, leaves much semantics implicit (e.g. signedness, width extension, combinatorial assignments, sub-signal assignments...);
* Hierarchical designs are useful for floorplanning and optimization, yet Migen does not support them at all;
* Migen's syntax is not easily composable, and something like an FSM requires extending Migen's syntax in non-orthogonal ways;
* Migen reimplements a lot of mature open-source tooling, such as conversion of RTL to Verilog (Yosys' Verilog backend), or simulation (Icarus Verilog, Verilator, etc.), and often lacks in features, speed, or corner case handling.
* Migen requires awkward specials for some FPGA features such as asynchronous resets.
It also observes that Yosys' intermediate language, RTLIL, is an ideal target for Migen-style logic, as conversion of FHDL to RTLIL is essentially a 1:1 translation, with the exception of the related issues of naming and hierarchy.
This proposal makes several major changes to Migen that hopefully solve all of these drawbacks:
* nMigen changes FHDL's internal representation to closely match that of RTLIL;
* nMigen outputs RTLIL and relies on Yosys for conversion to Verilog, EDIF, etc;
* nMigen uses an exact mapping between FHDL signals and RTLIL names to off-load logic simulation to Icarus Verilog, Verilator, etc;
* nMigen uses an uniform, composable Python eHDL;
* nMigen outputs hierarchical RTLIL, automatically threading signals through the hierarchy;
* nMigen supports asynchronous reset directly;
* nMigen makes driving a signal from multiple clock domains a precise, hard error.
This proposal keeps in mind but does not make the following major changes:
* nMigen could be easily modified to flatten the hierarchy if a signal is driven simultaneously from multiple modules;
* nMigen could be easily modified to support `x` values (invalid / don't care) by relying on RTLIL's ability to directly represent them;
* nMigen could be easily modified to support negative edge triggered flip-flops by relying on RTLIL's ability to directly represent them;
* nMigen could be easily modified to track Python source locations of primitives and export them to RTLIL/Verilog through the `src` attribute, displaying the Python source locations in timing reports directly.
This proposal also makes the following simplifications:
* Specials are eliminated. Primitives such as memory ports are represented directly, and primitives such as tristate buffers are lowered to a selectable implementation via ordinary dependency injection (`f.submodules += platform.get_tristate(triple, io)`).
The internals of nMigen in this proposal are cleaned up, yet they are kept sufficiently close to Migen that \~all Migen code should be possible to run directly on nMigen using a syntactic compatibility layer.
One might reasonably expect that a roundtrip through RTLIL would result in unreadable Verilog.
However, this is not the case, e.g. consider the examples:
<details>
<summary>alu.v</summary>
```verilog
module \$1 (co, sel, a, b, o);
wire [17:0] _04_;
input [15:0] a;
input [15:0] b;
output co;
reg \co$next ;
output [15:0] o;
reg [15:0] \o$next ;
input [1:0] sel;
assign _04_ = $signed(+ a) + $signed(- b);
always @* begin
\o$next = 16'h0000;
\co$next = 1'h0;
casez ({ 1'h1, sel == 2'h2, sel == 1'h1, sel == 0'b0 })
4'bzzz1:
\o$next = a | b;
4'bzz1z:
\o$next = a & b;
4'bz1zz:
\o$next = a ^ b;
4'b1zzz:
{ \co$next , \o$next } = _04_[16:0];
endcase
end
assign o = \o$next ;
assign co = \co$next ;
endmodule
```
</details>
<details>
<summary>alu_hier.v</summary>
```verilog
module add(b, o, a);
wire [16:0] _0_;
input [15:0] a;
input [15:0] b;
output [15:0] o;
reg [15:0] \o$next ;
assign _0_ = a + b;
always @* begin
\o$next = 16'h0000;
\o$next = _0_[15:0];
end
assign o = \o$next ;
endmodule
module sub(b, o, a);
wire [16:0] _0_;
input [15:0] a;
input [15:0] b;
output [15:0] o;
reg [15:0] \o$next ;
assign _0_ = a - b;
always @* begin
\o$next = 16'h0000;
\o$next = _0_[15:0];
end
assign o = \o$next ;
endmodule
module top(a, b, o, add_o, sub_o, op);
input [15:0] a;
wire [15:0] add_a;
reg [15:0] \add_a$next ;
wire [15:0] add_b;
reg [15:0] \add_b$next ;
input [15:0] add_o;
input [15:0] b;
output [15:0] o;
reg [15:0] \o$next ;
input op;
wire [15:0] sub_a;
reg [15:0] \sub_a$next ;
wire [15:0] sub_b;
reg [15:0] \sub_b$next ;
input [15:0] sub_o;
add add (
.a(add_a),
.b(add_b),
.o(add_o)
);
sub sub (
.a(sub_a),
.b(sub_b),
.o(sub_o)
);
always @* begin
\o$next = 16'h0000;
\add_a$next = 16'h0000;
\add_b$next = 16'h0000;
\sub_a$next = 16'h0000;
\sub_b$next = 16'h0000;
\add_a$next = a;
\sub_a$next = a;
\add_b$next = b;
\sub_b$next = b;
casez ({ 1'h1, op })
2'bz1:
\o$next = sub_o;
2'b1z:
\o$next = add_o;
endcase
end
assign o = \o$next ;
assign add_a = \add_a$next ;
assign add_b = \add_b$next ;
assign sub_a = \sub_a$next ;
assign sub_b = \sub_b$next ;
endmodule
```
</details>
<details>
<summary>clkdiv.v</summary>
```verilog
module \$1 (sys_clk, o);
wire [16:0] _0_;
output o;
reg \o$next ;
input sys_clk;
wire sys_rst;
(* init = 16'hffff *)
reg [15:0] v = 16'hffff;
reg [15:0] \v$next ;
assign _0_ = v + 1'h1;
always @(posedge sys_clk)
v <= \v$next ;
always @* begin
\o$next = 1'h0;
\v$next = _0_[15:0];
\o$next = v[15];
casez (sys_rst)
1'h1:
\v$next = 16'hffff;
endcase
end
assign o = \o$next ;
endmodule
```
</details>
<details>
<summary>arst.v</summary>
```verilog
module \$1 (o, sys_clk, sys_rst);
wire [16:0] _0_;
output o;
reg \o$next ;
input sys_clk;
input sys_rst;
(* init = 16'h0000 *)
reg [15:0] v = 16'h0000;
reg [15:0] \v$next ;
assign _0_ = v + 1'h1;
always @(posedge sys_clk or posedge sys_rst)
if (sys_rst)
v <= 16'h0000;
else
v <= \v$next ;
always @* begin
\o$next = 1'h0;
\v$next = _0_[15:0];
\o$next = v[15];
end
assign o = \o$next ;
endmodule
```
</details>
<details>
<summary>pmux.v</summary>
```verilog
module \$1 (c, o, s, a, b);
input [15:0] a;
input [15:0] b;
input [15:0] c;
output [15:0] o;
reg [15:0] \o$next ;
input [2:0] s;
always @* begin
\o$next = 16'h0000;
casez (s)
3'bzz1:
\o$next = a;
3'bz1z:
\o$next = b;
3'b1zz:
\o$next = c;
3'hz:
\o$next = 16'h0000;
endcase
end
assign o = \o$next ;
endmodule
```
</details>

View file

@ -1,12 +1,12 @@
import os, sys
sys.path.insert(0, os.path.abspath("."))
import nmigen
import amaranth
project = "nMigen toolchain"
version = nmigen.__version__
project = "Amaranth HDL toolchain"
version = amaranth.__version__
release = version.split("+")[0]
copyright = "2020, nMigen developers"
copyright = "2020—2021, Amaranth HDL developers"
extensions = [
"sphinx.ext.intersphinx",

View file

@ -1,8 +1,8 @@
The nMigen documentation
########################
Amaranth HDL documentation
##########################
.. toctree::
:maxdepth: 1
index
Board definitions <https://nmigen.info/nmigen-boards/latest/>
Board definitions <https://amaranth-lang.org/amaranth-boards/latest/>

View file

@ -4,19 +4,19 @@ Installation
System requirements
===================
nMigen requires Python 3.6; it works on CPython_ 3.6 (or newer), and works faster on PyPy3.6_ 7.2 (or newer).
Amaranth HDL requires Python 3.6; it works on CPython_ 3.6 (or newer), and works faster on PyPy3.6_ 7.2 (or newer).
For most workflows, nMigen requires Yosys_ 0.9 (or newer). A compatible version of Yosys is distributed via PyPI_ for most popular platforms.
For most workflows, Amaranth requires Yosys_ 0.9 (or newer). A compatible version of Yosys is distributed via PyPI_ for most popular platforms.
Simulating nMigen code requires no additional software. However, a waveform viewer like GTKWave_ is invaluable for debugging.
Simulating Amaranth code requires no additional software. However, a waveform viewer like GTKWave_ is invaluable for debugging.
Synthesizing, placing and routing an nMigen design for an FPGA requires the FPGA family specific toolchain.
Synthesizing, placing and routing an Amaranth design for an FPGA requires the FPGA family specific toolchain.
.. TODO: Link to FPGA family docs here
.. _CPython: https://www.python.org/
.. _PyPy3.6: https://www.pypy.org/
.. _Yosys: http://www.clifford.at/yosys/
.. _Yosys: https://yosyshq.net/yosys/
.. _PyPI: https://pypi.org/
.. _GTKWave: http://gtkwave.sourceforge.net/
@ -92,10 +92,10 @@ Installing prerequisites
.. _install:
Installing nMigen
=================
Installing Amaranth
===================
The latest release of nMigen should work well for most applications. A development snapshot---any commit from the ``master`` branch of nMigen---should be similarly reliable, but is likely to include experimental API changes that will be in flux until the next release. With that in mind, development snapshots can be used to try out new functionality or to avoid bugs fixed since the last release.
The latest release of Amaranth should work well for most applications. A development snapshot---any commit from the ``main`` branch of Amaranth---should be similarly reliable, but is likely to include experimental API changes that will be in flux until the next release. With that in mind, development snapshots can be used to try out new functionality or to avoid bugs fixed since the last release.
.. _install-release:
@ -103,7 +103,7 @@ The latest release of nMigen should work well for most applications. A developme
Latest release
--------------
.. |release:install| replace:: To install the latest release of nMigen, run:
.. |release:install| replace:: To install the latest release of Amaranth, run:
.. platform-picker::
@ -114,7 +114,7 @@ Latest release
.. code-block:: doscon
> pip install --upgrade nmigen[builtin-yosys]
> pip install --upgrade amaranth[builtin-yosys]
.. platform-choice:: macos
:title: macOS
@ -123,22 +123,22 @@ Latest release
.. code-block:: console
$ pip install --user --upgrade 'nmigen[builtin-yosys]'
$ pip install --user --upgrade 'amaranth[builtin-yosys]'
.. platform-choice:: linux
:title: Linux
If you **did not** install Yosys manually in the :ref:`previous step <install-deps>`, to install the latest release of nMigen, run:
If you **did not** install Yosys manually in the :ref:`previous step <install-deps>`, to install the latest release of Amaranth, run:
.. code-block:: console
$ pip3 install --user --upgrade 'nmigen[builtin-yosys]'
$ pip3 install --user --upgrade 'amaranth[builtin-yosys]'
If you **did** install Yosys manually in the previous step, run:
.. code-block:: console
$ pip3 install --user --upgrade nmigen
$ pip3 install --user --upgrade amaranth
.. platform-choice:: arch
:altname: linux
@ -148,7 +148,7 @@ Latest release
.. code-block:: console
$ sudo pacman -S python-nmigen
$ sudo pacman -S python-amaranth
.. _install-snapshot:
@ -156,7 +156,7 @@ Latest release
Development snapshot
--------------------
.. |snapshot:install| replace:: To install the latest development snapshot of nMigen, run:
.. |snapshot:install| replace:: To install the latest development snapshot of Amaranth, run:
.. platform-picker::
@ -167,7 +167,7 @@ Development snapshot
.. code-block:: doscon
> pip install git+https://github.com/nmigen/nmigen.git#egg=nmigen[builtin-yosys]
> pip install git+https://github.com/amaranth-lang/amaranth.git#egg=amaranth[builtin-yosys]
.. platform-choice:: macos
:title: macOS
@ -176,22 +176,22 @@ Development snapshot
.. code-block:: console
$ pip install --user 'git+https://github.com/nmigen/nmigen.git#egg=nmigen[builtin-yosys]'
$ pip install --user 'git+https://github.com/amaranth-lang/amaranth.git#egg=amaranth[builtin-yosys]'
.. platform-choice:: linux
:title: Linux
If you **did not** install Yosys manually in the :ref:`previous step <install-deps>`, to install the latest release of nMigen, run:
If you **did not** install Yosys manually in the :ref:`previous step <install-deps>`, to install the latest release of Amaranth, run:
.. code-block:: console
$ pip3 install --user 'git+https://github.com/nmigen/nmigen.git#egg=nmigen[builtin-yosys]'
$ pip3 install --user 'git+https://github.com/amaranth-lang/amaranth.git#egg=amaranth[builtin-yosys]'
If you **did** install Yosys manually in the previous step, run:
.. code-block:: console
$ pip3 install --user 'git+https://github.com/nmigen/nmigen.git#egg=nmigen'
$ pip3 install --user 'git+https://github.com/amaranth-lang/amaranth.git#egg=amaranth'
.. _install-develop:
@ -199,9 +199,9 @@ Development snapshot
Editable development snapshot
-----------------------------
.. |develop:first-time| replace:: To install an editable development snapshot of nMigen for the first time, run:
.. |develop:update| replace:: Any changes made to the ``nmigen`` directory will immediately affect any code that uses nMigen. To update the snapshot, run:
.. |develop:reinstall| replace:: each time the editable development snapshot is updated in case package dependencies have been added or changed. Otherwise, code using nMigen may misbehave or crash with an ``ImportError``.
.. |develop:first-time| replace:: To install an editable development snapshot of Amaranth for the first time, run:
.. |develop:update| replace:: Any changes made to the ``amaranth`` directory will immediately affect any code that uses Amaranth. To update the snapshot, run:
.. |develop:reinstall| replace:: each time the editable development snapshot is updated in case package dependencies have been added or changed. Otherwise, code using Amaranth may misbehave or crash with an ``ImportError``.
.. platform-picker::
@ -212,16 +212,16 @@ Editable development snapshot
.. code-block:: doscon
> git clone https://github.com/nmigen/nmigen
> cd nmigen
> git clone https://github.com/amaranth-lang/amaranth
> cd amaranth
> pip install --editable .[builtin-yosys]
|develop:update|
.. code-block:: doscon
> cd nmigen
> git pull --ff-only origin master
> cd amaranth
> git pull --ff-only origin main
> pip install --editable .[builtin-yosys]
Run the ``pip install --editable .[builtin-yosys]`` command |develop:reinstall|
@ -233,16 +233,16 @@ Editable development snapshot
.. code-block:: console
$ git clone https://github.com/nmigen/nmigen
$ cd nmigen
$ git clone https://github.com/amaranth-lang/amaranth
$ cd amaranth
$ pip install --user --editable '.[builtin-yosys]'
|develop:update|
.. code-block:: console
$ cd nmigen
$ git pull --ff-only origin master
$ cd amaranth
$ git pull --ff-only origin main
$ pip install --user --editable '.[builtin-yosys]'
Run the ``pip install --editable .[builtin-yosys]`` command |develop:reinstall|
@ -256,16 +256,16 @@ Editable development snapshot
.. code-block:: console
$ git clone https://github.com/nmigen/nmigen
$ cd nmigen
$ git clone https://github.com/amaranth-lang/amaranth
$ cd amaranth
$ pip3 install --user --editable '.[builtin-yosys]'
|develop:update|
.. code-block:: console
$ cd nmigen
$ git pull --ff-only origin master
$ cd amaranth
$ git pull --ff-only origin main
$ pip3 install --user --editable '.[builtin-yosys]'
Run the ``pip3 install --editable .[builtin-yosys]`` command |develop:reinstall|
@ -276,4 +276,4 @@ Installing board definitions
.. todo::
Explain how to install `<https://github.com/nmigen/nmigen-boards>`_.
Explain how to install `<https://github.com/amaranth-lang/amaranth-boards>`_.

View file

@ -1,61 +1,61 @@
.. TODO: this introduction is written for people well familiar with HDLs; we likely need
another one for people who will use nMigen as their first HDL
another one for people who will use Amaranth as their first HDL
Introduction
############
The core nMigen project provides an open-source toolchain for developing hardware based on synchronous digital logic using the Python programming language. It aims to be easy to learn and use, reduce or eliminate common coding mistakes, and simplify the design of complex hardware with reusable components.
The Amaranth project provides an open-source toolchain for developing hardware based on synchronous digital logic using the Python programming language. It aims to be easy to learn and use, reduce or eliminate common coding mistakes, and simplify the design of complex hardware with reusable components.
The nMigen toolchain consists of the :ref:`nMigen language <intro-lang>`, the :ref:`standard library <intro-stdlib>`, the :ref:`simulator <intro-sim>`, and the :ref:`build system <intro-build>`, covering all steps of a typical FPGA development workflow. At the same time, it does not restrict the designer's choice of tools: existing industry-standard (System)Verilog or VHDL code can be integrated into an nMigen design flow, or, conversely, nMigen code can be integrated into an existing Verilog-based design flow.
The Amaranth toolchain consists of the :ref:`Amaranth language <intro-lang>`, the :ref:`standard library <intro-stdlib>`, the :ref:`simulator <intro-sim>`, and the :ref:`build system <intro-build>`, covering all steps of a typical FPGA development workflow. At the same time, it does not restrict the designer's choice of tools: existing industry-standard (System)Verilog or VHDL code can be integrated into an Amaranth-based design flow, or, conversely, Amaranth code can be integrated into an existing Verilog-based design flow.
.. TODO: add links to connect_rpc docs once they exist
.. _intro-lang:
The nMigen language
===================
The Amaranth language
=====================
The :doc:`nMigen hardware description language <lang>` is a Python library for register transfer level modeling of synchronous logic. Ordinary Python code is used to construct a netlist of a digital circuit, which can be simulated, directly synthesized via Yosys_, or converted to human-readable Verilog code for use with industry-standard toolchains.
The :doc:`Amaranth hardware description language <lang>` is a Python library for register transfer level modeling of synchronous logic. Ordinary Python code is used to construct a netlist of a digital circuit, which can be simulated, directly synthesized via Yosys_, or converted to human-readable Verilog code for use with industry-standard toolchains.
By relying on the flexibility, rich functionality and widespread adoption of the Python language, the nMigen language is focused on a single task: modeling digital logic well. It has first-class support for building blocks like clock domains and finite state machines, and uses simple rules for arithmetic operations that closely match the Python semantics. Python classes, functions, loops and conditionals can be used to build organized and flexible designs; Python libraries can be seamlessly used with nMigen during design or verification; and Python development tools can process nMigen code.
By relying on the flexibility, rich functionality and widespread adoption of the Python language, the Amaranth language is focused on a single task: modeling digital logic well. It has first-class support for building blocks like clock domains and finite state machines, and uses simple rules for arithmetic operations that closely match the Python semantics. Python classes, functions, loops and conditionals can be used to build organized and flexible designs; Python libraries can be seamlessly used with Amaranth during design or verification; and Python development tools can process Amaranth code.
A core design principle of the nMigen language is to be not only easy to use, but also hard to accidentally misuse. Some HDLs provide functionality that has unexpected and undesirable behavior in synthesis, often with expensive consequences, and require a significant effort in learning a "safe" coding style and adopting third-party linting tools. nMigen lacks non-synthesizable constructs and avoids error-prone inference in favor of explicit instantiation. It has many diagnostics (and regularly adds new ones) highlighting potential design issues. Most importantly, all usability issues are considered `reportable bugs`_.
A core design principle of the Amaranth language is to be not only easy to use, but also hard to accidentally misuse. Some HDLs provide functionality that has unexpected and undesirable behavior in synthesis, often with expensive consequences, and require a significant effort in learning a "safe" coding style and adopting third-party linting tools. Amaranth lacks non-synthesizable constructs and avoids error-prone inference in favor of explicit instantiation. It has many diagnostics (and regularly adds new ones) highlighting potential design issues. Most importantly, all usability issues are considered `reportable bugs`_.
.. _Yosys: http://www.clifford.at/yosys/
.. _reportable bugs: https://github.com/nmigen/nmigen/issues
.. _Yosys: https://yosyshq.net/yosys/
.. _reportable bugs: https://github.com/amaranth-lang/amaranth/issues
.. _intro-stdlib:
The nMigen standard library
===========================
The Amaranth standard library
=============================
The nMigen language comes with a standard library---a collection of essential digital design components and interfaces. It includes clock domain crossing primitives, synchronous and asynchronous FIFOs, a flexible I/O buffer interface, and more. By providing reliable building blocks out of the box, nMigen allows the designer to focus on their application and avoids subtle differences in behavior between different designs.
The Amaranth language comes with a standard library---a collection of essential digital design components and interfaces. It includes clock domain crossing primitives, synchronous and asynchronous FIFOs, a flexible I/O buffer interface, and more. By providing reliable building blocks out of the box, Amaranth allows the designer to focus on their application and avoids subtle differences in behavior between different designs.
.. TODO: link to stdlib here
Clock domain crossing often requires special treatment, such as using vendor-defined attributes or instantiating device-specific primitives. The CDC primitives in the nMigen standard library can be overridden by the platform integration, and every platform integration included with nMigen follows the vendor recommendations for CDC.
Clock domain crossing often requires special treatment, such as using vendor-defined attributes or instantiating device-specific primitives. The CDC primitives in the Amaranth standard library can be overridden by the platform integration, and every platform integration included with Amaranth follows the vendor recommendations for CDC.
High-speed designs usually require the use of registered (and sometimes, geared) I/O buffers. The nMigen standard library provides a common interface to be used between I/O buffers and peripheral implementations. The nMigen build system, if used, can instantiate I/O buffers for every platform integration included with nMigen.
High-speed designs usually require the use of registered (and sometimes, geared) I/O buffers. The Amaranth standard library provides a common interface to be used between I/O buffers and peripheral implementations. The Amaranth build system, if used, can instantiate I/O buffers for every platform integration included with Amaranth.
While many designs will use at least some vendor-specific functionality, the components provided by the nMigen standard library reduce the amount of code that needs to be changed when migrating between FPGA families, and the common interfaces simplify peripherals, test benches and simulations.
While many designs will use at least some vendor-specific functionality, the components provided by the Amaranth standard library reduce the amount of code that needs to be changed when migrating between FPGA families, and the common interfaces simplify peripherals, test benches and simulations.
The nMigen standard library is optional: the nMigen language can be used without it. Conversely, it is possible to use the nMigen standard library components in Verilog or VHDL code, with some limitations.
The Amaranth standard library is optional: the Amaranth language can be used without it. Conversely, it is possible to use the Amaranth standard library components in Verilog or VHDL code, with some limitations.
.. TODO: link to connect_rpc docs here *again*
.. _intro-sim:
The nMigen simulator
====================
The Amaranth simulator
======================
The nMigen project includes an advanced simulator for nMigen code implemented in Python with no system dependencies; in this simulator, test benches are written as Python generator functions. Of course, it is always possible to convert an nMigen design to Verilog for use with well-known tool like `Icarus Verilog`_ or Verilator_.
The Amaranth project includes an advanced simulator for Amaranth code implemented in Python with no system dependencies; in this simulator, test benches are written as Python generator functions. Of course, it is always possible to convert an Amaranth design to Verilog for use with well-known tool like `Icarus Verilog`_ or Verilator_.
The nMigen simulator is event-driven and can simulate designs with multiple clocks or asynchronous resets. Although it is slower than `Icarus Verilog`_, it compiles the netlist to Python code ahead of time, achieving remarkably high performance for a pure Python implementation---especially when running on PyPy_.
The Amaranth simulator is event-driven and can simulate designs with multiple clocks or asynchronous resets. Although it is slower than `Icarus Verilog`_, it compiles the netlist to Python code ahead of time, achieving remarkably high performance for a pure Python implementation---especially when running on PyPy_.
Although nMigen does not support native code simulation or co-simulation at the moment, such support will be added in near future.
Although Amaranth does not support native code simulation or co-simulation at the moment, such support will be added in near future.
.. _Icarus Verilog: http://iverilog.icarus.com/
.. _Verilator: https://www.veripool.org/wiki/verilator
@ -65,10 +65,10 @@ Although nMigen does not support native code simulation or co-simulation at the
.. _intro-build:
The nMigen build system
=======================
The Amaranth build system
=========================
To achieve an end-to-end FPGA development workflow, the nMigen project integrates with all major FPGA toolchains and provides definitions for many common development boards.
To achieve an end-to-end FPGA development workflow, the Amaranth project integrates with all major FPGA toolchains and provides definitions for many common development boards.
.. TODO: link to vendor docs and board docs here
@ -76,18 +76,18 @@ To achieve an end-to-end FPGA development workflow, the nMigen project integrate
FPGA toolchain integration
--------------------------
Each FPGA family requires the use of synthesis and place & route tools specific for that device family. The nMigen build system directly integrates with every major open-source and commercial FPGA toolchain, and can be easily extended to cover others.
Each FPGA family requires the use of synthesis and place & route tools specific for that device family. The Amaranth build system directly integrates with every major open-source and commercial FPGA toolchain, and can be easily extended to cover others.
Through this integration, nMigen can specialize the CDC primitives and I/O buffers for a particular device and toolchain; generate I/O and clock constraints from board definition files; synchronize the power-on reset in single-clock designs; include (System)Verilog and VHDL files in the design (if supported by the toolchain); and finally, generate a script running synthesis, placement, routing, and timing analysis. The generated code can be customized to insert additional options, commands, constraints, and so on.
Through this integration, Amaranth can specialize the CDC primitives and I/O buffers for a particular device and toolchain; generate I/O and clock constraints from board definition files; synchronize the power-on reset in single-clock designs; include (System)Verilog and VHDL files in the design (if supported by the toolchain); and finally, generate a script running synthesis, placement, routing, and timing analysis. The generated code can be customized to insert additional options, commands, constraints, and so on.
The nMigen build system produces self-contained, portable build trees that require only the toolchain to be present in the environment. This makes builds easier to reproduce, or to run on a remote machine. The generated build scripts are always provided for both \*nix and Windows.
The Amaranth build system produces self-contained, portable build trees that require only the toolchain to be present in the environment. This makes builds easier to reproduce, or to run on a remote machine. The generated build scripts are always provided for both \*nix and Windows.
Development board definitions
-----------------------------
Getting started with a new FPGA development board often requires going through a laborous and error-prone process of deriving toolchain configuration and constraint files from the supplied documentation. The nMigen project includes a community-maintained repository of definitions for many open-source and commercial FPGA development boards.
Getting started with a new FPGA development board often requires going through a laborous and error-prone process of deriving toolchain configuration and constraint files from the supplied documentation. The Amaranth project includes a community-maintained repository of definitions for many open-source and commercial FPGA development boards.
These board definitions contain everything that is necessary to start using the board: FPGA family and model, clocks and resets, descriptions of on-board peripherals (including pin direction and attributes such as I/O standard), connector pinouts, and for boards with a built-in debug probe, the steps required to program the board. It takes a single Python invocation to generate, build, and download a test design that shows whether the board, toolchain, and programmer are working correctly.
nMigen establishes a pin naming convention for many common peripherals (such as 7-segment displays, SPI flashes and SDRAM memories), enabling the reuse of unmodified interface code with many different boards. Further, the polarity of all control signals is unified to be active high, eliminating accidental polarity inversions and making simulation traces easier to follow; active low signals are inverted during I/O buffer instantiation.
Amaranth establishes a pin naming convention for many common peripherals (such as 7-segment displays, SPI flashes and SDRAM memories), enabling the reuse of unmodified interface code with many different boards. Further, the polarity of all control signals is unified to be active high, eliminating accidental polarity inversions and making simulation traces easier to follow; active low signals are inverted during I/O buffer instantiation.

View file

@ -5,7 +5,7 @@ Language guide
This guide is a work in progress and is seriously incomplete!
This guide introduces the nMigen language in depth. It assumes familiarity with synchronous digital logic and the Python programming language, but does not require prior experience with any hardware description language. See the :doc:`tutorial <tutorial>` for a step-by-step introduction to the language.
This guide introduces the Amaranth language in depth. It assumes familiarity with synchronous digital logic and the Python programming language, but does not require prior experience with any hardware description language. See the :doc:`tutorial <tutorial>` for a step-by-step introduction to the language.
.. TODO: link to a good synchronous logic tutorial and a Python tutorial?
@ -15,23 +15,23 @@ This guide introduces the nMigen language in depth. It assumes familiarity with
The prelude
===========
Because nMigen is a regular Python library, it needs to be imported before use. The root ``nmigen`` module, called *the prelude*, is carefully curated to export a small amount of the most essential names, useful in nearly every design. In source files dedicated to nMigen code, it is a good practice to use a :ref:`glob import <python:tut-pkg-import-star>` for readability:
Because Amaranth is a regular Python library, it needs to be imported before use. The root ``amaranth`` module, called *the prelude*, is carefully curated to export a small amount of the most essential names, useful in nearly every design. In source files dedicated to Amaranth code, it is a good practice to use a :ref:`glob import <python:tut-pkg-import-star>` for readability:
.. code-block::
from nmigen import *
from amaranth import *
However, if a source file uses nMigen together with other libraries, or if glob imports are frowned upon, it is conventional to use a short alias instead:
However, if a source file uses Amaranth together with other libraries, or if glob imports are frowned upon, it is conventional to use a short alias instead:
.. code-block::
import nmigen as nm
import amaranth as am
All of the examples below assume that a glob import is used.
.. testsetup::
from nmigen import *
from amaranth import *
.. _lang-values:
@ -39,7 +39,7 @@ All of the examples below assume that a glob import is used.
Values
======
The basic building block of the nMigen language is a *value*, which is a term for a binary number that is computed or stored anywhere in the design. Each value has a *width*---the amount of bits used to represent the value---and a *signedness*---the interpretation of the value by arithmetic operations---collectively called its *shape*. Signed values always use `two's complement`_ representation.
The basic building block of the Amaranth language is a *value*, which is a term for a binary number that is computed or stored anywhere in the design. Each value has a *width*---the amount of bits used to represent the value---and a *signedness*---the interpretation of the value by arithmetic operations---collectively called its *shape*. Signed values always use `two's complement`_ representation.
.. _two's complement: https://en.wikipedia.org/wiki/Two's_complement
@ -49,14 +49,14 @@ The basic building block of the nMigen language is a *value*, which is a term fo
Constants
=========
The simplest nMigen value is a *constant*, representing a fixed number, and introduced using ``Const(...)`` or its short alias ``C(...)``:
The simplest Amaranth value is a *constant*, representing a fixed number, and introduced using ``Const(...)`` or its short alias ``C(...)``:
.. doctest::
>>> ten = Const(10)
>>> minus_two = C(-2)
The code above does not specify any shape for the constants. If the shape is omitted, nMigen uses unsigned shape for positive numbers and signed shape for negative numbers, with the width inferred from the smallest amount of bits necessary to represent the number. As a special case, in order to get the same inferred shape for ``True`` and ``False``, ``0`` is considered to be 1-bit unsigned.
The code above does not specify any shape for the constants. If the shape is omitted, Amaranth uses unsigned shape for positive numbers and signed shape for negative numbers, with the width inferred from the smallest amount of bits necessary to represent the number. As a special case, in order to get the same inferred shape for ``True`` and ``False``, ``0`` is considered to be 1-bit unsigned.
.. doctest::
@ -212,7 +212,7 @@ Specifying a shape with an enumeration is convenient for finite state machines,
Value casting
=============
Like shapes, values may be *cast* from other objects, which are called *value-castable*. Casting allows objects that are not provided by nMigen, such as integers or enumeration members, to be used in nMigen expressions directly.
Like shapes, values may be *cast* from other objects, which are called *value-castable*. Casting allows objects that are not provided by Amaranth, such as integers or enumeration members, to be used in Amaranth expressions directly.
.. TODO: link to UserValue
@ -348,7 +348,7 @@ Signals assigned in a :ref:`combinatorial <lang-comb>` domain are not affected b
Operators
=========
To describe computations, nMigen values can be combined with each other or with :ref:`value-castable <lang-valuecasting>` objects using a rich array of arithmetic, bitwise, logical, bit sequence, and other *operators* to form *expressions*, which are themselves values.
To describe computations, Amaranth values can be combined with each other or with :ref:`value-castable <lang-valuecasting>` objects using a rich array of arithmetic, bitwise, logical, bit sequence, and other *operators* to form *expressions*, which are themselves values.
.. _lang-abstractexpr:
@ -364,7 +364,7 @@ Code written in the Python language *performs* computations on concrete objects,
>>> a + 1
6
In contrast, code written in the nMigen language *describes* computations on abstract objects, like :ref:`signals <lang-signals>`, with the goal of generating a hardware *circuit* that can be simulated, synthesized, and so on. nMigen expressions are ordinary Python objects that represent parts of this circuit:
In contrast, code written in the Amaranth language *describes* computations on abstract objects, like :ref:`signals <lang-signals>`, with the goal of generating a hardware *circuit* that can be simulated, synthesized, and so on. Amaranth expressions are ordinary Python objects that represent parts of this circuit:
.. doctest::
@ -372,7 +372,7 @@ In contrast, code written in the nMigen language *describes* computations on abs
>>> a + 1
(+ (sig a) (const 1'd1))
Although the syntax is similar, it is important to remember that nMigen values exist on a higher level of abstraction than Python values. For example, expressions that include nMigen values cannot be used in Python control flow structures:
Although the syntax is similar, it is important to remember that Amaranth values exist on a higher level of abstraction than Python values. For example, expressions that include Amaranth values cannot be used in Python control flow structures:
.. doctest::
@ -380,9 +380,9 @@ Although the syntax is similar, it is important to remember that nMigen values e
... print("Zero!")
Traceback (most recent call last):
...
TypeError: Attempted to convert nMigen value to Python boolean
TypeError: Attempted to convert Amaranth value to Python boolean
Because the value of ``a``, and therefore ``a == 0``, is not known at the time when the ``if`` statement is executed, there is no way to decide whether the body of the statement should be executed---in fact, if the design is synthesized, by the time ``a`` has any concrete value, the Python program has long finished! To solve this problem, nMigen provides its own :ref:`control structures <lang-control>` that, also, manipulate circuits.
Because the value of ``a``, and therefore ``a == 0``, is not known at the time when the ``if`` statement is executed, there is no way to decide whether the body of the statement should be executed---in fact, if the design is synthesized, by the time ``a`` has any concrete value, the Python program has long finished! To solve this problem, Amaranth provides its own :ref:`control structures <lang-control>` that, also, manipulate circuits.
.. _lang-widthext:
@ -398,9 +398,9 @@ Many of the operations described below (for example, addition, equality, bitwise
Arithmetic operators
--------------------
Most arithmetic operations on integers provided by Python can be used on nMigen values, too.
Most arithmetic operations on integers provided by Python can be used on Amaranth values, too.
Although Python integers have unlimited precision and nMigen values are represented with a :ref:`finite amount of bits <lang-values>`, arithmetics on nMigen values never overflows because the width of the arithmetic expression is always sufficient to represent all possible results.
Although Python integers have unlimited precision and Amaranth values are represented with a :ref:`finite amount of bits <lang-values>`, arithmetics on Amaranth values never overflows because the width of the arithmetic expression is always sufficient to represent all possible results.
.. doctest::
@ -408,7 +408,7 @@ Although Python integers have unlimited precision and nMigen values are represen
>>> (a + 1).shape() # needs to represent 1 to 256
unsigned(9)
Similarly, although Python integers are always signed and nMigen values can be either :ref:`signed or unsigned <lang-values>`, if any of the operands of an nMigen arithmetic expression is signed, the expression itself is also signed, matching the behavior of Python.
Similarly, although Python integers are always signed and Amaranth values can be either :ref:`signed or unsigned <lang-values>`, if any of the operands of an Amaranth arithmetic expression is signed, the expression itself is also signed, matching the behavior of Python.
.. doctest::
@ -419,7 +419,7 @@ Similarly, although Python integers are always signed and nMigen values can be e
While arithmetic computations never result in an overflow, :ref:`assigning <lang-assigns>` their results to signals may truncate the most significant bits.
The following table lists the arithmetic operations provided by nMigen:
The following table lists the arithmetic operations provided by Amaranth:
============ ========================== ======
Operation Description Notes
@ -433,7 +433,7 @@ Operation Description Notes
``abs(a)`` absolute value
============ ========================== ======
.. [#opA1] Divisor must be unsigned; this is an nMigen limitation that may be lifted in the future.
.. [#opA1] Divisor must be unsigned; this is an Amaranth limitation that may be lifted in the future.
.. _lang-cmpops:
@ -441,11 +441,11 @@ Operation Description Notes
Comparison operators
--------------------
All comparison operations on integers provided by Python can be used on nMigen values. However, due to a limitation of Python, chained comparisons (e.g. ``a < b < c``) cannot be used.
All comparison operations on integers provided by Python can be used on Amaranth values. However, due to a limitation of Python, chained comparisons (e.g. ``a < b < c``) cannot be used.
Similar to arithmetic operations, if any operand of a comparison expression is signed, a signed comparison is performed. The result of a comparison is a 1-bit unsigned value.
The following table lists the comparison operations provided by nMigen:
The following table lists the comparison operations provided by Amaranth:
============ ==========================
Operation Description
@ -464,13 +464,13 @@ Operation Description
Bitwise, shift, and rotate operators
------------------------------------
All bitwise and shift operations on integers provided by Python can be used on nMigen values as well.
All bitwise and shift operations on integers provided by Python can be used on Amaranth values as well.
Similar to arithmetic operations, if any operand of a bitwise expression is signed, the expression itself is signed as well. A shift expression is signed if the shifted value is signed. A rotate expression is always unsigned.
Rotate operations with variable rotate amounts cannot be efficiently synthesized for non-power-of-2 widths of the rotated value. Because of that, the rotate operations are only provided for constant rotate amounts, specified as Python :py:class:`int`\ s.
The following table lists the bitwise and shift operations provided by nMigen:
The following table lists the bitwise and shift operations provided by Amaranth:
===================== ========================================== ======
Operation Description Notes
@ -497,14 +497,14 @@ Operation Description Notes
.. note::
Because nMigen ensures that the width of a variable left shift expression is wide enough to represent any possible result, variable left shift by a wide amount produces exponentially wider intermediate values, stressing the synthesis tools:
Because Amaranth ensures that the width of a variable left shift expression is wide enough to represent any possible result, variable left shift by a wide amount produces exponentially wider intermediate values, stressing the synthesis tools:
.. doctest::
>>> (1 << C(0, 32)).shape()
unsigned(4294967296)
Although nMigen will detect and reject expressions wide enough to break other tools, it is a good practice to explicitly limit the width of a shift amount in a variable left shift.
Although Amaranth will detect and reject expressions wide enough to break other tools, it is a good practice to explicitly limit the width of a shift amount in a variable left shift.
.. _lang-reduceops:
@ -516,7 +516,7 @@ Bitwise reduction operations on integers are not provided by Python, but are ver
The result of a reduction is a 1-bit unsigned value.
The following table lists the reduction operations provided by nMigen:
The following table lists the reduction operations provided by Amaranth:
============ ============================================= ======
Operation Description Notes
@ -536,12 +536,12 @@ Operation Description Notes
Logical operators
-----------------
Unlike the arithmetic or bitwise operators, it is not possible to change the behavior of the Python logical operators ``not``, ``and``, and ``or``. Due to that, logical expressions in nMigen are written using bitwise operations on boolean (1-bit unsigned) values, with explicit boolean conversions added where necessary.
Unlike the arithmetic or bitwise operators, it is not possible to change the behavior of the Python logical operators ``not``, ``and``, and ``or``. Due to that, logical expressions in Amaranth are written using bitwise operations on boolean (1-bit unsigned) values, with explicit boolean conversions added where necessary.
The following table lists the Python logical expressions and their nMigen equivalents:
The following table lists the Python logical expressions and their Amaranth equivalents:
================= ====================================
Python expression nMigen expression (any operands)
Python expression Amaranth expression (any operands)
================= ====================================
``not a`` ``~(a).bool()``
``a and b`` ``(a).bool() & (b).bool()``
@ -551,7 +551,7 @@ Python expression nMigen expression (any operands)
When the operands are known to be boolean values, such as comparisons, reductions, or boolean signals, the ``.bool()`` conversion may be omitted for clarity:
================= ====================================
Python expression nMigen expression (boolean operands)
Python expression Amaranth expression (boolean operands)
================= ====================================
``not p`` ``~(p)``
``p and q`` ``(p) & (q)``
@ -562,9 +562,9 @@ Python expression nMigen expression (boolean operands)
.. warning::
Because of Python :ref:`operator precedence <python:operator-summary>`, logical operators bind less tightly than comparison operators whereas bitwise operators bind more tightly than comparison operators. As a result, all logical expressions in nMigen **must** have parenthesized operands.
Because of Python :ref:`operator precedence <python:operator-summary>`, logical operators bind less tightly than comparison operators whereas bitwise operators bind more tightly than comparison operators. As a result, all logical expressions in Amaranth **must** have parenthesized operands.
Omitting parentheses around operands in an nMigen a logical expression is likely to introduce a subtle bug:
Omitting parentheses around operands in an Amaranth a logical expression is likely to introduce a subtle bug:
.. doctest::
@ -581,7 +581,7 @@ Python expression nMigen expression (boolean operands)
.. warning::
When applied to nMigen boolean values, the ``~`` operator computes negation, and when applied to Python boolean values, the ``not`` operator also computes negation. However, the ``~`` operator applied to Python boolean values produces an unexpected result:
When applied to Amaranth boolean values, the ``~`` operator computes negation, and when applied to Python boolean values, the ``not`` operator also computes negation. However, the ``~`` operator applied to Python boolean values produces an unexpected result:
.. doctest::
@ -590,7 +590,7 @@ Python expression nMigen expression (boolean operands)
>>> ~True
-2
Because of this, Python booleans used in nMigen logical expressions **must** be negated with the ``not`` operator, not the ``~`` operator. Negating a Python boolean with the ``~`` operator in an nMigen logical expression is likely to introduce a subtle bug:
Because of this, Python booleans used in Amaranth logical expressions **must** be negated with the ``not`` operator, not the ``~`` operator. Negating a Python boolean with the ``~`` operator in an Amaranth logical expression is likely to introduce a subtle bug:
.. doctest::
@ -601,7 +601,7 @@ Python expression nMigen expression (boolean operands)
>>> ~use_stb | stb # WRONG! MSB of 2-bit wide OR expression is always 1
(| (const 2'sd-2) (sig stb))
nMigen automatically detects some cases of misuse of ``~`` and emits a detailed diagnostic message.
Amaranth automatically detects some cases of misuse of ``~`` and emits a detailed diagnostic message.
.. TODO: this isn't quite reliable, #380
@ -611,13 +611,13 @@ Python expression nMigen expression (boolean operands)
Bit sequence operators
----------------------
Apart from acting as numbers, nMigen values can also be treated as bit :ref:`sequences <python:typesseq>`, supporting slicing, concatenation, replication, and other sequence operations. Since some of the operators Python defines for sequences clash with the operators it defines for numbers, nMigen gives these operators a different name. Except for the names, nMigen values follow Python sequence semantics, with the least significant bit at index 0.
Apart from acting as numbers, Amaranth values can also be treated as bit :ref:`sequences <python:typesseq>`, supporting slicing, concatenation, replication, and other sequence operations. Since some of the operators Python defines for sequences clash with the operators it defines for numbers, Amaranth gives these operators a different name. Except for the names, Amaranth values follow Python sequence semantics, with the least significant bit at index 0.
Because every nMigen value has a single fixed width, bit slicing and replication operations require the subscripts and count to be constant, specified as Python :py:class:`int`\ s. It is often useful to slice a value with a constant width and variable offset, but this cannot be expressed with the Python slice notation. To solve this problem, nMigen provides additional *part select* operations with the necessary semantics.
Because every Amaranth value has a single fixed width, bit slicing and replication operations require the subscripts and count to be constant, specified as Python :py:class:`int`\ s. It is often useful to slice a value with a constant width and variable offset, but this cannot be expressed with the Python slice notation. To solve this problem, Amaranth provides additional *part select* operations with the necessary semantics.
The result of any bit sequence operation is an unsigned value.
The following table lists the bit sequence operations provided by nMigen:
The following table lists the bit sequence operations provided by Amaranth:
======================= ================================================ ======
Operation Description Notes
@ -631,14 +631,14 @@ Operation Description Notes
``Repl(a, n)`` replication
======================= ================================================ ======
.. [#opS1] Words "length" and "width" have the same meaning when talking about nMigen values. Conventionally, "width" is used.
.. [#opS1] Words "length" and "width" have the same meaning when talking about Amaranth values. Conventionally, "width" is used.
.. [#opS2] All variations of the Python slice notation are supported, including "extended slicing". E.g. all of ``a[0]``, ``a[1:9]``, ``a[2:]``, ``a[:-2]``, ``a[::-1]``, ``a[0:8:2]`` select bits in the same way as other Python sequence types select their elements.
.. [#opS3] In the concatenated value, ``a`` occupies the least significant bits, and ``b`` the most significant bits.
For the operators introduced by nMigen, the following table explains them in terms of Python code operating on tuples of bits rather than nMigen values:
For the operators introduced by Amaranth, the following table explains them in terms of Python code operating on tuples of bits rather than Amaranth values:
======================= ======================
nMigen operation Equivalent Python code
Amaranth operation Equivalent Python code
======================= ======================
``Cat(a, b)`` ``a + b``
``Repl(a, n)`` ``a * n``
@ -654,7 +654,7 @@ nMigen operation Equivalent Python code
.. note::
Could nMigen have used a different indexing or iteration order for values? Yes, but it would be necessary to either place the most significant bit at index 0, or deliberately break the Python sequence type interface. Both of these options would cause more issues than using different iteration orders for numeric and sequence operations.
Could Amaranth have used a different indexing or iteration order for values? Yes, but it would be necessary to either place the most significant bit at index 0, or deliberately break the Python sequence type interface. Both of these options would cause more issues than using different iteration orders for numeric and sequence operations.
.. _lang-convops:
@ -664,7 +664,7 @@ Conversion operators
The ``.as_signed()`` and ``.as_unsigned()`` conversion operators reinterpret the bits of a value with the requested signedness. This is useful when the same value is sometimes treated as signed and sometimes as unsigned, or when a signed value is constructed using slices or concatenations. For example, ``(pc + imm[:7].as_signed()).as_unsigned()`` sign-extends the 7 least significant bits of ``imm`` to the width of ``pc``, performs the addition, and produces an unsigned result.
.. TODO: more general shape conversion? https://github.com/nmigen/nmigen/issues/381
.. TODO: more general shape conversion? https://github.com/amaranth-lang/amaranth/issues/381
.. _lang-muxop:
@ -680,12 +680,12 @@ The ``Mux(sel, val1, val0)`` choice expression (similar to the :ref:`conditional
Modules
=======
A *module* is a unit of the nMigen design hierarchy: the smallest collection of logic that can be independently simulated, synthesized, or otherwise processed. Modules associate signals with :ref:`control domains <lang-domains>`, provide :ref:`control structures <lang-control>`, manage clock domains, and aggregate submodules.
A *module* is a unit of the Amaranth design hierarchy: the smallest collection of logic that can be independently simulated, synthesized, or otherwise processed. Modules associate signals with :ref:`control domains <lang-domains>`, provide :ref:`control structures <lang-control>`, manage clock domains, and aggregate submodules.
.. TODO: link to clock domains
.. TODO: link to submodules
Every nMigen design starts with a fresh module:
Every Amaranth design starts with a fresh module:
.. doctest::
@ -721,7 +721,7 @@ Assigning to signals
>>> s.eq(1)
(eq (sig s) (const 1'd1))
Similar to :ref:`how nMigen operators work <lang-abstractexpr>`, an nMigen assignment is an ordinary Python object used to describe a part of a circuit. An assignment does not have any effect on the signal it changes until it is added to a control domain in a module. Once added, it introduces logic into the circuit generated from that module.
Similar to :ref:`how Amaranth operators work <lang-abstractexpr>`, an Amaranth assignment is an ordinary Python object used to describe a part of a circuit. An assignment does not have any effect on the signal it changes until it is added to a control domain in a module. Once added, it introduces logic into the circuit generated from that module.
.. _lang-assignlhs:
@ -783,11 +783,11 @@ Every signal included in the target of an assignment becomes a part of the domai
>>> m.d.sync += d.eq(0)
Traceback (most recent call last):
...
nmigen.hdl.dsl.SyntaxError: Driver-driver conflict: trying to drive (sig d) from d.sync, but it is already driven from d.comb
amaranth.hdl.dsl.SyntaxError: Driver-driver conflict: trying to drive (sig d) from d.sync, but it is already driven from d.comb
.. note::
Clearly, nMigen code that drives a single bit of a signal from two different domains does not describe a meaningful circuit. However, driving two different bits of a signal from two different domains does not inherently cause such a conflict. Would nMigen accept the following code?
Clearly, Amaranth code that drives a single bit of a signal from two different domains does not describe a meaningful circuit. However, driving two different bits of a signal from two different domains does not inherently cause such a conflict. Would Amaranth accept the following code?
.. testcode::
@ -844,7 +844,7 @@ Multiple assignments to the same signal bits are more useful when combined with
Control structures
------------------
Although it is possible to write any decision tree as a combination of :ref:`assignments <lang-assigns>` and :ref:`choice expressions <lang-muxop>`, nMigen provides *control structures* tailored for this task: If, Switch, and FSM. The syntax of all control structures is based on :ref:`context managers <python:context-managers>` and uses ``with`` blocks, for example:
Although it is possible to write any decision tree as a combination of :ref:`assignments <lang-assigns>` and :ref:`choice expressions <lang-muxop>`, Amaranth provides *control structures* tailored for this task: If, Switch, and FSM. The syntax of all control structures is based on :ref:`context managers <python:context-managers>` and uses ``with`` blocks, for example:
.. TODO: link to relevant subsections
@ -856,14 +856,14 @@ Although it is possible to write any decision tree as a combination of :ref:`ass
with m.Else():
m.d.sync += timer.eq(timer - 1)
While some nMigen control structures are superficially similar to imperative control flow statements (such as Python's ``if``), their function---together with :ref:`expressions <lang-abstractexpr>` and :ref:`assignments <lang-assigns>`---is to describe circuits. The code above is equivalent to:
While some Amaranth control structures are superficially similar to imperative control flow statements (such as Python's ``if``), their function---together with :ref:`expressions <lang-abstractexpr>` and :ref:`assignments <lang-assigns>`---is to describe circuits. The code above is equivalent to:
.. testcode::
timer = Signal(8)
m.d.sync += timer.eq(Mux(timer == 0, 10, timer - 1))
Because all branches of a decision tree affect the generated circuit, all of the Python code inside nMigen control structures is always evaluated in the order in which it appears in the program. This can be observed through Python code with side effects, such as ``print()``:
Because all branches of a decision tree affect the generated circuit, all of the Python code inside Amaranth control structures is always evaluated in the order in which it appears in the program. This can be observed through Python code with side effects, such as ``print()``:
.. testcode::
@ -886,7 +886,7 @@ Because all branches of a decision tree affect the generated circuit, all of the
Active and inactive assignments
-------------------------------
An assignment added inside an nMigen control structure, i.e. ``with m.<...>:`` block, is *active* if the condition of the control structure is satisfied, and *inactive* otherwise. For any given set of conditions, the final value of every signal assigned in a module is the same as if the inactive assignments were removed and the active assignments were performed unconditionally, taking into account the :ref:`assignment order <lang-assignorder>`.
An assignment added inside an Amaranth control structure, i.e. ``with m.<...>:`` block, is *active* if the condition of the control structure is satisfied, and *inactive* otherwise. For any given set of conditions, the final value of every signal assigned in a module is the same as if the inactive assignments were removed and the active assignments were performed unconditionally, taking into account the :ref:`assignment order <lang-assignorder>`.
For example, there are two possible cases in the circuit generated from the following code:
@ -945,15 +945,15 @@ Consider the following code:
Whenever the signals ``en`` or ``b`` change, the signal ``a`` changes as well. If ``en`` is false, the final value of ``a`` is its initial value, ``1``. If ``en`` is true, the final value of ``a`` is equal to ``b + 1``.
A combinatorial signal that is computed directly or indirectly based on its own value is a part of a *combinatorial feedback loop*, sometimes shortened to just *feedback loop*. Combinatorial feedback loops can be stable (i.e. implement a constant driver or a transparent latch), or unstable (i.e. implement a ring oscillator). nMigen prohibits using assignments to describe any kind of a combinatorial feedback loop, including transparent latches.
A combinatorial signal that is computed directly or indirectly based on its own value is a part of a *combinatorial feedback loop*, sometimes shortened to just *feedback loop*. Combinatorial feedback loops can be stable (i.e. implement a constant driver or a transparent latch), or unstable (i.e. implement a ring oscillator). Amaranth prohibits using assignments to describe any kind of a combinatorial feedback loop, including transparent latches.
.. warning::
The current version of nMigen does not detect combinatorial feedback loops, but processes the design under the assumption that there aren't any. If the design does in fact contain a combinatorial feedback loop, it will likely be **silently miscompiled**, though some cases will be detected during synthesis or place & route.
The current version of Amaranth does not detect combinatorial feedback loops, but processes the design under the assumption that there aren't any. If the design does in fact contain a combinatorial feedback loop, it will likely be **silently miscompiled**, though some cases will be detected during synthesis or place & route.
This hazard will be eliminated in the future.
.. TODO: fix this, either as a part of https://github.com/nmigen/nmigen/issues/6 or on its own
.. TODO: fix this, either as a part of https://github.com/amaranth-lang/amaranth/issues/6 or on its own
.. note::

View file

@ -1,7 +1,7 @@
Getting started
###############
This section demonstrates the basic nMigen workflow to provide a cursory overview of the language and the toolchain. See the :doc:`tutorial <tutorial>` for a step-by-step introduction to the language, and the :doc:`language guide <lang>` for a detailed explanation of every language construct.
This section demonstrates the basic Amaranth workflow to provide a cursory overview of the language and the toolchain. See the :doc:`tutorial <tutorial>` for a step-by-step introduction to the language, and the :doc:`language guide <lang>` for a detailed explanation of every language construct.
.. TODO: add link to build system doc
.. TODO: add link to more complex examples?
@ -20,14 +20,14 @@ As a first example, consider a counter with a fixed limit, enable, and overflow.
Implementing a counter
----------------------
A 16-bit up counter with enable input, overflow output, and a limit fixed at design time can be implemented in nMigen as follows:
A 16-bit up counter with enable input, overflow output, and a limit fixed at design time can be implemented in Amaranth as follows:
.. literalinclude:: _code/up_counter.py
:linenos:
:lineno-match:
:end-before: # --- TEST ---
The reusable building block of nMigen designs is an ``Elaboratable``: a Python class that includes HDL signals (``en`` and ``ovf``, in this case) as a part of its interface, and provides the ``elaborate`` method that defines its behavior.
The reusable building block of Amaranth designs is an ``Elaboratable``: a Python class that includes HDL signals (``en`` and ``ovf``, in this case) as a part of its interface, and provides the ``elaborate`` method that defines its behavior.
.. TODO: link to Elaboratable reference
@ -60,7 +60,7 @@ When run, the test bench finishes successfully, since all of the assertions hold
Converting a counter
--------------------
Although some nMigen workflows do not include Verilog at all, it is still the de facto standard for HDL interoperability. Any nMigen design can be converted to synthesizable Verilog using the corresponding backend:
Although some Amaranth workflows do not include Verilog at all, it is still the de facto standard for HDL interoperability. Any Amaranth design can be converted to synthesizable Verilog using the corresponding backend:
.. literalinclude:: _code/up_counter.py
:linenos:
@ -75,7 +75,7 @@ The signals that will be connected to the ports of the top-level Verilog module
:language: verilog
:linenos:
To aid debugging, the generated Verilog code has the same general structure as the nMigen source code (although more verbose), and contains extensive source location information.
To aid debugging, the generated Verilog code has the same general structure as the Amaranth source code (although more verbose), and contains extensive source location information.
.. note::
@ -85,14 +85,14 @@ To aid debugging, the generated Verilog code has the same general structure as t
A blinking LED
==============
Although nMigen works well as a standalone HDL, it also includes a build system that integrates with FPGA toolchains, and many board definition files for common developer boards that include pinouts and programming adapter invocations. The following code will blink a LED with a frequency of 1 Hz on any board that has a LED and an oscillator:
Although Amaranth works well as a standalone HDL, it also includes a build system that integrates with FPGA toolchains, and many board definition files for common developer boards that include pinouts and programming adapter invocations. The following code will blink a LED with a frequency of 1 Hz on any board that has a LED and an oscillator:
.. literalinclude:: _code/led_blinker.py
:linenos:
:lineno-match:
:end-before: # --- BUILD ---
The ``LEDBlinker`` module will use the first LED available on the board, and derive the clock divisor from the oscillator frequency specified in the clock constraint. It can be used, for example, with the `Lattice iCEStick evaluation board <https://www.latticesemi.com/icestick>`_, one of the many boards already supported by nMigen:
The ``LEDBlinker`` module will use the first LED available on the board, and derive the clock divisor from the oscillator frequency specified in the clock constraint. It can be used, for example, with the `Lattice iCEStick evaluation board <https://www.latticesemi.com/icestick>`_, one of the many boards already supported by Amaranth:
.. TODO: link to list of supported boards
@ -105,7 +105,7 @@ The ``LEDBlinker`` module will use the first LED available on the board, and der
:lineno-match:
:start-after: # --- BUILD ---
With only a single line of code, the design is synthesized, placed, routed, and programmed to the on-board Flash memory. Although not all applications will use the nMigen build system, the designs that choose it can benefit from the "turnkey" built-in workflows; if necessary, the built-in workflows can be customized to include user-specified options, commands, and files.
With only a single line of code, the design is synthesized, placed, routed, and programmed to the on-board Flash memory. Although not all applications will use the Amaranth build system, the designs that choose it can benefit from the "turnkey" built-in workflows; if necessary, the built-in workflows can be customized to include user-specified options, commands, and files.
.. TODO: link to build system reference
@ -115,6 +115,6 @@ With only a single line of code, the design is synthesized, placed, routed, and
.. code-block:: shell
$ python3 -m nmigen_boards.icestick
$ python3 -m amaranth_boards.icestick
This command will build and program a test bitstream similar to the example above.

View file

@ -3,7 +3,7 @@ Tutorial
.. todo::
The official tutorial is still being written. Until it's ready, consider following one of the tutorials written by the nMigen community:
The official tutorial is still being written. Until it's ready, consider following one of the tutorials written by the Amaranth community:
* `Learning FPGA Design with nMigen <https://vivonomicon.com/2020/04/14/learning-fpga-design-with-nmigen/>`_ by Vivonomicon;
* `nMigen Step by Step Tutorial <http://blog.lambdaconcept.com/doku.php?id=nmigen:tutorial>`_ by LambdaConcept;