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"
25 PRIVATE_NAMESPACE_BEGIN
27 struct Async2syncPass
: public Pass
{
28 Async2syncPass() : Pass("async2sync", "convert async FF inputs to sync circuits") { }
31 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
33 log(" async2sync [options] [selection]\n");
35 log("This command replaces async FF inputs with sync circuits emulating the same\n");
36 log("behavior for when the async signals are actually synchronized to the clock.\n");
38 log("This pass assumes negative hold time for the async FF inputs. For example when\n");
39 log("a reset deasserts with the clock edge, then the FF output will still drive the\n");
40 log("reset value in the next cycle regardless of the data-in value at the time of\n");
41 log("the clock edge.\n");
43 log("Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.\n");
46 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) override
48 // bool flag_noinit = false;
50 log_header(design
, "Executing ASYNC2SYNC pass.\n");
53 for (argidx
= 1; argidx
< args
.size(); argidx
++)
55 // if (args[argidx] == "-noinit") {
56 // flag_noinit = true;
61 extra_args(args
, argidx
, design
);
63 for (auto module
: design
->selected_modules())
65 SigMap
sigmap(module
);
66 FfInitVals
initvals(&sigmap
, module
);
68 for (auto cell
: vector
<Cell
*>(module
->selected_cells()))
70 if (cell
->type
.in(ID($adff
)))
72 // bool clk_pol = cell->parameters[ID::CLK_POLARITY].as_bool();
73 bool arst_pol
= cell
->parameters
[ID::ARST_POLARITY
].as_bool();
74 Const arst_val
= cell
->parameters
[ID::ARST_VALUE
];
76 // SigSpec sig_clk = cell->getPort(ID::CLK);
77 SigSpec sig_arst
= cell
->getPort(ID::ARST
);
78 SigSpec sig_d
= cell
->getPort(ID::D
);
79 SigSpec sig_q
= cell
->getPort(ID::Q
);
81 log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n",
82 log_id(module
), log_id(cell
), log_id(cell
->type
),
83 log_signal(sig_arst
), log_signal(sig_d
), log_signal(sig_q
));
85 Const init_val
= initvals(sig_q
);
86 initvals
.remove_init(sig_q
);
88 Wire
*new_d
= module
->addWire(NEW_ID
, GetSize(sig_d
));
89 Wire
*new_q
= module
->addWire(NEW_ID
, GetSize(sig_q
));
90 initvals
.set_init(new_q
, init_val
);
93 module
->addMux(NEW_ID
, sig_d
, arst_val
, sig_arst
, new_d
);
94 module
->addMux(NEW_ID
, new_q
, arst_val
, sig_arst
, sig_q
);
96 module
->addMux(NEW_ID
, arst_val
, sig_d
, sig_arst
, new_d
);
97 module
->addMux(NEW_ID
, arst_val
, new_q
, sig_arst
, sig_q
);
100 cell
->setPort(ID::D
, new_d
);
101 cell
->setPort(ID::Q
, new_q
);
102 cell
->unsetPort(ID::ARST
);
103 cell
->unsetParam(ID::ARST_POLARITY
);
104 cell
->unsetParam(ID::ARST_VALUE
);
105 cell
->type
= ID($dff
);
109 if (cell
->type
.in(ID($dffsr
)))
111 // bool clk_pol = cell->parameters[ID::CLK_POLARITY].as_bool();
112 bool set_pol
= cell
->parameters
[ID::SET_POLARITY
].as_bool();
113 bool clr_pol
= cell
->parameters
[ID::CLR_POLARITY
].as_bool();
115 // SigSpec sig_clk = cell->getPort(ID::CLK);
116 SigSpec sig_set
= cell
->getPort(ID::SET
);
117 SigSpec sig_clr
= cell
->getPort(ID::CLR
);
118 SigSpec sig_d
= cell
->getPort(ID::D
);
119 SigSpec sig_q
= cell
->getPort(ID::Q
);
121 log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n",
122 log_id(module
), log_id(cell
), log_id(cell
->type
),
123 log_signal(sig_set
), log_signal(sig_clr
), log_signal(sig_d
), log_signal(sig_q
));
125 Const init_val
= initvals(sig_q
);
126 initvals
.remove_init(sig_q
);
128 Wire
*new_d
= module
->addWire(NEW_ID
, GetSize(sig_d
));
129 Wire
*new_q
= module
->addWire(NEW_ID
, GetSize(sig_q
));
130 initvals
.set_init(new_q
, init_val
);
133 sig_set
= module
->Not(NEW_ID
, sig_set
);
136 sig_clr
= module
->Not(NEW_ID
, sig_clr
);
138 SigSpec tmp
= module
->Or(NEW_ID
, sig_d
, sig_set
);
139 module
->addAnd(NEW_ID
, tmp
, sig_clr
, new_d
);
141 tmp
= module
->Or(NEW_ID
, new_q
, sig_set
);
142 module
->addAnd(NEW_ID
, tmp
, sig_clr
, sig_q
);
144 cell
->setPort(ID::D
, new_d
);
145 cell
->setPort(ID::Q
, new_q
);
146 cell
->unsetPort(ID::SET
);
147 cell
->unsetPort(ID::CLR
);
148 cell
->unsetParam(ID::SET_POLARITY
);
149 cell
->unsetParam(ID::CLR_POLARITY
);
150 cell
->type
= ID($dff
);
154 if (cell
->type
.in(ID($dlatch
)))
156 bool en_pol
= cell
->parameters
[ID::EN_POLARITY
].as_bool();
158 SigSpec sig_en
= cell
->getPort(ID::EN
);
159 SigSpec sig_d
= cell
->getPort(ID::D
);
160 SigSpec sig_q
= cell
->getPort(ID::Q
);
162 log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
163 log_id(module
), log_id(cell
), log_id(cell
->type
),
164 log_signal(sig_en
), log_signal(sig_d
), log_signal(sig_q
));
166 Const init_val
= initvals(sig_q
);
167 initvals
.remove_init(sig_q
);
169 Wire
*new_q
= module
->addWire(NEW_ID
, GetSize(sig_q
));
170 initvals
.set_init(new_q
, init_val
);
173 module
->addMux(NEW_ID
, new_q
, sig_d
, sig_en
, sig_q
);
175 module
->addMux(NEW_ID
, sig_d
, new_q
, sig_en
, sig_q
);
178 cell
->setPort(ID::D
, sig_q
);
179 cell
->setPort(ID::Q
, new_q
);
180 cell
->unsetPort(ID::EN
);
181 cell
->unsetParam(ID::EN_POLARITY
);
182 cell
->type
= ID($ff
);
190 PRIVATE_NAMESPACE_END