back.pysim: close .vcd/.gtkw files on context manager exit.
[nmigen.git] / README.md
1 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:
2
3 * 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...);
4 * Hierarchical designs are useful for floorplanning and optimization, yet Migen does not support them at all;
5 * Migen's syntax is not easily composable, and something like an FSM requires extending Migen's syntax in non-orthogonal ways;
6 * 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.
7 * Migen requires awkward specials for some FPGA features such as asynchronous resets.
8
9 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.
10
11 This proposal makes several major changes to Migen that hopefully solve all of these drawbacks:
12
13 * nMigen changes FHDL's internal representation to closely match that of RTLIL;
14 * nMigen outputs RTLIL and relies on Yosys for conversion to Verilog, EDIF, etc;
15 * nMigen uses an exact mapping between FHDL signals and RTLIL names to off-load logic simulation to Icarus Verilog, Verilator, etc;
16 * nMigen uses an uniform, composable Python eHDL;
17 * nMigen outputs hierarchical RTLIL, automatically threading signals through the hierarchy;
18 * nMigen supports asynchronous reset directly;
19 * nMigen makes driving a signal from multiple clock domains a precise, hard error.
20
21 This proposal keeps in mind but does not make the following major changes:
22
23 * nMigen could be easily modified to flatten the hierarchy if a signal is driven simultaneously from multiple modules;
24 * nMigen could be easily modified to support `x` values (invalid / don't care) by relying on RTLIL's ability to directly represent them;
25 * nMigen could be easily modified to support negative edge triggered flip-flops by relying on RTLIL's ability to directly represent them;
26 * 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.
27
28 This proposal also makes the following simplifications:
29 * 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)`).
30
31 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.
32
33 FHDL features currently missing from this implementation:
34 * self.clock_domains +=
35 * Array
36 * Memory
37 * Tristate, TSTriple
38 * Instance
39 * FSM
40 * transformers: SplitMemory, FullMemoryWE
41 * transformers: ClockDomainsRenamer
42
43 `migen.genlib`, `migen.sim` and `migen.build` are missing completely.
44
45 One might reasonably expect that a roundtrip through RTLIL would result in unreadable Verilog.
46 However, this is not the case, e.g. consider the examples:
47
48 <details>
49 <summary>alu.v</summary>
50
51 ```verilog
52 module \$1 (co, sel, a, b, o);
53 wire [17:0] _04_;
54 input [15:0] a;
55 input [15:0] b;
56 output co;
57 reg \co$next ;
58 output [15:0] o;
59 reg [15:0] \o$next ;
60 input [1:0] sel;
61 assign _04_ = $signed(+ a) + $signed(- b);
62 always @* begin
63 \o$next = 16'h0000;
64 \co$next = 1'h0;
65 casez ({ 1'h1, sel == 2'h2, sel == 1'h1, sel == 0'b0 })
66 4'bzzz1:
67 \o$next = a | b;
68 4'bzz1z:
69 \o$next = a & b;
70 4'bz1zz:
71 \o$next = a ^ b;
72 4'b1zzz:
73 { \co$next , \o$next } = _04_[16:0];
74 endcase
75 end
76 assign o = \o$next ;
77 assign co = \co$next ;
78 endmodule
79 ```
80 </details>
81
82 <details>
83 <summary>alu_hier.v</summary>
84
85 ```verilog
86 module add(b, o, a);
87 wire [16:0] _0_;
88 input [15:0] a;
89 input [15:0] b;
90 output [15:0] o;
91 reg [15:0] \o$next ;
92 assign _0_ = a + b;
93 always @* begin
94 \o$next = 16'h0000;
95 \o$next = _0_[15:0];
96 end
97 assign o = \o$next ;
98 endmodule
99
100 module sub(b, o, a);
101 wire [16:0] _0_;
102 input [15:0] a;
103 input [15:0] b;
104 output [15:0] o;
105 reg [15:0] \o$next ;
106 assign _0_ = a - b;
107 always @* begin
108 \o$next = 16'h0000;
109 \o$next = _0_[15:0];
110 end
111 assign o = \o$next ;
112 endmodule
113
114 module top(a, b, o, add_o, sub_o, op);
115 input [15:0] a;
116 wire [15:0] add_a;
117 reg [15:0] \add_a$next ;
118 wire [15:0] add_b;
119 reg [15:0] \add_b$next ;
120 input [15:0] add_o;
121 input [15:0] b;
122 output [15:0] o;
123 reg [15:0] \o$next ;
124 input op;
125 wire [15:0] sub_a;
126 reg [15:0] \sub_a$next ;
127 wire [15:0] sub_b;
128 reg [15:0] \sub_b$next ;
129 input [15:0] sub_o;
130 add add (
131 .a(add_a),
132 .b(add_b),
133 .o(add_o)
134 );
135 sub sub (
136 .a(sub_a),
137 .b(sub_b),
138 .o(sub_o)
139 );
140 always @* begin
141 \o$next = 16'h0000;
142 \add_a$next = 16'h0000;
143 \add_b$next = 16'h0000;
144 \sub_a$next = 16'h0000;
145 \sub_b$next = 16'h0000;
146 \add_a$next = a;
147 \sub_a$next = a;
148 \add_b$next = b;
149 \sub_b$next = b;
150 casez ({ 1'h1, op })
151 2'bz1:
152 \o$next = sub_o;
153 2'b1z:
154 \o$next = add_o;
155 endcase
156 end
157 assign o = \o$next ;
158 assign add_a = \add_a$next ;
159 assign add_b = \add_b$next ;
160 assign sub_a = \sub_a$next ;
161 assign sub_b = \sub_b$next ;
162 endmodule
163 ```
164 </details>
165 <details>
166 <summary>clkdiv.v</summary>
167
168 ```verilog
169 module \$1 (sys_clk, o);
170 wire [16:0] _0_;
171 output o;
172 reg \o$next ;
173 input sys_clk;
174 wire sys_rst;
175 (* init = 16'hffff *)
176 reg [15:0] v = 16'hffff;
177 reg [15:0] \v$next ;
178 assign _0_ = v + 1'h1;
179 always @(posedge sys_clk)
180 v <= \v$next ;
181 always @* begin
182 \o$next = 1'h0;
183 \v$next = _0_[15:0];
184 \o$next = v[15];
185 casez (sys_rst)
186 1'h1:
187 \v$next = 16'hffff;
188 endcase
189 end
190 assign o = \o$next ;
191 endmodule
192 ```
193 </details>
194
195 <details>
196 <summary>arst.v</summary>
197
198 ```verilog
199 module \$1 (o, sys_clk, sys_rst);
200 wire [16:0] _0_;
201 output o;
202 reg \o$next ;
203 input sys_clk;
204 input sys_rst;
205 (* init = 16'h0000 *)
206 reg [15:0] v = 16'h0000;
207 reg [15:0] \v$next ;
208 assign _0_ = v + 1'h1;
209 always @(posedge sys_clk or posedge sys_rst)
210 if (sys_rst)
211 v <= 16'h0000;
212 else
213 v <= \v$next ;
214 always @* begin
215 \o$next = 1'h0;
216 \v$next = _0_[15:0];
217 \o$next = v[15];
218 end
219 assign o = \o$next ;
220 endmodule
221 ```
222 </details>
223
224 <details>
225 <summary>pmux.v</summary>
226
227 ```verilog
228 module \$1 (c, o, s, a, b);
229 input [15:0] a;
230 input [15:0] b;
231 input [15:0] c;
232 output [15:0] o;
233 reg [15:0] \o$next ;
234 input [2:0] s;
235 always @* begin
236 \o$next = 16'h0000;
237 casez (s)
238 3'bzz1:
239 \o$next = a;
240 3'bz1z:
241 \o$next = b;
242 3'b1zz:
243 \o$next = c;
244 3'hz:
245 \o$next = 16'h0000;
246 endcase
247 end
248 assign o = \o$next ;
249 endmodule
250 ```
251 </details>