\title{myHDL Combinational Logic Elements: Demultiplexers (DEMUXs))}
\author{Steven K Armour}
\maketitle

Table of Contents

1  Refrances

2  Libraries and Helper functions

3  Demultiplexers

4  1 Channel Input: 2 Channel Output demultiplexer in Gate Level Logic

4.1  Sympy Expression

4.2  myHDL Module

4.3  myHDL Testing

4.4  Verilog Conversion

4.5  myHDL to Verilog Testbech

4.6  PYNQ-Z1 Deployment

4.6.1  Board Circuit

4.6.2  Board Constraints

4.6.3  Video of Deployment

5  1 Channel Input:4 Channel Output demultiplexer in Gate Level Logic

5.1  Sympy Expression

5.2  myHDL Module

5.3  myHDL Testing

5.4  Verilog Conversion

5.5  myHDL to Verilog Testbench

5.6  PYNQ-Z1 Deployment

5.6.1  Board Circuit

5.6.2  Board Constraints

5.6.3  Video of Deployment

6  1 Channel Input:4 Channel Output demultiplexer via DEMUX Stacking

6.1  myHDL Module

6.2  myHDL Testing

6.3  Verilog Conversion

6.4  myHDL to Verilog Testbench

6.5  PYNQ-Z1 Deployment

6.5.1  Board Circuit

6.5.2  Board Constraint

6.5.3  Video of Deployment

7  1:2 DEMUX via Behavioral IF

7.1  myHDL Module

7.2  myHDL Testing

7.3  Verilog Conversion

7.4  myHDL to Verilog Testbench

7.5  PYNQ-Z1 Deployment

7.5.1  Board Circuit

7.5.2  Board Constraint

7.5.3  Video of Deployment

8  1:4 DEMUX via Behavioral if-elif-else

8.1  myHDL Module

8.2  myHDL Testing

8.3  Verilog Conversion

8.4  myHDL to Verilog Testbench

8.5  PYNQ-Z1 Deployment

8.5.1  Board Circuit

8.5.2  Board Constraint

8.5.3  Video of Deployment

9  Demultiplexer 1:4 Behavioral via Bitvectors

9.1  myHDL Module

9.2  myHDL Testing

9.3  Verilog Conversion

9.4  myHDL to Verilog Testbench

9.5  PYNQ-Z1 Board Deployment

9.5.1  Board Circuit

9.5.2  Board Constraints

9.5.3  Video of Deployment

# Refrances

# Libraries and Helper functions

```python
#This notebook also uses the `(some) LaTeX environments for Jupyter`
#https://github.com/ProfFan/latex_envs wich is part of the
#jupyter_contrib_nbextensions package

from myhdl import *
from myhdlpeek import Peeker
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

from sympy import *
init_printing()

import itertools

#EE drawing tools in python from https://cdelker.bitbucket.io/SchemDraw/
import SchemDraw as schem
import SchemDraw.elements as e
import SchemDraw.logic as l

#https://github.com/jrjohansson/version_information
%load_ext version_information
%version_information myhdl, myhdlpeek, numpy, pandas, matplotlib, sympy, itertools, SchemDraw
```

Software	Version

Python	3.6.2 64bit [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]

IPython	6.2.1

OS	Linux 4.15.0 30 generic x86_64 with debian stretch sid

myhdl	0.10

myhdlpeek	0.0.6

numpy	1.13.3

pandas	0.23.4

matplotlib	2.1.0

sympy	1.3

itertools	The 'itertools' distribution was not found and is required by the application

SchemDraw	0.3.0

Sun Sep 23 18:24:14 2018 MDT

```python
#helper  functions to read in the .v and .vhd generated files into python
def VerilogTextReader(loc, printresult=True):
    with open(f'{loc}.v', 'r') as vText:
        VerilogText=vText.read()
    if printresult:
        print(f'***Verilog modual from {loc}.v***\n\n', VerilogText)
    return VerilogText

def VHDLTextReader(loc, printresult=True):
    with open(f'{loc}.vhd', 'r') as vText:
        VerilogText=vText.read()
    if printresult:
        print(f'***VHDL modual from {loc}.vhd***\n\n', VerilogText)
    return VerilogText

def ConstraintXDCTextReader(loc, printresult=True):
    with open(f'{loc}.xdc', 'r') as xdcText:
        ConstraintText=xdcText.read()
    if printresult:
        print(f'***Constraint file from {loc}.xdc***\n\n', ConstraintText)
    return ConstraintText
```

```python
def TruthTabelGenrator(BoolSymFunc):
    """
    Function to generate a truth table from a sympy boolian expression
    BoolSymFunc: sympy boolian expression
    return TT: a Truth table stored in a pandas dataframe
    """
    colsL=sorted([i for i in list(BoolSymFunc.rhs.atoms())], key=lambda x:x.sort_key())
    colsR=sorted([i for i in list(BoolSymFunc.lhs.atoms())], key=lambda x:x.sort_key())
    bitwidth=len(colsL)
    cols=colsL+colsR; cols

    TT=pd.DataFrame(columns=cols, index=range(2**bitwidth))

    for i in range(2**bitwidth):
        inputs=[int(j) for j in list(np.binary_repr(i, bitwidth))]
        outputs=BoolSymFunc.rhs.subs({j:v for j, v in zip(colsL, inputs)})
        inputs.append(int(bool(outputs)))
        TT.iloc[i]=inputs

    return TT

```

# Demultiplexers
\begin{definition}\label{def:MUX}
A Demultiplexer, typically referred to as a DEMUX, is a Digital(or analog) switching unit that takes one input channel to be streamed to a single output channel from many via a control input. For single input DEMUXs with $2^n$ outputs, there are then $n$ input selection signals that make up the control word to select the output channel for the input.

Thus a DEMUX is the conjugate digital element to the MUX such that a MUX is an $N:1$ mapping device and a DEMUX is a $1:N$ mapping device.

From a behavioral standpoint DEMUXs are implemented with the same `if-elif-else (case)` control statements as a MUX but for each case, all outputs must be specified.

Furthermore, DEMUXs are often implemented via stacked MUXs since there governing equation is the Product SET (Cartesian product) all internal products of a MUXs SOP equation
\end{definition}

# 1 Channel Input: 2 Channel Output demultiplexer in Gate Level Logic

\begin{figure}
\centerline{\includegraphics{DEMUX12Gate.png}}
\caption{\label{fig:D12G} 1:2 DEMUX Symbol and Gate internals}
\end{figure}

## Sympy Expression

```python
x, s, y0, y1=symbols('x, s, y_0, y_1')
y12_0Eq=Eq(y0, ~s&x)
y12_1Eq=Eq(y1, s&x)
y12_0Eq, y12_1Eq
```

```python
T0=TruthTabelGenrator(y12_0Eq)
T1=TruthTabelGenrator(y12_1Eq)
T10=pd.merge(T1, T0, how='left')
T10
```

      s
      x
      y_1
      y_0

      0
      0
      0
      0
      0

      1
      0
      1
      0
      1

      2
      1
      0
      0
      0

      3
      1
      1
      1
      0

```python
y12_0EqN=lambdify([s, x], y12_0Eq.rhs, dummify=False)
y12_1EqN=lambdify([s, x], y12_1Eq.rhs, dummify=False)
SystmaticVals=np.array(list(itertools.product([0,1], repeat=2)))
print(SystmaticVals)
print(y12_0EqN(SystmaticVals[:, 0], SystmaticVals[:, 1]).astype(int))
print(y12_1EqN(SystmaticVals[:, 0], SystmaticVals[:, 1]).astype(int))
```

    [[0 0]
     [0 1]
     [1 0]
     [1 1]]
    [0 1 0 0]
    [0 0 0 1]

## myHDL Module

```python
@block
def DEMUX1_2_Combo(x, s, y0, y1):
    """
    1:2 DEMUX written in full combo
    Inputs:
        x(bool): input feed
        s(bool): channel select
    Outputs:
        y0(bool): ouput channel 0
        y1(bool): ouput channel 1
    """

    @always_comb
    def logic():
        y0.next= not s and x
        y1.next= s and x

    return instances()
```

## myHDL Testing

```python
TestLen=10
SystmaticVals=list(itertools.product([0,1], repeat=2))

xTVs=np.array([i[1] for i in SystmaticVals]).astype(int)
np.random.seed(15)
xTVs=np.append(xTVs, np.random.randint(0,2, TestLen)).astype(int)

sTVs=np.array([i[0] for i in SystmaticVals]).astype(int)
#the random genrator must have a differint seed beween each generation
#call in order to produce differint values for each call
np.random.seed(16)
sTVs=np.append(sTVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(xTVs)
SystmaticVals, sTVs, xTVs
```

    ([(0, 0), (0, 1), (1, 0), (1, 1)],
     array([0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0]),
     array([0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]))

```python
Peeker.clear()
x=Signal(bool(0)); Peeker(x, 'x')
s=Signal(bool(0)); Peeker(s, 's')
y0=Signal(bool(0)); Peeker(y0, 'y0')
y1=Signal(bool(0)); Peeker(y1, 'y1')

DUT=DEMUX1_2_Combo(x, s, y0, y1)

def DEMUX1_2_Combo_TB():
    """
    myHDL only testbench for module `DEMUX1_2_Combo`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTVs[i])
            s.next=int(sTVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

sim=Simulation(DUT, DEMUX1_2_Combo_TB(), *Peeker.instances()).run()
```

```python
Peeker.to_wavedrom('x', 's', 'y0','y1')
```

```python
DEMUX1_2_ComboData=Peeker.to_dataframe()
DEMUX1_2_ComboData=DEMUX1_2_ComboData[['x', 's', 'y0','y1']]
DEMUX1_2_ComboData
```

      x
      s
      y0
      y1

      0
      0
      0
      0
      0

      1
      1
      0
      1
      0

      2
      0
      1
      0
      0

      3
      1
      1
      0
      1

      4
      0
      1
      0
      0

      5
      1
      0
      1
      0

      6
      0
      1
      0
      0

      7
      1
      1
      0
      1

      9
      0
      1
      0
      0

      10
      0
      0
      0
      0

      11
      1
      1
      0
      1

      13
      1
      0
      1
      0

```python
DEMUX1_2_ComboData['y0Ref']=DEMUX1_2_ComboData.apply(lambda row:y12_0EqN(row['s'], row['x']), axis=1).astype(int)
DEMUX1_2_ComboData['y1Ref']=DEMUX1_2_ComboData.apply(lambda row:y12_1EqN(row['s'], row['x']), axis=1).astype(int)
DEMUX1_2_ComboData
```

      x
      s
      y0
      y1
      y0Ref
      y1Ref

      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      1
      0
      1
      0

      2
      0
      1
      0
      0
      0
      0

      3
      1
      1
      0
      1
      0
      1

      4
      0
      1
      0
      0
      0
      0

      5
      1
      0
      1
      0
      1
      0

      6
      0
      1
      0
      0
      0
      0

      7
      1
      1
      0
      1
      0
      1

      9
      0
      1
      0
      0
      0
      0

      10
      0
      0
      0
      0
      0
      0

      11
      1
      1
      0
      1
      0
      1

      13
      1
      0
      1
      0
      1
      0

```python
Test0=(DEMUX1_2_ComboData['y0']==DEMUX1_2_ComboData['y0Ref']).all()
Test1=(DEMUX1_2_ComboData['y1']==DEMUX1_2_ComboData['y1Ref']).all()
Test=Test0&Test1
print(f'Module `DEMUX1_2_Combo` works as exspected: {Test}')
```

    Module `DEMUX1_2_Combo` works as exspected: True

## Verilog Conversion

```python
DUT.convert()
VerilogTextReader('DEMUX1_2_Combo');
```

    ***Verilog modual from DEMUX1_2_Combo.v***

     // File: DEMUX1_2_Combo.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:15 2018

    `timescale 1ns/10ps

    module DEMUX1_2_Combo (
        x,
        s,
        y0,
        y1
    );
    // 1:2 DEMUX written in full combo
    // Inputs:
    //     x(bool): input feed
    //     s(bool): channel select
    // Outputs:
    //     y0(bool): ouput channel 0
    //     y1(bool): ouput channel 1

    input x;
    input s;
    output y0;
    wire y0;
    output y1;
    wire y1;

    assign y0 = ((!s) && x);
    assign y1 = (s && x);

    endmodule

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_2_Combo_RTL.png}}
\caption{\label{fig:D12CRTL} DEMUX1_2_Combo RTL schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_2_Combo_SYN.png}}
\caption{\label{fig:D12CSYN} DEMUX1_2_Combo Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_2_Combo_IMP.png}}
\caption{\label{fig:D12CIMP} DEMUX1_2_Combo Implementated Schematic; Xilinx Vivado 2017.4}
\end{figure}

## myHDL to Verilog Testbech

```python
#create BitVectors
xTVs=intbv(int(''.join(xTVs.astype(str)), 2))[TestLen:]
sTVs=intbv(int(''.join(sTVs.astype(str)), 2))[TestLen:]

xTVs, bin(xTVs), sTVs, bin(sTVs)
```

    (intbv(5479), '1010101100111', intbv(3830), '111011110110')

```python
@block
def DEMUX1_2_Combo_TBV():
    """
    myHDL -> testbench for module `DEMUX1_2_Combo`
    """

    x=Signal(bool(0))
    s=Signal(bool(0))
    y0=Signal(bool(0))
    y1=Signal(bool(0))

    @always_comb
    def print_data():
        print(x, s, y0, y1)

    #Test Signal Bit Vectors

    xTV=Signal(xTVs)
    sTV=Signal(sTVs)

    DUT=DEMUX1_2_Combo(x, s, y0, y1)

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTV[i])
            s.next=int(sTV[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

TB=DEMUX1_2_Combo_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('DEMUX1_2_Combo_TBV');
```

    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    ***Verilog modual from DEMUX1_2_Combo_TBV.v***

     // File: DEMUX1_2_Combo_TBV.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:16 2018

    `timescale 1ns/10ps

    module DEMUX1_2_Combo_TBV (

    );
    // myHDL -> testbench for module `DEMUX1_2_Combo`

    reg x = 0;
    reg s = 0;
    wire y0;
    wire y1;
    wire [13:0] xTV;
    wire [13:0] sTV;

    assign xTV = 14'd5479;
    assign sTV = 14'd3830;

    always @(x, y0, s, y1) begin: DEMUX1_2_COMBO_TBV_PRINT_DATA
        $write("%h", x);
        $write(" ");
        $write("%h", s);
        $write(" ");
        $write("%h", y0);
        $write(" ");
        $write("%h", y1);
        $write("\n");
    end

    assign y0 = ((!s) && x);
    assign y1 = (s && x);

    initial begin: DEMUX1_2_COMBO_TBV_STIMULES
        integer i;
        for (i=0; i<14; i=i+1) begin
            x <= xTV[i];
            s <= sTV[i];
            # 1;
        end
        $finish;
    end

    endmodule

    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: xTV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: sTV
      category=ToVerilogWarning

## PYNQ-Z1 Deployment

### Board Circuit
\begin{figure}
\centerline{\includegraphics[width=5cm]{DEMUX12PYNQZ1Circ.png}}
\caption{\label{fig:D12Circ} 1:2 DEMUX PYNQ-Z1 (Non SoC) conceptualized circuit}
\end{figure}

### Board Constraints

```python
ConstraintXDCTextReader('DEMUX1_2');
```

    ***Constraint file from DEMUX1_2.xdc***

     ## Switches
    set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports {s}]; ##SW0

    ## Buttons
    set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports {x}]; ##BT3

    ## RGBLEDs
    set_property -dict { PACKAGE_PIN L15   IOSTANDARD LVCMOS33 } [get_ports {y0}]; ##LD4_Blue
    set_property -dict { PACKAGE_PIN G17   IOSTANDARD LVCMOS33 } [get_ports {y1}]; ##LD4_Green

### Video of Deployment
DEMUX1_2_Combo on PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=LJG4Z2kxEKE))

# 1 Channel Input:4 Channel Output demultiplexer in Gate Level Logic

## Sympy Expression

```python
x, s0, s1, y0, y1, y2, y3=symbols('x, s0, s1, y0, y1, y2, y3')
y14_0Eq=Eq(y0, ~s0&~s1&x)
y14_1Eq=Eq(y1, s0&~s1&x)
y14_2Eq=Eq(y2, ~s0&s1&x)
y14_3Eq=Eq(y3, s0&s1&x)
y14_0Eq, y14_1Eq, y14_2Eq, y14_3Eq
```

```python
T0=TruthTabelGenrator(y14_0Eq)
T1=TruthTabelGenrator(y14_1Eq)
T2=TruthTabelGenrator(y14_2Eq)
T3=TruthTabelGenrator(y14_3Eq)
T10=pd.merge(T1, T0, how='left')
T20=pd.merge(T2, T10, how='left')
T30=pd.merge(T3, T20, how='left')
T30
```

      s0
      s1
      x
      y3
      y2
      y1
      y0

      0
      0
      0
      0
      0
      0
      0
      0

      1
      0
      0
      1
      0
      0
      0
      1

      2
      0
      1
      0
      0
      0
      0
      0

      3
      0
      1
      1
      0
      1
      0
      0

      4
      1
      0
      0
      0
      0
      0
      0

      5
      1
      0
      1
      0
      0
      1
      0

      6
      1
      1
      0
      0
      0
      0
      0

      7
      1
      1
      1
      1
      0
      0
      0

```python
y14_0EqN=lambdify([x, s0, s1], y14_0Eq.rhs, dummify=False)
y14_1EqN=lambdify([x, s0, s1], y14_1Eq.rhs, dummify=False)
y14_2EqN=lambdify([x, s0, s1], y14_2Eq.rhs, dummify=False)
y14_3EqN=lambdify([x, s0, s1], y14_3Eq.rhs, dummify=False)
SystmaticVals=np.array(list(itertools.product([0,1], repeat=3)))
print(SystmaticVals)
print(y14_0EqN(SystmaticVals[:, 2], SystmaticVals[:, 1], SystmaticVals[:, 0]).astype(int))
print(y14_1EqN(SystmaticVals[:, 2], SystmaticVals[:, 1], SystmaticVals[:, 0]).astype(int))
print(y14_2EqN(SystmaticVals[:, 2], SystmaticVals[:, 1], SystmaticVals[:, 0]).astype(int))
print(y14_3EqN(SystmaticVals[:, 2], SystmaticVals[:, 1], SystmaticVals[:, 0]).astype(int))
```

    [[0 0 0]
     [0 0 1]
     [0 1 0]
     [0 1 1]
     [1 0 0]
     [1 0 1]
     [1 1 0]
     [1 1 1]]
    [0 1 0 0 0 0 0 0]
    [0 0 0 1 0 0 0 0]
    [0 0 0 0 0 1 0 0]
    [0 0 0 0 0 0 0 1]

## myHDL Module

```python
@block
def DEMUX1_4_Combo(x, s0, s1, y0, y1, y2, y3):
    """
    1:4 DEMUX written in full combo

    Inputs:
        x(bool): input feed
        s0(bool): channel select 0
        s1(bool): channel select 1

    Outputs:
        y0(bool): ouput channel 0
        y1(bool): ouput channel 1
        y2(bool): ouput channel 2
        y3(bool): ouput channel 3
    """

    @always_comb
    def logic():
        y0.next= (not s0) and (not s1) and x
        y1.next= s0 and (not s1) and x
        y2.next= (not s0) and s1 and x
        y3.next= s0 and s1 and x

    return instances()
```

## myHDL Testing

```python
TestLen=10
SystmaticVals=list(itertools.product([0,1], repeat=3))

xTVs=np.array([i[2] for i in SystmaticVals]).astype(int)
np.random.seed(15)
xTVs=np.append(xTVs, np.random.randint(0,2, TestLen)).astype(int)

s0TVs=np.array([i[1] for i in SystmaticVals]).astype(int)
#the random genrator must have a differint seed beween each generation
#call in order to produce differint values for each call
np.random.seed(16)
s0TVs=np.append(s0TVs, np.random.randint(0,2, TestLen)).astype(int)

s1TVs=np.array([i[0] for i in SystmaticVals]).astype(int)
#the random genrator must have a differint seed beween each generation
#call in order to produce differint values for each call
np.random.seed(17)
s1TVs=np.append(s1TVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(xTVs)
SystmaticVals, xTVs, s0TVs, s1TVs
```

    ([(0, 0, 0),
      (0, 0, 1),
      (0, 1, 0),
      (0, 1, 1),
      (1, 0, 0),
      (1, 0, 1),
      (1, 1, 0),
      (1, 1, 1)],
     array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]),
     array([0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0]),
     array([0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1]))

```python
Peeker.clear()
x=Signal(bool(0)); Peeker(x, 'x')
s0=Signal(bool(0)); Peeker(s0, 's0')
s1=Signal(bool(0)); Peeker(s1, 's1')
y0=Signal(bool(0)); Peeker(y0, 'y0')
y1=Signal(bool(0)); Peeker(y1, 'y1')
y2=Signal(bool(0)); Peeker(y2, 'y2')
y3=Signal(bool(0)); Peeker(y3, 'y3')

DUT=DEMUX1_4_Combo(x, s0, s1, y0, y1, y2, y3)

def DEMUX1_4_Combo_TB():
    """
    myHDL only testbench for module `DEMUX1_4_Combo`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTVs[i])
            s0.next=int(s0TVs[i])
            s1.next=int(s1TVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

sim=Simulation(DUT, DEMUX1_4_Combo_TB(), *Peeker.instances()).run()
```

```python
Peeker.to_wavedrom('x', 's1', 's0', 'y0', 'y1', 'y2', 'y3')
```

```python
DEMUX1_4_ComboData=Peeker.to_dataframe()
DEMUX1_4_ComboData=DEMUX1_4_ComboData[['x', 's1', 's0', 'y0', 'y1', 'y2', 'y3']]
DEMUX1_4_ComboData
```

      x
      s1
      s0
      y0
      y1
      y2
      y3

      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      1
      0
      0
      0

      2
      0
      0
      1
      0
      0
      0
      0

      3
      1
      0
      1
      0
      1
      0
      0

      4
      0
      1
      0
      0
      0
      0
      0

      5
      1
      1
      0
      0
      0
      1
      0

      6
      0
      1
      1
      0
      0
      0
      0

      7
      1
      1
      1
      0
      0
      0
      1

      8
      0
      1
      1
      0
      0
      0
      0

      9
      1
      1
      0
      0
      0
      1
      0

      10
      0
      1
      1
      0
      0
      0
      0

      11
      1
      0
      1
      0
      1
      0
      0

      13
      0
      1
      1
      0
      0
      0
      0

      14
      0
      0
      0
      0
      0
      0
      0

      15
      1
      1
      1
      0
      0
      0
      1

      16
      1
      0
      1
      0
      1
      0
      0

      17
      1
      1
      0
      0
      0
      1
      0

```python
DEMUX1_4_ComboData['y0Ref']=DEMUX1_4_ComboData.apply(lambda row:y14_0EqN(row['x'], row['s0'], row['s1']), axis=1).astype(int)
DEMUX1_4_ComboData['y1Ref']=DEMUX1_4_ComboData.apply(lambda row:y14_1EqN(row['x'], row['s0'], row['s1']), axis=1).astype(int)
DEMUX1_4_ComboData['y2Ref']=DEMUX1_4_ComboData.apply(lambda row:y14_2EqN(row['x'], row['s0'], row['s1']), axis=1).astype(int)
DEMUX1_4_ComboData['y3Ref']=DEMUX1_4_ComboData.apply(lambda row:y14_3EqN(row['x'], row['s0'], row['s1']), axis=1).astype(int)
DEMUX1_4_ComboData
```

      x
      s1
      s0
      y0
      y1
      y2
      y3
      y0Ref
      y1Ref
      y2Ref
      y3Ref

      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      1
      0
      0
      0
      1
      0
      0
      0

      2
      0
      0
      1
      0
      0
      0
      0
      0
      0
      0
      0

      3
      1
      0
      1
      0
      1
      0
      0
      0
      1
      0
      0

      4
      0
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      5
      1
      1
      0
      0
      0
      1
      0
      0
      0
      1
      0

      6
      0
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0

      7
      1
      1
      1
      0
      0
      0
      1
      0
      0
      0
      1

      8
      0
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0

      9
      1
      1
      0
      0
      0
      1
      0
      0
      0
      1
      0

      10
      0
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0

      11
      1
      0
      1
      0
      1
      0
      0
      0
      1
      0
      0

      13
      0
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0

      14
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      15
      1
      1
      1
      0
      0
      0
      1
      0
      0
      0
      1

      16
      1
      0
      1
      0
      1
      0
      0
      0
      1
      0
      0

      17
      1
      1
      0
      0
      0
      1
      0
      0
      0
      1
      0

```python
Test0=(DEMUX1_4_ComboData['y0']==DEMUX1_4_ComboData['y0Ref']).all()
Test1=(DEMUX1_4_ComboData['y1']==DEMUX1_4_ComboData['y1Ref']).all()
Test2=(DEMUX1_4_ComboData['y2']==DEMUX1_4_ComboData['y2Ref']).all()
Test3=(DEMUX1_4_ComboData['y3']==DEMUX1_4_ComboData['y3Ref']).all()
Test=Test0&Test1&Test2&Test3
print(f'Module `DEMUX1_4_Combo` works as exspected: {Test}')
```

    Module `DEMUX1_4_Combo` works as exspected: True

## Verilog Conversion

```python
DUT.convert()
VerilogTextReader('DEMUX1_4_Combo');
```

    ***Verilog modual from DEMUX1_4_Combo.v***

     // File: DEMUX1_4_Combo.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:17 2018

    `timescale 1ns/10ps

    module DEMUX1_4_Combo (
        x,
        s0,
        s1,
        y0,
        y1,
        y2,
        y3
    );
    // 1:4 DEMUX written in full combo
    //
    // Inputs:
    //     x(bool): input feed
    //     s0(bool): channel select 0
    //     s1(bool): channel select 1
    //
    // Outputs:
    //     y0(bool): ouput channel 0
    //     y1(bool): ouput channel 1
    //     y2(bool): ouput channel 2
    //     y3(bool): ouput channel 3

    input x;
    input s0;
    input s1;
    output y0;
    wire y0;
    output y1;
    wire y1;
    output y2;
    wire y2;
    output y3;
    wire y3;

    assign y0 = ((!s0) && (!s1) && x);
    assign y1 = (s0 && (!s1) && x);
    assign y2 = ((!s0) && s1 && x);
    assign y3 = (s0 && s1 && x);

    endmodule

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_Combo_RTL.png}}
\caption{\label{fig:D14CRTL} DEMUX1_4_Combo RTL schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_Combo_SYN.png}}
\caption{\label{fig:D14CSYN} DEMUX1_4_Combo Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_Combo_IMP.png}}
\caption{\label{fig:D14CIMP} DEMUX1_4_Combo Implementated Schematic; Xilinx Vivado 2017.4}
\end{figure}

## myHDL to Verilog Testbench

```python
#create BitVectors
xTVs=intbv(int(''.join(xTVs.astype(str)), 2))[TestLen:]
s0TVs=intbv(int(''.join(s0TVs.astype(str)), 2))[TestLen:]
s1TVs=intbv(int(''.join(s1TVs.astype(str)), 2))[TestLen:]

xTVs, bin(xTVs), s0TVs, bin(s0TVs), s1TVs, bin(s1TVs)
```

    (intbv(87399),
     '10101010101100111',
     intbv(52982),
     '1100111011110110',
     intbv(16277),
     '11111110010101')

```python
@block
def DEMUX1_4_Combo_TBV():
    """
    myHDL -> testbench for module `DEMUX1_4_Combo`
    """

    x=Signal(bool(0))
    s0=Signal(bool(0))
    s1=Signal(bool(0))
    y0=Signal(bool(0))
    y1=Signal(bool(0))
    y2=Signal(bool(0))
    y3=Signal(bool(0))

    @always_comb
    def print_data():
        print(x, s0, s1, y0, y1, y2, y3)

    #Test Signal Bit Vectors

    xTV=Signal(xTVs)
    s0TV=Signal(s0TVs)
    s1TV=Signal(s1TVs)

    DUT=DEMUX1_4_Combo(x, s0, s1, y0, y1, y2, y3)

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTV[i])
            s0.next=int(s0TV[i])
            s1.next=int(s1TV[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

TB=DEMUX1_4_Combo_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('DEMUX1_4_Combo_TBV');
```

    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    ***Verilog modual from DEMUX1_4_Combo_TBV.v***

     // File: DEMUX1_4_Combo_TBV.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:18 2018

    `timescale 1ns/10ps

    module DEMUX1_4_Combo_TBV (

    );
    // myHDL -> testbench for module `DEMUX1_4_Combo`

    reg x = 0;
    wire y0;
    wire y1;
    reg s0 = 0;
    reg s1 = 0;
    wire y2;
    wire y3;
    wire [17:0] xTV;
    wire [17:0] s0TV;
    wire [17:0] s1TV;

    assign xTV = 18'd87399;
    assign s0TV = 18'd52982;
    assign s1TV = 18'd16277;

    always @(x, y0, s1, s0, y3, y2, y1) begin: DEMUX1_4_COMBO_TBV_PRINT_DATA
        $write("%h", x);
        $write(" ");
        $write("%h", s0);
        $write(" ");
        $write("%h", s1);
        $write(" ");
        $write("%h", y0);
        $write(" ");
        $write("%h", y1);
        $write(" ");
        $write("%h", y2);
        $write(" ");
        $write("%h", y3);
        $write("\n");
    end

    assign y0 = ((!s0) && (!s1) && x);
    assign y1 = (s0 && (!s1) && x);
    assign y2 = ((!s0) && s1 && x);
    assign y3 = (s0 && s1 && x);

    initial begin: DEMUX1_4_COMBO_TBV_STIMULES
        integer i;
        for (i=0; i<18; i=i+1) begin
            x <= xTV[i];
            s0 <= s0TV[i];
            s1 <= s1TV[i];
            # 1;
        end
        $finish;
    end

    endmodule

    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: xTV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: s0TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: s1TV
      category=ToVerilogWarning

## PYNQ-Z1 Deployment

### Board Circuit
\begin{figure}
\centerline{\includegraphics[width=5cm]{DEMUX14PYNQZ1Circ.png}}
\caption{\label{fig:D14Circ} 1:4 DEMUX PYNQ-Z1 (Non SoC) conceptualized circuit}
\end{figure}

### Board Constraints

```python
ConstraintXDCTextReader('DEMUX1_4');
```

    ***Constraint file from DEMUX1_4.xdc***

     ## Switches
    set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports {s0}]; ##SW0
    set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports {s1}]; ##SW1

    ## Buttons

    set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports {x}]; ##BT3

    ## RGBLEDs
    set_property -dict { PACKAGE_PIN L15   IOSTANDARD LVCMOS33 } [get_ports {y0}]; ##LD4_Blue
    set_property -dict { PACKAGE_PIN G17   IOSTANDARD LVCMOS33 } [get_ports {y1}]; ##LD4_Green
    set_property -dict { PACKAGE_PIN L14   IOSTANDARD LVCMOS33 } [get_ports {y2}]; ##LD5_Green
    set_property -dict { PACKAGE_PIN M15   IOSTANDARD LVCMOS33 } [get_ports {y3}]; ##LD5_Red

### Video of Deployment
DEMUX1_4_Combo on PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=VT5Iyy8dMdg))

# 1 Channel Input:4 Channel Output demultiplexer via DEMUX Stacking

## myHDL Module

```python
@block
def DEMUX1_4_DMS(x, s0, s1, y0, y1, y2, y3):
    """
    1:4 DEMUX via DEMUX Stacking
    Inputs:
        x(bool): input feed
        s0(bool): channel select 0
        s1(bool): channel select 1

    Outputs:
        y0(bool): ouput channel 0
        y1(bool): ouput channel 1
        y2(bool): ouput channel 2
        y3(bool): ouput channel 3
    """

    s0_y0y1_WIRE=Signal(bool(0))
    s0_y2y3_WIRE=Signal(bool(0))
    x_s1_DEMUX=DEMUX1_2_Combo(x, s1, s0_y0y1_WIRE, s0_y2y3_WIRE)

    s1_y0y1_DEMUX=DEMUX1_2_Combo(s0_y0y1_WIRE, s0, y0, y1)
    s1_y2y3_DEMUX=DEMUX1_2_Combo(s0_y2y3_WIRE, s0, y2, y3)

    return instances()
```

## myHDL Testing

```python
TestLen=10
SystmaticVals=list(itertools.product([0,1], repeat=3))

xTVs=np.array([i[2] for i in SystmaticVals]).astype(int)
np.random.seed(15)
xTVs=np.append(xTVs, np.random.randint(0,2, TestLen)).astype(int)

s0TVs=np.array([i[1] for i in SystmaticVals]).astype(int)
#the random genrator must have a differint seed beween each generation
#call in order to produce differint values for each call
np.random.seed(16)
s0TVs=np.append(s0TVs, np.random.randint(0,2, TestLen)).astype(int)

s1TVs=np.array([i[0] for i in SystmaticVals]).astype(int)
#the random genrator must have a differint seed beween each generation
#call in order to produce differint values for each call
np.random.seed(17)
s1TVs=np.append(s1TVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(xTVs)
SystmaticVals, xTVs, s0TVs, s1TVs
```

    ([(0, 0, 0),
      (0, 0, 1),
      (0, 1, 0),
      (0, 1, 1),
      (1, 0, 0),
      (1, 0, 1),
      (1, 1, 0),
      (1, 1, 1)],
     array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]),
     array([0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0]),
     array([0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1]))

```python
Peeker.clear()
x=Signal(bool(0)); Peeker(x, 'x')
s0=Signal(bool(0)); Peeker(s0, 's0')
s1=Signal(bool(0)); Peeker(s1, 's1')
y0=Signal(bool(0)); Peeker(y0, 'y0')
y1=Signal(bool(0)); Peeker(y1, 'y1')
y2=Signal(bool(0)); Peeker(y2, 'y2')
y3=Signal(bool(0)); Peeker(y3, 'y3')

DUT=DEMUX1_4_DMS(x, s0, s1, y0, y1, y2, y3)

def DEMUX1_4_DMS_TB():
    """
    myHDL only testbench for module `DEMUX1_4_DMS`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTVs[i])
            s0.next=int(s0TVs[i])
            s1.next=int(s1TVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

sim=Simulation(DUT, DEMUX1_4_DMS_TB(), *Peeker.instances()).run()
```

```python
Peeker.to_wavedrom('x', 's1', 's0', 'y0', 'y1', 'y2', 'y3')
```

```python
DEMUX1_4_DMSData=Peeker.to_dataframe()
DEMUX1_4_DMSData=DEMUX1_4_DMSData[['x', 's1', 's0', 'y0', 'y1', 'y2', 'y3']]
DEMUX1_4_DMSData
```

      x
      s1
      s0
      y0
      y1
      y2
      y3

      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      1
      0
      0
      0

      2
      0
      0
      1
      0
      0
      0
      0

      3
      1
      0
      1
      0
      1
      0
      0

      4
      0
      1
      0
      0
      0
      0
      0

      5
      1
      1
      0
      0
      0
      1
      0

      6
      0
      1
      1
      0
      0
      0
      0

      7
      1
      1
      1
      0
      0
      0
      1

      8
      0
      1
      1
      0
      0
      0
      0

      9
      1
      1
      0
      0
      0
      1
      0

      10
      0
      1
      1
      0
      0
      0
      0

      11
      1
      0
      1
      0
      1
      0
      0

      13
      0
      1
      1
      0
      0
      0
      0

      14
      0
      0
      0
      0
      0
      0
      0

      15
      1
      1
      1
      0
      0
      0
      1

      16
      1
      0
      1
      0
      1
      0
      0

      17
      1
      1
      0
      0
      0
      1
      0

```python
Test=DEMUX1_4_DMSData==DEMUX1_4_ComboData[['x', 's1', 's0', 'y0', 'y1', 'y2', 'y3']]
Test=Test.all().all()
print(f'DEMUX1_4_DMS equivlinet to DEMUX1_4_Combo: {Test}')
```

    DEMUX1_4_DMS equivlinet to DEMUX1_4_Combo: True

## Verilog Conversion

```python
DUT.convert()
VerilogTextReader('DEMUX1_4_DMS');
```

    ***Verilog modual from DEMUX1_4_DMS.v***

     // File: DEMUX1_4_DMS.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:20 2018

    `timescale 1ns/10ps

    module DEMUX1_4_DMS (
        x,
        s0,
        s1,
        y0,
        y1,
        y2,
        y3
    );
    // 1:4 DEMUX via DEMUX Stacking
    // Inputs:
    //     x(bool): input feed
    //     s0(bool): channel select 0
    //     s1(bool): channel select 1
    //
    // Outputs:
    //     y0(bool): ouput channel 0
    //     y1(bool): ouput channel 1
    //     y2(bool): ouput channel 2
    //     y3(bool): ouput channel 3

    input x;
    input s0;
    input s1;
    output y0;
    wire y0;
    output y1;
    wire y1;
    output y2;
    wire y2;
    output y3;
    wire y3;

    wire s0_y2y3_WIRE;
    wire s0_y0y1_WIRE;

    assign s0_y0y1_WIRE = ((!s1) && x);
    assign s0_y2y3_WIRE = (s1 && x);

    assign y0 = ((!s0) && s0_y0y1_WIRE);
    assign y1 = (s0 && s0_y0y1_WIRE);

    assign y2 = ((!s0) && s0_y2y3_WIRE);
    assign y3 = (s0 && s0_y2y3_WIRE);

    endmodule

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_DMS_RTL.png}}
\caption{\label{fig:D14DMSRTL} DEMUX1_4_DMS RTL schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_DMS_SYN.png}}
\caption{\label{fig:D14DMSSYN} DEMUX1_4_DMS Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_DMS_IMP.png}}
\caption{\label{fig:D14DMSIMP} DEMUX1_4_DMS Implementated Schematic; Xilinx Vivado 2017.4}
\end{figure}

## myHDL to Verilog Testbench

```python
#create BitVectors
xTVs=intbv(int(''.join(xTVs.astype(str)), 2))[TestLen:]
s0TVs=intbv(int(''.join(s0TVs.astype(str)), 2))[TestLen:]
s1TVs=intbv(int(''.join(s1TVs.astype(str)), 2))[TestLen:]

xTVs, bin(xTVs), s0TVs, bin(s0TVs), s1TVs, bin(s1TVs)
```

    (intbv(87399),
     '10101010101100111',
     intbv(52982),
     '1100111011110110',
     intbv(16277),
     '11111110010101')

```python
@block
def DEMUX1_4_DMS_TBV():
    """
    myHDL -> testbench for module `DEMUX1_4_DMS`
    """

    x=Signal(bool(0))
    s0=Signal(bool(0))
    s1=Signal(bool(0))
    y0=Signal(bool(0))
    y1=Signal(bool(0))
    y2=Signal(bool(0))
    y3=Signal(bool(0))

    @always_comb
    def print_data():
        print(x, s0, s1, y0, y1, y2, y3)

    #Test Signal Bit Vectors

    xTV=Signal(xTVs)
    s0TV=Signal(s0TVs)
    s1TV=Signal(s1TVs)

    DUT=DEMUX1_4_DMS(x, s0, s1, y0, y1, y2, y3)

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTV[i])
            s0.next=int(s0TV[i])
            s1.next=int(s1TV[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

TB=DEMUX1_4_DMS_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('DEMUX1_4_DMS_TBV');
```

    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    ***Verilog modual from DEMUX1_4_DMS_TBV.v***

     // File: DEMUX1_4_DMS_TBV.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:21 2018

    `timescale 1ns/10ps

    module DEMUX1_4_DMS_TBV (

    );
    // myHDL -> testbench for module `DEMUX1_4_DMS`

    reg x = 0;
    wire y0;
    wire y1;
    reg s0 = 0;
    reg s1 = 0;
    wire y2;
    wire y3;
    wire [17:0] xTV;
    wire [17:0] s0TV;
    wire [17:0] s1TV;
    wire DEMUX1_4_DMS0_0_s0_y2y3_WIRE;
    wire DEMUX1_4_DMS0_0_s0_y0y1_WIRE;

    assign xTV = 18'd87399;
    assign s0TV = 18'd52982;
    assign s1TV = 18'd16277;

    always @(x, y0, s1, s0, y3, y2, y1) begin: DEMUX1_4_DMS_TBV_PRINT_DATA
        $write("%h", x);
        $write(" ");
        $write("%h", s0);
        $write(" ");
        $write("%h", s1);
        $write(" ");
        $write("%h", y0);
        $write(" ");
        $write("%h", y1);
        $write(" ");
        $write("%h", y2);
        $write(" ");
        $write("%h", y3);
        $write("\n");
    end

    assign DEMUX1_4_DMS0_0_s0_y0y1_WIRE = ((!s1) && x);
    assign DEMUX1_4_DMS0_0_s0_y2y3_WIRE = (s1 && x);

    assign y0 = ((!s0) && DEMUX1_4_DMS0_0_s0_y0y1_WIRE);
    assign y1 = (s0 && DEMUX1_4_DMS0_0_s0_y0y1_WIRE);

    assign y2 = ((!s0) && DEMUX1_4_DMS0_0_s0_y2y3_WIRE);
    assign y3 = (s0 && DEMUX1_4_DMS0_0_s0_y2y3_WIRE);

    initial begin: DEMUX1_4_DMS_TBV_STIMULES
        integer i;
        for (i=0; i<18; i=i+1) begin
            x <= xTV[i];
            s0 <= s0TV[i];
            s1 <= s1TV[i];
            # 1;
        end
        $finish;
    end

    endmodule

    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: xTV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: s0TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: s1TV
      category=ToVerilogWarning

## PYNQ-Z1 Deployment

### Board Circuit
See Board Circuit for "1 Channel Input:4 Channel Output demultiplexer in Gate Level Logic"

### Board Constraint
uses same 'DEMUX1_4.xdc' as "# 1 Channel Input:4 Channel Output demultiplexer in Gate Level Logic"

### Video of Deployment
DEMUX1_4_DMS on PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=8A9iDf4nh74))

# 1:2 DEMUX via Behavioral IF

## myHDL Module

```python
@block
def DEMUX1_2_B(x, s, y0, y1):
    """
    1:2 DMUX in behavioral
    Inputs:
        x(bool): input feed
        s(bool): channel select
    Outputs:
        y0(bool): ouput channel 0
        y1(bool): ouput channel 1
    """

    @always_comb
    def logic():
        if s==0:
            #take note that since we have
            #two ouputs there next state values
            #must both be set, else the last
            #value will presist till it changes
            y0.next=x
            y1.next=0
        else:
            y0.next=0
            y1.next=x

    return instances()
```

## myHDL Testing

```python
TestLen=10
SystmaticVals=list(itertools.product([0,1], repeat=2))

xTVs=np.array([i[1] for i in SystmaticVals]).astype(int)
np.random.seed(15)
xTVs=np.append(xTVs, np.random.randint(0,2, TestLen)).astype(int)

sTVs=np.array([i[0] for i in SystmaticVals]).astype(int)
#the random genrator must have a differint seed beween each generation
#call in order to produce differint values for each call
np.random.seed(16)
sTVs=np.append(sTVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(xTVs)
SystmaticVals, sTVs, xTVs
```

    ([(0, 0), (0, 1), (1, 0), (1, 1)],
     array([0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0]),
     array([0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]))

```python
Peeker.clear()
x=Signal(bool(0)); Peeker(x, 'x')
s=Signal(bool(0)); Peeker(s, 's')
y0=Signal(bool(0)); Peeker(y0, 'y0')
y1=Signal(bool(0)); Peeker(y1, 'y1')

DUT=DEMUX1_2_B(x, s, y0, y1)

def DEMUX1_2_B_TB():
    """
    myHDL only testbench for module `DEMUX1_2_B`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTVs[i])
            s.next=int(sTVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

sim=Simulation(DUT, DEMUX1_2_B_TB(), *Peeker.instances()).run()
```

```python
Peeker.to_wavedrom('x', 's', 'y0','y1')
```

```python
DEMUX1_2_BData=Peeker.to_dataframe()
DEMUX1_2_BData=DEMUX1_2_BData[['x', 's', 'y0','y1']]
DEMUX1_2_BData
```

      x
      s
      y0
      y1

      0
      0
      0
      0
      0

      1
      1
      0
      1
      0

      2
      0
      1
      0
      0

      3
      1
      1
      0
      1

      4
      0
      1
      0
      0

      5
      1
      0
      1
      0

      6
      0
      1
      0
      0

      7
      1
      1
      0
      1

      9
      0
      1
      0
      0

      10
      0
      0
      0
      0

      11
      1
      1
      0
      1

      13
      1
      0
      1
      0

```python
Test=DEMUX1_2_BData==DEMUX1_2_ComboData[['x', 's', 'y0','y1']]
Test=Test.all().all()
print(f'DEMUX1_2_BD is equivlent to DEMUX1_2_Combo: {Test}')
```

    DEMUX1_2_BD is equivlent to DEMUX1_2_Combo: True

## Verilog Conversion

```python
DUT.convert()
VerilogTextReader('DEMUX1_2_B');
```

    ***Verilog modual from DEMUX1_2_B.v***

     // File: DEMUX1_2_B.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:23 2018

    `timescale 1ns/10ps

    module DEMUX1_2_B (
        x,
        s,
        y0,
        y1
    );
    // 1:2 DMUX in behavioral
    // Inputs:
    //     x(bool): input feed
    //     s(bool): channel select
    // Outputs:
    //     y0(bool): ouput channel 0
    //     y1(bool): ouput channel 1

    input x;
    input s;
    output y0;
    reg y0;
    output y1;
    reg y1;

    always @(s, x) begin: DEMUX1_2_B_LOGIC
        if ((s == 0)) begin
            y0 = x;
            y1 = 0;
        end
        else begin
            y0 = 0;
            y1 = x;
        end
    end

    endmodule

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_2_B_RTL.png}}
\caption{\label{fig:D12BRTL} DEMUX1_2_B RTL schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_2_B_SYN.png}}
\caption{\label{fig:D12BSYN} DEMUX1_2_B Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_2_B_IMP.png}}
\caption{\label{fig:D12BIMP} DEMUX1_2_B Implementated Schematic; Xilinx Vivado 2017.4}
\end{figure}

## myHDL to Verilog Testbench

```python
#create BitVectors
xTVs=intbv(int(''.join(xTVs.astype(str)), 2))[TestLen:]
sTVs=intbv(int(''.join(sTVs.astype(str)), 2))[TestLen:]

xTVs, bin(xTVs), sTVs, bin(sTVs)
```

    (intbv(5479), '1010101100111', intbv(3830), '111011110110')

```python
@block
def DEMUX1_2_B_TBV():
    """
    myHDL -> testbench for module `DEMUX1_2_B`
    """

    x=Signal(bool(0))
    s=Signal(bool(0))
    y0=Signal(bool(0))
    y1=Signal(bool(0))

    @always_comb
    def print_data():
        print(x, s, y0, y1)

    #Test Signal Bit Vectors

    xTV=Signal(xTVs)
    sTV=Signal(sTVs)

    DUT=DEMUX1_2_B(x, s, y0, y1)

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTV[i])
            s.next=int(sTV[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

TB=DEMUX1_2_B_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('DEMUX1_2_B_TBV');
```

    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    ***Verilog modual from DEMUX1_2_B_TBV.v***

     // File: DEMUX1_2_B_TBV.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:23 2018

    `timescale 1ns/10ps

    module DEMUX1_2_B_TBV (

    );
    // myHDL -> testbench for module `DEMUX1_2_B`

    reg x = 0;
    reg s = 0;
    reg y0 = 0;
    reg y1 = 0;
    wire [13:0] xTV;
    wire [13:0] sTV;

    assign xTV = 14'd5479;
    assign sTV = 14'd3830;

    always @(x, y0, s, y1) begin: DEMUX1_2_B_TBV_PRINT_DATA
        $write("%h", x);
        $write(" ");
        $write("%h", s);
        $write(" ");
        $write("%h", y0);
        $write(" ");
        $write("%h", y1);
        $write("\n");
    end

    always @(s, x) begin: DEMUX1_2_B_TBV_DEMUX1_2_B0_0_LOGIC
        if ((s == 0)) begin
            y0 = x;
            y1 = 0;
        end
        else begin
            y0 = 0;
            y1 = x;
        end
    end

    initial begin: DEMUX1_2_B_TBV_STIMULES
        integer i;
        for (i=0; i<14; i=i+1) begin
            x <= xTV[i];
            s <= sTV[i];
            # 1;
        end
        $finish;
    end

    endmodule

    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: xTV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: sTV
      category=ToVerilogWarning

## PYNQ-Z1 Deployment

### Board Circuit
See Board Circuit for "1 Channel Input: 2 Channel Output demultiplexer in Gate Level Logic"

### Board Constraint
uses same 'DEMUX1_2.xdc' as "1 Channel Input: 2 Channel Output demultiplexer in Gate Level Logic"

### Video of Deployment
DEMUX1_2_B on PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=Ux0olpi2ppI))

# 1:4 DEMUX via Behavioral if-elif-else

## myHDL Module

```python
@block
def DEMUX1_4_B(x, s0, s1, y0, y1, y2, y3):
    """
    1:4 DEMUX written via behaviorial

    Inputs:
        x(bool): input feed
        s0(bool): channel select 0
        s1(bool): channel select 1

    Outputs:
        y0(bool): ouput channel 0
        y1(bool): ouput channel 1
        y2(bool): ouput channel 2
        y3(bool): ouput channel 3
    """

    @always_comb
    def logic():
        if s0==0 and s1==0:
            y0.next=x; y1.next=0
            y2.next=0; y3.next=0

        elif s0==1 and s1==0:
            y0.next=0; y1.next=x
            y2.next=0; y3.next=0

        elif s0==0 and s1==1:
            y0.next=0; y1.next=0
            y2.next=x; y3.next=0

        else:
            y0.next=0; y1.next=0
            y2.next=0; y3.next=x

    return instances()
```

## myHDL Testing

```python
TestLen=10
SystmaticVals=list(itertools.product([0,1], repeat=3))

xTVs=np.array([i[2] for i in SystmaticVals]).astype(int)
np.random.seed(15)
xTVs=np.append(xTVs, np.random.randint(0,2, TestLen)).astype(int)

s0TVs=np.array([i[1] for i in SystmaticVals]).astype(int)
#the random genrator must have a differint seed beween each generation
#call in order to produce differint values for each call
np.random.seed(16)
s0TVs=np.append(s0TVs, np.random.randint(0,2, TestLen)).astype(int)

s1TVs=np.array([i[0] for i in SystmaticVals]).astype(int)
#the random genrator must have a differint seed beween each generation
#call in order to produce differint values for each call
np.random.seed(17)
s1TVs=np.append(s1TVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(xTVs)
SystmaticVals, xTVs, s0TVs, s1TVs
```

    ([(0, 0, 0),
      (0, 0, 1),
      (0, 1, 0),
      (0, 1, 1),
      (1, 0, 0),
      (1, 0, 1),
      (1, 1, 0),
      (1, 1, 1)],
     array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]),
     array([0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0]),
     array([0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1]))

```python
Peeker.clear()
x=Signal(bool(0)); Peeker(x, 'x')
s0=Signal(bool(0)); Peeker(s0, 's0')
s1=Signal(bool(0)); Peeker(s1, 's1')
y0=Signal(bool(0)); Peeker(y0, 'y0')
y1=Signal(bool(0)); Peeker(y1, 'y1')
y2=Signal(bool(0)); Peeker(y2, 'y2')
y3=Signal(bool(0)); Peeker(y3, 'y3')

DUT=DEMUX1_4_B(x, s0, s1, y0, y1, y2, y3)

def DEMUX1_4_B_TB():
    """
    myHDL only testbench for module `DEMUX1_4_Combo`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTVs[i])
            s0.next=int(s0TVs[i])
            s1.next=int(s1TVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

sim=Simulation(DUT, DEMUX1_4_B_TB(), *Peeker.instances()).run()
```

```python
Peeker.to_wavedrom('x', 's1', 's0', 'y0', 'y1', 'y2', 'y3')
```

```python
DEMUX1_4_BData=Peeker.to_dataframe()
DEMUX1_4_BData=DEMUX1_4_BData[['x', 's1', 's0', 'y0', 'y1', 'y2', 'y3']]
DEMUX1_4_BData
```

      x
      s1
      s0
      y0
      y1
      y2
      y3

      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      1
      0
      0
      0

      2
      0
      0
      1
      0
      0
      0
      0

      3
      1
      0
      1
      0
      1
      0
      0

      4
      0
      1
      0
      0
      0
      0
      0

      5
      1
      1
      0
      0
      0
      1
      0

      6
      0
      1
      1
      0
      0
      0
      0

      7
      1
      1
      1
      0
      0
      0
      1

      8
      0
      1
      1
      0
      0
      0
      0

      9
      1
      1
      0
      0
      0
      1
      0

      10
      0
      1
      1
      0
      0
      0
      0

      11
      1
      0
      1
      0
      1
      0
      0

      13
      0
      1
      1
      0
      0
      0
      0

      14
      0
      0
      0
      0
      0
      0
      0

      15
      1
      1
      1
      0
      0
      0
      1

      16
      1
      0
      1
      0
      1
      0
      0

      17
      1
      1
      0
      0
      0
      1
      0

```python
Test=DEMUX1_4_BData==DEMUX1_4_ComboData[['x', 's1', 's0', 'y0', 'y1', 'y2', 'y3']]
Test=Test.all().all()
print(f'DEMUX1_4_B equivlinet to DEMUX1_4_Combo: {Test}')
```

    DEMUX1_4_B equivlinet to DEMUX1_4_Combo: True

## Verilog Conversion

```python
DUT.convert()
VerilogTextReader('DEMUX1_4_B');
```

    ***Verilog modual from DEMUX1_4_B.v***

     // File: DEMUX1_4_B.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:25 2018

    `timescale 1ns/10ps

    module DEMUX1_4_B (
        x,
        s0,
        s1,
        y0,
        y1,
        y2,
        y3
    );
    // 1:4 DEMUX written via behaviorial
    //
    // Inputs:
    //     x(bool): input feed
    //     s0(bool): channel select 0
    //     s1(bool): channel select 1
    //
    // Outputs:
    //     y0(bool): ouput channel 0
    //     y1(bool): ouput channel 1
    //     y2(bool): ouput channel 2
    //     y3(bool): ouput channel 3

    input x;
    input s0;
    input s1;
    output y0;
    reg y0;
    output y1;
    reg y1;
    output y2;
    reg y2;
    output y3;
    reg y3;

    always @(x, s1, s0) begin: DEMUX1_4_B_LOGIC
        if (((s0 == 0) && (s1 == 0))) begin
            y0 = x;
            y1 = 0;
            y2 = 0;
            y3 = 0;
        end
        else if (((s0 == 1) && (s1 == 0))) begin
            y0 = 0;
            y1 = x;
            y2 = 0;
            y3 = 0;
        end
        else if (((s0 == 0) && (s1 == 1))) begin
            y0 = 0;
            y1 = 0;
            y2 = x;
            y3 = 0;
        end
        else begin
            y0 = 0;
            y1 = 0;
            y2 = 0;
            y3 = x;
        end
    end

    endmodule

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_B_RTL.png}}
\caption{\label{fig:D14BRTL} DEMUX1_4_B RTL schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_B_SYN.png}}
\caption{\label{fig:D14BSYN} DEMUX1_4_B Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_B_IMP.png}}
\caption{\label{fig:D14BIMP} DEMUX1_4_B Implementated Schematic; Xilinx Vivado 2017.4}
\end{figure}

## myHDL to Verilog Testbench

```python
#create BitVectors
xTVs=intbv(int(''.join(xTVs.astype(str)), 2))[TestLen:]
s0TVs=intbv(int(''.join(s0TVs.astype(str)), 2))[TestLen:]
s1TVs=intbv(int(''.join(s1TVs.astype(str)), 2))[TestLen:]

xTVs, bin(xTVs), s0TVs, bin(s0TVs), s1TVs, bin(s1TVs)
```

    (intbv(87399),
     '10101010101100111',
     intbv(52982),
     '1100111011110110',
     intbv(16277),
     '11111110010101')

```python
@block
def DEMUX1_4_B_TBV():
    """
    myHDL -> testbench for module `DEMUX1_4_B`
    """

    x=Signal(bool(0))
    s0=Signal(bool(0))
    s1=Signal(bool(0))
    y0=Signal(bool(0))
    y1=Signal(bool(0))
    y2=Signal(bool(0))
    y3=Signal(bool(0))

    @always_comb
    def print_data():
        print(x, s0, s1, y0, y1, y2, y3)

    #Test Signal Bit Vectors

    xTV=Signal(xTVs)
    s0TV=Signal(s0TVs)
    s1TV=Signal(s1TVs)

    DUT=DEMUX1_4_B(x, s0, s1, y0, y1, y2, y3)

    @instance
    def stimules():
        for i in range(TestLen):
            x.next=int(xTV[i])
            s0.next=int(s0TV[i])
            s1.next=int(s1TV[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

TB=DEMUX1_4_B_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('DEMUX1_4_B_TBV');
```

    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    <class 'myhdl._Signal._Signal'> <class '_ast.Name'>
    ***Verilog modual from DEMUX1_4_B_TBV.v***

     // File: DEMUX1_4_B_TBV.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:24:26 2018

    `timescale 1ns/10ps

    module DEMUX1_4_B_TBV (

    );
    // myHDL -> testbench for module `DEMUX1_4_B`

    reg x = 0;
    reg y0 = 0;
    reg y1 = 0;
    reg s0 = 0;
    reg s1 = 0;
    reg y2 = 0;
    reg y3 = 0;
    wire [17:0] xTV;
    wire [17:0] s0TV;
    wire [17:0] s1TV;

    assign xTV = 18'd87399;
    assign s0TV = 18'd52982;
    assign s1TV = 18'd16277;

    always @(x, y0, s1, s0, y3, y2, y1) begin: DEMUX1_4_B_TBV_PRINT_DATA
        $write("%h", x);
        $write(" ");
        $write("%h", s0);
        $write(" ");
        $write("%h", s1);
        $write(" ");
        $write("%h", y0);
        $write(" ");
        $write("%h", y1);
        $write(" ");
        $write("%h", y2);
        $write(" ");
        $write("%h", y3);
        $write("\n");
    end

    always @(x, s1, s0) begin: DEMUX1_4_B_TBV_DEMUX1_4_B0_0_LOGIC
        if (((s0 == 0) && (s1 == 0))) begin
            y0 = x;
            y1 = 0;
            y2 = 0;
            y3 = 0;
        end
        else if (((s0 == 1) && (s1 == 0))) begin
            y0 = 0;
            y1 = x;
            y2 = 0;
            y3 = 0;
        end
        else if (((s0 == 0) && (s1 == 1))) begin
            y0 = 0;
            y1 = 0;
            y2 = x;
            y3 = 0;
        end
        else begin
            y0 = 0;
            y1 = 0;
            y2 = 0;
            y3 = x;
        end
    end

    initial begin: DEMUX1_4_B_TBV_STIMULES
        integer i;
        for (i=0; i<18; i=i+1) begin
            x <= xTV[i];
            s0 <= s0TV[i];
            s1 <= s1TV[i];
            # 1;
        end
        $finish;
    end

    endmodule

    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: xTV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: s0TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: s1TV
      category=ToVerilogWarning

## PYNQ-Z1 Deployment

### Board Circuit
See Board Circuit for "1 Channel Input:4 Channel Output demultiplexer in Gate Level Logic"

### Board Constraint
uses same 'DEMUX1_4.xdc' as "# 1 Channel Input:4 Channel Output demultiplexer in Gate Level Logic"

### Video of Deployment
DEMUX1_4_B on PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=MezWijKoDuk))

# Demultiplexer 1:4 Behavioral via Bitvectors

## myHDL Module

```python
@block
def DEMUX1_4_BV(x, S, Y):
    """
    1:4 DEMUX written via behaviorial with
    bit vectors

    Inputs:
        x(bool): input feed
        S(2bit vector): channel select bitvector;
            min=0, max=3

    Outputs:
        Y(4bit vector): ouput channel bitvector;
            values min=0, max=15; allowed is: 0,1,2,4,8
            in this application

    """

    @always_comb
    def logic():
        #here concat is used to build up the word
        #from the x input
        if S==0:
            Y.next=concat(intbv(0)[3:], x); '0001'
        elif S==1:
            Y.next=concat(intbv(0)[2:], x, intbv(0)[1:]); '0010'
        elif S==2:
            Y.next=concat(intbv(0)[1:], x, intbv(0)[2:]); '0100'
        else:
            Y.next=concat(x, intbv(0)[3:]); '1000'

    return instances()
```

## myHDL Testing

```python
xTVs=np.array([0,1])
xTVs=np.append(xTVs, np.random.randint(0,2,6)).astype(int)
TestLen=len(xTVs)

np.random.seed(12)
STVs=np.arange(0,4)
STVs=np.append(STVs, np.random.randint(0,4, 5))
TestLen, xTVs, STVs
```

    (8, array([0, 1, 0, 1, 0, 0, 1, 1]), array([0, 1, 2, 3, 3, 3, 2, 1, 1]))

```python
Peeker.clear()
x=Signal(bool(0)); Peeker(x, 'x')
S=Signal(intbv(0)[2:]); Peeker(S, 'S')
Y=Signal(intbv(0)[4:]); Peeker(Y, 'Y')

DUT=DEMUX1_4_BV(x, S, Y)

def DEMUX1_4_BV_TB():

    @instance
    def stimules():
        for i in STVs:
            for j in xTVs:
                S.next=int(i)
                x.next=int(j)
                yield delay(1)

        raise StopSimulation()

    return instances()

sim=Simulation(DUT, DEMUX1_4_BV_TB(), *Peeker.instances()).run()
```

```python
Peeker.to_wavedrom('x', 'S', 'Y', start_time=0, stop_time=2*TestLen+2)
```

```python
DEMUX1_4_BVData=Peeker.to_dataframe()
DEMUX1_4_BVData=DEMUX1_4_BVData[['x', 'S', 'Y']]
DEMUX1_4_BVData
```

      x
      S
      Y

      0
      0
      0
      0

      1
      1
      0
      1

      2
      0
      0
      0

      3
      1
      0
      1

      4
      0
      0
      0

      6
      1
      0
      1

      8
      0
      1
      0

      9
      1
      1
      2

      10
      0
      1
      0

      11
      1
      1
      2

      12
      0
      1
      0

      14
      1
      1
      2

      16
      0
      2
      0

      17
      1
      2
      4

      18
      0
      2
      0

      19
      1
      2
      4

      20
      0
      2
      0

      22
      1
      2
      4

      24
      0
      3
      0

      25
      1
      3
      8

      26
      0
      3
      0

      27
      1
      3
      8

      28
      0
      3
      0

      30
      1
      3
      8

      32
      0
      3
      0

      33
      1
      3
      8

      34
      0
      3
      0

      35
      1
      3
      8

      36
      0
      3
      0

      38
      1
      3
      8

      40
      0
      3
      0

      41
      1
      3
      8

      42
      0
      3
      0

      43
      1
      3
      8

      44
      0
      3
      0

      46
      1
      3
      8

      48
      0
      2
      0

      49
      1
      2
      4

      50
      0
      2
      0

      51
      1
      2
      4

      52
      0
      2
      0

      54
      1
      2
      4

      56
      0
      1
      0

      57
      1
      1
      2

      58
      0
      1
      0

      59
      1
      1
      2

      60
      0
      1
      0

      62
      1
      1
      2

      64
      0
      1
      0

      65
      1
      1
      2

      66
      0
      1
      0

      67
      1
      1
      2

      68
      0
      1
      0

      70
      1
      1
      2

```python
DEMUX1_4_BVData['y0']=None; DEMUX1_4_BVData['y1']=None; DEMUX1_4_BVData['y2']=None; DEMUX1_4_BVData['y3']=None
DEMUX1_4_BVData[['y3', 'y2', 'y1', 'y0']]=DEMUX1_4_BVData[['Y']].apply(lambda bv: [int(i) for i in bin(bv, 4)], axis=1, result_type='expand')

DEMUX1_4_BVData['s0']=None; DEMUX1_4_BVData['s1']=None
DEMUX1_4_BVData[['s1', 's0']]=DEMUX1_4_BVData[['S']].apply(lambda bv: [int(i) for i in bin(bv, 2)], axis=1, result_type='expand')

DEMUX1_4_BVData=DEMUX1_4_BVData[['x', 'S', 's0', 's1', 'Y', 'y3', 'y2', 'y1', 'y0']]
DEMUX1_4_BVData
```

      x
      S
      s0
      s1
      Y
      y3
      y2
      y1
      y0

      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      0
      1
      0
      0
      0
      1

      2
      0
      0
      0
      0
      0
      0
      0
      0
      0

      3
      1
      0
      0
      0
      1
      0
      0
      0
      1

      4
      0
      0
      0
      0
      0
      0
      0
      0
      0

      6
      1
      0
      0
      0
      1
      0
      0
      0
      1

      8
      0
      1
      1
      0
      0
      0
      0
      0
      0

      9
      1
      1
      1
      0
      2
      0
      0
      1
      0

      10
      0
      1
      1
      0
      0
      0
      0
      0
      0

      11
      1
      1
      1
      0
      2
      0
      0
      1
      0

      12
      0
      1
      1
      0
      0
      0
      0
      0
      0

      14
      1
      1
      1
      0
      2
      0
      0
      1
      0

      16
      0
      2
      0
      1
      0
      0
      0
      0
      0

      17
      1
      2
      0
      1
      4
      0
      1
      0
      0

      18
      0
      2
      0
      1
      0
      0
      0
      0
      0

      19
      1
      2
      0
      1
      4
      0
      1
      0
      0

      20
      0
      2
      0
      1
      0
      0
      0
      0
      0

      22
      1
      2
      0
      1
      4
      0
      1
      0
      0

      24
      0
      3
      1
      1
      0
      0
      0
      0
      0

      25
      1
      3
      1
      1
      8
      1
      0
      0
      0

      26
      0
      3
      1
      1
      0
      0
      0
      0
      0

      27
      1
      3
      1
      1
      8
      1
      0
      0
      0

      28
      0
      3
      1
      1
      0
      0
      0
      0
      0

      30
      1
      3
      1
      1
      8
      1
      0
      0
      0

      32
      0
      3
      1
      1
      0
      0
      0
      0
      0

      33
      1
      3
      1
      1
      8
      1
      0
      0
      0

      34
      0
      3
      1
      1
      0
      0
      0
      0
      0

      35
      1
      3
      1
      1
      8
      1
      0
      0
      0

      36
      0
      3
      1
      1
      0
      0
      0
      0
      0

      38
      1
      3
      1
      1
      8
      1
      0
      0
      0

      40
      0
      3
      1
      1
      0
      0
      0
      0
      0

      41
      1
      3
      1
      1
      8
      1
      0
      0
      0

      42
      0
      3
      1
      1
      0
      0
      0
      0
      0

      43
      1
      3
      1
      1
      8
      1
      0
      0
      0

      44
      0
      3
      1
      1
      0
      0
      0
      0
      0

      46
      1
      3
      1
      1
      8
      1
      0
      0
      0

      48
      0
      2
      0
      1
      0
      0
      0
      0
      0

      49
      1
      2
      0
      1
      4
      0
      1
      0
      0

      50
      0
      2
      0
      1
      0
      0
      0
      0
      0

      51
      1
      2
      0
      1
      4
      0
      1
      0
      0

      52
      0
      2
      0
      1
      0
      0
      0
      0
      0

      54
      1
      2
      0
      1
      4
      0
      1
      0
      0

      56
      0
      1
      1
      0
      0
      0
      0
      0
      0

      57
      1
      1
      1
      0
      2
      0
      0
      1
      0

      58
      0
      1
      1
      0
      0
      0
      0
      0
      0

      59
      1
      1
      1
      0
      2
      0
      0
      1
      0

      60
      0
      1
      1
      0
      0
      0
      0
      0
      0

      62
      1
      1
      1
      0
      2
      0
      0
      1
      0

      64
      0
      1
      1
      0
      0
      0
      0
      0
      0

      65
      1
      1
      1
      0
      2
      0
      0
      1
      0

limit_output extension: Maximum message size of 10000 exceeded with 10802 characters

```python
DEMUX1_4_BVData['y0Ref']=DEMUX1_4_BVData.apply(lambda row:y14_0EqN(row['x'], row['s0'], row['s1']), axis=1).astype(int)
DEMUX1_4_BVData['y1Ref']=DEMUX1_4_BVData.apply(lambda row:y14_1EqN(row['x'], row['s0'], row['s1']), axis=1).astype(int)
DEMUX1_4_BVData['y2Ref']=DEMUX1_4_BVData.apply(lambda row:y14_2EqN(row['x'], row['s0'], row['s1']), axis=1).astype(int)
DEMUX1_4_BVData['y3Ref']=DEMUX1_4_BVData.apply(lambda row:y14_3EqN(row['x'], row['s0'], row['s1']), axis=1).astype(int)

DEMUX1_4_BVData
```

    /home/iridium/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning:
    A value is trying to be set on a copy of a slice from a DataFrame.
    Try using .loc[row_indexer,col_indexer] = value instead

    See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
      """Entry point for launching an IPython kernel.
    /home/iridium/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:2: SettingWithCopyWarning:
    A value is trying to be set on a copy of a slice from a DataFrame.
    Try using .loc[row_indexer,col_indexer] = value instead

    See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

    /home/iridium/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:3: SettingWithCopyWarning:
    A value is trying to be set on a copy of a slice from a DataFrame.
    Try using .loc[row_indexer,col_indexer] = value instead

    See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
      This is separate from the ipykernel package so we can avoid doing imports until
    /home/iridium/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:4: SettingWithCopyWarning:
    A value is trying to be set on a copy of a slice from a DataFrame.
    Try using .loc[row_indexer,col_indexer] = value instead

    See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
      after removing the cwd from sys.path.

      x
      S
      s0
      s1
      Y
      y3
      y2
      y1
      y0
      y0Ref
      y1Ref
      y2Ref
      y3Ref

      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      0
      1
      0
      0
      0
      1
      1
      0
      0
      0

      2
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      3
      1
      0
      0
      0
      1
      0
      0
      0
      1
      1
      0
      0
      0

      4
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      6
      1
      0
      0
      0
      1
      0
      0
      0
      1
      1
      0
      0
      0

      8
      0
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      9
      1
      1
      1
      0
      2
      0
      0
      1
      0
      0
      1
      0
      0

      10
      0
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      11
      1
      1
      1
      0
      2
      0
      0
      1
      0
      0
      1
      0
      0

      12
      0
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      14
      1
      1
      1
      0
      2
      0
      0
      1
      0
      0
      1
      0
      0

      16
      0
      2
      0
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      17
      1
      2
      0
      1
      4
      0
      1
      0
      0
      0
      0
      1
      0

      18
      0
      2
      0
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      19
      1
      2
      0
      1
      4
      0
      1
      0
      0
      0
      0
      1
      0

      20
      0
      2
      0
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      22
      1
      2
      0
      1
      4
      0
      1
      0
      0
      0
      0
      1
      0

      24
      0
      3
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      25
      1
      3
      1
      1
      8
      1
      0
      0
      0
      0
      0
      0
      1

      26
      0
      3
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      27
      1
      3
      1
      1
      8
      1
      0
      0
      0
      0
      0
      0
      1

      28
      0
      3
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      30
      1
      3
      1
      1
      8
      1
      0
      0
      0
      0
      0
      0
      1

      32
      0
      3
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      33
      1
      3
      1
      1
      8
      1
      0
      0
      0
      0
      0
      0
      1

      34
      0
      3
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      35
      1
      3
      1
      1
      8
      1
      0
      0
      0
      0
      0
      0
      1

      36
      0
      3
      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0

      38
      1
      3
      1
      1
      8
      1
      0
      0
      0
      0
      0
      0
      1

      40
      0
      3
      1
      1</td

limit_output extension: Maximum message size of 10000 exceeded with 16125 characters

```python
Test=DEMUX1_4_BVData[['y0', 'y1', 'y2', 'y3']].sort_index(inplace=True)==DEMUX1_4_BVData[['y0Ref', 'y1Ref', 'y2Ref', 'y3Ref']].sort_index(inplace=True)
print(f'Module `DEMUX1_4_BVData` works as exspected: {Test}')
```

    Module `DEMUX1_4_BVData` works as exspected: True

## Verilog Conversion

```python
DUT.convert()
VerilogTextReader('DEMUX1_4_BV');
```

    ***Verilog modual from DEMUX1_4_BV.v***

     // File: DEMUX1_4_BV.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:48:43 2018

    `timescale 1ns/10ps

    module DEMUX1_4_BV (
        x,
        S,
        Y
    );
    // 1:4 DEMUX written via behaviorial with
    // bit vectors
    //
    // Inputs:
    //     x(bool): input feed
    //     S(2bit vector): channel select bitvector;
    //         min=0, max=3
    //
    // Outputs:
    //     Y(4bit vector): ouput channel bitvector;
    //         values min=0, max=15; allowed is: 0,1,2,4,8
    //         in this application
    //

    input x;
    input [1:0] S;
    output [3:0] Y;
    reg [3:0] Y;

    always @(x, S) begin: DEMUX1_4_BV_LOGIC
        case (S)
            'h0: begin
                Y = {3'h0, x};
                // 0001
            end
            'h1: begin
                Y = {2'h0, x, 1'h0};
                // 0010
            end
            'h2: begin
                Y = {1'h0, x, 2'h0};
                // 0100
            end
            default: begin
                Y = {x, 3'h0};
                // 1000
            end
        endcase
    end

    endmodule

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_BV_RTL.png}}
\caption{\label{fig:D14BVRTL} DEMUX1_4_BV RTL schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_BV_SYN.png}}
\caption{\label{fig:D14BVSYN} DEMUX1_4_BV Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}

\begin{figure}
\centerline{\includegraphics[width=10cm]{DEMUX1_4_BV_IMP.png}}
\caption{\label{fig:D14BVIMP} DEMUX1_4_BV Implementated Schematic; Xilinx Vivado 2017.4}
\end{figure}

## myHDL to Verilog Testbench
(To Do!)

## PYNQ-Z1 Board Deployment

### Board Circuit

### Board Constraints

```python
ConstraintXDCTextReader('DEMUX1_4_BV');
```

    ***Constraint file from DEMUX1_4_BV.xdc***

     ## Switches
    set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS33} [get_ports {S[0]}]; ##SW0
    set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports {S[1]}]; ##SW1

    ## Buttons

    set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports {x}]; ##BT3

    ## RGBLEDs
    set_property -dict { PACKAGE_PIN L15   IOSTANDARD LVCMOS33 } [get_ports {Y[0]}]; ##LD4_Blue
    set_property -dict { PACKAGE_PIN G17   IOSTANDARD LVCMOS33 } [get_ports {Y[1]}]; ##LD4_Green
    set_property -dict { PACKAGE_PIN L14   IOSTANDARD LVCMOS33 } [get_ports {Y[2]}]; ##LD5_Green
    set_property -dict { PACKAGE_PIN M15   IOSTANDARD LVCMOS33 } [get_ports {Y[3]}]; ##LD5_Red

### Video of Deployment
DEMUX1_4_BV on PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=mVyTlkbJpKg))


```python
import numpy as np
#from pydgrid.pydgrid import grid
from pydgrid.plot_bokeh import plot_results
import sympy as sym
import pydae.build as db
from pydae.grid_urisi import unb_ri_si
import json
```

```python
data = {
        "buses":[
                 {"bus": "B1",  "pos_x":   0, "pos_y":  0, "units": "m", "U_kV":0.4},
                 {"bus": "B2",  "pos_x":  20, "pos_y":  0, "units": "m", "U_kV":0.4},
                 {"bus": "B3",  "pos_x": 120, "pos_y":  0, "units": "m", "U_kV":0.4},
                 {"bus": "B4",  "pos_x": 140, "pos_y":  0, "units": "m", "U_kV":0.4}
                ],
        "grid_formers":[
                      #  {"bus": "B1",
                      #  "bus_nodes": [1, 2, 3], "deg": [0, -120, -240],
                      #  "kV": [0.231, 0.231, 0.231]},
                      # {"bus": "B4",
                      # "bus_nodes": [1, 2, 3], "deg": [0, -120, -240],
                     #  "kV": [0.231, 0.231, 0.231]}
                       ],
        "lines":[
                 {"bus_j": "B1",  "bus_k": "B2",  "code": "lv_cu_150", "m":  20.0,'monitor':True},
                 {"bus_j": "B2",  "bus_k": "B3",  "code": "lv_cu_150", "m": 100.0,'monitor':True},
                 {"bus_j": "B3",  "bus_k": "B4",  "code": "lv_cu_150", "m":  20.0,'monitor':True}
                ],
        "loads":[
                 {"bus": "B2" , "kVA": [0.1]*3, "pf":[ 1]*3,"type":"3P+N"},
                 {"bus": "B3" , "kVA": [0.1]*3, "pf":[ 1]*3,"type":"3P+N"},
                # {"bus": "B4" , "kVA": [0.1]*3, "pf":[ 1]*3,"type":"3P+N"},
                ],
        "shunts":[
                 #{"bus": "B1" , "R": 0.001, "X": 0.0, "bus_nodes": [4,0]},
                 #{"bus": "B4" , "R": 0.001, "X": 0.0, "bus_nodes": [4,0]}
                 ],
        "line_codes":
            {"lv_cu_150":  {"Rph":0.167,"Xph":0.08, "Rn":0.167, "Xn": 0.08}
            }
       }
```

```python
alpha = np.exp(2.0/3*np.pi*1j)
A_0a =  np.array([[1, 1, 1],
                  [1, alpha**2, alpha],
                  [1, alpha, alpha**2]])

A_a0 = 1/3* np.array([[1, 1, 1],
                      [1, alpha, alpha**2],
                      [1, alpha**2, alpha]])
```

```python
grid_4bus = unb_ri_si(data)

params_dict  = grid_4bus.dae['params']
f_list = grid_4bus.dae['f']
x_list = grid_4bus.dae['x']
g_list = grid_4bus.dae['g']
y_list = grid_4bus.dae['y']
u_dict = grid_4bus.dae['u']
h_dict = grid_4bus.dae['h_v_m_dict']

omega_coi_i = 0
HS_coi = 0

omega_coi = sym.Symbol('omega_coi',real=True)
xi_freq = sym.Symbol('xi_freq',real=True)
K_agc = sym.Symbol('K_agc',real=True)

vscs = [
       {'bus':'B1','S_n':100e3,'R':0.01,'X':0.1,'K_f':0.1,'T_f':1.0,'K_sec':0.5,'K_delta':0.001},
       {'bus':'B4','S_n':100e3,'R':0.01,'X':0.1,'K_f':0.1,'T_f':1.0,'K_sec':0.5,'K_delta':0.000},
       ]
for vsc in vscs:

    name = vsc['bus']

    # inputs
    e_an,e_bn,e_cn,e_ng = sym.symbols(f'e_{name}_an,e_{name}_bn,e_{name}_cn,e_{name}_ng', real=True)
    omega_ref,p_ref = sym.symbols(f'omega_{name}_ref,p_{name}_ref', real=True)

    # parameters
    S_n,H,K_f,T_f,K_sec,K_delta  = sym.symbols(f'S_n_{name},H_{name},K_f_{name},T_f_{name},K_sec_{name},K_delta_{name}', real=True)
    R_sa,R_sb,R_sc,R_sn,R_ng = sym.symbols(f'R_{name}_sa,R_{name}_sb,R_{name}_sc,R_{name}_sn,R_{name}_ng', real=True)
    X_sa,X_sb,X_sc,X_sn,X_ng = sym.symbols(f'X_{name}_sa,X_{name}_sb,X_{name}_sc,X_{name}_sn,X_{name}_ng', real=True)

    # dynamical states
    phi = sym.Symbol(f'phi_{name}', real=True)
    omega = sym.Symbol(f'omega_{name}', real=True)

    # algebraic states
    #e_an_i,e_bn_i,e_cn_i,e_ng_i = sym.symbols(f'e_{name}_an_i,e_{name}_bn_i,e_{name}_cn_i,e_{name}_ng_i', real=True)
    v_sa_r,v_sb_r,v_sc_r,v_sn_r,v_ng_r = sym.symbols(f'v_{name}_a_r,v_{name}_b_r,v_{name}_c_r,v_{name}_n_r,v_{name}_n_r', real=True)
    v_sa_i,v_sb_i,v_sc_i,v_sn_i,v_ng_i = sym.symbols(f'v_{name}_a_i,v_{name}_b_i,v_{name}_c_i,v_{name}_n_i,v_{name}_n_i', real=True)
    i_sa_r,i_sb_r,i_sc_r,i_sn_r,i_ng_r = sym.symbols(f'i_{name}_a_r,i_{name}_b_r,i_{name}_c_r,i_{name}_n_r,i_{name}_ng_r', real=True)
    i_sa_i,i_sb_i,i_sc_i,i_sn_i,i_ng_i = sym.symbols(f'i_{name}_a_i,i_{name}_b_i,i_{name}_c_i,i_{name}_n_i,i_{name}_ng_i', real=True)
    omega = sym.Symbol(f'omega_{name}', real=True)

    e_ng_r,e_ng_i = sym.symbols(f'e_{name}_ng_r,e_{name}_ng_i', real=True)

    Z_sa = R_sa + 1j*X_sa
    Z_sb = R_sb + 1j*X_sb
    Z_sc = R_sc + 1j*X_sc
    Z_sn = R_sn + 1j*X_sn
    Z_ng = R_ng + 1j*X_ng

    i_sa = i_sa_r + 1j*i_sa_i
    i_sb = i_sb_r + 1j*i_sb_i
    i_sc = i_sc_r + 1j*i_sc_i
    i_sn = i_sn_r + 1j*i_sn_i
    i_ng = i_ng_r + 1j*i_ng_i

    v_sa = v_sa_r + 1j*v_sa_i
    v_sb = v_sb_r + 1j*v_sb_i
    v_sc = v_sc_r + 1j*v_sc_i
    v_sn = v_sn_r + 1j*v_sn_i
    v_ng = v_ng_r + 1j*v_ng_i

    e_an_r = e_an*sym.cos(phi)
    e_an_i = e_an*sym.sin(phi)
    e_bn_r = e_bn*sym.cos(phi-2/3*np.pi)
    e_bn_i = e_bn*sym.sin(phi-2/3*np.pi)
    e_cn_r = e_cn*sym.cos(phi-4/3*np.pi)
    e_cn_i = e_cn*sym.sin(phi-4/3*np.pi)

    e_an_cplx = e_an_r + 1j*e_an_i
    e_bn_cplx = e_bn_r + 1j*e_bn_i
    e_cn_cplx = e_cn_r + 1j*e_cn_i
    e_ng_cplx = e_ng_r + 1j*e_ng_i

    v_san = v_sa - v_sn
    v_sbn = v_sb - v_sn
    v_scn = v_sc - v_sn

    eq_i_sa_cplx = e_an_cplx - i_sa*Z_sa - v_san
    eq_i_sb_cplx = e_bn_cplx - i_sb*Z_sb - v_sbn
    eq_i_sc_cplx = e_cn_cplx - i_sc*Z_sc - v_scn
    eq_i_sn_cplx = e_ng_cplx - i_sn*Z_sn - v_ng
    eq_i_ng_cplx = -i_ng + i_sa + i_sb + i_sc + i_sn
    eq_e_ng_cplx  = -e_ng_cplx  + i_ng*Z_ng

    g_list += [sym.re(eq_i_sa_cplx)]
    g_list += [sym.re(eq_i_sb_cplx)]
    g_list += [sym.re(eq_i_sc_cplx)]
    g_list += [sym.re(eq_i_sn_cplx)]
    g_list += [sym.re(eq_i_ng_cplx)]
    g_list += [sym.re(eq_e_ng_cplx)]
    g_list += [sym.im(eq_i_sa_cplx)]
    g_list += [sym.im(eq_i_sb_cplx)]
    g_list += [sym.im(eq_i_sc_cplx)]
    g_list += [sym.im(eq_i_sn_cplx)]
    g_list += [sym.im(eq_i_ng_cplx)]
    g_list += [sym.im(eq_e_ng_cplx)]

    y_list += [i_sa_r,i_sb_r,i_sc_r,i_sn_r,i_ng_r,e_ng_r]
    y_list += [i_sa_i,i_sb_i,i_sc_i,i_sn_i,i_ng_i,e_ng_i]

    y_ini_str = [str(item) for item in y_list]

    for ph in ['a','b','c','n']:
        i_s_r = sym.Symbol(f'i_{name}_{ph}_r', real=True)
        i_s_i = sym.Symbol(f'i_{name}_{ph}_i', real=True)
        g_list[y_ini_str.index(f'v_{name}_{ph}_r')] += i_s_r
        g_list[y_ini_str.index(f'v_{name}_{ph}_i')] += i_s_i

    V_1 = 400/np.sqrt(3)
#    V_1 = 400/np.sqrt(3)*np.exp(1j*np.deg2rad(0))
   # A_1toabc = np.array([1, alpha**2, alpha])
    #V_abc = V_1 * A_1toabc
    #e_an_r,e_bn_r,e_cn_r = V_abc.real
    #e_an_i,e_bn_i,e_cn_i = V_abc.imag

    u_dict.update({f'e_{name}_an':V_1,f'e_{name}_bn':V_1,f'e_{name}_cn':V_1})
    u_dict.update({f'phi_{name}':0.0})
    u_dict.update({f'p_{name}_ref':0.0})
    u_dict.update({f'omega_{name}_ref':1.0})

    for ph in ['a','b','c','n']:
        u_dict.pop(f'i_{name}_{ph}_r')
        u_dict.pop(f'i_{name}_{ph}_i')

    for ph in ['a','b','c','n']:
        params_dict.update({f'X_{name}_s{ph}':vsc['X'],f'R_{name}_s{ph}':vsc['R']})

    params_dict.update({f'S_n_{name}':vsc['S_n']})
    params_dict.update({f'X_{name}_ng':vsc['X'],f'R_{name}_ng':vsc['R']})
    params_dict.update({f'K_f_{name}':vsc['K_f']})
    params_dict.update({f'T_f_{name}':vsc['T_f']})
    params_dict.update({f'K_sec_{name}':vsc['K_sec']})
    params_dict.update({f'K_delta_{name}':vsc['K_delta']})

    v_sabc = sym.Matrix([[v_sa],[v_sb],[v_sc]])
    i_sabc = sym.Matrix([[i_sa],[i_sb],[i_sc]])

    v_szpn = A_a0*v_sabc
    i_szpn = A_a0*i_sabc

    s_pos = 3*v_szpn[1]*sym.conjugate(i_szpn[1])
    s_neg = 3*v_szpn[2]*sym.conjugate(i_szpn[2])
    s_zer = 3*v_szpn[0]*sym.conjugate(i_szpn[0])

    p_pos = sym.re(s_pos)

    dphi   = 2*np.pi*50*(omega - omega_coi) - K_delta*phi
    domega = 1/T_f*(omega_ref - K_f*(p_ref + K_sec*xi_freq - p_pos)/S_n - omega)

    f_list += [dphi,domega]
    x_list += [ phi, omega]

    h_dict.update({f'p_{name}_pos':sym.re(s_pos),f'p_{name}_neg':sym.re(s_neg),f'p_{name}_zer':sym.re(s_zer)})
    h_dict.update({str(e_an):e_an,str(e_bn):e_bn,str(e_cn):e_cn})
    h_dict.update({str(p_ref):p_ref,str(omega_ref):omega_ref})
    HS_coi += S_n
    omega_coi_i+= S_n*omega

g_list += [omega_coi -  omega_coi_i/HS_coi]
y_list += [omega_coi]

dxi_freq = K_agc*(1 - omega_coi)

f_list += [dxi_freq]
x_list += [ xi_freq]

params_dict.update({f'K_agc':0.001})

```

    Matrix(16, 0, [])

```python
sys_dict = {'name':'oc_4bus4wire2src',
           'params_dict':params_dict,
           'f_list':f_list,
           'g_list':g_list,
           'x_list':x_list,
           'y_ini_list':y_list,
           'y_run_list':y_list,
           'u_run_dict':u_dict,
           'u_ini_dict':u_dict,
           'h_dict':h_dict
           }

db.system(sys_dict)
db.sys2num(sys_dict)

data_new = json.dumps(grid_4bus.dae['xy_0_dict'], indent=4)
fobj = open("xy_0_dict.json","w")
fobj.write(data_new)
fobj.close()
```

```python
grid_4bus.pf()  # solve power flow
p=plot_results(grid_4bus)
```

```python
Y_ii = grid_4bus.Y_ii.toarray()
Y_vv = grid_4bus.Y_vv
Y_vi = grid_4bus.Y_vi
inv_Y_ii = np.linalg.inv(Y_ii)
N_nz_nodes = grid_4bus.params_pf[0].N_nz_nodes
N_v = grid_4bus.params_pf[0].N_nodes_v
nodes_list = grid_4bus.nodes
Y_primitive = grid_4bus.Y_primitive_sp.toarray()
A_conect = grid_4bus.A_sp.toarray()
node_sorter  = grid_4bus.node_sorter
N_v = grid_4bus.N_nodes_v

np.savez('matrices',Y_primitive=Y_primitive,A_conect=A_conect,nodes_list=nodes_list,
         node_sorter=node_sorter,N_v=N_v, Y_vv=Y_vv, Y_vi=Y_vi)

with open("grid_data.json", "w") as fobj:
    json.dump(grid_4bus.data, fobj, indent=4, sort_keys=True)

```

```python
print(sys_dict['g'][y_ini_str.index('v_B1_n_i')])
```

    i_B1_n_i - 1243.51832949342*v_B1_n_i + 116.655487182478*v_B1_n_r + 243.518329493424*v_B2_n_i - 116.655487182478*v_B2_n_r

```python
sys_dict['y_ini'].T
```

$\displaystyle \left[\begin{matrix}v_{B2 a r}\\v_{B2 a i}\\v_{B2 b r}\\v_{B2 b i}\\v_{B2 c r}\\v_{B2 c i}\\v_{B2 n r}\\v_{B2 n i}\\v_{B3 a r}\\v_{B3 a i}\\v_{B3 b r}\\v_{B3 b i}\\v_{B3 c r}\\v_{B3 c i}\\v_{B3 n r}\\v_{B3 n i}\\v_{B1 a r}\\v_{B1 a i}\\v_{B1 b r}\\v_{B1 b i}\\v_{B1 c r}\\v_{B1 c i}\\v_{B1 n r}\\v_{B1 n i}\\v_{B4 a r}\\v_{B4 a i}\\v_{B4 b r}\\v_{B4 b i}\\v_{B4 c r}\\v_{B4 c i}\\v_{B4 n r}\\v_{B4 n i}\\i_{l B1 B2 a r}\\i_{l B1 B2 a i}\\i_{l B1 B2 b r}\\i_{l B1 B2 b i}\\i_{l B1 B2 c r}\\i_{l B1 B2 c i}\\i_{l B1 B2 n r}\\i_{l B1 B2 n i}\\i_{l B2 B3 a r}\\i_{l B2 B3 a i}\\i_{l B2 B3 b r}\\i_{l B2 B3 b i}\\i_{l B2 B3 c r}\\i_{l B2 B3 c i}\\i_{l B2 B3 n r}\\i_{l B2 B3 n i}\\i_{l B3 B4 a r}\\i_{l B3 B4 a i}\\i_{l B3 B4 b r}\\i_{l B3 B4 b i}\\i_{l B3 B4 c r}\\i_{l B3 B4 c i}\\i_{l B3 B4 n r}\\i_{l B3 B4 n i}\\i_{load B2 a r}\\i_{load B2 a i}\\i_{load B2 b r}\\i_{load B2 b i}\\i_{load B2 c r}\\i_{load B2 c i}\\i_{load B2 n r}\\i_{load B2 n i}\\i_{load B3 a r}\\i_{load B3 a i}\\i_{load B3 b r}\\i_{load B3 b i}\\i_{load B3 c r}\\i_{load B3 c i}\\i_{load B3 n r}\\i_{load B3 n i}\\i_{B1 a r}\\i_{B1 b r}\\i_{B1 c r}\\i_{B1 n r}\\i_{B1 ng r}\\e_{B4 ng r}\\i_{B1 a i}\\i_{B1 b i}\\i_{B1 c i}\\i_{B1 n i}\\i_{B1 ng i}\\e_{B4 ng i}\\i_{B4 a r}\\i_{B4 b r}\\i_{B4 c r}\\i_{B4 n r}\\i_{B4 ng r}\\e_{B4 ng r}\\i_{B4 a i}\\i_{B4 b i}\\i_{B4 c i}\\i_{B4 n i}\\i_{B4 ng i}\\e_{B4 ng i}\end{matrix}\right]$

```python

```


```python
from tectosaur2.nb_config import setup

setup()
```

```python
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
from tectosaur2 import gauss_rule, refine_surfaces, integrate_term, tensor_dot
from tectosaur2.laplace2d import double_layer, hypersingular
from tectosaur2.mesh import panelize_symbolic_surface
from tectosaur2.debug import plot_centers
```

```python
t = sp.var("t")
surf = refine_surfaces(
    [(t, t, 0 * t)], gauss_rule(12), control_points=[(0, 0, 0, 0.2)]
)
displacement = 1 - np.abs(surf.pts[:, 0])
from tectosaur2.laplace2d import Hypersingular
mat,report = integrate_term(
    Hypersingular(max_p=50),
    surf.pts,
    surf,
    tol=1e-11,
    safety_mode=True,
    singularities=[(-1, 0), (1, 0)],
    return_report=True
)
stress = tensor_dot(mat, displacement)
import matplotlib.pyplot as plt
# plt.figure(figsize=(8, 4))
# plt.subplot(1, 2, 1)
# plt.plot(surf.pts[:, 0], displacement)
# plt.subplot(1, 2, 2)
# plt.plot(surf.pts[:, 0], stress[:, 0])
# plt.plot(surf.pts[:, 0], stress[:, 1])
# plt.show()

plt.plot(report['integration_failed'])
plt.show()
plt.plot(report['p'])
plt.show()
plt.plot(stress[:,0]+np.sign(surf.pts[:,0]) * 0.5)
plt.show()
np.testing.assert_allclose(stress[:,0], -np.sign(surf.pts[:,0]) * 0.5)
```

```python
surf_half_L = 100000
fault_bottom = 40000
max_panel_length = 2000
n_fault=40
shear_modulus = 3.2e10

qx, qw = gauss_rule(7)
t = sp.var("t")

# The number of fault panels should be a multiple of 40.
# so that the kinks in the "a" parameter profile occur at panel boundaries.
edges = np.linspace(-1, 1, n_fault+1)
panel_bounds = np.stack((edges[:-1],edges[1:]), axis=1)
fault = panelize_symbolic_surface(
    t, t * 0, fault_bottom * (t + 1) * -0.5,
    panel_bounds,
    qx, qw
)

print(
    f"The fault mesh has {fault.n_panels} panels with a total of {fault.n_pts} points."
)
```

    The fault mesh has 40 panels with a total of 280 points.

```python
%%time
safe_slip_to_stress, safe_report = integrate_term(
    hypersingular,
    fault.pts,
    fault,
    tol=1e-14,
    safety_mode=True,
    return_report=True,
)
```

    CPU times: user 887 ms, sys: 30.5 ms, total: 918 ms
    Wall time: 114 ms

    /Users/tbent/Dropbox/active/eq/tectosaur2/tectosaur2/integrate.py:174: UserWarning: Some integrals failed to converge during adaptive integration. This an indication of a problem in either the integration or the problem formulation.
      warnings.warn(
    /Users/tbent/Dropbox/active/eq/tectosaur2/tectosaur2/integrate.py:180: UserWarning: Some expanded integrals reached maximum expansion order. These integrals may be inaccurate.
      warnings.warn(

```python

%%time
unsafe_slip_to_stress, unsafe_report = integrate_term(
    hypersingular,
    fault.pts,
    fault,
    tol=1e-14,
    safety_mode=False,
    return_report=True,
)
```

    CPU times: user 140 ms, sys: 13.9 ms, total: 154 ms
    Wall time: 26.9 ms

```python
plt.figure(figsize=(8,4))
plt.subplot(1,2,1)
plot_centers(unsafe_report,[-1000,1000], [-31000, -29000])
plt.subplot(1,2,2)
plot_centers(safe_report,[-1000,1000], [-31000, -29000])
plt.show()
```

```python
unsafe_slip_to_stress *= -2 * shear_modulus
safe_slip_to_stress *= -2 * shear_modulus
```

```python
fy = fault.pts[:,1]
v = -np.abs(fy + 20000) + 10000
slip = np.where(v > 0, v, 0)
true_syz = np.where(fy > -30000, np.where(fy < -20000, shear_modulus, np.where(fy < -10000, -shear_modulus, 0)), 0)
safe_stress = tensor_dot(safe_slip_to_stress, slip)
unsafe_stress = tensor_dot(unsafe_slip_to_stress, slip)
plt.figure(figsize=(8,8))
plt.subplot(2,2,1)
plt.plot(fy, slip)
plt.subplot(2,2,2)
plt.plot(fy,safe_stress[:,0],'b-')
plt.plot(fy,true_syz,'r-')
plt.subplot(2,2,3)
plt.plot(fy, np.log10(np.abs((safe_stress[:,1] - true_syz) / shear_modulus)))
plt.ylim([-20,0])
plt.subplot(2,2,4)
plt.plot(fy, np.log10(np.abs((unsafe_stress[:,1] - true_syz) / shear_modulus)))
plt.ylim([-20,0])
plt.show()
```

```python
import quadpy
S = quadpy.c1.gauss_kronrod(7)
S2 = quadpy.c1.gauss_legendre(7)
S.points, S.weights, S2.weights
```

    (array([-9.91455371e-01, -9.49107912e-01, -8.64864423e-01, -7.41531186e-01,
            -5.86087235e-01, -4.05845151e-01, -2.07784955e-01,  7.77156117e-16,
             2.07784955e-01,  4.05845151e-01,  5.86087235e-01,  7.41531186e-01,
             8.64864423e-01,  9.49107912e-01,  9.91455371e-01]),
     array([0.02293532, 0.06309209, 0.10479001, 0.14065326, 0.16900473,
            0.19035058, 0.20443294, 0.20948214, 0.20443294, 0.19035058,
            0.16900473, 0.14065326, 0.10479001, 0.06309209, 0.02293532]),
     array([0.12948497, 0.27970539, 0.38183005, 0.41795918, 0.38183005,
            0.27970539, 0.12948497]))

```python
(S.weights * (S.points ** 22)).sum() - (2.0 / 23)
```

    -8.187894806610529e-16


```python
# autoreload nangs
%reload_ext autoreload
%autoreload 2
%matplotlib inline
```

    Bad key "text.kerning_factor" on line 4 in
    C:\Users\sensio\miniconda3\lib\site-packages\matplotlib\mpl-data\stylelib\_classic_test_patch.mplstyle.
    You probably need to get an updated matplotlibrc file from
    https://github.com/matplotlib/matplotlib/blob/v3.1.3/matplotlibrc.template
    or from the matplotlib source distribution

# High Order Derivatives

In this notebook you will learn how to solve PDEs that involve higher order derivatives. We want to solve the following PDE:

\begin{equation}
    u \frac{\partial \phi}{\partial x} + v \frac{\partial \phi}{\partial y} = \Gamma (\phi_{xx} + \phi_{yy})
\end{equation}

The independen variables, $x$ and $y$, are used as input values for the NN, and the solution (i.e. $\phi(x,y)$) is the output. In order to find the solution, at each step the NN outputs are derived w.r.t the inputs to obtain the first order derivatives. The same is done for the gradients to obtain the second order derivatives. Then, a loss function that matches the PDE is built and the weights are updated accordingly. A loss function that matches the PDE is then used for optimization. If the loss function goes to zero, we can assume that our NN is indeed the solution to our PDE. The geometry of the problem is as follows:

```python
#imports

import numpy as np
import matplotlib.pyplot as plt
import torch
import nangs

device = "cuda" if torch.cuda.is_available() else "cpu"

nangs.__version__, torch.__version__
```

    ('0.1.2', '1.5.0')

```python
from nangs import PDE

TAU = 0.1
ALPHA = 10

# velocity field
vel = lambda x, y: (2*y*(1-x**2), -2*x*(1-y**2))

class SH(PDE):
    def computePDELoss(self, inputs, outputs):

        # compute first-order derivatives
        grads = self.computeGrads(outputs, inputs)
        dpdx, dpdy = grads[:, 0], grads[:, 1]

        # compute second-order derivatives
        dp2dx2 = self.computeGrads(dpdx, inputs)[:, 0]
        dp2dy2 = self.computeGrads(dpdy, inputs)[:, 1]

        # compute loss
        x, y = inputs[:, 0], inputs[:, 1]
        u, v = vel(x, y)
        return {'pde': u*dpdx + v*dpdy - TAU*(dp2dx2 + dp2dy2)}

# instanciate pde
pde = SH(inputs=('x', 'y'), outputs='p')
```

```python
# define the mesh

from nangs import Mesh

x = np.linspace(-1, 1, 80)
y = np.linspace(0, 1, 40)

mesh = Mesh({'x': x, 'y': y}, device=device)
pde.set_mesh(mesh)
```

```python
# boundary conditions

from nangs import Dirichlet

# left and rigth b.c

x1 = np.array([-1, 1])
p = np.full(2*len(y), 1. - np.tanh(ALPHA))
boco = Dirichlet({'x': x1, 'y': y}, {'p': p}, name='left_rigth', device=device)
pde.add_boco(boco)
```

```python
# top b.c

p = np.full(len(x), 1. - np.tanh(ALPHA))
boco = Dirichlet({'x': x, 'y': y[-1:]}, {'p': p}, device=device, name='top')
pde.add_boco(boco)
```

```python
# bottom b.c

x1, x2 = x[x<0], x[x>=0]
p1 = 1. + np.tanh(ALPHA*(2*x1+1))

# bottom left b.c

boco = Dirichlet({'x': x1, 'y': y[:1]}, {'p': p1}, name='bottom_left', device=device)
pde.add_boco(boco)
```

```python
plt.plot(x1, p1)
plt.xlabel('x')
plt.ylabel('p      ', rotation=np.pi/2)
plt.title('Solution at y=0')
plt.grid()
plt.show()
```

```python
# bottom right b.c

from nangs import Neumann

class MyNeumann(Neumann):
    def computeBocoLoss(self, inputs, outputs):
        dpdy = self.computeGrads(outputs, inputs)[:, 1]
        return {'gradY': dpdy}

boco = MyNeumann({'x': x2, 'y': y[:1]}, name='bottom_right', device=device)
pde.add_boco(boco)
```

```python
from nangs import MLP

BATCH_SIZE = 1024
LR = 5e-3
EPOCHS = 100
NUM_LAYERS = 5
NUM_HIDDEN = 256

mlp = MLP(len(pde.inputs), len(pde.outputs), NUM_LAYERS, NUM_HIDDEN).to(device)
optimizer = torch.optim.Adam(mlp.parameters())
scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr=LR, pct_start=0.1, total_steps=EPOCHS)

pde.compile(mlp, optimizer, scheduler)
%time hist = pde.solve(EPOCHS, BATCH_SIZE)
```

```python
# evaluate the solution
#pde.load_state_dict('best.pth')

x = np.linspace(-1,1,100)
y = np.linspace(0,1,50)

eval_mesh = Mesh({'x': x, 'y': y}, device=device)
p = pde.eval(eval_mesh).cpu().view(len(y),len(x)).numpy()

fig, ax = plt.subplots(1, 1, figsize=(10,10))
ax.imshow(p, vmin=p.min(), vmax=p.max(), origin='lower', extent=[x.min(), x.max(), y.min(), y.max()])
ax.set_title(f"$\\Gamma$ = 0.1")
plt.show()
```

```python
# experimental results

exp = {
    'x': [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
    'g_0.1': [1.989,1.402,1.146,0.946,0.775,0.621,0.480,0.349,0.227,0.111,0.0],
    'g_0.001': [2.0000,1.9990,1.9997,1.985,1.841,0.951,0.154,0.001,0.0,0.0,0.0],
    'g_0.000001': [2.0000,2.0,2.0,1.999,1.964,1.0,0.036,0.001,0.0,0.0,0.0]
}

x = np.linspace(-1,1,200)
y = np.array([0])
eval_mesh = Mesh({'x': x, 'y': y}, device=device)
p = pde.eval(eval_mesh).cpu().numpy().reshape(len(x))

plt.plot(x, p, label=f"$\\Gamma$ = 0.1")

p1 = 1. + np.tanh(ALPHA*(2*x[x<0]+1))
plt.plot(x[x<0], p1)

plt.plot(exp['x'], exp['g_0.1'], '.k')
plt.grid()
plt.xlabel('x (y = 0)')
plt.ylabel('$\\phi$       ', rotation=np.pi/2)
plt.legend()
plt.show()
```