2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/ffinit.h"
23 #include "kernel/ff.h"
26 PRIVATE_NAMESPACE_BEGIN
28 struct Async2syncPass
: public Pass
{
29 Async2syncPass() : Pass("async2sync", "convert async FF inputs to sync circuits") { }
32 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
34 log(" async2sync [options] [selection]\n");
36 log("This command replaces async FF inputs with sync circuits emulating the same\n");
37 log("behavior for when the async signals are actually synchronized to the clock.\n");
39 log("This pass assumes negative hold time for the async FF inputs. For example when\n");
40 log("a reset deasserts with the clock edge, then the FF output will still drive the\n");
41 log("reset value in the next cycle regardless of the data-in value at the time of\n");
42 log("the clock edge.\n");
44 log("Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.\n");
47 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) override
49 // bool flag_noinit = false;
51 log_header(design
, "Executing ASYNC2SYNC pass.\n");
54 for (argidx
= 1; argidx
< args
.size(); argidx
++)
56 // if (args[argidx] == "-noinit") {
57 // flag_noinit = true;
62 extra_args(args
, argidx
, design
);
64 for (auto module
: design
->selected_modules())
66 SigMap
sigmap(module
);
67 FfInitVals
initvals(&sigmap
, module
);
69 for (auto cell
: vector
<Cell
*>(module
->selected_cells()))
71 if (!RTLIL::builtin_ff_cell_types().count(cell
->type
))
74 FfData
ff(&initvals
, cell
);
76 // Skip for $_FF_ and $ff cells.
77 if (ff
.has_d
&& !ff
.has_clk
&& !ff
.has_en
)
82 if (!ff
.has_sr
&& !ff
.has_arst
)
86 ff
.unmap_ce_srst(module
);
88 log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n",
89 log_id(module
), log_id(cell
), log_id(cell
->type
),
90 log_signal(ff
.sig_set
), log_signal(ff
.sig_clr
), log_signal(ff
.sig_d
), log_signal(ff
.sig_q
));
92 initvals
.remove_init(ff
.sig_q
);
94 Wire
*new_d
= module
->addWire(NEW_ID
, ff
.width
);
95 Wire
*new_q
= module
->addWire(NEW_ID
, ff
.width
);
97 SigSpec sig_set
= ff
.sig_set
;
98 SigSpec sig_clr
= ff
.sig_clr
;
102 sig_set
= module
->Not(NEW_ID
, sig_set
);
104 sig_set
= module
->NotGate(NEW_ID
, sig_set
);
109 sig_clr
= module
->Not(NEW_ID
, sig_clr
);
111 sig_clr
= module
->NotGate(NEW_ID
, sig_clr
);
115 SigSpec tmp
= module
->Or(NEW_ID
, ff
.sig_d
, sig_set
);
116 module
->addAnd(NEW_ID
, tmp
, sig_clr
, new_d
);
118 tmp
= module
->Or(NEW_ID
, new_q
, sig_set
);
119 module
->addAnd(NEW_ID
, tmp
, sig_clr
, ff
.sig_q
);
121 SigSpec tmp
= module
->OrGate(NEW_ID
, ff
.sig_d
, sig_set
);
122 module
->addAndGate(NEW_ID
, tmp
, sig_clr
, new_d
);
124 tmp
= module
->OrGate(NEW_ID
, new_q
, sig_set
);
125 module
->addAndGate(NEW_ID
, tmp
, sig_clr
, ff
.sig_q
);
131 } else if (ff
.has_arst
) {
132 ff
.unmap_srst(module
);
134 log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n",
135 log_id(module
), log_id(cell
), log_id(cell
->type
),
136 log_signal(ff
.sig_arst
), log_signal(ff
.sig_d
), log_signal(ff
.sig_q
));
138 initvals
.remove_init(ff
.sig_q
);
140 Wire
*new_q
= module
->addWire(NEW_ID
, ff
.width
);
144 module
->addMux(NEW_ID
, new_q
, ff
.val_arst
, ff
.sig_arst
, ff
.sig_q
);
146 module
->addMuxGate(NEW_ID
, new_q
, ff
.val_arst
[0], ff
.sig_arst
, ff
.sig_q
);
149 module
->addMux(NEW_ID
, ff
.val_arst
, new_q
, ff
.sig_arst
, ff
.sig_q
);
151 module
->addMuxGate(NEW_ID
, ff
.val_arst
[0], new_q
, ff
.sig_arst
, ff
.sig_q
);
157 ff
.val_srst
= ff
.val_arst
;
158 ff
.sig_srst
= ff
.sig_arst
;
159 ff
.pol_srst
= ff
.pol_arst
;
165 log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
166 log_id(module
), log_id(cell
), log_id(cell
->type
),
167 log_signal(ff
.sig_en
), log_signal(ff
.sig_d
), log_signal(ff
.sig_q
));
169 initvals
.remove_init(ff
.sig_q
);
171 Wire
*new_q
= module
->addWire(NEW_ID
, ff
.width
);
175 new_d
= module
->addWire(NEW_ID
, ff
.width
);
178 module
->addMux(NEW_ID
, new_q
, ff
.sig_d
, ff
.sig_en
, new_d
);
180 module
->addMuxGate(NEW_ID
, new_q
, ff
.sig_d
, ff
.sig_en
, new_d
);
183 module
->addMux(NEW_ID
, ff
.sig_d
, new_q
, ff
.sig_en
, new_d
);
185 module
->addMuxGate(NEW_ID
, ff
.sig_d
, new_q
, ff
.sig_en
, new_d
);
192 SigSpec sig_set
= ff
.sig_set
;
193 SigSpec sig_clr
= ff
.sig_clr
;
197 sig_set
= module
->Not(NEW_ID
, sig_set
);
199 sig_set
= module
->NotGate(NEW_ID
, sig_set
);
204 sig_clr
= module
->Not(NEW_ID
, sig_clr
);
206 sig_clr
= module
->NotGate(NEW_ID
, sig_clr
);
210 SigSpec tmp
= module
->Or(NEW_ID
, new_d
, sig_set
);
211 module
->addAnd(NEW_ID
, tmp
, sig_clr
, ff
.sig_q
);
213 SigSpec tmp
= module
->OrGate(NEW_ID
, new_d
, sig_set
);
214 module
->addAndGate(NEW_ID
, tmp
, sig_clr
, ff
.sig_q
);
216 } else if (ff
.has_arst
) {
219 module
->addMux(NEW_ID
, new_d
, ff
.val_arst
, ff
.sig_arst
, ff
.sig_q
);
221 module
->addMuxGate(NEW_ID
, new_d
, ff
.val_arst
[0], ff
.sig_arst
, ff
.sig_q
);
224 module
->addMux(NEW_ID
, ff
.val_arst
, new_d
, ff
.sig_arst
, ff
.sig_q
);
226 module
->addMuxGate(NEW_ID
, ff
.val_arst
[0], new_d
, ff
.sig_arst
, ff
.sig_q
);
229 module
->connect(ff
.sig_q
, new_d
);
240 IdString name
= cell
->name
;
241 module
->remove(cell
);
242 ff
.emit(module
, name
);
248 PRIVATE_NAMESPACE_END