From ec2b5548fe9b8d291365a84a0c3fc87654643359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Fri, 1 Oct 2021 04:33:00 +0200 Subject: [PATCH] Add $aldff and $aldffe: flip-flops with async load. --- CHANGELOG | 2 + kernel/celltypes.h | 11 ++ kernel/constids.inc | 3 + kernel/rtlil.cc | 110 +++++++++++++ kernel/rtlil.h | 6 + manual/CHAPTER_CellLib.tex | 15 +- techlibs/common/gen_fine_ffs.py | 49 ++++++ techlibs/common/simcells.v | 284 ++++++++++++++++++++++++++++++++ techlibs/common/simlib.v | 49 ++++++ 9 files changed, 527 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fe85723af..a6285ddb2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,8 @@ List of major changes and improvements between releases Yosys 0.10 .. Yosys 0.10-dev -------------------------- + * Various + - Added $aldff and $aldffe (flip-flops with async load) cells Yosys 0.9 .. Yosys 0.10 -------------------------- diff --git a/kernel/celltypes.h b/kernel/celltypes.h index a977501e3..879ac0edc 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -142,6 +142,8 @@ struct CellTypes setup_type(ID($dffsre), {ID::CLK, ID::SET, ID::CLR, ID::D, ID::EN}, {ID::Q}); setup_type(ID($adff), {ID::CLK, ID::ARST, ID::D}, {ID::Q}); setup_type(ID($adffe), {ID::CLK, ID::ARST, ID::D, ID::EN}, {ID::Q}); + setup_type(ID($aldff), {ID::CLK, ID::ALOAD, ID::AD, ID::D}, {ID::Q}); + setup_type(ID($aldffe), {ID::CLK, ID::ALOAD, ID::AD, ID::D, ID::EN}, {ID::Q}); setup_type(ID($sdff), {ID::CLK, ID::SRST, ID::D}, {ID::Q}); setup_type(ID($sdffe), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q}); setup_type(ID($sdffce), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q}); @@ -224,6 +226,15 @@ struct CellTypes for (auto c4 : list_np) setup_type(stringf("$_DFFE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}); + for (auto c1 : list_np) + for (auto c2 : list_np) + setup_type(stringf("$_ALDFF_%c%c_", c1, c2), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}); + + for (auto c1 : list_np) + for (auto c2 : list_np) + for (auto c3 : list_np) + setup_type(stringf("$_ALDFFE_%c%c%c_", c1, c2, c3), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}); + for (auto c1 : list_np) for (auto c2 : list_np) for (auto c3 : list_np) diff --git a/kernel/constids.inc b/kernel/constids.inc index 68d10def6..8d8e97eb7 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -11,9 +11,12 @@ X(abc9_mergeability) X(abc9_scc_id) X(abcgroup) X(ABITS) +X(AD) X(ADDR) X(allconst) X(allseq) +X(ALOAD) +X(ALOAD_POLARITY) X(always_comb) X(always_ff) X(always_latch) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a05023c52..3778972bc 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -58,6 +58,8 @@ const pool &RTLIL::builtin_ff_cell_types() { ID($dffsre), ID($adff), ID($adffe), + ID($aldff), + ID($aldffe), ID($sdff), ID($sdffe), ID($sdffce), @@ -118,6 +120,18 @@ const pool &RTLIL::builtin_ff_cell_types() { ID($_DFFE_PP0P_), ID($_DFFE_PP1N_), ID($_DFFE_PP1P_), + ID($_ALDFF_NN_), + ID($_ALDFF_NP_), + ID($_ALDFF_PN_), + ID($_ALDFF_PP_), + ID($_ALDFFE_NNN_), + ID($_ALDFFE_NNP_), + ID($_ALDFFE_NPN_), + ID($_ALDFFE_NPP_), + ID($_ALDFFE_PNN_), + ID($_ALDFFE_PNP_), + ID($_ALDFFE_PPN_), + ID($_ALDFFE_PPP_), ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), @@ -1337,6 +1351,32 @@ namespace { return; } + if (cell->type == ID($aldff)) { + param_bool(ID::CLK_POLARITY); + param_bool(ID::ALOAD_POLARITY); + port(ID::CLK, 1); + port(ID::ALOAD, 1); + port(ID::D, param(ID::WIDTH)); + port(ID::AD, param(ID::WIDTH)); + port(ID::Q, param(ID::WIDTH)); + check_expected(); + return; + } + + if (cell->type == ID($aldffe)) { + param_bool(ID::CLK_POLARITY); + param_bool(ID::EN_POLARITY); + param_bool(ID::ALOAD_POLARITY); + port(ID::CLK, 1); + port(ID::EN, 1); + port(ID::ALOAD, 1); + port(ID::D, param(ID::WIDTH)); + port(ID::AD, param(ID::WIDTH)); + port(ID::Q, param(ID::WIDTH)); + check_expected(); + return; + } + if (cell->type == ID($dlatch)) { param_bool(ID::EN_POLARITY); port(ID::EN, 1); @@ -1648,6 +1688,15 @@ namespace { ID($_DFFE_PP0N_), ID($_DFFE_PP0P_), ID($_DFFE_PP1N_), ID($_DFFE_PP1P_))) { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); port(ID::E,1); check_expected(); return; } + if (cell->type.in( + ID($_ALDFF_NN_), ID($_ALDFF_NP_), ID($_ALDFF_PN_), ID($_ALDFF_PP_))) + { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::L,1); port(ID::AD,1); check_expected(); return; } + + if (cell->type.in( + ID($_ALDFFE_NNN_), ID($_ALDFFE_NNP_), ID($_ALDFFE_NPN_), ID($_ALDFFE_NPP_), + ID($_ALDFFE_PNN_), ID($_ALDFFE_PNP_), ID($_ALDFFE_PPN_), ID($_ALDFFE_PPP_))) + { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::L,1); port(ID::AD,1); port(ID::E,1); check_expected(); return; } + if (cell->type.in( ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_))) @@ -2675,6 +2724,40 @@ RTLIL::Cell* RTLIL::Module::addAdffe(RTLIL::IdString name, const RTLIL::SigSpec return cell; } +RTLIL::Cell* RTLIL::Module::addAldff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src) +{ + RTLIL::Cell *cell = addCell(name, ID($aldff)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::ALOAD_POLARITY] = aload_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::ALOAD, sig_aload); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::AD, sig_ad); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; +} + +RTLIL::Cell* RTLIL::Module::addAldffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src) +{ + RTLIL::Cell *cell = addCell(name, ID($aldffe)); + cell->parameters[ID::CLK_POLARITY] = clk_polarity; + cell->parameters[ID::EN_POLARITY] = en_polarity; + cell->parameters[ID::ALOAD_POLARITY] = aload_polarity; + cell->parameters[ID::WIDTH] = sig_q.size(); + cell->setPort(ID::CLK, sig_clk); + cell->setPort(ID::EN, sig_en); + cell->setPort(ID::ALOAD, sig_aload); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::AD, sig_ad); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; +} + RTLIL::Cell* RTLIL::Module::addSdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity, bool srst_polarity, const std::string &src) { @@ -2865,6 +2948,33 @@ RTLIL::Cell* RTLIL::Module::addAdffeGate(RTLIL::IdString name, const RTLIL::SigS return cell; } +RTLIL::Cell* RTLIL::Module::addAldffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src) +{ + RTLIL::Cell *cell = addCell(name, stringf("$_ALDFF_%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::L, sig_aload); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::AD, sig_ad); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; +} + +RTLIL::Cell* RTLIL::Module::addAldffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src) +{ + RTLIL::Cell *cell = addCell(name, stringf("$_ALDFFE_%c%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); + cell->setPort(ID::C, sig_clk); + cell->setPort(ID::L, sig_aload); + cell->setPort(ID::E, sig_en); + cell->setPort(ID::D, sig_d); + cell->setPort(ID::AD, sig_ad); + cell->setPort(ID::Q, sig_q); + cell->set_src_attribute(src); + return cell; +} + RTLIL::Cell* RTLIL::Module::addSdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool srst_value, bool clk_polarity, bool srst_polarity, const std::string &src) { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 06198b26a..e072d5bd1 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1312,6 +1312,8 @@ public: RTLIL::Cell* addDffsre (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); RTLIL::Cell* addAdff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = ""); RTLIL::Cell* addAdffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, const std::string &src = ""); + RTLIL::Cell* addAldff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool aload_polarity = true, const std::string &src = ""); + RTLIL::Cell* addAldffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool en_polarity = true, bool aload_polarity = true, const std::string &src = ""); RTLIL::Cell* addSdff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool srst_polarity = true, const std::string &src = ""); RTLIL::Cell* addSdffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = ""); RTLIL::Cell* addSdffce (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = ""); @@ -1349,6 +1351,10 @@ public: bool arst_value = false, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = ""); RTLIL::Cell* addAdffeGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool arst_value = false, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, const std::string &src = ""); + RTLIL::Cell* addAldffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool aload_polarity = true, const std::string &src = ""); + RTLIL::Cell* addAldffeGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, + const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool en_polarity = true, bool aload_polarity = true, const std::string &src = ""); RTLIL::Cell* addSdffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool srst_value = false, bool clk_polarity = true, bool srst_polarity = true, const std::string &src = ""); RTLIL::Cell* addSdffeGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, diff --git a/manual/CHAPTER_CellLib.tex b/manual/CHAPTER_CellLib.tex index 74ba224df..3c9fb31cc 100644 --- a/manual/CHAPTER_CellLib.tex +++ b/manual/CHAPTER_CellLib.tex @@ -287,13 +287,24 @@ The state of \B{Q} will be set to this value when the reset is active. Note that the {\tt \$adff} and {\tt \$sdff} cells can only be used when the reset value is constant. +D-type flip-flops with asynchronous load are represented by {\tt \$aldff} cells. As the {\tt \$dff} +cells they have \B{CLK}, \B{D} and \B{Q} ports. In addition they also have a single-bit \B{ALOAD} +input port for the async load enable pin, a \B{AD} input port with the same width as data for +the async load data, and the following additional parameter: + +\begin{itemize} +\item \B{ALOAD\_POLARITY} \\ +The asynchronous load is active-high if this parameter has the value {\tt 1'b1} and active-low +if this parameter is {\tt 1'b0}. +\end{itemize} + D-type flip-flops with asynchronous set and reset are represented by {\tt \$dffsr} cells. As the {\tt \$dff} cells they have \B{CLK}, \B{D} and \B{Q} ports. In addition they also have multi-bit \B{SET} and \B{CLR} input ports and the corresponding polarity parameters, like {\tt \$sr} cells. -D-type flip-flops with enable are represented by {\tt \$dffe}, {\tt \$adffe}, {\tt \$dffsre}, -{\tt \$sdffe}, and {\tt \$sdffce} cells, which are enhanced variants of {\tt \$dff}, {\tt \$adff}, {\tt \$dffsr}, +D-type flip-flops with enable are represented by {\tt \$dffe}, {\tt \$adffe}, {\tt \$aldffe}, {\tt \$dffsre}, +{\tt \$sdffe}, and {\tt \$sdffce} cells, which are enhanced variants of {\tt \$dff}, {\tt \$adff}, {\tt \$aldff}, {\tt \$dffsr}, {\tt \$sdff} (with reset over enable) and {\tt \$sdff} (with enable over reset) cells, respectively. They have the same ports and parameters as their base cell. In addition they also have a single-bit \B{EN} input port for the enable pin and the following parameter: diff --git a/techlibs/common/gen_fine_ffs.py b/techlibs/common/gen_fine_ffs.py index 5d331e767..25c6ef171 100644 --- a/techlibs/common/gen_fine_ffs.py +++ b/techlibs/common/gen_fine_ffs.py @@ -133,6 +133,55 @@ endmodule """ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- +//- $_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q) +//- +//- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - {L:0|1} a | a +//- d {C:\\|/} - - | d +//- - - - - | q +//- +module \$_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @({C:neg|pos}edge C or {L:neg|pos}edge L) begin + if (L == {L:0|1}) + Q <= AD; + else + Q <= D; +end +endmodule +""", +""" +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q) +//- +//- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load and {E:negative|positive} +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - {L:0|1} a - | a +//- d {C:\\|/} - - {E:0|1} | d +//- - - - - - | q +//- +module \$_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @({C:neg|pos}edge C or {L:neg|pos}edge L) begin + if (L == {L:0|1}) + Q <= AD; + else if (E == {E:0|1}) + Q <= D; +end +endmodule +""", +""" +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- //- $_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q) //- //- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set and {R:negative|positive} diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index 7d9bebe2a..ad1fdc817 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -1252,6 +1252,290 @@ always @(posedge C or posedge R) begin end endmodule +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFF_NN_ (D, C, L, AD, Q) +//- +//- A negative edge D-type flip-flop with negative polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - 0 a | a +//- d \ - - | d +//- - - - - | q +//- +module \$_ALDFF_NN_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @(negedge C or negedge L) begin + if (L == 0) + Q <= AD; + else + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFF_NP_ (D, C, L, AD, Q) +//- +//- A negative edge D-type flip-flop with positive polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - 1 a | a +//- d \ - - | d +//- - - - - | q +//- +module \$_ALDFF_NP_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @(negedge C or posedge L) begin + if (L == 1) + Q <= AD; + else + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFF_PN_ (D, C, L, AD, Q) +//- +//- A positive edge D-type flip-flop with negative polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - 0 a | a +//- d / - - | d +//- - - - - | q +//- +module \$_ALDFF_PN_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @(posedge C or negedge L) begin + if (L == 0) + Q <= AD; + else + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFF_PP_ (D, C, L, AD, Q) +//- +//- A positive edge D-type flip-flop with positive polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - 1 a | a +//- d / - - | d +//- - - - - | q +//- +module \$_ALDFF_PP_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @(posedge C or posedge L) begin + if (L == 1) + Q <= AD; + else + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_NNN_ (D, C, L, AD, E, Q) +//- +//- A negative edge D-type flip-flop with negative polarity async load and negative +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 0 a - | a +//- d \ - - 0 | d +//- - - - - - | q +//- +module \$_ALDFFE_NNN_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(negedge C or negedge L) begin + if (L == 0) + Q <= AD; + else if (E == 0) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_NNP_ (D, C, L, AD, E, Q) +//- +//- A negative edge D-type flip-flop with negative polarity async load and positive +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 0 a - | a +//- d \ - - 1 | d +//- - - - - - | q +//- +module \$_ALDFFE_NNP_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(negedge C or negedge L) begin + if (L == 0) + Q <= AD; + else if (E == 1) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_NPN_ (D, C, L, AD, E, Q) +//- +//- A negative edge D-type flip-flop with positive polarity async load and negative +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 1 a - | a +//- d \ - - 0 | d +//- - - - - - | q +//- +module \$_ALDFFE_NPN_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(negedge C or posedge L) begin + if (L == 1) + Q <= AD; + else if (E == 0) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_NPP_ (D, C, L, AD, E, Q) +//- +//- A negative edge D-type flip-flop with positive polarity async load and positive +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 1 a - | a +//- d \ - - 1 | d +//- - - - - - | q +//- +module \$_ALDFFE_NPP_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(negedge C or posedge L) begin + if (L == 1) + Q <= AD; + else if (E == 1) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_PNN_ (D, C, L, AD, E, Q) +//- +//- A positive edge D-type flip-flop with negative polarity async load and negative +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 0 a - | a +//- d / - - 0 | d +//- - - - - - | q +//- +module \$_ALDFFE_PNN_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(posedge C or negedge L) begin + if (L == 0) + Q <= AD; + else if (E == 0) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_PNP_ (D, C, L, AD, E, Q) +//- +//- A positive edge D-type flip-flop with negative polarity async load and positive +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 0 a - | a +//- d / - - 1 | d +//- - - - - - | q +//- +module \$_ALDFFE_PNP_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(posedge C or negedge L) begin + if (L == 0) + Q <= AD; + else if (E == 1) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_PPN_ (D, C, L, AD, E, Q) +//- +//- A positive edge D-type flip-flop with positive polarity async load and negative +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 1 a - | a +//- d / - - 0 | d +//- - - - - - | q +//- +module \$_ALDFFE_PPN_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(posedge C or posedge L) begin + if (L == 1) + Q <= AD; + else if (E == 0) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_PPP_ (D, C, L, AD, E, Q) +//- +//- A positive edge D-type flip-flop with positive polarity async load and positive +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 1 a - | a +//- d / - - 1 | d +//- - - - - - | q +//- +module \$_ALDFFE_PPP_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(posedge C or posedge L) begin + if (L == 1) + Q <= AD; + else if (E == 1) + Q <= D; +end +endmodule + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- //- $_DFFSR_NNN_ (C, S, R, D, Q) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index cf0839ebe..e9129f690 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1890,6 +1890,30 @@ endmodule // -------------------------------------------------------- +module \$aldff (CLK, ALOAD, AD, D, Q); + +parameter WIDTH = 0; +parameter CLK_POLARITY = 1'b1; +parameter ALOAD_POLARITY = 1'b1; + +input CLK, ALOAD; +input [WIDTH-1:0] AD; +input [WIDTH-1:0] D; +output reg [WIDTH-1:0] Q; +wire pos_clk = CLK == CLK_POLARITY; +wire pos_aload = ALOAD == ALOAD_POLARITY; + +always @(posedge pos_clk, posedge pos_aload) begin + if (pos_aload) + Q <= AD; + else + Q <= D; +end + +endmodule + +// -------------------------------------------------------- + module \$sdff (CLK, SRST, D, Q); parameter WIDTH = 0; @@ -1939,6 +1963,31 @@ endmodule // -------------------------------------------------------- +module \$aldffe (CLK, ALOAD, AD, EN, D, Q); + +parameter WIDTH = 0; +parameter CLK_POLARITY = 1'b1; +parameter EN_POLARITY = 1'b1; +parameter ALOAD_POLARITY = 1'b1; + +input CLK, ALOAD, EN; +input [WIDTH-1:0] D; +input [WIDTH-1:0] AD; +output reg [WIDTH-1:0] Q; +wire pos_clk = CLK == CLK_POLARITY; +wire pos_aload = ALOAD == ALOAD_POLARITY; + +always @(posedge pos_clk, posedge pos_aload) begin + if (pos_aload) + Q <= AD; + else if (EN == EN_POLARITY) + Q <= D; +end + +endmodule + +// -------------------------------------------------------- + module \$sdffe (CLK, SRST, EN, D, Q); parameter WIDTH = 0;