// license:BSD-3-Clause // copyright-holders:Couriersud /* * nld_4013.cpp * * CD4013: Dual Positive-Edge-Triggered D Flip-Flops * with Set, Reset and Complementary Outputs * * +--------------+ * Q1 |1 ++ 14| VDD * Q1Q |2 13| Q2 * CLOCK1 |3 12| Q2Q * RESET1 |4 4013 11| CLOCK2 * DATA1 |5 10| RESET2 * SET1 |6 9| DATA2 * VSS |7 8| SET2 * +--------------+ * * +-----+-----+-----+---++---+-----+ * | SET | RES | CLK | D || Q | QQ | * +=====+=====+=====+===++===+=====+ * | 1 | 0 | X | X || 1 | 0 | * | 0 | 1 | X | X || 0 | 1 | * | 1 | 1 | X | X || 1 | 1 | (*) * | 0 | 0 | R | 1 || 1 | 0 | * | 0 | 0 | R | 0 || 0 | 1 | * | 0 | 0 | 0 | X || Q0| Q0Q | * +-----+-----+-----+---++---+-----+ * * (*) This configuration is not stable, i.e. it will not persist * when either the preset and or clear inputs return to their inactive (high) level * * Q0 The output logic level of Q before the indicated input conditions were established * * R: 0 -. 1 * * Naming conventions follow National Semiconductor datasheet * * FIXME: Check that (*) is emulated properly */ #include "nl_base.h" #include "nl_factory.h" namespace netlist::devices { NETLIB_OBJECT(CD4013) { NETLIB_CONSTRUCTOR_MODEL(CD4013, "CD4XXX") , m_D(*this, "DATA", NETLIB_DELEGATE(inputs)) , m_RESET(*this, "RESET", NETLIB_DELEGATE(inputs)) , m_SET(*this, "SET", NETLIB_DELEGATE(inputs)) , m_CLK(*this, "CLOCK", NETLIB_DELEGATE(clk)) , m_Q(*this, "Q") , m_QQ(*this, "QQ") , m_nextD(*this, "m_nextD", 0) , m_power_pins(*this) { } private: NETLIB_RESETI() { m_CLK.set_state(logic_t::STATE_INP_LH); m_D.set_state(logic_t::STATE_INP_ACTIVE); m_nextD = 0; } NETLIB_HANDLERI(inputs) { const auto set(m_SET()); const auto reset(m_RESET()); if ((set ^ 1) & (reset ^ 1)) { m_D.activate(); m_nextD = m_D(); m_CLK.activate_lh(); } else { newstate_setreset(set, reset); m_CLK.inactivate(); m_D.inactivate(); } } NETLIB_HANDLERI(clk) { newstate_clk(m_nextD); m_CLK.inactivate(); } logic_input_t m_D; logic_input_t m_RESET; logic_input_t m_SET; logic_input_t m_CLK; logic_output_t m_Q; logic_output_t m_QQ; state_var m_nextD; nld_power_pins m_power_pins; void newstate_clk(const netlist_sig_t stateQ) { static constexpr auto delay = NLTIME_FROM_NS(150); m_Q.push(stateQ, delay); m_QQ.push(!stateQ, delay); } void newstate_setreset(const netlist_sig_t stateQ, const netlist_sig_t stateQQ) { // Q: 150 ns, QQ: 200 ns static constexpr const std::array delay = { NLTIME_FROM_NS(150), NLTIME_FROM_NS(200) }; m_Q.push(stateQ, delay[0]); m_QQ.push(stateQQ, delay[1]); } }; NETLIB_DEVICE_IMPL(CD4013, "CD4013", "+CLOCK,+DATA,+RESET,+SET,@VDD,@VSS") } // namespace netlist::devices