within Modelica.Electrical;
package Digital
  "Library for digital electrical components based on the VHDL standard with 9-valued logic and conversion to 2-,3-,4-valued logic"
  extends Modelica.Icons.Package;

    package UsersGuide "User's Guide"
      extends Modelica.Icons.Information;

      class ReleaseNotes "Release notes"
          extends Modelica.Icons.ReleaseNotes;
      end ReleaseNotes;

      class Literature "Literature"
          extends Modelica.Icons.References;

      end Literature;

      class Contact "Contact"
        extends Modelica.Icons.Contact;

      end Contact;
    end UsersGuide;

      package Examples "Examples that demonstrate the usage of the Digital electrical components"
        extends Modelica.Icons.ExamplesPackage;

        model Multiplexer "4 to 1 Bit Multiplexer Example"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          D.Sources.DigitalClock CLK(period=20, startTime=0, width=50)
          D.Sources.Table D0(
            y0=L.'0',
            x={L.'1',L.'0',L.'1',L.'0'},
            t={50,100,145,200})
          D.Sources.Table D1(
            y0=L.'0',
            x={L.'1',L.'0',L.'1',L.'0'},
            t={22,140,150,180})
          D.Examples.Utilities.MUX4 MUX
          D.Sources.Table D2(
            y0=L.'0',
            x={L.'1',L.'0',L.'1',L.'0'},
            t={22,140,150,180})
          D.Sources.Table D3(
            y0=L.'0',
            x={L.'1',L.'0',L.'1',L.'0'},
            t={22,140,150,180})
          D.Examples.Utilities.JKFF FF
          D.Sources.Set Enable(x=Modelica.Electrical.Digital.Interfaces.Logic.'1')
        equation
          connect(CLK.y, FF.clk)
          connect(Enable.y, FF.k)
          connect(Enable.y, FF.j)
          connect(CLK.y, MUX.a0)
          connect(D0.y, MUX.d0)
          connect(D1.y, MUX.d1)
          connect(D2.y, MUX.d2)
          connect(D3.y, MUX.d3)
          connect(FF.q, MUX.a1)
        end Multiplexer;

        model FlipFlop "Pulse Triggered Master Slave Flip-Flop"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          D.Examples.Utilities.JKFF FF
          D.Sources.DigitalClock CLK(period=10, startTime=0, width=50)
          D.Sources.Table J(
            y0=L.'0',
            x={L.'1',L.'0',L.'1',L.'0'},
            t={50,100,145,200})
          D.Sources.Table K(
            y0=L.'0',
            x={L.'1',L.'0',L.'1',L.'0'},
            t={22,140,150,180})
        equation
          connect(J.y, FF.j)
          connect(CLK.y, FF.clk)
          connect(K.y, FF.k)
        end FlipFlop;

        model HalfAdder "Adding circuit for binary numbers without input carry bit"
          import Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table a(
            t={1,2,3,4},
            x={L.'1',L.'0',L.'1',L.'0'},
            y0=L.'0')
          Modelica.Electrical.Digital.Sources.Table b(
            x={L.'1',L.'0'},
            t={2,4},
            y0=L.'0')
          Modelica.Electrical.Digital.Examples.Utilities.HalfAdder Adder(delayTime=0.3, AND(G2(
                                                                                y(       start=L.'U', fixed=true))),
        XOR(G2(                                                                                y(       start=L.'U', fixed=true))))
          Modelica.Electrical.Digital.Converters.LogicToReal s(
        n=1,
        value_U=0.5,
        value_X=0.5,
        value_0=0,
        value_1=1,
        value_Z=0.5,
        value_W=0.5,
        value_L=0,
        value_H=1,
        value_m=0.5)
          Modelica.Electrical.Digital.Converters.LogicToReal c(
        n=1,
        value_U=0.5,
        value_X=0.5,
        value_0=0,
        value_1=1,
        value_Z=0.5,
        value_W=0.5,
        value_L=0,
        value_H=1,
        value_m=0.5)
        equation
          connect(b.y,Adder. b)
          connect(a.y,Adder. a)
          connect(Adder.s, s.x[1])
          connect(Adder.c, c.x[1])
        end HalfAdder;

        model FullAdder "Full 1 Bit Adder Example"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          D.Examples.Utilities.FullAdder Adder1
          D.Converters.LogicToReal s(value_0=0, value_1=1, value_H=1, value_L=0, value_m=0.5, value_U=0.5, value_W=0.5, value_X=0.5, value_Z=0.5, n=1)
          D.Converters.LogicToReal c_out(value_0=0, value_1=1, value_H=1, value_L=0, value_m=0.5, value_U=0.5, value_W=0.5, value_X=0.5, value_Z=0.5, n=1)
          D.Examples.Utilities.Counter3 Counter
          D.Sources.Set Enable(x=L.'1')
          D.Sources.DigitalClock CLK(period=1, startTime=0, width=50)
        equation
          connect(Adder1.s, s.x[1])
          connect(Adder1.c_out, c_out.x[1])
          connect(CLK.y, Counter.count)
          connect(Enable.y, Counter.enable)
          connect(Counter.q2, Adder1.a)
          connect(Counter.q1, Adder1.b)
          connect(Counter.q0, Adder1.c_in)
        end FullAdder;

        model Adder4 "4 Bit Adder Example"
          import Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;

          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table b4(
            y0=L.'0',
            x={L.'1',L.'0'},
            t={1,3})
          Modelica.Electrical.Digital.Sources.Table b1(
            x={L.'1',L.'0',L.'1'},
            y0=L.'0',
            t={1,2,3})
          Modelica.Electrical.Digital.Sources.Table b2(
            y0=L.'0',
            x={L.'1'},
            t={4})
          Modelica.Electrical.Digital.Sources.Table b3(
            y0=L.'0',
            x={L.'1'},
            t={1})
          Modelica.Electrical.Digital.Sources.Table a1(
            y0=L.'0',
            x={L.'1',L.'0',L.'1'},
            t={1,2,3})
          Modelica.Electrical.Digital.Sources.Table a2(
            y0=L.'0',
            x={L.'1'},
            t={1})
          Modelica.Electrical.Digital.Sources.Table a3(
            y0=L.'0',
            x={L.'1',L.'0'},
            t={1,4})
          Modelica.Electrical.Digital.Sources.Table a4(
            y0=L.'0',
            x={L.'0'},
            t={1})
          Modelica.Electrical.Digital.Sources.Set Set(x=L.'0')
          Modelica.Electrical.Digital.Examples.Utilities.FullAdder Adder1(Adder1(AND(G2(
                                                                          y(      start=L.'U', fixed=true))),XOR(G2(y(start=L.'U', fixed=true)))),Adder2(AND(G2(
                                                                          y(      start=L.'U', fixed=true))),XOR(G2(y(start=L.'U', fixed=true)))))
          Modelica.Electrical.Digital.Examples.Utilities.FullAdder Adder2(Adder1(AND(G2(
                                                                          y(      start=L.'U', fixed=true))),XOR(G2(y(start=L.'U', fixed=true)))),Adder2(AND(G2(
                                                                          y(      start=L.'U', fixed=true))),XOR(G2(y(start=L.'U', fixed=true)))))
          Modelica.Electrical.Digital.Examples.Utilities.FullAdder Adder3(Adder1(AND(G2(
                                                                          y(      start=L.'U', fixed=true))),XOR(G2(y(start=L.'U', fixed=true)))),Adder2(AND(G2(
                                                                          y(      start=L.'U', fixed=true))),XOR(G2(y(start=L.'U', fixed=true)))))
          Modelica.Electrical.Digital.Examples.Utilities.FullAdder Adder4(Adder1(AND(G2(
                                                                          y(      start=L.'U', fixed=true))),XOR(G2(y(start=L.'U', fixed=true)))),Adder2(AND(G2(
                                                                          y(      start=L.'U', fixed=true))),XOR(G2(y(start=L.'U', fixed=true)))))
        equation
          connect(b1.y, Adder1.b)
          connect(a1.y, Adder1.a)
          connect(Set.y, Adder1.c_in)
          connect(Adder1.c_out, Adder2.c_in)
          connect(Adder2.c_out, Adder3.c_in)
          connect(Adder3.c_out, Adder4.c_in)
          connect(b2.y, Adder2.b)
          connect(a2.y, Adder2.a)
          connect(b3.y, Adder3.b)
          connect(a3.y, Adder3.a)
          connect(b4.y, Adder4.b)
          connect(a4.y, Adder4.a)
        end Adder4;

        model Counter3 "3 Bit Counter Example"
          import D = Modelica.Electrical.Digital;
          extends Modelica.Icons.Example;

          D.Sources.Step Enable(after=D.Interfaces.Logic.'1', before=D.Interfaces.Logic.'0', stepTime=1)
          D.Sources.DigitalClock clock(period=1, startTime=0, width=50)
          D.Examples.Utilities.Counter3 Counter
        equation
          connect(Enable.y, Counter.enable)
          connect(clock.y, Counter.count)
        end Counter3;

        model Counter "Generic N Bit Counter Example"
          import D = Modelica.Electrical.Digital;
          extends Modelica.Icons.Example;

          D.Sources.Step Enable(after=D.Interfaces.Logic.'1', before=D.Interfaces.Logic.'0', stepTime=1)
          D.Sources.DigitalClock clock(period=1, startTime=0, width=50)
          D.Examples.Utilities.Counter Counter(n=4)
          D.Converters.LogicToReal Q0(value_0=0, value_1=1, value_H=1, value_L=0, value_m=0.5, value_U=0.5, value_W=0.5, value_X=0.5, value_Z=0.5, n=1)
          D.Converters.LogicToReal Q1(value_0=0, value_1=1, value_H=1, value_L=0, value_m=0.5, value_U=0.5, value_W=0.5, value_X=0.5, value_Z=0.5, n=1)
          D.Converters.LogicToReal Q2(value_0=0, value_1=1, value_H=1, value_L=0, value_m=0.5, value_U=0.5, value_W=0.5, value_X=0.5, value_Z=0.5, n=1)
          D.Converters.LogicToReal Q3(value_0=0, value_1=1, value_H=1, value_L=0, value_m=0.5, value_U=0.5, value_W=0.5, value_X=0.5, value_Z=0.5, n=1)
        equation
          connect(Enable.y, Counter.enable)
          connect(clock.y, Counter.count)
          connect(Q0.x[1], Counter.q[1])
          connect(Q1.x[1], Counter.q[2])
          connect(Q2.x[1], Counter.q[3])
          connect(Q3.x[1], Counter.q[4])
        end Counter;

        model VectorDelay "Vector delay"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Delay.InertialDelaySensitiveVector delay(
            final tHL=1,
            final tLH=2,
            final n=3, inertialDelaySensitive(each y(start=L.'U', fixed=true)))
          Modelica.Electrical.Digital.Sources.Table table(x={L.'0',L.'1',L.'0', L.'1', L.'0'}, t={0,1,5,7,8})
          Modelica.Electrical.Digital.Sources.Table table1(x={L.'0',L.'1'}, t={0,1})
          Modelica.Electrical.Digital.Sources.Table table2(x={L.'0', L.'1', L.'0'}, t={0,1,6})
        equation

          connect(table.y, delay.x[1])
          connect(table1.y, delay.x[2])
          connect(table2.y, delay.x[3])
        end VectorDelay;

        model DFFREG "Pulse triggered D-Register-Bank, high active reset"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table clock(x={L.'0',L.'1',L.'0',L.'1',L.'0',L.'1',L.'0'}, t={0,7,8,10,11,15,16})
          Modelica.Electrical.Digital.Sources.Table data_0(x={L.'1',L.'0'}, t={0,12})
          Modelica.Electrical.Digital.Sources.Table reset(x={L.'0',L.'1',L.'0'}, t={0,1,2})
          Modelica.Electrical.Digital.Sources.Table data_1(t={0,10}, x={L.'H',L.'X'})
          Modelica.Electrical.Digital.Registers.DFFREG dFFREG(
            n=2,
            tHL=5,
            tLH=6,
            delay( inertialDelaySensitive(each y(start=L.'U', fixed=true))),
        dFFR(                                                            clock(     start=L.'U', fixed=true), reset(     start=L.'U',fixed=true)))

        equation
          connect(clock.y, dFFREG.clock)
          connect(reset.y, dFFREG.reset)
          connect(data_0.y, dFFREG.dataIn[1])
          connect(data_1.y, dFFREG.dataIn[2])
        end DFFREG;

        model DFFREGL "Pulse triggered D-Register-Bank, low active reset"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table clock(x={L.'0',L.'1',L.'0',L.'1',L.'0',L.'1',L.'0'}, t={0,7,8,10,11,15,16})
          Modelica.Electrical.Digital.Sources.Table data_0(x={L.'1',L.'0'}, t={0,12})
          Modelica.Electrical.Digital.Sources.Table reset(t={0,1,2}, x={L.'1',L.'0',L.'1'})
          Modelica.Electrical.Digital.Sources.Table data_1(t={0,10}, x={L.'H',L.'X'})
          Modelica.Electrical.Digital.Registers.DFFREGL dFFREGL(
            n=2,
            tHL=5,
            tLH=6,delay(inertialDelaySensitive(each y(start=L.'U', fixed=true))),
        dFFR(                                                                 clock(     start=L.'U', fixed=true), reset(     start=L.'U', fixed=true)))
        equation

          connect(reset.y, dFFREGL.reset)
          connect(clock.y, dFFREGL.clock)
          connect(data_0.y, dFFREGL.dataIn[1])
          connect(data_1.y, dFFREGL.dataIn[2])
        end DFFREGL;

        model DFFREGSRH "Pulse triggered D-Register-Bank, high active set and reset"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table clock(x={L.'0',L.'1',L.'0'}, t={0,10,11})
          Modelica.Electrical.Digital.Sources.Table data_0(x={L.'W'}, t={0})
          Modelica.Electrical.Digital.Sources.Table reset(x={L.'0',L.'1',L.'0'}, t={0,1,2})
          Modelica.Electrical.Digital.Sources.Table data_1(x={L.'0'}, t={0})
          Modelica.Electrical.Digital.Sources.Table set(x={L.'0',L.'1',L.'0'}, t={0,5,6})
          Modelica.Electrical.Digital.Registers.DFFREGSRH dFFREGSRH(
            tHL=2,
            tLH=3,
            n=2)
        equation

          connect(clock.y, dFFREGSRH.clock)
          connect(set.y, dFFREGSRH.set)
          connect(reset.y, dFFREGSRH.reset)
          connect(data_0.y, dFFREGSRH.dataIn[1])
          connect(data_1.y, dFFREGSRH.dataIn[2])
        end DFFREGSRH;

        model DFFREGSRL "Pulse triggered D-Register-Bank, low active set and reset"
      import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table clock(x={L.'0',L.'1',L.'0'}, t={0,10,11})
          Modelica.Electrical.Digital.Sources.Table data_0(x={L.'W'}, t={0})
          Modelica.Electrical.Digital.Sources.Table reset(t={0,1,2}, x={L.'1',L.'0',L.'1'})
          Modelica.Electrical.Digital.Sources.Table data_1(x={L.'0'}, t={0})
          Modelica.Electrical.Digital.Sources.Table set(t={0,5,6}, x={L.'1',L.'0',L.'1'})
          Modelica.Electrical.Digital.Registers.DFFREGSRL dFFREGSRL(
            tHL=2,
            tLH=3,
            n=2)
        equation
          connect(reset.y, dFFREGSRL.reset)
          connect(clock.y, dFFREGSRL.clock)
          connect(set.y, dFFREGSRL.set)
          connect(data_0.y, dFFREGSRL.dataIn[1])
          connect(data_1.y, dFFREGSRL.dataIn[2])
        end DFFREGSRL;

        model DLATREG "Level sensitive D-Register-Bank, high active reset"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table enable(x={L.'0',L.'1',L.'0'}, t={0,10,18})
          Modelica.Electrical.Digital.Sources.Table data_0(x={L.'W',L.'1'}, t={0,15})
          Modelica.Electrical.Digital.Sources.Table reset(x={L.'0',L.'1',L.'0',L.'1',L.'0'}, t={0,1,2,20,21})
          Modelica.Electrical.Digital.Sources.Table data_1(x={L.'0',L.'1'}, t={0,16})
          Modelica.Electrical.Digital.Registers.DLATREG dLATREG(
            n=2,
            tHL=2,
            tLH=3, delay(inertialDelaySensitive(each y( start=L.'U', fixed=true))))
        equation

          connect(reset.y, dLATREG.reset)
          connect(enable.y, dLATREG.enable)
          connect(data_0.y, dLATREG.dataIn[1])
          connect(data_1.y, dLATREG.dataIn[2])
        end DLATREG;

        model DLATREGL "Level sensitive D-Register-Bank, low active reset"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table enable(x={L.'0',L.'1',L.'0'}, t={0,10,18})
          Modelica.Electrical.Digital.Sources.Table data_0(x={L.'W',L.'1'}, t={0,15})
          Modelica.Electrical.Digital.Sources.Table reset(t={0,1,2,20,21}, x={L.'1',L.'0',L.'1',L.'0',L.'1'})
          Modelica.Electrical.Digital.Sources.Table data_1(x={L.'0',L.'1'}, t={0,16})
          Modelica.Electrical.Digital.Registers.DLATREGL dLATREGL(
            tHL=2,
            tLH=3,
            n=2, delay(inertialDelaySensitive(each y(start=L.'U', fixed=true))))
        equation

          connect(reset.y, dLATREGL.reset)
          connect(enable.y, dLATREGL.enable)
          connect(data_0.y, dLATREGL.dataIn[1])
          connect(data_1.y, dLATREGL.dataIn[2])
        end DLATREGL;

        model DLATREGSRH "Level sensitive D-Register-Bank, high active set and reset"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table enable(x={L.'0',L.'1',L.'0'}, t={0,10,18})
          Modelica.Electrical.Digital.Sources.Table data_0(x={L.'W',L.'1'}, t={0,15})
          Modelica.Electrical.Digital.Sources.Table reset(x={L.'0',L.'1',L.'0',L.'1',L.'0'}, t={0,1,2,20,21})
          Modelica.Electrical.Digital.Sources.Table data_1(x={L.'0',L.'1'}, t={0,16})
          Modelica.Electrical.Digital.Sources.Table set(x={L.'0',L.'1',L.'0'}, t={0,5,6})
          Modelica.Electrical.Digital.Registers.DLATREGSRH dLATREGSRH(
            tHL=2,
            tLH=3,
            n=2, delay(inertialDelaySensitive(each y(start=L.'U', fixed=true))))
        equation

          connect(reset.y, dLATREGSRH.reset)
          connect(enable.y, dLATREGSRH.enable)
          connect(data_0.y, dLATREGSRH.dataIn[1])
          connect(data_1.y, dLATREGSRH.dataIn[2])
          connect(set.y, dLATREGSRH.set)
        end DLATREGSRH;

        model DLATREGSRL "Level sensitive D-Register-Bank, low active set and reset"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table enable(t={0,10,18}, x={L.'0',L.'1',L.'0'})
          Modelica.Electrical.Digital.Sources.Table data_0(x={L.'W',L.'1'}, t={0,15})
          Modelica.Electrical.Digital.Sources.Table reset(t={0,1,2,20,21}, x={L.'1',L.'0',L.'1',L.'0',L.'1'})
          Modelica.Electrical.Digital.Sources.Table data_1(x={L.'0',L.'1'}, t={0,16})
          Modelica.Electrical.Digital.Sources.Table set(t={0,5,6}, x={L.'1',L.'0',L.'1'})
          Modelica.Electrical.Digital.Registers.DLATREGSRL dLATREGSRL(
            tHL=2,
            tLH=3,
            n=2, delay(inertialDelaySensitive(each y(start=L.'U',fixed=true))))
        equation

          connect(reset.y, dLATREGSRL.reset)
          connect(enable.y, dLATREGSRL.enable)
          connect(data_0.y, dLATREGSRL.dataIn[1])
          connect(data_1.y, dLATREGSRL.dataIn[2])
          connect(set.y, dLATREGSRL.set)
        end DLATREGSRL;

        model NXFER "Functionality test of NXFERGATE"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;
          Modelica.Electrical.Digital.Sources.Table e_table(
        y0=Modelica.Electrical.Digital.Interfaces.Logic.'U',
        x={L.'0',L.'1',L.'Z'},
        t={0,5,9})
          Modelica.Electrical.Digital.Sources.Table x_table(
        y0=Modelica.Electrical.Digital.Interfaces.Logic.'U',
        x={L.'1',L.'0'},
        t={1,7})
          Modelica.Electrical.Digital.Tristates.NXFERGATE nXFERGATE(
                                            tHL=1, tLH=1)
        equation

          connect(x_table.y, nXFERGATE.x)
          connect(e_table.y, nXFERGATE.enable)
        end NXFER;

        model NRXFER "Functionality test of NRXFERGATE"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table e_table(
        y0=Modelica.Electrical.Digital.Interfaces.Logic.'U',
        x={L.'0',L.'1',L.'Z'},
        t={0,5,9})
          Modelica.Electrical.Digital.Sources.Table x_table(
        y0=Modelica.Electrical.Digital.Interfaces.Logic.'U',
        x={L.'1',L.'0'},
        t={1,7})
          Modelica.Electrical.Digital.Tristates.NRXFERGATE nRXFERGATE(
                                              tHL=1, tLH=1)
        equation
          connect(x_table.y, nRXFERGATE.x)
          connect(e_table.y, nRXFERGATE.enable)
        end NRXFER;

        model BUF3S "Functionality test of BUF3S"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;
          Modelica.Electrical.Digital.Sources.Table e_table(
        y0=Modelica.Electrical.Digital.Interfaces.Logic.'U',
        x={L.'0',L.'1',L.'Z'},
        t={0,5,9})
          Modelica.Electrical.Digital.Sources.Table x_table(
        y0=Modelica.Electrical.Digital.Interfaces.Logic.'U',
        x={L.'1',L.'0'},
        t={1,7})
          Modelica.Electrical.Digital.Tristates.BUF3S bUF3S(
            tHL=1,
            tLH=1,
            strength=Modelica.Electrical.Digital.Interfaces.Strength.'S_X01')
        equation
          connect(x_table.y, bUF3S.x)
          connect(e_table.y, bUF3S.enable)
        end BUF3S;

        model INV3S "Functionality test of INV3S"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Sources.Table e_table(
        y0=L.'U',
        x={L.'0',L.'1',L.'Z'},
        t={0,5,9})
          Modelica.Electrical.Digital.Sources.Table x_table(
        y0=L.'U',
        x={L.'1',L.'0'},
        t={1,7})
          Modelica.Electrical.Digital.Tristates.INV3S iNV3S
        equation
          connect(x_table.y, iNV3S.x)
          connect(e_table.y, iNV3S.enable)
        end INV3S;

        model WiredX "Functionality test of WiredX"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;
        Modelica.Electrical.Digital.Sources.Table e_table2(
        y0=L.'U',
        x={L.'0',L.'1',L.'0'},
        t={0,3,9})
          Modelica.Electrical.Digital.Sources.Table x_table2(
        y0=L.'U',
        x={L.'1',L.'0'},
        t={1,7})
          Modelica.Electrical.Digital.Tristates.BUF3S bUF3S2(
            tHL=1,
            tLH=1,
            strength=Modelica.Electrical.Digital.Interfaces.Strength.'S_X01')
          Modelica.Electrical.Digital.Sources.Table e_table1(
        y0=L.'U',
        t={0,3,9},
        x={L.'0',L.'1',L.'0'})
          Modelica.Electrical.Digital.Sources.Table x_table1(
        y0=L.'U',
        x={L.'0',L.'1',L.'0'},
        t={1,5,7})
          Modelica.Electrical.Digital.Tristates.BUF3S bUF3S1(
            tHL=1,
            tLH=1,
            strength=Modelica.Electrical.Digital.Interfaces.Strength.'S_X01')
          Modelica.Electrical.Digital.Tristates.WiredX wiredX(n=2)
        equation
          connect(x_table2.y, bUF3S2.x)
          connect(e_table2.y, bUF3S2.enable)
          connect(x_table1.y, bUF3S1.x)
          connect(e_table1.y, bUF3S1.enable)
          connect(bUF3S1.y, wiredX.x[1])
          connect(bUF3S2.y, wiredX.x[2])
        end WiredX;

        model MUX2x1 "Simple Multiplexer test"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;
          D.Multiplexers.MUX2x1 Mux2x1
          D.Sources.Table Input1(
            y0=L.'U',
            x={L.'X',L.'0',L.'1',L.'0',L.'X',L.'U'},
            t={2,4,6,8,10,12})
          D.Sources.Step Select(
            before=L.'0',
            after=L.'1',
            stepTime=7)
          D.Sources.Table Input0(
            y0=L.'U',
            t={2,4,6,8,10,12},
            x={L.'1',L.'X',L.'0',L.'X',L.'1',L.'U'})
        equation
          connect(Select.y, Mux2x1.sel)
          connect(Input0.y, Mux2x1.in0)
          connect(Input1.y, Mux2x1.in1)
        end MUX2x1;

        model RAM "Simple RAM test example"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends Modelica.Icons.Example;

          Modelica.Electrical.Digital.Memories.DLATRAM
                         dLATRAM
          Modelica.Electrical.Digital.Sources.Table
                        addr_1(
            y0=L.'U',
            x={L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-',
               L.'U',L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-',
               L.'U',L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-',
               L.'U',L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-',
               L.'U',L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-',
               L.'U',L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-',
               L.'U',L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-',
               L.'U',L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-',
               L.'U',L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-'},
            t={5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,
                115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,
                200,205,210,215,220,225,230,235,240,245,250,255,260,265,270,275,280,
                285,290,295,300,305,310,315,320,325,330,335,340,345,350,355,360,365,
                370,375,380,385,390,395,400})
          Modelica.Electrical.Digital.Sources.Set
                      data_1(x=Modelica.Electrical.Digital.Interfaces.Logic.'0')
          Modelica.Electrical.Digital.Sources.Set
                      data_0(x=Modelica.Electrical.Digital.Interfaces.Logic.'0')
          Modelica.Electrical.Digital.Sources.Set
                      WE(x=Modelica.Electrical.Digital.Interfaces.Logic.'1')
          Modelica.Electrical.Digital.Sources.Table
                        addr_0(
            y0=Modelica.Electrical.Digital.Interfaces.Logic.'U',
            t={45,90,135,180,225,270,315,360},
            x={L.'X',L.'0',L.'1',L.'Z',L.'W',L.'L',L.'H',L.'-'})
          Modelica.Electrical.Digital.Sources.Set
                      RE(x=Modelica.Electrical.Digital.Interfaces.Logic.'1')

        equation
          connect(RE.y,dLATRAM. RE)
          connect(WE.y,dLATRAM. WE)
          connect(addr_0.y,dLATRAM. addr[1])
          connect(addr_1.y,dLATRAM. addr[2])
          connect(data_1.y,dLATRAM. dataIn[2])
          connect(data_0.y,dLATRAM. dataIn[1])
        end RAM;

      package Utilities "Utility components used by package Examples"
        extends Modelica.Icons.UtilitiesPackage;

        model MUX4 "4 to 1 Bit Multiplexer"
        import D = Modelica.Electrical.Digital;
        import L = Modelica.Electrical.Digital.Interfaces.Logic;

          parameter SI.Time delayTime=0.001 "Delay time";
          parameter D.Interfaces.Logic q0=L.'0' "Initial value";
            D.Interfaces.DigitalInput d0
            D.Interfaces.DigitalInput d1
            D.Interfaces.DigitalInput d2
            D.Interfaces.DigitalInput d3
            D.Interfaces.DigitalInput a0
            D.Interfaces.DigitalInput a1
            D.Interfaces.DigitalOutput d
            D.Basic.Or Or1(n=4)
            D.Basic.And And1(n=3)
            D.Basic.And And2(n=3)
            D.Basic.And And3(n=3)
            D.Basic.And And4(n=3)
            D.Basic.Not Not1
            D.Basic.Not Not2
        equation
            connect(a0, Not1.x)
            connect(a1, Not2.x)
            connect(d0, And1.x[2])
            connect(d1, And2.x[2])
            connect(d2, And3.x[2])
            connect(d3, And4.x[2])
            connect(And4.y, Or1.x[1])
            connect(And3.y, Or1.x[2])
            connect(And2.y, Or1.x[3])
            connect(And1.y, Or1.x[4])
            connect(Or1.y, d)
            connect(Not1.y, And1.x[3])
            connect(Not1.y, And3.x[3])
            connect(Not2.y, And1.x[1])
            connect(Not2.y, And2.x[1])
            connect(a0, And4.x[3])
            connect(a0, And2.x[3])
            connect(a1, And4.x[1])
            connect(a1, And3.x[1])
        end MUX4;

        model RS "Unclocked RS FlipFlop"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;

          parameter SI.Time delayTime=0 "Delay time";
          parameter D.Interfaces.Logic q0=L.'U' "Initial value of output";
          D.Basic.Nor Nor1
          D.Basic.Nor Nor2
          D.Interfaces.DigitalInput s
          D.Interfaces.DigitalInput r
          D.Interfaces.DigitalOutput q
          D.Interfaces.DigitalOutput qn
          D.Delay.TransportDelay TD1(final delayTime=delayTime, final y0=q0)
        equation
          connect(s, Nor1.x[2])
          connect(r, Nor2.x[1])
          connect(Nor2.y, Nor1.x[1])
          connect(Nor1.y,qn)
          connect(Nor2.y,q)
          connect(TD1.y, Nor2.x[2])
          connect(TD1.x, Nor1.y)
        end RS;

        model RSFF "Unclocked RS FlipFlop"
        import D = Modelica.Electrical.Digital;
        import L = Modelica.Electrical.Digital.Interfaces.Logic;

          parameter SI.Time delayTime=0.01 "Delay time";
          parameter D.Interfaces.Logic q0=L.'U' "Initial value";
          D.Interfaces.DigitalInput s
          D.Interfaces.DigitalInput r
          D.Interfaces.DigitalOutput q
          D.Interfaces.DigitalOutput qn "not Q"
          D.Interfaces.DigitalInput clk
          D.Examples.Utilities.RS RS1(final delayTime=delayTime, final q0=q0)
          D.Basic.And And1
          D.Basic.And And2
        equation
          connect(And2.y, RS1.r)
          connect(And1.y, RS1.s)
          connect(s, And1.x[2])
          connect(clk, And1.x[1])
          connect(clk, And2.x[2])
          connect(r, And2.x[1])
          connect(RS1.q,q)
          connect(RS1.qn,qn)
        end RSFF;

        model DFF "D FlipFlop"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;

          parameter SI.Time delayTime=0.01 "Delay time";
          parameter L q0=L.'U' "Initial value";
          D.Interfaces.DigitalInput d
          D.Interfaces.DigitalOutput q
          D.Interfaces.DigitalOutput qn "not Q"
          D.Interfaces.DigitalInput clk
          D.Examples.Utilities.RSFF RSFF1(final delayTime=delayTime, final q0=q0)
          D.Basic.Not Not1
        equation
          connect(RSFF1.q,q)
          connect(RSFF1.qn,qn)
          connect(Not1.y, RSFF1.r)
          connect(d, Not1.x)
          connect(d, RSFF1.s)
        connect(clk, RSFF1.clk)
        end DFF;

        model JKFF "JK FlipFlop"
        import D = Modelica.Electrical.Digital;
        import L = Modelica.Electrical.Digital.Interfaces.Logic;

          parameter SI.Time delayTime=0.001 "Delay time";
          parameter D.Interfaces.Logic q0=L.'0' "Initial value";
          D.Interfaces.DigitalInput j
          D.Interfaces.DigitalOutput q
          D.Interfaces.DigitalOutput qn "not Q"
          D.Interfaces.DigitalInput clk
          D.Interfaces.DigitalInput k
          D.Examples.Utilities.RS RS1(final delayTime=delayTime, final q0=q0)
          D.Examples.Utilities.RS RS2(final delayTime=delayTime, final q0=q0)
          D.Basic.And And1(n=3)
          D.Basic.And And2(n=3)
          D.Basic.And And3
          D.Basic.And And4
          D.Basic.Not Not1
        equation
            connect(And2.y, RS2.r)
            connect(And1.y, RS2.s)
            connect(clk, And2.x[3])
            connect(clk, And1.x[1])
            connect(k, And2.x[2])
            connect(And4.y, RS1.r)
            connect(And3.y, RS1.s)
            connect(RS2.qn, And4.x[2])
            connect(RS2.q, And3.x[2])
            connect(clk, Not1.x)
            connect(Not1.y, And3.x[1])
            connect(Not1.y, And4.x[1])
            connect(j, And1.x[2])
            connect(RS1.q, And2.x[1])
            connect(RS1.qn, And1.x[3])
          connect(RS1.qn, q)
          connect(RS1.q, qn)
        end JKFF;

                  model HalfAdder "Half adder"
                    import L = Modelica.Electrical.Digital.Interfaces.Logic;
                    parameter Real delayTime=0 "Delay time";
                    Modelica.Electrical.Digital.Interfaces.DigitalInput b
                    Modelica.Electrical.Digital.Interfaces.DigitalOutput s
                    Modelica.Electrical.Digital.Interfaces.DigitalInput a
                    Modelica.Electrical.Digital.Interfaces.DigitalOutput c
                    Modelica.Electrical.Digital.Gates.AndGate AND(tLH=delayTime, tHL=delayTime, G2(y(start=L.'U',fixed=true)))
                    Modelica.Electrical.Digital.Gates.XorGate XOR(tLH=delayTime, tHL=delayTime, G2(y(start=L.'U', fixed=true)))

                  equation
                    connect(AND.y, c)
                    connect(XOR.y, s)
                    connect(b, AND.x[1])
                    connect(b, XOR.x[1])
                    connect(a, XOR.x[2])
                    connect(a, AND.x[2])
                  end HalfAdder;

        model FullAdder
        "Adding circuit for binary numbers with input carry bit"

          HalfAdder Adder2(delayTime=0.001)
          HalfAdder Adder1(delayTime=0.001)
          Modelica.Electrical.Digital.Interfaces.DigitalInput a
          Modelica.Electrical.Digital.Interfaces.DigitalInput b
          Modelica.Electrical.Digital.Interfaces.DigitalInput c_in
          Modelica.Electrical.Digital.Interfaces.DigitalOutput s
          Modelica.Electrical.Digital.Interfaces.DigitalOutput c_out
          Modelica.Electrical.Digital.Basic.Or OR
        equation

          connect(c_out, OR.y)
          connect(Adder2.c, OR.x[2])
          connect(Adder2.s, s)
            connect(Adder1.a, a)
            connect(b, Adder1.b)
            connect(Adder1.s, Adder2.a)
            connect(Adder1.c, OR.x[1])
            connect(c_in, Adder2.b)
        end FullAdder;

        model Adder "Generic N Bit Adder"
        import Modelica.Electrical.Digital;

          parameter Integer n=2 "Number of single adders";
          Modelica.Electrical.Digital.Examples.Utilities.FullAdder Adder[n]
          Modelica.Electrical.Digital.Interfaces.DigitalInput a[n]
          Modelica.Electrical.Digital.Interfaces.DigitalInput b[n]
          Modelica.Electrical.Digital.Interfaces.DigitalInput c_in
          Modelica.Electrical.Digital.Interfaces.DigitalOutput s[n]
          Modelica.Electrical.Digital.Interfaces.DigitalOutput c_out
        equation
          connect(c_in,Adder[1].c_in);
          for i in 1:n loop
            connect(a[i],Adder[i].a);
            connect(b[i],Adder[i].b);
            connect(Adder[i].a,s[i]);
            if i>1 then
              connect(Adder[i-1].c_out,Adder[i].c_in);
            end if;
          end for;
          connect(Adder[n].c_out,c_out);
        end Adder;

        model Counter3 "3 Bit Counter"
        import D = Modelica.Electrical.Digital;
        import L = Modelica.Electrical.Digital.Interfaces.Logic;

          D.Interfaces.DigitalInput enable
          D.Interfaces.DigitalOutput q2
          D.Interfaces.DigitalInput count
          D.Examples.Utilities.JKFF FF1
          D.Examples.Utilities.JKFF FF2
          D.Examples.Utilities.JKFF FF3
          D.Interfaces.DigitalOutput q1
          D.Interfaces.DigitalOutput q0
        equation
          connect(enable, FF1.j)
          connect(enable, FF1.k)
          connect(count, FF1.clk)
          connect(FF1.q, FF2.clk)
          connect(FF2.q, FF3.clk)
          connect(FF2.j, enable)
          connect(FF2.k, FF2.j)
          connect(FF3.k, FF3.j)
          connect(FF3.j, enable)
          connect(FF3.q, q2)
          connect(FF1.q, q0)
          connect(FF2.q, q1)
        end Counter3;

        model Counter "Generic N Bit Counter"
        import D = Modelica.Electrical.Digital;
        import L = Modelica.Electrical.Digital.Interfaces.Logic;

          parameter Integer n=3 "Number of bits";
          parameter SI.Time delayTime=0.001 "Delay of each JKFF";
          parameter D.Interfaces.Logic q0=L.'0' "Initial value";
          D.Interfaces.DigitalInput enable
          D.Interfaces.DigitalInput count
          D.Examples.Utilities.JKFF FF[n](each delayTime=delayTime,each q0=q0);
          D.Interfaces.DigitalOutput q[n]
        equation
          connect(enable,FF[1].j);
          connect(enable,FF[1].k);
          connect(count,FF[1].clk);
          connect(FF[1].q,q[1]);
          for i in 2:n loop
            connect(enable,FF[i].j);
            connect(enable,FF[i].k);
            connect(FF[i-1].q,FF[i].clk);
            connect(FF[i].q,q[i]);
          end for;
        end Counter;
      end Utilities;

      end Examples;

      package Interfaces "Basic definitions"
        extends Modelica.Icons.InterfacesPackage;

        type Logic = enumeration(
        'U' "U  Uninitialized",
        'X' "X  Forcing Unknown",
        '0' "0  Forcing 0",
        '1' "1  Forcing 1",
        'Z' "Z  High Impedance",
        'W' "W  Weak Unknown",
        'L' "L  Weak 0",
        'H' "H  Weak 1",
        '-' "-  Do not care") "Logic values and their coding according to IEEE 1164 STD_ULOGIC type"

        type UX01 = enumeration(
        'U' "U  Uninitialized",
        'X' "X  Forcing Unknown",
        '0' "0  Forcing 0",
        '1' "1  Forcing 1") "4-valued subtype of IEEE 1164 STD_ULOGIC type"
        type Strength = enumeration(
        'S_X01' "S_X01  Forcing X, 0 and 1",
        'S_X0H' "S_X0H  Forcing X, 0 and Weak 1",
        'S_XL1' "S_XL1  Forcing X, 1 and Weak 0",
        'S_X0Z' "S_X0Z  Forcing X, 0 and High Impedance",
        'S_XZ1' "S_XZ1  Forcing X, 1 and High Impedance",
        'S_WLH' "S_WLH  Weak X, 0 and 1",
        'S_WLZ' "S_WLZ  Weak X, 0 and High Impedance",
        'S_WZH' "S_WZH  Weak X, 1 and High Impedance",
        'S_W0H' "S_W0H  Weak X, 1 and Forcing 0",
        'S_WL1' "S_WL1  Weak X, 0 and Forcing 1") "Output strengths of registers"

        connector DigitalSignal = Logic "Digital port (both input/output possible)"

        connector DigitalInput = input DigitalSignal "Input DigitalSignal as connector"

        connector DigitalOutput = output DigitalSignal "Output DigitalSignal as connector"

        partial block SISO "Single input, single output"
      import D = Modelica.Electrical.Digital;
          D.Interfaces.DigitalInput x "Connector of Digital input signal"
          D.Interfaces.DigitalOutput y "Connector of Digital output signal"
        end SISO;

        partial block MISO "Multiple input - single output"
      import D = Modelica.Electrical.Digital;

          parameter Integer n(final min=2) = 2 "Number of inputs";
          D.Interfaces.DigitalInput x[n]
        "Connector of Digital input signal vector"
          D.Interfaces.DigitalOutput y "Connector of Digital output signal"
        end MISO;

        partial block MIMO "Multiple input - multiple output"
      import D = Modelica.Electrical.Digital;

          parameter Integer n(final min=1) = 1
        "Number of inputs = Number of outputs";
          D.Interfaces.DigitalInput x[n]
        "Connector of Digital input signal vector"
          D.Interfaces.DigitalOutput y[n]
        "Connector of Digital output signal vector"
        end MIMO;

        partial model MemoryBase "Base model for memory elements"
              import D = Modelica.Electrical.Digital;
              import L = Modelica.Electrical.Digital.Interfaces.Logic;
              import S = Modelica.Electrical.Digital.Interfaces.Strength;
              import T = Modelica.Electrical.Digital.Tables;

              parameter SI.Time tHL=0 "High->Low delay";
              parameter SI.Time tLH=0 "Low->High delay";
              parameter S strength = S.'S_X01' "Output strength";
              parameter Integer n_addr(min=1) = 2 "Addr width";
              parameter Integer n_data(min=1) = 2 "Data width";
              parameter String fileName = Modelica.Utilities.Files.loadResource("modelica://Modelica/Resources/Data/Electrical/Digital/Memory_Matrix.txt")
                "File where matrix for memory is stored"

              DigitalInput RE "Read enable"
              DigitalInput addr[n_addr] "Address"
              DigitalOutput dataOut[n_data] "Data output"

              function getMemory "Get Memory"
                extends Modelica.Icons.Function;
                input String filename;
                input Integer n_addr "Addr width";
                input Integer n_data "Data width";
                output L m[integer(2^n_addr),n_data] "Memory with data, lowest bit on left side";
                output String data;
                output Integer bit;
              algorithm
                for i in 1:(2^n_addr) loop
                  data := Modelica.Utilities.Streams.readLine(filename, integer(i));
                  for j in 1:n_data loop
                    bit := Modelica.Utilities.Strings.scanInteger(data, (2*j-1));
                    if bit == 1 then
                      m[integer(i),j] := L.'1';
                    elseif bit == 0 then
                      m[integer(i),j] := L.'0';
                    else
                      m[integer(i),j] := L.'X';
                    end if;
                  end for;
                end for;
              end getMemory;

    protected
              L nextstate[n_data](start=fill(L.'U',n_data));
              L mem_word[n_data](start=fill(L.'U',n_data));
              Integer int_addr;
              DigitalOutput yy[n_data](start=fill(L.'U',n_data));
              D.Delay.InertialDelaySensitive inertialDelaySensitive[n_data](each tLH=tLH, each tHL=tHL);

              function address "Compute memory address"
                extends Modelica.Icons.Function;
                input Integer n_addr;
                input L addr[n_addr];
                output Integer int_addr;
      protected
                L addr_bit;
              algorithm
                int_addr := 1;
                for i in 1:n_addr loop
                  addr_bit := T.X01Table[addr[i]];
                  if addr_bit == L.'1' then
                     int_addr := int_addr + integer(2^(i-1));
                  elseif addr_bit == L.'X' then
                     int_addr := 0;
                     break;
                  end if;
                end for;
              end address;

        equation
              for i in 1:n_data loop
                connect(yy[i], inertialDelaySensitive[i].x);
                connect(inertialDelaySensitive[i].y, dataOut[i]);
              end for;
        end MemoryBase;
      end Interfaces;

  package Tables "Truth tables for all components of package Digital"
    extends Modelica.Icons.Package;

    import D = Modelica.Electrical.Digital;
    import L = Modelica.Electrical.Digital.Interfaces.Logic;
    import R = Modelica.Electrical.Digital.Interfaces.UX01;
    import S = Modelica.Electrical.Digital.Interfaces.Strength;

    constant D.Interfaces.Logic AndTable[L, L]=[
        L.'U', L.'U', L.'0', L.'U', L.'U', L.'U', L.'0', L.'U', L.'U';
        L.'U', L.'X', L.'0', L.'X', L.'X', L.'X', L.'0', L.'X', L.'X';
        L.'0', L.'0', L.'0', L.'0', L.'0', L.'0', L.'0', L.'0', L.'0';
        L.'U', L.'X', L.'0', L.'1', L.'X', L.'X', L.'0', L.'1', L.'X';
        L.'U', L.'X', L.'0', L.'X', L.'X', L.'X', L.'0', L.'X', L.'X';
        L.'U', L.'X', L.'0', L.'X', L.'X', L.'X', L.'0', L.'X', L.'X';
        L.'0', L.'0', L.'0', L.'0', L.'0', L.'0', L.'0', L.'0', L.'0';
        L.'U', L.'X', L.'0', L.'1', L.'X', L.'X', L.'0', L.'1', L.'X';
        L.'U', L.'X', L.'0', L.'X', L.'X', L.'X', L.'0', L.'X', L.'X']
      "9-value logic for 'and'";

    constant D.Interfaces.Logic OrTable[L, L]=[
        L.'U', L.'U', L.'U', L.'1', L.'U', L.'U', L.'U', L.'1', L.'U';
        L.'U', L.'X', L.'X', L.'1', L.'X', L.'X', L.'X', L.'1', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'X', L.'X', L.'0', L.'1', L.'X';
        L.'1', L.'1', L.'1', L.'1', L.'1', L.'1', L.'1', L.'1', L.'1';
        L.'U', L.'X', L.'X', L.'1', L.'X', L.'X', L.'X', L.'1', L.'X';
        L.'U', L.'X', L.'X', L.'1', L.'X', L.'X', L.'X', L.'1', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'X', L.'X', L.'0', L.'1', L.'X';
        L.'1', L.'1', L.'1', L.'1', L.'1', L.'1', L.'1', L.'1', L.'1';
        L.'U', L.'X', L.'X', L.'1', L.'X', L.'X', L.'X', L.'1', L.'X']
      "9-value logic for 'or'";

    constant D.Interfaces.Logic NotTable[L]={
        L.'U',L.'X',L.'1',L.'0',L.'X',L.'X',L.'1',L.'0',L.'X'}
      "9-value logic for 'not'";

    constant D.Interfaces.Logic XorTable[L, L]=[
        L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'X', L.'X', L.'0', L.'1', L.'X';
        L.'U', L.'X', L.'1', L.'0', L.'X', L.'X', L.'1', L.'0', L.'X';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'X', L.'X', L.'0', L.'1', L.'X';
        L.'U', L.'X', L.'1', L.'0', L.'X', L.'X', L.'1', L.'0', L.'X';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X']
      "9-value logic for 'xor'";

    constant D.Interfaces.Logic ResolutionTable[L, L]=[
        L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'U', L.'X', L.'0', L.'X', L.'0', L.'0', L.'0', L.'0', L.'X';
        L.'U', L.'X', L.'X', L.'1', L.'1', L.'1', L.'1', L.'1', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'Z', L.'W', L.'L', L.'H', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'W', L.'W', L.'W', L.'W', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'L', L.'W', L.'L', L.'W', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'H', L.'W', L.'W', L.'H', L.'X';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X']
      "9-value logic for 'wiredX'";
    constant D.Interfaces.Logic X01Table[L]={
        L.'X',L.'X',L.'0',L.'1',L.'X',L.'X',L.'0',L.'1',L.'X'};

    constant D.Interfaces.Logic X01ZTable[L]={
        L.'X',L.'X',L.'0',L.'1',L.'Z',L.'X',L.'0',L.'1',L.'Z'};

    constant D.Interfaces.Logic UX01Table[L]={
        L.'U',L.'X',L.'0',L.'1',L.'X',L.'X',L.'0',L.'1',L.'X'};

    constant D.Interfaces.UX01 UX01Conv[L]={
        R.'U',R.'X',R.'0',R.'1',R.'X',R.'X',R.'0',R.'1',R.'X'};

    constant Integer DelayTable[L, L]=[
         0,  0, -1,  1,  0,  0, -1,  1,  0;
         0,  0, -1,  1,  0,  0, -1,  1,  0;
         1,  1,  0,  1,  1,  1,  0,  1,  1;
        -1, -1, -1,  0, -1, -1, -1,  0, -1;
         0,  0, -1,  1,  0,  0, -1,  1,  0;
         0,  0, -1,  1,  0,  0, -1,  1,  0;
         1,  1,  0,  1,  1,  1,  0,  1,  1;
        -1, -1, -1,  0, -1, -1, -1,  0, -1;
         0,  0, -1,  1,  0,  0, -1,  1,  0] "Delay selection for signal change by [old_signal, new_signal] reading:
      -1: High-Low delay |
       0: no delay |
       1: Low-High delay";

    constant Integer ClockMap[L, L]=[
        0, 0, 0, 2, 0, 0, 0, 2, 0;
        0, 0, 0, 2, 0, 0, 0, 2, 0;
        2, 2, 0, 1, 2, 2, 0, 1, 2;
        0, 0, 0, 0, 0, 0, 0, 0, 0;
        0, 0, 0, 2, 0, 0, 0, 2, 0;
        0, 0, 0, 2, 0, 0, 0, 2, 0;
        2, 2, 0, 1, 2, 2, 0, 1, 0;
        0, 0, 0, 0, 0, 0, 0, 0, 0;
        0, 0, 0, 2, 0, 0, 0, 2, 0] "Edge detection by [pre(clock), clock] reading:
    0: 0-Transition |
    1: rising edge  |
    2: X-Transition";

    constant D.Interfaces.Logic StrengthMap[L, S]=
        [L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U';
         L.'X', L.'X', L.'X', L.'X', L.'X', L.'W', L.'W', L.'W', L.'W', L.'W';
         L.'0', L.'0', L.'L', L.'0', L.'Z', L.'L', L.'L', L.'Z', L.'0', L.'L';
         L.'1', L.'H', L.'1', L.'Z', L.'1', L.'H', L.'Z', L.'H', L.'H', L.'1';
         L.'X', L.'X', L.'X', L.'X', L.'X', L.'W', L.'W', L.'W', L.'W', L.'W';
         L.'X', L.'X', L.'X', L.'X', L.'X', L.'W', L.'W', L.'W', L.'W', L.'W';
         L.'0', L.'0', L.'L', L.'0', L.'Z', L.'L', L.'L', L.'Z', L.'0', L.'L';
         L.'1', L.'H', L.'1', L.'Z', L.'1', L.'H', L.'Z', L.'H', L.'H', L.'1';
         L.'X', L.'X', L.'X', L.'X', L.'X', L.'W', L.'W', L.'W', L.'W', L.'W']
      "Output strength conversion by [signal, strength] reading";

    constant D.Interfaces.Logic NXferTable[L, L]=[
        L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z';
        L.'U', L.'X', L.'0', L.'1', L.'Z', L.'W', L.'L', L.'H', L.'X';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z';
        L.'U', L.'X', L.'0', L.'1', L.'Z', L.'W', L.'L', L.'H', L.'X';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X']
      "NX Transfer by [enable, input] reading";

    constant D.Interfaces.Logic NRXferTable[L, L]=[
        L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U';
        L.'U', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W';
        L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z';
        L.'U', L.'W', L.'L', L.'H', L.'Z', L.'W', L.'L', L.'H', L.'W';
        L.'U', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W';
        L.'U', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W';
        L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z';
        L.'U', L.'W', L.'L', L.'H', L.'Z', L.'W', L.'L', L.'H', L.'W';
        L.'U', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W']
      "NRX Transfer by [enable, input] reading";

    constant D.Interfaces.Logic PXferTable[L, L]=[
        L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'Z', L.'W', L.'L', L.'H', L.'X';
        L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X';
        L.'U', L.'X', L.'0', L.'1', L.'Z', L.'W', L.'L', L.'H', L.'X';
        L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z';
        L.'U', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X', L.'X']
      "PX Transfer by [enable, input] reading";

    constant D.Interfaces.Logic PRXferTable[L, L]=[
        L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U', L.'U';
        L.'U', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W';
        L.'U', L.'W', L.'L', L.'H', L.'Z', L.'W', L.'L', L.'H', L.'W';
        L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z';
        L.'U', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W';
        L.'U', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W';
        L.'U', L.'W', L.'L', L.'H', L.'Z', L.'W', L.'L', L.'H', L.'W';
        L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z', L.'Z';
        L.'U', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W', L.'W']
      "PRX Transfer by [enable, input] reading";

    constant D.Interfaces.Logic Buf3sTable[S, R, R]=[
        {{{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'X',L.'X',L.'X'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'X',L.'0',L.'1'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'X',L.'X',L.'X'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'X',L.'0',L.'H'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'X',L.'X',L.'X'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'X',L.'L',L.'1'}},
         {{L.'U',L.'U',L.'U',L.'Z'},{L.'U',L.'X',L.'X',L.'Z'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'X',L.'0',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'X',L.'X',L.'X'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'X',L.'Z',L.'1'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'W'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'W',L.'L',L.'H'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'Z'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'W',L.'L',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'W'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'W',L.'Z',L.'H'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'W'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'W',L.'0',L.'H'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'W'},{L.'Z',L.'Z',L.'Z',L.'Z'},{L.'U',L.'W',L.'L',L.'1'}}}]
      "Tristate Table by [strength, enable, input] reading, high-active enable";

    constant D.Interfaces.Logic Buf3slTable[S, R, R]=[
        {{{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'X',L.'X',L.'X'},{L.'U',L.'X',L.'0',L.'1'},{L.'Z',L.'Z',L.'Z',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'X',L.'X',L.'X'},{L.'U',L.'X',L.'0',L.'H'},{L.'Z',L.'Z',L.'Z',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'X',L.'X',L.'X'},{L.'U',L.'X',L.'L',L.'1'},{L.'Z',L.'Z',L.'Z',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'Z'},{L.'U',L.'X',L.'X',L.'Z'},{L.'U',L.'X',L.'0',L.'Z'},{L.'Z',L.'Z',L.'Z',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'X',L.'X',L.'X'},{L.'U',L.'X',L.'Z',L.'1'},{L.'Z',L.'Z',L.'Z',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'W'},{L.'U',L.'W',L.'L',L.'H'},{L.'Z',L.'Z',L.'Z',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'Z'},{L.'U',L.'W',L.'L',L.'Z'},{L.'Z',L.'Z',L.'Z',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'W'},{L.'U',L.'W',L.'Z',L.'H'},{L.'Z',L.'Z',L.'Z',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'W'},{L.'U',L.'W',L.'0',L.'H'},{L.'Z',L.'Z',L.'Z',L.'Z'}},
         {{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'W',L.'W',L.'W'},{L.'U',L.'W',L.'L',L.'1'},{L.'Z',L.'Z',L.'Z',L.'Z'}}}]
      "Tristate Table by [strength, enable, input] reading, low-active enable";

    constant D.Interfaces.Logic MUX2x1Table[R, R, R]=[
        {{{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'U',L.'U',L.'U'},{L.'U',L.'X',L.'0',L.'1'},{L.'U',L.'U',L.'U',L.'U'}},
         {{L.'U',L.'X',L.'U',L.'U'},{L.'U',L.'X',L.'X',L.'X'},{L.'U',L.'X',L.'0',L.'1'},{L.'X',L.'X',L.'X',L.'X'}},
         {{L.'U',L.'U',L.'0',L.'U'},{L.'U',L.'X',L.'0',L.'X'},{L.'U',L.'X',L.'0',L.'1'},{L.'0',L.'0',L.'0',L.'0'}},
         {{L.'U',L.'U',L.'U',L.'1'},{L.'U',L.'X',L.'X',L.'1'},{L.'U',L.'X',L.'0',L.'1'},{L.'1',L.'1',L.'1',L.'1'}}}]
      "Multiplexer Table by [select, input1, input0] reading";
  end Tables;

      package Delay "Delay blocks"
        extends Modelica.Icons.Package;

        partial block DelayParams "Definition of delay parameters"
      import L = Modelica.Electrical.Digital.Interfaces.Logic;
          parameter SI.Time tLH(start=0) "Rise inertial delay";
          parameter SI.Time tHL(start=0) "Fall inertial delay";
          parameter L y0=L.'U' "Initial value of output";
        end DelayParams;

        model TransportDelay "Transport delay with initial parameter"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.SISO(x(start=L.'U',fixed=true));
          parameter SI.Time delayTime(start=0) "Delay time";
          parameter D.Interfaces.Logic y0=L.'U' "Initial value of output";
          constant D.Interfaces.Logic LogicValues[:]=L.'U':L.'-';
    protected
          D.Interfaces.Logic x_delayed;
          Real xr "Auxiliary variable of type Real to use in delay()";

        equation
          xr = Integer(pre(x));
          x_delayed = LogicValues[integer(delay(xr, delayTime))];
          y = if delayTime > 0 then
                   (if time >= delayTime then x_delayed else y0) else
                     pre(x);
        end TransportDelay;

        block InertialDelay "Inertial delay with initial parameter"
      import D = Modelica.Electrical.Digital;
      import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.SISO;
          parameter SI.Time delayTime(start=0)
        "Minimum time to hold value";
          parameter D.Interfaces.Logic y0=L.'U' "Initial value of output y";
    protected
          D.Interfaces.Logic y_auxiliary(start=y0, fixed=true);
          D.Interfaces.Logic x_old(start=y0, fixed=true);
          discrete SI.Time t_next(start=delayTime, fixed=true);

        algorithm
          when delayTime > 0 and change(x) then
            x_old := x;
            t_next := time + delayTime;
          elsewhen time >= t_next then
            y_auxiliary := x;
          end when;
          y := if delayTime > 0 then y_auxiliary else x;
        end InertialDelay;

        model InertialDelaySensitive "Provide the input as output if it holds its value for a specific amount of time"

          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.SISO(x(start=L.'U',fixed=true),y(start=y0, fixed=true));
          parameter SI.Time tLH(start=0) "Rise inertial delay";
          parameter SI.Time tHL(start=0) "Fall inertial delay";
          parameter D.Interfaces.Logic y0=L.'U' "Initial value of output";
    protected
          constant Integer delayTable[L,L]=Modelica.Electrical.Digital.Tables.DelayTable
        "Specification of delay according to signal change";
          SI.Time delayTime;
          D.Interfaces.Logic y_auxiliary(start=y0, fixed=true);
          D.Interfaces.Logic y_old(start=y0, fixed=true);
          Integer lh;
          discrete SI.Time t_next;

        algorithm
          when {initial(),(tLH > 0 or tHL > 0) and change(x) and not initial()} then
            y_old := if initial() or pre(y) == L.'U' then y0 else pre(y);
            lh := delayTable[y_old, x];
            delayTime := if (lh > 0) then tLH else (if (lh < 0) then tHL else 0);
            t_next := time + delayTime;
            if (lh == 0 or abs(delayTime) < Modelica.Constants.small) then
              y_auxiliary := x;
            end if;
         elsewhen time >= t_next then
            y_auxiliary := x;
         end when;
         y := if ((tLH > 0 or tHL > 0)) then y_auxiliary else x;
        end InertialDelaySensitive;

        model InertialDelaySensitiveVector "Delay of a vector of digital signals"
      import D = Modelica.Electrical.Digital;
      import L = Modelica.Electrical.Digital.Interfaces.Logic;
      import S = Modelica.Electrical.Digital.Interfaces.Strength;
      import T = Modelica.Electrical.Digital.Tables;
          parameter SI.Time tHL=0 "High->Low delay";
          parameter SI.Time tLH=0 "Low->High delay";
          parameter Integer n(min=1) = 1 "Data width";
          D.Interfaces.DigitalInput x[n]
          D.Interfaces.DigitalOutput y[n]
          Digital.Delay.InertialDelaySensitive inertialDelaySensitive[n](each tLH=
                tLH, each tHL=tHL);
        equation
          for i in 1:n loop
            connect(x[i], inertialDelaySensitive[i].x);
            connect(inertialDelaySensitive[i].y, y[i]);
          end for;
        end InertialDelaySensitiveVector;
      end Delay;

      package Basic "Basic logic blocks without delays"
        extends Modelica.Icons.Package;

        model Not "Not logic component without delay"
      import D = Modelica.Electrical.Digital;
      import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.SISO;
    protected
          D.Interfaces.Logic auxiliary(start=L.'0', fixed=true);
        equation
          auxiliary =Modelica.Electrical.Digital.Tables.NotTable[x];
          y = pre(auxiliary);
        end Not;

        model And "And logic component with multiple input and one output"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.MISO;
    protected
          D.Interfaces.Logic auxiliary[n](each start=L.'U');
          D.Interfaces.Logic auxiliary_n( start=L.'U', fixed=true);
        equation
          auxiliary[1] = x[1];
          for i in 1:n - 1 loop
            auxiliary[i + 1] =Modelica.Electrical.Digital.Tables.AndTable[
          auxiliary[i], x[i + 1]];
          end for;
          auxiliary_n = auxiliary[n];
          y = pre(auxiliary_n);
        end And;

        model Nand "Nand logic component with multiple input and one output"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.MISO;
    protected
          D.Interfaces.Logic auxiliary[n](each start=L.'U');
          D.Interfaces.Logic auxiliary_n( start=L.'U', fixed=true);
        equation
          auxiliary[1] = x[1];
          for i in 1:n - 1 loop
            auxiliary[i + 1] =Modelica.Electrical.Digital.Tables.AndTable[
          auxiliary[i], x[i + 1]];
          end for;
          auxiliary_n = Modelica.Electrical.Digital.Tables.NotTable[auxiliary[n]];
          y = pre(auxiliary_n);
        end Nand;

        model Or "Or logic component with multiple input and one output"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.MISO;
    protected
          D.Interfaces.Logic auxiliary[n](each start=L.'U');
          D.Interfaces.Logic auxiliary_n( start=L.'U', fixed=true);
        equation
          auxiliary[1] = x[1];
          for i in 1:n - 1 loop
            auxiliary[i + 1] =Modelica.Electrical.Digital.Tables.OrTable[
          auxiliary[i], x[i + 1]];
          end for;
          auxiliary_n = auxiliary[n];
          y = pre(auxiliary_n);
        end Or;

        model Nor "Nor logic component with multiple input and one output"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.MISO;
        //  D.Interfaces.Logic auxiliary[n](each start=L.'U', each fixed=true);
    protected
          D.Interfaces.Logic auxiliary[n](each start=L.'U');
          D.Interfaces.Logic auxiliary_n( start=L.'U', fixed=true);
        equation
          auxiliary[1] = x[1];
          for i in 1:n - 1 loop
            auxiliary[i + 1] =Modelica.Electrical.Digital.Tables.OrTable[
          auxiliary[i], x[i + 1]];
          end for;
          auxiliary_n = Modelica.Electrical.Digital.Tables.NotTable[auxiliary[n]];
          y = pre(auxiliary_n);
        end Nor;

        model Xor "Xor logic component with multiple input and one output"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.MISO;
    protected
          D.Interfaces.Logic auxiliary[n](each start=L.'U');
          D.Interfaces.Logic auxiliary_n( start=L.'U', fixed=true);
        equation
          auxiliary[1] = x[1];
          for i in 1:n - 1 loop
            auxiliary[i + 1] =Modelica.Electrical.Digital.Tables.XorTable[
          auxiliary[i], x[i + 1]];
          end for;
          auxiliary_n = auxiliary[n];
          y = pre(auxiliary_n);
        end Xor;

        model Xnor "Xnor logic component with multiple input and one output"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          extends D.Interfaces.MISO;
    protected
          D.Interfaces.Logic auxiliary[n](each start=L.'U');
          D.Interfaces.Logic auxiliary_n( start=L.'U', fixed=true);
        equation
          auxiliary[1] = x[1];
          for i in 1:n - 1 loop
            auxiliary[i + 1] =Modelica.Electrical.Digital.Tables.XorTable[
          auxiliary[i], x[i + 1]];
          end for;
          auxiliary_n = Modelica.Electrical.Digital.Tables.NotTable[auxiliary[n]];
          y = pre(auxiliary_n);
        end Xnor;
      end Basic;

      package Gates "Logic gates including delays"
        extends Modelica.Icons.Package;

        model InvGate "InvGate with 1 input value, composed by Not and sensitive inertial delay"
      import D = Modelica.Electrical.Digital;
          extends D.Delay.DelayParams;
          extends D.Interfaces.SISO;
          D.Basic.Not G1
          D.Delay.InertialDelaySensitive G2(tLH=tLH, tHL=tHL)
        equation
          connect(G2.y, y)
          connect(G1.x, x)
          connect(G1.y, G2.x)
        end InvGate;

        model AndGate "AndGate with multiple input"
      import D = Modelica.Electrical.Digital;
          extends D.Interfaces.MISO;
          extends D.Delay.DelayParams;
          D.Basic.And G1(final n=n)
          D.Delay.InertialDelaySensitive G2(
            tLH=tLH,
            tHL=tHL,
            y0=y0)
        equation
          connect(x, G1.x)
          connect(y, G2.y)
          connect(G1.y, G2.x)
        end AndGate;

        model NandGate "NandGate with multiple input"
      import D = Modelica.Electrical.Digital;
          extends D.Delay.DelayParams;
          extends D.Interfaces.MISO;
          D.Basic.Nand G1(final n=n)
          D.Delay.InertialDelaySensitive G2(
            tLH=tLH,
            tHL=tHL,
            y0=y0)
        equation
          connect(x, G1.x)
          connect(G1.y, G2.x)
          connect(G2.y, y)
        end NandGate;

        model OrGate "OrGate with multiple input"
      import D = Modelica.Electrical.Digital;
          extends D.Delay.DelayParams;
          extends D.Interfaces.MISO;
          D.Basic.Or G1(final n=n)
          D.Delay.InertialDelaySensitive G2(
            tLH=tLH,
            tHL=tHL,
            y0=y0)
        equation
          connect(G1.y, G2.x)
          connect(x,G1. x)
          connect(y, G2.y)
        end OrGate;

        model NorGate "NorGate with multiple input"
      import D = Modelica.Electrical.Digital;
          extends D.Delay.DelayParams;
          extends D.Interfaces.MISO;
          D.Basic.Nor G1(final n=n)
          D.Delay.InertialDelaySensitive G2(
            tLH=tLH,
            tHL=tHL,
            y0=y0)
        equation
          connect(G1.y, G2.x)
          connect(x, G1.x)
          connect(y, G2.y)
        end NorGate;

        model XorGate "XorGate with multiple input"
      import D = Modelica.Electrical.Digital;
          extends D.Delay.DelayParams;
          extends D.Interfaces.MISO;
          D.Basic.Xor G1(final n=n)
          D.Delay.InertialDelaySensitive G2(
            tLH=tLH,
            tHL=tHL,
            y0=y0)
        equation
          connect(x, G1.x)
          connect(G1.y, G2.x)
          connect(G2.y, y)
        end XorGate;

        model XnorGate "XnorGate with multiple input"
      import D = Modelica.Electrical.Digital;
          extends D.Delay.DelayParams;
          extends D.Interfaces.MISO;
          D.Basic.Xnor G1(final n=n)
          D.Delay.InertialDelaySensitive G2(
            tLH=tLH,
            tHL=tHL,
            y0=y0)
        equation
          connect(x, G1.x)
          connect(G2.y, y)
          connect(G1.y, G2.x)
        end XnorGate;

        model BufGate "BufGate with 1 input value, composed by Not and sensitive inertial delay"
      import D = Modelica.Electrical.Digital;
          extends D.Delay.DelayParams;
          extends D.Interfaces.SISO;
          D.Delay.InertialDelaySensitive G1(tLH=tLH, tHL=tHL)
        equation
          connect(G1.y, y)
          connect(G1.x, x)
        end BufGate;
      end Gates;

      package Sources "Time-dependent digital signal sources"
        extends Modelica.Icons.SourcesPackage;

        block Set "Digital Set Source"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          parameter D.Interfaces.Logic x(start=L.'1') "Logic value to be set";
          D.Interfaces.DigitalOutput y
        algorithm
          y := x;
        end Set;

        block Step "Digital Step Source"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          parameter D.Interfaces.Logic before(start=L.'0')
        "Logic value before step";
          parameter D.Interfaces.Logic after(start=L.'1')
        "Logic value after step";
          parameter Real stepTime(start=1) "Step time";
          D.Interfaces.DigitalOutput y
        algorithm
          // assert(before >= L.min and before <= L.max, "Parameter is no logic value");
          // assert(after >= L.min and after <= L.max, "Parameter is no logic value");
          if time >= stepTime then
            y := after;
          else
            y := before;
          end if;
        end Step;

        block Table "Digital Tabular Source"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          parameter D.Interfaces.Logic x[:]={L.'1'} "Vector of values";
          parameter Real t[size(x, 1)]={1}
        "Vector of corresponding time points";
          parameter D.Interfaces.Logic y0=L.'U' "Initial output value";
          final parameter Integer n=size(x, 1) "Table size";
          D.Interfaces.DigitalOutput y
        algorithm
          if initial() then
            // assert(y0 >= L.min and y0 <= L.max, "Parameter y0 is not of type Logic");
            assert(n > 0, "Invalid size of table (n < 1)");
            for i in 1:n loop
              // assert(x[i] >= L.min and x[i] <= L.max, "Table element is not of type Logic");
            end for;
          end if;
          y := y0;
          for i in 1:n loop
            if time >= t[i] then
              y := x[i];
            end if;
          end for;
        end Table;

        model Pulse "Digital Pulse Source"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          parameter Real width(
            final min=Modelica.Constants.small,
            final max=100, start=50) "Widths of pulses in % of periods";
          parameter SI.Time period(final min=Modelica.Constants.small, start=1)
        "Time for one period";
          parameter SI.Time startTime(start=0)
        "Output = quiet for time < startTime";
          parameter D.Interfaces.Logic pulse(start=L.'0') "Pulsed value";
          parameter D.Interfaces.Logic quiet(start=L.'1') "Quiet value";
          SI.Time T0(final start=startTime, fixed=true)
        "Start time of current period";
          parameter Integer nperiod(start=-1)
        "Number of periods (< 0 means infinite number of periods)";
          Integer np(start=0, fixed=true);
          D.Interfaces.DigitalOutput y
    protected
          Boolean sampling;

        equation
          sampling = nperiod <> 0 and (nperiod >= pre(np) or nperiod < 0);

          when sampling and sample(startTime, period) then
             T0 = time;
             np = if nperiod > 0 then pre(np) + 1 else pre(np);
          end when;

          if sampling then
             y = if time < startTime or time >= T0 + ((width*period)/100) then quiet else pulse;
          else
             y = quiet;
          end if;
        end Pulse;

        model DigitalClock "Digital Clock Source"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          parameter SI.Time startTime(start=0)
        "Output = offset for time < startTime";
          parameter SI.Time period(
            final min=Modelica.Constants.small, start=1) "Time for one period";
          parameter Real width(
            final min=Modelica.Constants.small,
            final max=100, start=50) "Width of pulses in % of period";
          D.Interfaces.DigitalOutput y "Connector of Digital output signal"
    protected
          SI.Time t_i(final start=startTime, fixed=true)
        "Start time of current period";
          SI.Time t_width=period*width/100;
        equation
          when sample(startTime, period) then
            t_i =  time;
          end when;
          y =  if (not time>=startTime) or time >= t_i + t_width then L.'0' else L.'1';
        end DigitalClock;
      end Sources;

      package Converters "Converters between 2-,3-,4- and 9-valued logic"
        extends Modelica.Icons.Package;

        block LogicToX01 "Conversion to X01"
          import D = Modelica.Electrical.Digital;
          import T = Modelica.Electrical.Digital.Tables;
          D.Interfaces.DigitalInput x[n]
          D.Interfaces.DigitalOutput y[n]
          parameter Integer n(final min=1, start=1) "Signal width";
        algorithm
          for i in 1:n loop
            y[i] := T.X01Table[x[i]];
          end for;
        end LogicToX01;

        block LogicToX01Z "Conversion to X01Z"
          import D = Modelica.Electrical.Digital;
          import T = Modelica.Electrical.Digital.Tables;
          D.Interfaces.DigitalInput x[n]
          D.Interfaces.DigitalOutput y[n]
          parameter Integer n(final min=1, start=1) "Signal width";
        algorithm
          for i in 1:n loop
            y[i] := T.X01ZTable[x[i]];
          end for;
        end LogicToX01Z;

        block LogicToUX01 "Conversion to UX01"
          import D = Modelica.Electrical.Digital;
          import T = Modelica.Electrical.Digital.Tables;
          D.Interfaces.DigitalInput x[n]
          D.Interfaces.DigitalOutput y[n]
          parameter Integer n(final min=1, start=1) "Signal width";
        algorithm
          for i in 1:n loop
            y[i] := T.UX01Table[x[i]];
          end for;
        end LogicToUX01;

        block BooleanToLogic "Boolean to Logic converter"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          Modelica.Blocks.Interfaces.BooleanInput x[n]
          parameter Integer n(final min=1, start=1) "Signal width";
          Modelica.Electrical.Digital.Interfaces.DigitalOutput y[n]
        equation
          for i in 1:n loop
            y[i] = if x[i] then L.'1' else L.'0';
          end for;
        end BooleanToLogic;

        block LogicToBoolean "Logic to Boolean converter"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          Modelica.Electrical.Digital.Interfaces.DigitalInput x[n]
          Modelica.Blocks.Interfaces.BooleanOutput y[n]
          parameter Integer n(final min=1, start=2) "Signal width";
        equation
          for i in 1:n loop
            y[i] = (x[i] == L.'1' or x[i] == L.'H');
          end for;
        end LogicToBoolean;

        block RealToLogic "Real to Logic converter"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          Modelica.Blocks.Interfaces.RealInput x[n]
          Digital.Interfaces.DigitalOutput y[n]
          parameter Integer n(final min=1, start=1) "Signal width";
          parameter Real upper_limit(start=1) "Upper limit";
          parameter Real lower_limit(start=0) "Lower limit";
          parameter L upper_value(start=L.'1') "Output if input > upper_limit";
          parameter L lower_value(start=L.'0') "Output if input < lower_limit";
          parameter L middle_value(start=L.'X') "Output else";
        equation
          for i in 1:n loop
            y[i] = if x[i] > upper_limit then upper_value else
              if x[i] < lower_limit then lower_value else middle_value;
          end for;
        end RealToLogic;

        block LogicToReal "Logic to Real converter"
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          Modelica.Electrical.Digital.Interfaces.DigitalInput x[n]
          Modelica.Blocks.Interfaces.RealOutput y[n]
          parameter Integer n(final min=1, start=1) "Signal width";
          parameter Real value_U(start=0.5)
        "Value for digital U (uninitialized)";
          parameter Real value_X(start=0.5)
        "Value for digital X (Forcing Unknown)";
          parameter Real value_0(start=0) "Value for digital 0 (Forcing 0)";
          parameter Real value_1(start=1) "Value for digital 1 (Forcing 1)";
          parameter Real value_Z(start=0.5)
        "Value for digital Z (High Impedance)";
          parameter Real value_W(start=0.5)
        "Value for digital W (Weak    Unknown)";
          parameter Real value_L(start=0) "Value for digital L (Weak 0)";
          parameter Real value_H(start=1) "Value for digital H (Weak 1)";
          parameter Real value_m(start=0.5) "Value for digital m (Do not care)";
        equation
          for i in 1:n loop
           y[i]= if x[i] == L.'U' then value_U else
                    if x[i] == L.'X' then value_X else if
              x[i] == L.'0' then value_0 else if x[i] == L.'1' then
                   value_1 else if x[i] == L.
              'Z' then value_Z else if x[i] == L.'W' then value_W else
                    if x[i] == L.'L' then value_L else if
              x[i] == L.'H' then value_H else value_m;
          end for;
        end LogicToReal;
      end Converters;

      package Registers "Registers with N-bit input data and output data"
        extends Modelica.Icons.Package;

        model DFFR "Edge triggered register bank with reset"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          import S = Modelica.Electrical.Digital.Interfaces.Strength;
          import T = Modelica.Electrical.Digital.Tables;
          parameter Integer ResetMap[L] = {1, 4, 3, 2, 4, 4, 3, 2, 4}
        "Function selection, defaults for high active reset";
          parameter D.Interfaces.Strength strength = S.'S_X01'
        "Output strength";
          parameter Integer n(min=1) = 1 "Data width";

          D.Interfaces.DigitalInput reset
          D.Interfaces.DigitalInput clock
          D.Interfaces.DigitalInput dataIn[n]
          D.Interfaces.DigitalOutput dataOut[n]
    protected
                  Integer clock_flag(start=0);
                    // 0: 0-Transition
                    // 1: rising edge
                    // 2: X-Transition

                   Integer reset_flag(start=1);
                    // 1: output := U
                    // 2: output := 0
                    // 3: output := -dataInUX
                    // 4: output := U-0X
    protected
                  D.Interfaces.Logic nextstate[n](start=fill(L.'U',n));
                  D.Interfaces.Logic next_assign_val[n](start=fill(L.'U',n));

        algorithm
        if change(clock) or change(reset) then

          if change(clock) then
            if initial() then
              clock_flag := T.ClockMap[L.'U',clock];
            else
              clock_flag := T.ClockMap[pre(clock),clock];
            end if;
          end if;

          reset_flag :=  ResetMap[reset];
          for i in 1:n loop
            if reset_flag == 1 then
              nextstate[i] := L.'U';
            elseif reset_flag == 2 then
              nextstate[i] := T.StrengthMap[L.'0', strength];
            elseif reset_flag == 3 then
              if clock_flag == 0 then
                break;
              elseif clock_flag == 1 then
                nextstate[i] := T.StrengthMap[dataIn[i], strength];
              else
                if (next_assign_val[i] == T.StrengthMap[dataIn[i], strength])
                  or (next_assign_val[i] == L.'U') then
                    break;
                elseif dataIn[i] == L.'U' then
                    nextstate[i] := L.'U';
                else
                    nextstate[i] := T.StrengthMap[L.'X', strength];
                end if;
              end if;
            elseif reset_flag == 4 then
              if (next_assign_val[i] == T.StrengthMap[L.'0', strength])
                and (dataIn[i] == L.'0' or dataIn[i] == L.'L' or clock_flag == 0) then
                  break;
              elseif (dataIn[i] == L.'0' or dataIn[i] == L.'L') and (clock_flag == 1) then
                  nextstate[i] := T.StrengthMap[L.'0', strength];
              elseif ((next_assign_val[i] == L.'U') and not (clock_flag == 1))
                or ((dataIn[i] == L.'U') and not (clock_flag == 0)) then
                  nextstate[i] := L.'U';
              else
                nextstate[i] := T.StrengthMap[L.'X', strength];
              end if;
            end if;
          end for;
        end if;
        next_assign_val := nextstate;
        dataOut := nextstate;
        end DFFR;

        model DFFREG "Edge triggered register bank with high active reset"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          import S = Modelica.Electrical.Digital.Interfaces.Strength;
          import T = Modelica.Electrical.Digital.Tables;
          parameter SI.Time tHL=0 "High->Low delay";
          parameter SI.Time tLH=0 "Low->High delay";
          parameter D.Interfaces.Strength strength = S.'S_X01'
        "Output strength";
          parameter Integer n(min=1) = 1 "Data width";
    protected
          constant Integer ResetMap[L] = {1, 4, 3, 2, 4, 4, 3, 2, 4};
              // Function selection by [reset] reading
              // 1: output := U
              // 2: output := 0
              // 3: output := -dataInUX
              // 4: output := U-0X

    public
          Modelica.Electrical.Digital.Delay.InertialDelaySensitiveVector delay(
            tHL=tHL,
            tLH=tLH,
            n=n)
          D.Interfaces.DigitalInput reset
          D.Interfaces.DigitalInput clock
          D.Interfaces.DigitalInput dataIn[n]
          D.Interfaces.DigitalOutput dataOut[n]

          D.Registers.DFFR dFFR(n=n,
            ResetMap=ResetMap,
            strength=strength)
        equation
          connect(delay.y, dataOut)
          connect(dataIn, dFFR.dataIn)
          connect(dFFR.dataOut, delay.x)
          connect(clock, dFFR.clock)
          connect(reset, dFFR.reset)
        end DFFREG;

        model DFFREGL "Edge triggered register bank with low active reset"
          extends DFFREG(final ResetMap = {1, 4, 2, 3, 4, 4, 2, 3, 4});
              // Function selection by [reset] reading
              // 1: output := U
              // 2: output := 0
              // 3: output := -dataInUX
              // 4: output := U-0X;
        end DFFREGL;

        model DFFSR "Edge triggered register bank with set and reset"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          import S = Modelica.Electrical.Digital.Interfaces.Strength;
          import T = Modelica.Electrical.Digital.Tables;
          parameter Integer ResetSetMap[L, L]=[
                     1,  1,  1,  1,  1,  1,  1,  1,  1;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  5,  8,  2,  5,  5,  8,  2,  5;
                     1,  6,  3,  2,  6,  6,  3,  2,  6;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  5,  8,  2,  5,  5,  8,  2,  5;
                     1,  6,  3,  2,  6,  6,  3,  2,  6;
                     1,  4,  7,  2,  4,  4,  7,  2,  4]
        "Function selection by [reset, set] reading";
            /* Defaults for set and reset are active high */
          parameter D.Interfaces.Strength strength = S.'S_X01'
        "Output strength";
          parameter Integer n(min=1) = 1 "Data width";

          D.Interfaces.DigitalInput set
          D.Interfaces.DigitalInput reset
          D.Interfaces.DigitalInput clock
          D.Interfaces.DigitalInput dataIn[n]
          D.Interfaces.DigitalOutput dataOut[n]

    protected
                  Integer clock_flag(start=0);
                    // 0: 0-Transition
                    // 1: rising edge
                    // 2: X-Transition

                  Integer reset_set_flag(start=1);
                    // 1: output := U
                    // 2: output := 1
                    // 3: output := 0
                    // 4: output := UX
                    // 5: output := -1UX
                    // 6: output := X
                    // 7: output := -0UX
                    // 8: output := -dataInUX

                  D.Interfaces.Logic nextstate[n](start=fill(L.'U',n));
                  D.Interfaces.Logic next_assign_val[n](start=fill(L.'U',n));

        algorithm
        if change(clock) or change(reset) or change(set) then

          if change(clock) then
            if initial() then
              clock_flag := T.ClockMap[L.'U',clock];
            else
              clock_flag := T.ClockMap[pre(clock),clock];
            end if;
          end if;

          reset_set_flag := ResetSetMap[reset, set];
          for i in 1:n loop
            if reset_set_flag == 1 then
                  nextstate[i] := L.'U';
            elseif reset_set_flag == 2 then
                  nextstate[i] := T.StrengthMap[L.'1', strength];
            elseif reset_set_flag == 3 then
                  nextstate[i] := T.StrengthMap[L.'0', strength];
            elseif reset_set_flag == 4 then
              if (next_assign_val[i] == L.'U' and clock_flag <> 1)
                or (dataIn[i] == L.'U' and clock_flag <> 0) then
                  nextstate[i] := L.'U';
              else
                  nextstate[i] := T.StrengthMap[L.'X', strength];
              end if;
            elseif reset_set_flag == 5 then
              if next_assign_val[i] == T.StrengthMap[L.'1', strength]
                and (dataIn[i] == L.'1' or dataIn[i] == L.'H' or clock_flag == 0) then
                  break;
              elseif (dataIn[i] == L.'1' or dataIn[i] == L.'H')  and clock_flag == 1 then
                  nextstate[i] := T.StrengthMap[L.'1', strength];
              elseif (next_assign_val[i] == L.'U' and clock_flag <> 1)
                or (dataIn[i] == L.'U' and clock_flag <> 0) then
                  nextstate[i] := L.'U';
              else
                  nextstate[i] := T.StrengthMap[L.'X', strength];
              end if;
            elseif reset_set_flag == 6 then
                  nextstate[i] := T.StrengthMap[L.'X', strength];
            elseif reset_set_flag == 7 then
              if next_assign_val[i] == T.StrengthMap[L.'0', strength]
                and (dataIn[i] == L.'0' or dataIn[i] == L.'L' or clock_flag == 0) then
                  break;
              elseif (dataIn[i] == L.'0' or dataIn[i] == L.'L') and clock_flag == 1 then
                  nextstate[i] :=  T.StrengthMap[L.'0', strength];
              elseif (next_assign_val[i] == L.'U' and clock_flag <> 1)
                or (dataIn[i] == L.'U' and clock_flag <> 0) then
                  nextstate[i] := L.'U';
              else
                  nextstate[i] := T.StrengthMap[L.'X', strength];
              end if;
            elseif reset_set_flag == 8 then
              if clock_flag == 0 then
                  break;
              elseif clock_flag == 1 then
                  nextstate[i] := T.StrengthMap[dataIn[i], strength];
              else
                if next_assign_val[i] == T.StrengthMap[dataIn[i],strength]
                or next_assign_val[i] == L.'U' then
                    break;
                elseif (dataIn[i] == L.'U') then
                    nextstate[i] := L.'U';
                else
                    nextstate[i] := T.StrengthMap[L.'X', strength];
                end if;
               end if;
              end if;
            end for;
          end if;

        next_assign_val := nextstate;
        dataOut := nextstate;
        end DFFSR;

        model DFFREGSRH "Edge triggered register bank with high active set and reset"
          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          import S = Modelica.Electrical.Digital.Interfaces.Strength;
          import T = Modelica.Electrical.Digital.Tables;
          parameter SI.Time tHL=0 "High->Low delay";
          parameter SI.Time tLH=0 "Low->High delay";
          parameter D.Interfaces.Strength strength = S.'S_X01'
        "Output strength";
          parameter Integer n(min=1) = 1 "Data width";

    protected
          constant Integer ResetSetMap[L, L]=[
                     1,  1,  1,  1,  1,  1,  1,  1,  1;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  5,  8,  2,  5,  5,  8,  2,  5;
                     1,  6,  3,  2,  6,  6,  3,  2,  6;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  5,  8,  2,  5,  5,  8,  2,  5;
                     1,  6,  3,  2,  6,  6,  3,  2,  6;
                     1,  4,  7,  2,  4,  4,  7,  2,  4];
                    // Function selection by [reset, set] reading, active high;

    protected
          D.Delay.InertialDelaySensitiveVector delay(
            tHL=tHL,
            tLH=tLH,
            n=n,inertialDelaySensitive(each y(start=L.'U', fixed= true)))

          D.Registers.DFFSR dFFSR(
            strength=strength,
            n=n,
            ResetSetMap=ResetSetMap, clock( start=L.'U', fixed=true), reset( start=L.'U', fixed=true), set( start=L.'U', fixed=true))
    public
          D.Interfaces.DigitalInput set
          D.Interfaces.DigitalInput reset
          D.Interfaces.DigitalInput clock
          D.Interfaces.DigitalInput dataIn[n]
          D.Interfaces.DigitalOutput dataOut[n]
        equation
          connect(dFFSR.dataOut, delay.x)
          connect(set, dFFSR.set)
          connect(reset, dFFSR.reset)
          connect(clock, dFFSR.clock)
          connect(dataIn, dFFSR.dataIn)
          connect(delay.y, dataOut)
        end DFFREGSRH;

        model DFFREGSRL "Edge triggered register bank with low active set and reset"
          extends Digital.Registers.DFFREGSRH(final ResetSetMap=[1,1,1,1,1,1,1,1,1;
                1,4,2,7,4,4,2,7,4; 1,6,2,3,6,6,2,3,6; 1,5,2,8,5,5,2,8,5; 1,4,2,7,4,
                4,2,7,4; 1,4,2,7,4,4,2,7,4; 1,6,2,3,6,6,2,3,6; 1,5,2,8,5,5,2,8,5; 1,
                4,2,7,4,4,2,7,4]);
                   // Function selection by [reset, set] reading;
        end DFFREGSRL;

        model DLATR "Level sensitive register bank with reset"

          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          import S = Modelica.Electrical.Digital.Interfaces.Strength;
          import T = Modelica.Electrical.Digital.Tables;
          parameter Integer ResetMap[L] = {1, 4, 3, 2, 4, 4, 3, 2, 4}
        "Function selection, defaults for high active reset";
          parameter D.Interfaces.Strength strength = S.'S_X01'
        "Output strength";
          parameter Integer n(min=1) = 1 "Data width";

          D.Interfaces.DigitalInput reset
          D.Interfaces.DigitalInput enable
          D.Interfaces.DigitalInput dataIn[n]
          D.Interfaces.DigitalOutput dataOut[n]

    protected
                   Integer enable_flag(start=0);
                    // 0: low level
                    // 1: high level
                    // 2: unknown
                    // 3: uninitialized

                   Integer reset_flag(start=1);
                    // 1: output := U
                    // 2: output := 0
                    // 3: output := -UdataIn
                    // 4: output := U-0X

                  D.Interfaces.Logic nextstate[n](start=fill(L.'U',n));
                  D.Interfaces.Logic next_assign_val[n](start=fill(L.'U',n));
        algorithm
          if enable == L.'1' or enable == L.'H' then
            enable_flag := 1;
          elseif enable == L.'0' or enable == L.'L' then
            enable_flag := 0;
          elseif enable == L.'U' then
            enable_flag := 3;
          else
            enable_flag := 2;
          end if;

          reset_flag :=  ResetMap[reset];
          for i in 1:n loop
            if reset_flag == 1 then
                  nextstate[i] := L.'U';
            elseif reset_flag == 2 then
                  nextstate[i] := T.StrengthMap[L.'0', strength];
            elseif reset_flag == 3 then
              if enable_flag == 0 then
                  break;
              elseif enable_flag == 3 then
                  nextstate[i] := L.'U';
              elseif enable_flag == 1 then
                  nextstate[i] := T.StrengthMap[dataIn[i], strength];
              else
                if next_assign_val[i] == T.StrengthMap[dataIn[i],strength]
                or next_assign_val[i] == L.'U' then
                    break;
                elseif dataIn[i] == L.'U' then
                    nextstate[i] := L.'U';
                else
                    nextstate[i] := T.StrengthMap[L.'X', strength];
                end if;
              end if;
            elseif reset_flag == 4 then
             if enable_flag == 3
                or (next_assign_val[i] == L.'U' and enable_flag <> 1)
                or (dataIn[i] == L.'U' and enable_flag <> 0) then
                  nextstate[i] := L.'U';
              elseif next_assign_val[i] == T.StrengthMap[L.'0', strength]
                and (dataIn[i] == L.'0' or dataIn[i] == L.'L' or enable_flag == 0) then
                  break;
              elseif (dataIn[i] == L.'0' or dataIn[i] == L.'L') and enable_flag == 1 then
                  nextstate[i] :=  T.StrengthMap[L.'0', strength];
              else
                  nextstate[i] := T.StrengthMap[L.'X', strength];
              end if;
            end if;
          end for;
          next_assign_val := nextstate;
          dataOut := nextstate;
        end DLATR;

        model DLATREG "Level sensitive register bank with reset active high"

          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          import S = Modelica.Electrical.Digital.Interfaces.Strength;
          import T = Modelica.Electrical.Digital.Tables;
          parameter SI.Time tHL=0 "High->Low delay";
          parameter SI.Time tLH=0 "Low->High delay";
          parameter D.Interfaces.Strength strength = S.'S_X01'
        "Output strength";
          parameter Integer n(min=1) = 1 "Data width";

    protected
          constant Integer ResetMap[L] = {1, 4, 3, 2, 4, 4, 3, 2, 4};
              // Function selection by [reset] reading
              // 1: output := U
              // 2: output := 0
              // 3: output := -UdataIn
              // 4: output := U-0X

    public
          D.Delay.InertialDelaySensitiveVector delay(
            tHL=tHL,
            tLH=tLH,
            n=n)
          D.Interfaces.DigitalInput reset
          D.Interfaces.DigitalInput enable
          D.Interfaces.DigitalInput dataIn[n]
          D.Interfaces.DigitalOutput dataOut[n]
          D.Registers.DLATR dLATR(n=n,
            strength=strength,
            ResetMap=ResetMap)
        equation

          connect(delay.y, dataOut)
          connect(dLATR.dataOut, delay.x)
          connect(dataIn, dLATR.dataIn)
          connect(enable, dLATR.enable)
          connect(reset, dLATR.reset)
        end DLATREG;

        model DLATREGL "Level sensitive register bank with reset active low"

          extends DLATREG(final ResetMap = {1, 4, 2, 3, 4, 4, 2, 3, 4});
              // Function selection by [reset] reading
              // 1: output := U
              // 2: output := 0
              // 3: output := -UdataIn
              // 4: output := U-0X
        end DLATREGL;

        model DLATSR "Level sensitive register bank with set and reset"

          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          import S = Modelica.Electrical.Digital.Interfaces.Strength;
          import T = Modelica.Electrical.Digital.Tables;
          parameter Integer ResetSetMap[L, L]=[
                     1,  1,  1,  1,  1,  1,  1,  1,  1;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  5,  8,  2,  5,  5,  8,  2,  5;
                     1,  6,  3,  2,  6,  6,  3,  2,  6;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  5,  8,  2,  5,  5,  8,  2,  5;
                     1,  6,  3,  2,  6,  6,  3,  2,  6;
                     1,  4,  7,  2,  4,  4,  7,  2,  4]
        "Function selection by [reset, set] reading";
            /* Defaults for set and reset are active high */
          parameter D.Interfaces.Strength strength = S.'S_X01'
        "Output strength";
          parameter Integer n(min=1) = 1 "Data width";

          D.Interfaces.DigitalInput set
          D.Interfaces.DigitalInput reset
          D.Interfaces.DigitalInput enable
          D.Interfaces.DigitalInput dataIn[n]
          D.Interfaces.DigitalOutput dataOut[n]

    protected
                  Integer enable_flag(start=0);
                    // 0: low level
                    // 1: high level
                    // 2: unknown
                    // 3: uninitialized

                  Integer reset_set_flag(start=1);
                    // 1: output := U
                    // 2: output := 1
                    // 3: output := 0
                    // 4: output := UX
                    // 5: output := U-1X
                    // 6: output := X
                    // 7: output := U-0X
                    // 8: output := -UdataInX

                  D.Interfaces.Logic nextstate[n](start=fill(L.'U',n));
                  D.Interfaces.Logic next_assign_val[n](start=fill(L.'U',n));

        algorithm
          if enable == L.'1' or enable == L.'H' then
            enable_flag := 1;
          elseif enable == L.'0' or enable == L.'L' then
            enable_flag := 0;
          elseif enable == L.'U' then
            enable_flag := 3;
          else
            enable_flag := 2;
          end if;

          reset_set_flag :=  ResetSetMap[reset, set];
          for i in 1:n loop
            if reset_set_flag == 1 then
                  nextstate[i] := L.'U';
            elseif reset_set_flag == 2 then
                  nextstate[i] := T.StrengthMap[L.'1', strength];
            elseif reset_set_flag == 3 then
                  nextstate[i] := T.StrengthMap[L.'0', strength];
            elseif reset_set_flag == 4 then
              if enable_flag == 3
                or (next_assign_val[i] == L.'U' and enable_flag <> 1)
                or (dataIn[i] == L.'U' and enable_flag <> 0) then
                  nextstate[i] := L.'U';
              else
                  nextstate[i] := T.StrengthMap[L.'X', strength];
              end if;
            elseif reset_set_flag == 5 then
              if enable_flag == 3
                or (next_assign_val[i] == L.'U' and enable_flag <> 1)
                or (dataIn[i] == L.'U' and enable_flag <> 0) then
                  nextstate[i] := L.'U';
              elseif next_assign_val[i] == T.StrengthMap[L.'1', strength]
                and (dataIn[i] == L.'1' or dataIn[i] == L.'H' or enable_flag == 0) then
                  break;
              elseif (dataIn[i] == L.'1' or dataIn[i] == L.'H')  and enable_flag == 1 then
                  nextstate[i] := T.StrengthMap[L.'1', strength];
              else
                  nextstate[i] := T.StrengthMap[L.'X', strength];
              end if;
            elseif reset_set_flag == 6 then
                  nextstate[i] := T.StrengthMap[L.'X', strength];
            elseif reset_set_flag == 7 then
              if enable_flag == 3
                or (next_assign_val[i] == L.'U' and enable_flag <> 1)
                or (dataIn[i] == L.'U' and enable_flag <> 0) then
                  nextstate[i] := L.'U';
              elseif next_assign_val[i] == T.StrengthMap[L.'0', strength]
                and (dataIn[i] == L.'0' or dataIn[i] == L.'L' or enable_flag == 0) then
                  break;
              elseif (dataIn[i] == L.'0' or dataIn[i] == L.'L') and enable_flag == 1 then
                  nextstate[i] :=  T.StrengthMap[L.'0', strength];
              else
                  nextstate[i] := T.StrengthMap[L.'X', strength];
              end if;
            elseif reset_set_flag == 8 then
              if enable_flag == 0 then
                  break;
              elseif enable_flag == 3 then
                  nextstate[i] := L.'U';
              elseif enable_flag == 1 then
                  nextstate[i] := T.StrengthMap[dataIn[i], strength];
              else
                if next_assign_val[i] == T.StrengthMap[dataIn[i],strength]
                or next_assign_val[i] == L.'U' then
                    break;
                elseif dataIn[i] == L.'U' then
                    nextstate[i] := L.'U';
                else
                    nextstate[i] := T.StrengthMap[L.'X', strength];
                end if;
              end if;
            end if;
          end for;
          next_assign_val := nextstate;
          dataOut := nextstate;
        end DLATSR;

        model DLATREGSRH "Level sensitive register bank with set and reset, active high"

          import D = Modelica.Electrical.Digital;
          import L = Modelica.Electrical.Digital.Interfaces.Logic;
          import S = Modelica.Electrical.Digital.Interfaces.Strength;
          import T = Modelica.Electrical.Digital.Tables;
          parameter SI.Time tHL=0 "High->Low delay";
          parameter SI.Time tLH=0 "Low->High delay";
          parameter D.Interfaces.Strength strength = S.'S_X01'
        "Output strength";
          parameter Integer n(min=1) = 1 "Data width";

    protected
          constant Integer ResetSetMap[L, L]=[
                     1,  1,  1,  1,  1,  1,  1,  1,  1;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  5,  8,  2,  5,  5,  8,  2,  5;
                     1,  6,  3,  2,  6,  6,  3,  2,  6;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  4,  7,  2,  4,  4,  7,  2,  4;
                     1,  5,  8,  2,  5,  5,  8,  2,  5;
                     1,  6,  3,  2,  6,  6,  3,  2,  6;
                     1,  4,  7,  2,  4,  4,  7,  2,  4];
                    // Function selection by [reset, set] reading, active high;

    public
          D.Delay.InertialDelaySensitiveVector delay(
            tHL=tHL,
            tLH=tLH,
            n=n)
          D.Interfaces.DigitalInput set
          D.Interfaces.DigitalInput reset
          D.Interfaces.DigitalInput enable
          D.Interfaces.DigitalInput dataIn[n]
          D.Interfaces.DigitalOutput dataOut[n]
          D.Registers.DLATSR dLATSR(n=n,
            ResetSetMap=ResetSetMap,
            strength=strength)
        equation

          connect(delay.y, dataOut)
          connect(set, dLATSR.set)
          connect(reset, dLATSR.reset)
          connect(enable, dLATSR.enable)
          connect(dataIn, dLATSR.dataIn)
          connect(dLATSR.dataOut, delay.x)
        end DLATREGSRH;

        model DLATREGSRL "Level sensitive register bank with set and reset, active low"

          extends Digital.Registers.DLATREGSRH(final ResetSetMap=[1,1,1,1,1,1,1,1,1;
                1,4,2,7,4,4,2,7,4; 1,6,2,3,5,5,2,3,6; 1,5,2,8,6,6,2,8,5; 1,4,2,7,4,
                4,2,7,4; 1,4,2,7,4,4,2,7,4; 1,6,2,3,5,5,2,3,6; 1,5,2,8,6,6,2,8,5; 1,
                4,2,7,4,4,2,7,4]);
                   // Function selection by [reset, set] reading;
        end DLATREGSRL;
      end Registers;

  package Tristates "Transfergates, Buffers, Inverters, and WiredX"
      extends Modelica.Icons.Package;
    import D = Modelica.Electrical.Digital;
    import L = Modelica.Electrical.Digital.Interfaces.Logic;
    import T = Modelica.Electrical.Digital.Tables;
    import S = Modelica.Electrical.Digital.Interfaces.Strength;

    model NXFERGATE "Transfergate with enable active high"
      parameter SI.Time tHL=0 "High->Low delay";
      parameter SI.Time tLH=0 "Low->High delay";
      D.Interfaces.DigitalInput enable
      D.Interfaces.DigitalInput x
      D.Interfaces.DigitalOutput y
    protected
      D.Interfaces.Logic nextstate(start=L.'U');
      D.Interfaces.DigitalOutput yy(start=L.'U');
      D.Delay.InertialDelaySensitive inertialDelaySensitive(tLH=tLH, tHL=tHL,y(start=L.'U', fixed=true));
    algorithm
      nextstate := T.NXferTable[enable, x];
      yy := nextstate;
    equation
      connect(yy, inertialDelaySensitive.x);
      connect(inertialDelaySensitive.y, y);
    end NXFERGATE;

    model NRXFERGATE
      "Transfergate with enable active high. Output strength reduced."
      parameter SI.Time tHL=0 "High->Low delay";
      parameter SI.Time tLH=0 "Low->High delay";
      D.Interfaces.DigitalInput enable
      D.Interfaces.DigitalInput x
      D.Interfaces.DigitalOutput y
    protected
      D.Interfaces.Logic nextstate(start=L.'U');
      D.Interfaces.DigitalOutput yy(start=L.'U');
      D.Delay.InertialDelaySensitive inertialDelaySensitive(tLH=tLH, tHL=tHL, y(start=L.'U', fixed=true));
    algorithm
      nextstate := T.NRXferTable[enable, x];
      yy := nextstate;
    equation
      connect(yy, inertialDelaySensitive.x);
      connect(inertialDelaySensitive.y, y);
    end NRXFERGATE;

    model PXFERGATE "Transfergate with enable active low"
      parameter SI.Time tHL=0 "High->Low delay";
      parameter SI.Time tLH=0 "Low->High delay";
      D.Interfaces.DigitalInput enable
      D.Interfaces.DigitalInput x
      D.Interfaces.DigitalOutput y
    protected
      D.Interfaces.Logic nextstate(start=L.'U');
      D.Interfaces.DigitalOutput yy(start=L.'U');
      D.Delay.InertialDelaySensitive inertialDelaySensitive(tLH=tLH, tHL=tHL);
    algorithm
      nextstate := T.PXferTable[enable, x];
      yy := nextstate;
    equation
      connect(yy, inertialDelaySensitive.x);
      connect(inertialDelaySensitive.y, y);
    end PXFERGATE;

    model PRXFERGATE
      "Transfergate with enable active low. Output strength reduced."
      parameter SI.Time tHL=0 "High->Low delay";
      parameter SI.Time tLH=0 "Low->High delay";
      D.Interfaces.DigitalInput enable
      D.Interfaces.DigitalInput x
      D.Interfaces.DigitalOutput y
    protected
      D.Interfaces.Logic nextstate(start=L.'U');
      D.Interfaces.DigitalOutput yy(start=L.'U');
      D.Delay.InertialDelaySensitive inertialDelaySensitive(tLH=tLH, tHL=tHL);
    algorithm
      nextstate := T.PRXferTable[enable, x];
      yy := nextstate;
    equation
      connect(yy, inertialDelaySensitive.x);
      connect(inertialDelaySensitive.y, y);
    end PRXFERGATE;

    model BUF3S "Tristate buffer with enable active high"
      parameter SI.Time tHL=0 "High->Low delay";
      parameter SI.Time tLH=0 "Low->High delay";
      parameter D.Interfaces.Strength strength = S.'S_X01' "Output strength";
      D.Interfaces.DigitalInput enable
      D.Interfaces.DigitalInput x
      D.Interfaces.DigitalOutput y
    protected
      D.Interfaces.Logic nextstate(start=L.'U');
      D.Interfaces.DigitalOutput yy(start=L.'U');
      D.Delay.InertialDelaySensitive inertialDelaySensitive(tLH=tLH, tHL=tHL, y(start=L.'U', fixed=true));
    algorithm
      nextstate := T.Buf3sTable[strength, T.UX01Conv[enable], T.UX01Conv[x]];
      yy := nextstate;
    equation
      connect(yy, inertialDelaySensitive.x);
      connect(inertialDelaySensitive.y, y);
    end BUF3S;

    model BUF3SL "Tristate buffer with enable active low"
      parameter SI.Time tHL=0 "High->Low delay";
      parameter SI.Time tLH=0 "Low->High delay";
      parameter D.Interfaces.Strength strength = S.'S_X01' "Output strength";
      D.Interfaces.DigitalInput enable
      D.Interfaces.DigitalInput x
      D.Interfaces.DigitalOutput y
    protected
      D.Interfaces.Logic nextstate(start=L.'U');
      D.Interfaces.DigitalOutput yy(start=L.'U');
      D.Delay.InertialDelaySensitive inertialDelaySensitive(tLH=tLH, tHL=tHL);
    algorithm
      nextstate := T.Buf3slTable[strength, T.UX01Conv[enable], T.UX01Conv[x]];
      yy := nextstate;
    equation
      connect(yy, inertialDelaySensitive.x);
      connect(inertialDelaySensitive.y, y);
    end BUF3SL;

    model INV3S "Tristate Inverter with enable active high"
      parameter SI.Time tHL=0 "High->Low delay";
      parameter SI.Time tLH=0 "Low->High delay";
      parameter D.Interfaces.Strength strength = S.'S_X01' "Output strength";
      D.Interfaces.DigitalInput enable
      D.Interfaces.DigitalInput x
      D.Interfaces.DigitalOutput y
    protected
     D.Interfaces.Logic nextstate(start=L.'U');
     D.Interfaces.DigitalOutput yy(start=L.'U');
     D.Delay.InertialDelaySensitive inertialDelaySensitive(tLH=tLH, tHL=tHL, y(start=L.'U',fixed=true));
    algorithm
      nextstate := T.Buf3sTable[strength, T.UX01Conv[enable], T.UX01Conv[T.NotTable[x]]];
      yy := nextstate;
    equation
      connect(yy, inertialDelaySensitive.x);
      connect(inertialDelaySensitive.y, y);
    end INV3S;

    model INV3SL "Tristate inverter with enable active low"
      parameter SI.Time tHL=0 "High->Low delay";
      parameter SI.Time tLH=0 "Low->High delay";
      parameter D.Interfaces.Strength strength = S.'S_X01' "Output strength";
      D.Interfaces.DigitalInput enable
      D.Interfaces.DigitalInput x
      D.Interfaces.DigitalOutput y
    protected
     D.Interfaces.Logic nextstate(start=L.'U');
     D.Interfaces.DigitalOutput yy(start=L.'U');
     D.Delay.InertialDelaySensitive inertialDelaySensitive(tLH=tLH, tHL=tHL);
    algorithm
      nextstate := T.Buf3sTable[strength, T.UX01Conv[T.NotTable[enable]], T.UX01Conv[T.NotTable[x]]];
      yy := nextstate;
    equation
      connect(yy, inertialDelaySensitive.x);
      connect(inertialDelaySensitive.y, y);
    end INV3SL;

    model WiredX "Wired node with multiple input and one output"
      extends D.Interfaces.MISO;
    protected
      D.Interfaces.Logic auxiliary[n](each start=L.'Z', each fixed=true);
    equation
      auxiliary[1] = x[1];
      for i in 1:n - 1 loop
        auxiliary[i + 1] = D.Tables.ResolutionTable[auxiliary[i], x[i + 1]];
      end for;
      y = pre(auxiliary[n]);
    end WiredX;
  end Tristates;

  package Memories
    extends Modelica.Icons.Package;

    model DLATRAM "Level sensitive Random Access Memory"
      import L = Modelica.Electrical.Digital.Interfaces.Logic;
      import T = Modelica.Electrical.Digital.Tables;
      extends Interfaces.MemoryBase;

      Interfaces.DigitalInput WE "Write enable"
      Interfaces.DigitalInput dataIn[n_data] "Data input"
      L mem[integer(2^n_addr),n_data](start=fill(L.'U',integer(2^n_addr),n_data)) "Memory with data, lowest bit on left side";

    algorithm
      if initial() then
        mem := getMemory(fileName, n_addr, n_data);
      end if;

      /* write into memory */
      if WE == L.'1' or WE == L.'H' then
        // write data
        int_addr := address(n_addr, addr);
        //assert(int_addr > 0, "Attempted write to bad RAM address");
        if int_addr > 0 then
          for i in 1:n_data loop
            mem_word[i] := T.X01Table[dataIn[i]];
          end for;
          mem[int_addr,1:n_data] := mem_word;
        end if;
      elseif WE == L.'X' or WE == L.'W' or WE == L.'Z' or WE == L.'U' or WE == L.'-' then
        // write X
        int_addr := address(n_addr, addr);
        //assert(int_addr > 0, "Attempted write to bad RAM address");
        if int_addr > 0 then
          mem_word :=fill(L.'X',n_data);
          mem[int_addr,1:n_data] := mem_word;
        end if;
      end if;

      /* read from memory */
      if RE == L.'0' or RE == L.'L' then
        nextstate := fill(L.'Z',n_data);
      elseif RE == L.'1' or RE == L.'H' then
        int_addr := address(n_addr, addr);
        // read data
        if int_addr > 0 then
          mem_word := mem[int_addr,1:n_data];
          for i in 1:n_data loop
            nextstate[i] := T.StrengthMap[mem_word[i], strength];
          end for;
        else
          nextstate := fill(T.StrengthMap[L.'X', strength],n_data);
        end if;
      else
        nextstate := fill(T.StrengthMap[L.'X', strength],n_data);
      end if;
      yy := nextstate;
    end DLATRAM;

    model DLATROM "Level sensitive Read Only Memory"
      import L = Modelica.Electrical.Digital.Interfaces.Logic;
      import T = Modelica.Electrical.Digital.Tables;
      extends Interfaces.MemoryBase;

    protected
      L m[integer(2^n_addr),n_data](start=fill(L.'U',integer(2^n_addr),n_data)) "Memory with data, lowest bit on left side";

    algorithm
      if initial() then
        m := getMemory(fileName, n_addr, n_data);
      end if;

      if RE == L.'0' or RE == L.'L' then
        nextstate := fill(L.'Z',n_data);
      elseif RE == L.'1' or RE == L.'H' then
        int_addr := address(n_addr, addr);
        // read data
        if int_addr > 0 then
           mem_word := m[int_addr,1:n_data];
           for i in 1:n_data loop
              nextstate[i] := T.StrengthMap[mem_word[i], strength];
           end for;
        else
           nextstate := fill(T.StrengthMap[L.'X', strength],n_data);
        end if;
      else
        nextstate := fill(T.StrengthMap[L.'X', strength],n_data);
      end if;
      yy := nextstate;
    end DLATROM;
  end Memories;

  package Multiplexers
    extends Modelica.Icons.Package;
    model MUX2x1 "A two inputs MULTIPLEXER for multiple value logic (2 data inputs, 1 select input, 1 output)"

      import D = Modelica.Electrical.Digital;
      import L = Modelica.Electrical.Digital.Interfaces.Logic;
      import S = Modelica.Electrical.Digital.Interfaces.Strength;
      import T = Modelica.Electrical.Digital.Tables;
      parameter SI.Time tHL=0 "High->Low delay";
      parameter SI.Time tLH=0 "Low->High delay";
      parameter D.Interfaces.Strength strength = S.'S_X01' "Output strength";
      D.Interfaces.DigitalInput in1 "Data input 1"
      D.Interfaces.DigitalInput in0 "Data input 0"
      D.Interfaces.DigitalInput sel "Select input"
      D.Interfaces.DigitalOutput out "Output"

    protected
      D.Interfaces.Logic nextstate(start=L.'U');
      D.Interfaces.DigitalOutput yy(start=L.'U');
      D.Delay.InertialDelaySensitive inertialDelaySensitive(tLH=tLH, tHL=tHL, y(start=L.'U',fixed=true));

    algorithm
      nextstate := T.MUX2x1Table[T.UX01Conv[in1], T.UX01Conv[sel], T.UX01Conv[in0]];

      nextstate := T.StrengthMap[nextstate, strength];

      yy := nextstate;
    equation
      connect(yy, inertialDelaySensitive.x);
      connect(inertialDelaySensitive.y, out);
    end MUX2x1;
  end Multiplexers;
end Digital;