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

Table of Contents

1  Refrances

2  Libraries and Helper functions

3  Multiplexers

4  2 Channel Input:1 Channel Output multiplexer 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 Testbench

4.6  PYNQ-Z1 Deployment

4.6.1  Board Circuit

4.6.2  Board Constraint

4.6.3  Video of Deployment

5  4 Channel Input : 1 Channel Output multiplexer 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 Constraint

5.6.3  Video of Deployment

6  Shannon's Expansion Formula & Stacking of MUXs

7  4 Channel Input: 1 Channel Output multiplexer via MUX Stacking

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  Introduction to HDL Behavioral Modeling

9  2:1 MUX via Behavioral IF

9.1  myHDL Module

9.2  myHDL Testing

9.3  Verilog Conversion

9.4  myHDL to Verilog Testbench

9.5  PYNQ-Z1 Deployment

9.5.1  Board Circuit

9.5.2  Board Constraint

9.5.3  Video of Deployment

10  4:1 MUX via Behavioral if-elif-else

10.1  myHDL Module

10.2  myHDL Testing

10.3  Verilog Conversion

10.4  myHDL to Verilog Testbench

10.5  PYNQ-Z1 Deployment

10.5.1  Board Circuit

10.5.2  Board Constraint

10.5.3  Video of Deployment

11  Multiplexer 4:1 Behavioral via Bitvectors

11.1  myHDL Module

11.2  myHDL Testing

11.3  Verilog Conversion

11.4  myHDL to Verilog Testbench

11.5  PYNQ-Z1 Deployment

11.5.1  Board Circuit

11.5.2  Board Constraint

11.5.3  Video of Deployment

# Refrances
@misc{xu_2018,
title={Introduction to Digital Systems Supplementary Reading Shannon's Expansion Formulas and Compressed Truth Table},
author={Xu, Xuping},
year={Fall 2017}
site=http://ecse.bd.psu.edu/cse271/comprttb.pdf
}

# 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

#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:19:19 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

```

# Multiplexers
\begin{definition}\label{def:MUX}
A Multiplexer, typically referred to as a MUX, is a Digital(or analog) switching unit that picks one input channel to be streamed to an output via a control input. For single output MUXs with $2^n$ inputs, there are then $n$ input selection signals that make up the control word to select the input channel for output.

From a behavioral standpoint, a MUX can be thought of as an element that performs the same functionality as the `if-elif-else (case)` control statements found in almost every software language.
\end{definition}

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

\begin{figure}
\centerline{\includegraphics{MUX21Gate.png}}
\caption{\label{fig:M21G} 2:1 MUX Symbol and Gate internals}
\end{figure}

## Sympy Expression

```python
x0, x1, s, y=symbols('x0, x1, s, y')
y21Eq=Eq(y, (~s&x0) |(s&x1) ); y21Eq
```

```python
TruthTabelGenrator(y21Eq)[[x1, x0, s, y]]
```

      x1
      x0
      s
      y

      0
      0
      0
      0
      0

      1
      1
      0
      0
      0

      2
      0
      1
      0
      1

      3
      1
      1
      0
      1

      4
      0
      0
      1
      0

      5
      1
      0
      1
      1

      6
      0
      1
      1
      0

      7
      1
      1
      1
      1

```python
y21EqN=lambdify([x0, x1, s], y21Eq.rhs, dummify=False)
SystmaticVals=np.array(list(itertools.product([0,1], repeat=3)))
print(SystmaticVals)
y21EqN(SystmaticVals[:, 1], SystmaticVals[:, 2], 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]]

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

## myHDL Module

```python
@block
def MUX2_1_Combo(x0, x1, s, y):
    """
    2:1 Multiplexer written in full combo
    Input:
        x0(bool): input channel 0
        x1(bool): input channel 1
        s(bool): channel selection input
    Output:
        y(bool): ouput
    """

    @always_comb
    def logic():
        y.next= (not s and x0) |(s and x1)

    return instances()
```

## myHDL Testing

```python
#generate systmatic and random test values
#stimules inputs X1 and X2
TestLen=10
SystmaticVals=list(itertools.product([0,1], repeat=3))

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

x1TVs=np.array([i[2] 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)
x1TVs=np.append(x1TVs, 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(17)
sTVs=np.append(sTVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(x0TVs)
x0TVs, x1TVs, sTVs, TestLen
```

    (array([0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]),
     array([0, 1, 0, 1, 0, 1, 0, 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]),
     18)

```python
Peeker.clear()
x0=Signal(bool(0)); Peeker(x0, 'x0')
x1=Signal(bool(0)); Peeker(x1, 'x1')
s=Signal(bool(0)); Peeker(s, 's')
y=Signal(bool(0)); Peeker(y, 'y')

DUT=MUX2_1_Combo(x0, x1, s, y)

def MUX2_1_Combo_TB():
    """
    myHDL only testbench for module `MUX2_1_Combo`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TVs[i])
            x1.next=int(x1TVs[i])
            s.next=int(sTVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

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

```python
Peeker.to_wavedrom('x1', 'x0', 's', 'y')
```

```python
MUX2_1_ComboData=Peeker.to_dataframe()
MUX2_1_ComboData=MUX2_1_ComboData[['x1', 'x0', 's', 'y']]
MUX2_1_ComboData
```

      x1
      x0
      s
      y

      0
      0
      0
      0
      0

      1
      1
      0
      0
      0

      2
      0
      1
      0
      1

      3
      1
      1
      0
      1

      4
      0
      0
      1
      0

      5
      1
      0
      1
      1

      6
      0
      1
      1
      0

      7
      1
      1
      1
      1

      8
      1
      0
      1
      1

      9
      0
      1
      1
      0

      10
      1
      0
      1
      1

      11
      1
      1
      0
      1

      13
      1
      0
      1
      1

      14
      0
      0
      0
      0

      15
      1
      1
      1
      1

      16
      1
      1
      0
      1

      17
      0
      1
      1
      0

```python
MUX2_1_ComboData['yRef']=MUX2_1_ComboData.apply(lambda row:y21EqN(row['x0'], row['x1'], row['s']), axis=1).astype(int)
MUX2_1_ComboData
```

      x1
      x0
      s
      y
      yRef

      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      0
      0

      2
      0
      1
      0
      1
      1

      3
      1
      1
      0
      1
      1

      4
      0
      0
      1
      0
      0

      5
      1
      0
      1
      1
      1

      6
      0
      1
      1
      0
      0

      7
      1
      1
      1
      1
      1

      8
      1
      0
      1
      1
      1

      9
      0
      1
      1
      0
      0

      10
      1
      0
      1
      1
      1

      11
      1
      1
      0
      1
      1

      13
      1
      0
      1
      1
      1

      14
      0
      0
      0
      0
      0

      15
      1
      1
      1
      1
      1

      16
      1
      1
      0
      1
      1

      17
      0
      1
      1
      0
      0

```python
Test=(MUX2_1_ComboData['y']==MUX2_1_ComboData['yRef']).all()
print(f'Module `MUX2_1_Combo` works as exspected: {Test}')
```

    Module `MUX2_1_Combo` works as exspected: True

## Verilog Conversion

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

    ***Verilog modual from MUX2_1_Combo.v***

     // File: MUX2_1_Combo.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:19:36 2018

    `timescale 1ns/10ps

    module MUX2_1_Combo (
        x0,
        x1,
        s,
        y
    );
    // 2:1 Multiplexer written in full combo
    // Input:
    //     x0(bool): input channel 0
    //     x1(bool): input channel 1
    //     s(bool): channel selection input
    // Output:
    //     y(bool): ouput

    input x0;
    input x1;
    input s;
    output y;
    wire y;

    assign y = (((!s) && x0) | (s && x1));

    endmodule

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

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

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

## myHDL to Verilog Testbench

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

x0TVs, bin(x0TVs), x1TVs, bin(x1TVs), sTVs, bin(sTVs)
```

    (intbv(52583),
     '1100110101100111',
     intbv(87798),
     '10101011011110110',
     intbv(16277),
     '11111110010101')

```python
@block
def MUX2_1_Combo_TBV():
    """
    myHDL -> Verilog testbench for module `MUX2_1_Combo`
    """
    x0=Signal(bool(0))
    x1=Signal(bool(0))
    s=Signal(bool(0))
    y=Signal(bool(0))

    @always_comb
    def print_data():
        print(x0, x1, s, y)

    #Test Signal Bit Vectors
    x0TV=Signal(x0TVs)
    x1TV=Signal(x1TVs)
    sTV=Signal(sTVs)

    DUT=MUX2_1_Combo(x0, x1, s, y)

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TV[i])
            x1.next=int(x1TV[i])
            s.next=int(sTV[i])
            yield delay(1)

        raise StopSimulation()
    return instances()

TB=MUX2_1_Combo_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('MUX2_1_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 MUX2_1_Combo_TBV.v***

     // File: MUX2_1_Combo_TBV.v
    // Generated by MyHDL 0.10
    // Date: Sun Sep 23 18:19:44 2018

    `timescale 1ns/10ps

    module MUX2_1_Combo_TBV (

    );
    // myHDL -> Verilog testbench for module `MUX2_1_Combo`

    reg x0 = 0;
    reg x1 = 0;
    reg s = 0;
    wire y;
    wire [17:0] x0TV;
    wire [17:0] x1TV;
    wire [17:0] sTV;

    assign x0TV = 18'd52583;
    assign x1TV = 18'd87798;
    assign sTV = 18'd16277;

    always @(s, y, x0, x1) begin: MUX2_1_COMBO_TBV_PRINT_DATA
        $write("%h", x0);
        $write(" ");
        $write("%h", x1);
        $write(" ");
        $write("%h", s);
        $write(" ");
        $write("%h", y);
        $write("\n");
    end

    assign y = (((!s) && x0) | (s && x1));

    initial begin: MUX2_1_COMBO_TBV_STIMULES
        integer i;
        for (i=0; i<18; i=i+1) begin
            x0 <= x0TV[i];
            x1 <= x1TV[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: x0TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x1TV
      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]{MUX21PYNQZ1Circ.png}}
\caption{\label{fig:M21Circ} 2:1 MUX PYNQ-Z1 (Non SoC) conceptualized circuit}
\end{figure}

### Board Constraint

```python
ConstraintXDCTextReader('MUX2_1');
```

    ***Constraint file from MUX2_1.xdc***

     ## PYNQ-Z1 Constraint File for MUX2_1_Combo
    ## Based on https://github.com/Xilinx/PYNQ/blob/master/boards/Pynq-Z1/base/vivado/constraints/base.xdc

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

    ## Buttons
    set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports {x0}]; ## BT0
    set_property -dict {PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports {x1}]; ##BT1

    ## LEDs
    set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports {y}]; ## Led 0

### Video of Deployment
MUX2_1_Combo myHDL PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=UkXbnFdF010))

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

## Sympy Expression

```python
x0, x1, x2, x3, s0, s1, y=symbols('x0, x1, x2, x3, s0, s1, y')
y41Eq=Eq(y, (~s0&~s1&x0) | (s0&~s1&x1)| (~s0&s1&x2)|(s0&s1&x3))
y41Eq
```

```python
TruthTabelGenrator(y41Eq)[[x3, x2, x1, x0, s1, s0, y]]
```

      x3
      x2
      x1
      x0
      s1
      s0
      y

      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      0
      0
      0
      0

      2
      0
      1
      0
      0
      0
      0
      0

      3
      1
      1
      0
      0
      0
      0
      0

      4
      0
      0
      1
      0
      0
      0
      0

      5
      1
      0
      1
      0
      0
      0
      0

      6
      0
      1
      1
      0
      0
      0
      0

      7
      1
      1
      1
      0
      0
      0
      0

      8
      0
      0
      0
      1
      0
      0
      1

      9
      1
      0
      0
      1
      0
      0
      1

      10
      0
      1
      0
      1
      0
      0
      1

      11
      1
      1
      0
      1
      0
      0
      1

      12
      0
      0
      1
      1
      0
      0
      1

      13
      1
      0
      1
      1
      0
      0
      1

      14
      0
      1
      1
      1
      0
      0
      1

      15
      1
      1
      1
      1
      0
      0
      1

      16
      0
      0
      0
      0
      1
      0
      0

      17
      1
      0
      0
      0
      1
      0
      0

      18
      0
      1
      0
      0
      1
      0
      1

      19
      1
      1
      0
      0
      1
      0
      1

      20
      0
      0
      1
      0
      1
      0
      0

      21
      1
      0
      1
      0
      1
      0
      0

      22
      0
      1
      1
      0
      1
      0
      1

      23
      1
      1
      1
      0
      1
      0
      1

      24
      0
      0
      0
      1
      1
      0
      0

      25
      1
      0
      0
      1
      1
      0
      0

      26
      0
      1
      0
      1
      1
      0
      1

      27
      1
      1
      0
      1
      1
      0
      1

      28
      0
      0
      1
      1
      1
      0
      0

      29
      1
      0
      1
      1
      1
      0
      0

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      34
      0
      1
      0
      0
      0
      1
      0

      35
      1
      1
      0
      0
      0
      1
      0

      36
      0
      0
      1
      0
      0
      1
      1

      37
      1
      0
      1
      0
      0
      1
      1

      38
      0
      1
      1
      0
      0
      1
      1

      39
      1
      1
      1
      0
      0
      1
      1

      40
      0
      0
      0
      1
      0
      1
      0

      41
      1
      0
      0
      1
      0
      1
      0

      42
      0
      1
      0
      1
      0
      1
      0

      43
      1
      1
      0
      1
      0
      1
      0

      44
      0
      0
      1
      1
      0
      1
      1

      45
      1
      0
      1
      1
      0
      1
      1

      46
      0
      1
      1
      1
      0
      1
      1

      47
      1
      1
      1
      1
      0
      1
      1

      48
      0
      0
      0
      0
      1
      1
      0

      49
      1
      0
      0
      0
      1
      1
      1

      50
      0
      1
      0
      0
      1
      1
      0

      51
      1
      1
      0
      0
      1
      1
      1

      52
      0
      0
      1
      0
      1
      1
      0

      53
      1
      0
      1
      0
      1
      1
      1

      54
      0
      1
      1
      0
      1
      1
      0

      55
      1
      1
      1
      0
      1
      1
      1

      56
      0
      0
      0
      1
      1
      1
      0

      57
      1
      0
      0
      1
      1
      1
      1

      58
      0
      1
      0
      1
      1
      1
      0

      59
      1
      1
      0
      1
      1
      1
      1

      60
      0
      0
      1
      1
      1
      1
      0

      61
      1
      0
      1
      1
      1
      1
      1

      62
      0
      1
      1
      1
      1
      1
      0

      63
      1
      1
      1
      1
      1
      1
      1

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

```python
y41EqN=lambdify([x0, x1, x2, x3, s0, s1], y41Eq.rhs, dummify=False)
SystmaticVals=np.array(list(itertools.product([0,1], repeat=6)))
SystmaticVals
y41EqN(*[SystmaticVals[:, i] for i in range(6)] ).astype(int)
```

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

## myHDL Module

```python
@block
def MUX4_1_Combo(x0, x1, x2, x3, s0, s1, y):
    """
    4:1 Multiplexer written in full combo
    Input:
        x0(bool): input channel 0
        x1(bool): input channel 1
        x2(bool): input channel 2
        x3(bool): input channel 3
        s1(bool): channel selection input bit 1
        s0(bool): channel selection input bit 0
    Output:
        y(bool): ouput
    """

    @always_comb
    def logic():
        y.next= (not s0 and not s1 and x0)  or  (s0 and not s1 and x1) or  (not s0 and s1 and x2) or (s0 and s1 and x3)

    return instances()
```

## myHDL Testing

```python
#generate systmatic and random test values
TestLen=5
SystmaticVals=list(itertools.product([0,1], repeat=6))

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

s1TVs=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)
s1TVs=np.append(s1TVs, np.random.randint(0,2, TestLen)).astype(int)

x0TVs=np.array([i[2] 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)
x0TVs=np.append(x0TVs, np.random.randint(0,2, TestLen)).astype(int)

x1TVs=np.array([i[3] 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(18)
x1TVs=np.append(x1TVs, np.random.randint(0,2, TestLen)).astype(int)

x2TVs=np.array([i[4] 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(19)
x2TVs=np.append(x2TVs, np.random.randint(0,2, TestLen)).astype(int)

x3TVs=np.array([i[5] 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(20)
x3TVs=np.append(x3TVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(x0TVs)
SystmaticVals, s0TVs, s1TVs, x3TVs, x2TVs, x1TVs, x0TVs, TestLen
```

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

```python
Peeker.clear()
x0=Signal(bool(0)); Peeker(x0, 'x0')
x1=Signal(bool(0)); Peeker(x1, 'x1')
x2=Signal(bool(0)); Peeker(x2, 'x2')
x3=Signal(bool(0)); Peeker(x3, 'x3')

s0=Signal(bool(0)); Peeker(s0, 's0')
s1=Signal(bool(0)); Peeker(s1, 's1')
y=Signal(bool(0)); Peeker(y, 'y')

DUT=MUX4_1_Combo(x0, x1, x2, x3, s0, s1, y)

def MUX4_1_Combo_TB():
    """
    myHDL only testbench for module `MUX4_1_Combo`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TVs[i])
            x1.next=int(x1TVs[i])
            x2.next=int(x2TVs[i])
            x3.next=int(x3TVs[i])
            s0.next=int(s0TVs[i])
            s1.next=int(s1TVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

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

```python
Peeker.to_wavedrom()
```

```python
MUX4_1_ComboData=Peeker.to_dataframe()
MUX4_1_ComboData=MUX4_1_ComboData[['x3', 'x2', 'x1', 'x0', 's1', 's0', 'y']]
MUX4_1_ComboData
```

      x3
      x2
      x1
      x0
      s1
      s0
      y

      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      0
      0
      0
      0

      2
      0
      1
      0
      0
      0
      0
      0

      3
      1
      1
      0
      0
      0
      0
      0

      4
      0
      0
      1
      0
      0
      0
      0

      5
      1
      0
      1
      0
      0
      0
      0

      6
      0
      1
      1
      0
      0
      0
      0

      7
      1
      1
      1
      0
      0
      0
      0

      8
      0
      0
      0
      1
      0
      0
      1

      9
      1
      0
      0
      1
      0
      0
      1

      10
      0
      1
      0
      1
      0
      0
      1

      11
      1
      1
      0
      1
      0
      0
      1

      12
      0
      0
      1
      1
      0
      0
      1

      13
      1
      0
      1
      1
      0
      0
      1

      14
      0
      1
      1
      1
      0
      0
      1

      15
      1
      1
      1
      1
      0
      0
      1

      16
      0
      0
      0
      0
      1
      0
      0

      17
      1
      0
      0
      0
      1
      0
      0

      18
      0
      1
      0
      0
      1
      0
      1

      19
      1
      1
      0
      0
      1
      0
      1

      20
      0
      0
      1
      0
      1
      0
      0

      21
      1
      0
      1
      0
      1
      0
      0

      22
      0
      1
      1
      0
      1
      0
      1

      23
      1
      1
      1
      0
      1
      0
      1

      24
      0
      0
      0
      1
      1
      0
      0

      25
      1
      0
      0
      1
      1
      0
      0

      26
      0
      1
      0
      1
      1
      0
      1

      27
      1
      1
      0
      1
      1
      0
      1

      28
      0
      0
      1
      1
      1
      0
      0

      29
      1
      0
      1
      1
      1
      0
      0

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      39
      1
      1
      1
      0
      0
      1
      1

      40
      0
      0
      0
      1
      0
      1
      0

      41
      1
      0
      0
      1
      0
      1
      0

      42
      0
      1
      0
      1
      0
      1
      0

      43
      1
      1
      0
      1
      0
      1
      0

      44
      0
      0
      1
      1
      0
      1
      1

      45
      1
      0
      1
      1
      0
      1
      1

      46
      0
      1
      1
      1
      0
      1
      1

      47
      1
      1
      1
      1
      0
      1
      1

      48
      0
      0
      0
      0
      1
      1
      0

      49
      1
      0
      0
      0
      1
      1
      1

      50
      0
      1
      0
      0
      1
      1
      0

      51
      1
      1
      0
      0
      1
      1
      1

      52
      0
      0
      1
      0
      1
      1
      0

      53
      1
      0
      1
      0
      1
      1
      1

      54
      0
      1
      1
      0
      1
      1
      0

      55
      1
      1
      1
      0
      1
      1
      1

      56
      0
      0
      0
      1
      1
      1
      0

      57
      1
      0
      0
      1
      1
      1
      1

      58
      0
      1
      0
      1
      1
      1
      0

      59
      1
      1
      0
      1
      1
      1
      1

      60
      0
      0
      1
      1
      1
      1
      0

      61
      1
      0
      1
      1
      1
      1
      1

      62
      0
      1
      1
      1
      1
      1
      0

      63
      1
      1
      1
      1
      1
      1
      1

      64
      1
      1
      0
      1
      1
      0
      1

      65
      0
      0
      1
      1
      0
      1
      1

      66
      1
      1
      0
      1
      1
      0
      1

      67
      1
      0
      1
      0
      1
      1
      1

      68
      0
      0
      0
      0
      1
      1
      0

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

```python
MUX4_1_ComboData['yRef']=MUX4_1_ComboData.apply(lambda row:y41EqN(row['x0'], row['x1'], row['x2'], row['x3'], row['s0'], row['s1']), axis=1).astype(int)
MUX4_1_ComboData
```

      x3
      x2
      x1
      x0
      s1
      s0
      y
      yRef

      0
      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      0
      0
      0
      0
      0

      2
      0
      1
      0
      0
      0
      0
      0
      0

      3
      1
      1
      0
      0
      0
      0
      0
      0

      4
      0
      0
      1
      0
      0
      0
      0
      0

      5
      1
      0
      1
      0
      0
      0
      0
      0

      6
      0
      1
      1
      0
      0
      0
      0
      0

      7
      1
      1
      1
      0
      0
      0
      0
      0

      8
      0
      0
      0
      1
      0
      0
      1
      1

      9
      1
      0
      0
      1
      0
      0
      1
      1

      10
      0
      1
      0
      1
      0
      0
      1
      1

      11
      1
      1
      0
      1
      0
      0
      1
      1

      12
      0
      0
      1
      1
      0
      0
      1
      1

      13
      1
      0
      1
      1
      0
      0
      1
      1

      14
      0
      1
      1
      1
      0
      0
      1
      1

      15
      1
      1
      1
      1
      0
      0
      1
      1

      16
      0
      0
      0
      0
      1
      0
      0
      0

      17
      1
      0
      0
      0
      1
      0
      0
      0

      18
      0
      1
      0
      0
      1
      0
      1
      1

      19
      1
      1
      0
      0
      1
      0
      1
      1

      20
      0
      0
      1
      0
      1
      0
      0
      0

      21
      1
      0
      1
      0
      1
      0
      0
      0

      22
      0
      1
      1
      0
      1
      0
      1
      1

      23
      1
      1
      1
      0
      1
      0
      1
      1

      24
      0
      0
      0
      1
      1
      0
      0
      0

      25
      1
      0
      0
      1
      1
      0
      0
      0

      26
      0
      1
      0
      1
      1
      0
      1
      1

      27
      1
      1
      0
      1
      1
      0
      1
      1

      28
      0
      0
      1
      1
      1
      0
      0
      0

      29
      1
      0
      1
      1
      1
      0
      0
      0

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      39
      1
      1
      1
      0
      0
      1
      1
      1

      40
      0
      0
      0
      1
      0
      1
      0
      0

      41
      1
      0
      0
      1
      0
      1
      0
      0

      42
      0
      1
      0
      1
      0
      1
      0
      0

      43
      1
      1
      0
      1
      0
      1
      0
      0

      44
      0
      0
      1
      1
      0
      1
      1
      1

      45
      1
      0
      1
      1
      0
      1
      1
      1

      46
      0
      1
      1
      1
      0
      1
      1
      1

      47
      1
      1
      1
      1
      0
      1
      1
      1

      48
      0
      0
      0
      0
      1
      1
      0
      0

      49
      1
      0
      0
      0
      1
      1
      1
      1

      50
      0
      1
      0
      0
      1
      1
      0
      0

      51
      1
      1
      0
      0
      1
      1
      1
      1

      52
      0
      0
      1
      0
      1
      1
      0
      0

      53
      1
      0
      1
      0
      1
      1
      1
      1

      54
      0
      1
      1
      0
      1
      1
      0
      0

      55
      1
      1
      1
      0
      1
      1
      1
      1

      56
      0
      0
      0
      1
      1
      1
      0
      0

      57
      1
      0
      0
      1
      1
      1
      1
      1

      58
      0
      1
      0
      1
      1
      1
      0
      0

      59
      1
      1
      0
      1
      1
      1
      1
      1

      60
      0
      0
      1
      1
      1
      1
      0
      0

      61
      1
      0
      1
      1
      1
      1
      1
      1

      62
      0
      1
      1
      1
      1
      1
      0<

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

```python
Test=(MUX4_1_ComboData['y']==MUX4_1_ComboData['yRef']).all()
print(f'Module `MUX4_1_Combo` works as exspected: {Test}')
```

    Module `MUX4_1_Combo` works as exspected: True

## Verilog Conversion

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

    ***Verilog modual from MUX4_1_Combo.v***

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

    `timescale 1ns/10ps

    module MUX4_1_Combo (
        x0,
        x1,
        x2,
        x3,
        s0,
        s1,
        y
    );
    // 4:1 Multiplexer written in full combo
    // Input:
    //     x0(bool): input channel 0
    //     x1(bool): input channel 1
    //     x2(bool): input channel 2
    //     x3(bool): input channel 3
    //     s1(bool): channel selection input bit 1
    //     s0(bool): channel selection input bit 0
    // Output:
    //     y(bool): ouput

    input x0;
    input x1;
    input x2;
    input x3;
    input s0;
    input s1;
    output y;
    wire y;

    assign y = (((!s0) && (!s1) && x0) || (s0 && (!s1) && x1) || ((!s0) && s1 && x2) || (s0 && s1 && x3));

    endmodule

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

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

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

## myHDL to Verilog Testbench

```python
#create BitVectors for MUX4_1_Combo_TBV
x0TVs=intbv(int(''.join(x0TVs.astype(str)), 2))[TestLen:]
x1TVs=intbv(int(''.join(x1TVs.astype(str)), 2))[TestLen:]
x2TVs=intbv(int(''.join(x2TVs.astype(str)), 2))[TestLen:]
x3TVs=intbv(int(''.join(x3TVs.astype(str)), 2))[TestLen:]

s0TVs=intbv(int(''.join(s0TVs.astype(str)), 2))[TestLen:]
s1TVs=intbv(int(''.join(s1TVs.astype(str)), 2))[TestLen:]

x0TVs, bin(x0TVs), x1TVs, bin(x1TVs), x2TVs, bin(x2TVs), x3TVs, bin(x3TVs), s0TVs, bin(s0TVs), s1TVs, bin(s1TVs)
```

    (intbv(2296870857426870268),
     '1111111100000000111111110000000011111111000000001111111111100',
     intbv(34723282962276803050),
     '11110000111100001111000011110000111100001111000011110000111101010',
     intbv(118059162071741130356),
     '1100110011001100110011001100110011001100110011001100110011001110100',
     intbv(196765270119568550582),
     '10101010101010101010101010101010101010101010101010101010101010110110',
     intbv(137438953451),
     '1111111111111111111111111111111101011',
     intbv(9007061817884663),
     '11111111111111110000000000000000111111111111111110111')

```python
@block
def MUX4_1_Combo_TBV():
    """
    myHDL -> Verilog testbench for module `MUX4_1_Combo`
    """

    x0=Signal(bool(0))
    x1=Signal(bool(0))
    x2=Signal(bool(0))
    x3=Signal(bool(0))
    y=Signal(bool(0))
    s0=Signal(bool(0))
    s1=Signal(bool(0))

    @always_comb
    def print_data():
        print(x0, x1, x2, x3, s0, s1, y)

    #Test Signal Bit Vectors
    x0TV=Signal(x0TVs)
    x1TV=Signal(x1TVs)
    x2TV=Signal(x2TVs)
    x3TV=Signal(x3TVs)
    s0TV=Signal(s0TVs)
    s1TV=Signal(s1TVs)

    DUT=MUX4_1_Combo(x0, x1, x2, x3, s0, s1, y)

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TV[i])
            x1.next=int(x1TV[i])
            x2.next=int(x2TV[i])
            x3.next=int(x3TV[i])
            s0.next=int(s0TV[i])
            s1.next=int(s1TV[i])
            yield delay(1)

        raise StopSimulation()
    return instances()

TB=MUX4_1_Combo_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('MUX4_1_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 MUX4_1_Combo_TBV.v***

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

    `timescale 1ns/10ps

    module MUX4_1_Combo_TBV (

    );
    // myHDL -> Verilog testbench for module `MUX4_1_Combo`

    reg x0 = 0;
    reg x1 = 0;
    wire y;
    reg x2 = 0;
    reg x3 = 0;
    reg s0 = 0;
    reg s1 = 0;
    wire [68:0] x0TV;
    wire [68:0] x1TV;
    wire [68:0] x2TV;
    wire [68:0] x3TV;
    wire [68:0] s0TV;
    wire [68:0] s1TV;

    assign x0TV = 69'd2296870857426870268;
    assign x1TV = 69'd34723282962276803050;
    assign x2TV = 69'd118059162071741130356;
    assign x3TV = 69'd196765270119568550582;
    assign s0TV = 69'd137438953451;
    assign s1TV = 69'd9007061817884663;

    always @(x0, x3, s0, x2, y, x1, s1) begin: MUX4_1_COMBO_TBV_PRINT_DATA
        $write("%h", x0);
        $write(" ");
        $write("%h", x1);
        $write(" ");
        $write("%h", x2);
        $write(" ");
        $write("%h", x3);
        $write(" ");
        $write("%h", s0);
        $write(" ");
        $write("%h", s1);
        $write(" ");
        $write("%h", y);
        $write("\n");
    end

    assign y = (((!s0) && (!s1) && x0) || (s0 && (!s1) && x1) || ((!s0) && s1 && x2) || (s0 && s1 && x3));

    initial begin: MUX4_1_COMBO_TBV_STIMULES
        integer i;
        for (i=0; i<69; i=i+1) begin
            x0 <= x0TV[i];
            x1 <= x1TV[i];
            x2 <= x2TV[i];
            x3 <= x3TV[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: x0TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x1TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x2TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x3TV
      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]{MUX41PYNQZ1Circ.png}}
\caption{\label{fig:M41Circ} 4:1 MUX PYNQ-Z1 (Non SoC) conceptualized circuit}
\end{figure}

### Board Constraint

```python
ConstraintXDCTextReader('MUX4_1');
```

    ***Constraint file from MUX4_1.xdc***

     ## PYNQ-Z1 Constraint File for MUX4_1_*
    ## Based on https://github.com/Xilinx/PYNQ/blob/master/boards/Pynq-Z1/base/vivado/constraints/base.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 D19 IOSTANDARD LVCMOS33} [get_ports {x0}]; ## BT0
    set_property -dict {PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports {x1}]; ## BT1
    set_property -dict {PACKAGE_PIN L20 IOSTANDARD LVCMOS33} [get_ports {x2}]; ## BT2
    set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports {x3}]; ## BT3

    ## LEDs
    set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports {y}]; ## Led 0

### Video of Deployment
MUX4_1_MS myHDL PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=ZdwGjRM9WFk))

# Shannon's Expansion Formula & Stacking of MUXs

[Claude Shannon](https://en.wikipedia.org/wiki/Claude_Shannon), of the famed Shannon-Nyquist theorem, discovered that any boolean expression $F(x_0, x_1,  \ldots, x_n)$ can be decomposed in a manner akin to polynomials of perfect squares via

$$
F(x_0, x_1,  \ldots, x_n)=x_0 \cdot F(x_0=1, x_1,  \ldots, x_n) +\overline{x_0} \cdot F(x_0=0, x_1,  \ldots, x_n)
$$
known as the Sum of Products (SOP) form since when the expansion is completed for all $x_n$ the result is that
$$
F(x_0, x_1,  \ldots, x_n)=\sum^{2^n-1}_{i=0} (m_i \cdot F(m_i))
$$
aka the Sum of all Minterms ($m_i$) belonging to the original boolean expression $F$ factored down to the $i$th of $n$ variables belonging to $F$ and product (&) of $F$ evaluated with the respective minterm as the argument

The Dual to the SOP form of Shannon's expansion formula is the Product of Sum (POS) form
$$
F(x_0, x_1,  \ldots, x_n)=(x_0+ F(x_0=1, x_1,  \ldots, x_n)) \cdot (\overline{x_0} + F(x_0=0, x_1,  \ldots, x_n))
$$
thus

$$F(x_0, x_1,  \ldots, x_n)=\prod^{2^n-1}_{i=0} (M_i + F(M_i))
$$
with $M_i$ being the $i$th Maxterm

it is for this reason that Shannon's Expansion Formula is known is further liked to the fundamental theorem of algebra that it is called the "fundamental theorem of Boolean algebra"

So why then is Shannon's decomposition formula discussed in terms of Multiplexers. Because the general expression for a $2^n:1$ multiplexer is
$$y_{\text{MUX}}=\sum^{2^n-1}_{i=0}m_i\cdot x_n$$ where then $n$ is the required number of control inputs (referred to in this tutorial as $s_i$). Which is the same as the SOP form of Shannon's Formula for a boolean expression that has been fully decomposed (Factored). And further, if the boolean expression has not been fully factored we can replace $n-1$ parts of the partially factored expression with multiplexers. This then gives way to what is called "Multiplexer Stacking" in order to implement large boolean expressions and or large multiplexers

# 4 Channel Input: 1 Channel Output multiplexer via MUX Stacking

\begin{figure}
\centerline{\includegraphics{MUX41MS.png}}
\caption{\label{fig:M41MS} 4:1 MUX via MUX stacking 2:1MUXs}
\end{figure}

## myHDL Module

```python
@block
def MUX4_1_MS(x0, x1, x2, x3, s0, s1, y):
    """
    4:1 Multiplexer via 2:1 MUX stacking
    Input:
        x0(bool): input channel 0
        x1(bool): input channel 1
        x2(bool): input channel 2
        x3(bool): input channel 3
        s1(bool): channel selection input bit 1
        s0(bool): channel selection input bit 0
    Output:
        y(bool): ouput
    """
    #create ouput from x0x1 input MUX to y ouput MUX
    x0x1_yWire=Signal(bool(0))
    #create instance of 2:1 mux and wire in inputs
    #a, b, s0 and wire to ouput mux
    x0x1MUX=MUX2_1_Combo(x0, x1, s0, x0x1_yWire)

    #create ouput from x2x3 input MUX to y ouput MUX
    x2x3_yWire=Signal(bool(0))
    #create instance of 2:1 mux and wire in inputs
    #c, d, s0 and wire to ouput mux
    x2x3MUX=MUX2_1_Combo(x2, x3, s0, x2x3_yWire)

    #create ouput MUX and wire to internal wires,
    #s1 and ouput y
    yMUX=MUX2_1_Combo(x0x1_yWire, x2x3_yWire, s1, y)

    return instances()
```

## myHDL Testing

```python
#generate systmatic and random test values
TestLen=5
SystmaticVals=list(itertools.product([0,1], repeat=6))

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

s1TVs=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)
s1TVs=np.append(s1TVs, np.random.randint(0,2, TestLen)).astype(int)

x0TVs=np.array([i[2] 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)
x0TVs=np.append(x0TVs, np.random.randint(0,2, TestLen)).astype(int)

x1TVs=np.array([i[3] 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(18)
x1TVs=np.append(x1TVs, np.random.randint(0,2, TestLen)).astype(int)

x2TVs=np.array([i[4] 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(19)
x2TVs=np.append(x2TVs, np.random.randint(0,2, TestLen)).astype(int)

x3TVs=np.array([i[5] 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(20)
x3TVs=np.append(x3TVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(x0TVs)
SystmaticVals, s0TVs, s1TVs, x3TVs, x2TVs, x1TVs, x0TVs, TestLen
```

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

```python
Peeker.clear()
x0=Signal(bool(0)); Peeker(x0, 'x0')
x1=Signal(bool(0)); Peeker(x1, 'x1')
x2=Signal(bool(0)); Peeker(x2, 'x2')
x3=Signal(bool(0)); Peeker(x3, 'x3')

s0=Signal(bool(0)); Peeker(s0, 's0')
s1=Signal(bool(0)); Peeker(s1, 's1')
y=Signal(bool(0)); Peeker(y, 'y')

DUT=MUX4_1_MS(x0, x1, x2, x3, s0, s1, y)

def MUX4_1_MS_TB():
    """
    myHDL only testbench for module `MUX4_1_MS`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TVs[i])
            x1.next=int(x1TVs[i])
            x2.next=int(x2TVs[i])
            x3.next=int(x3TVs[i])
            s0.next=int(s0TVs[i])
            s1.next=int(s1TVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

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

```python
Peeker.to_wavedrom()
```

```python
MUX4_1_MSData=Peeker.to_dataframe()
MUX4_1_MSData=MUX4_1_MSData[['x3', 'x2', 'x1', 'x0', 's1', 's0', 'y']]
MUX4_1_MSData
```

      x3
      x2
      x1
      x0
      s1
      s0
      y

      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      0
      0
      0
      0

      2
      0
      1
      0
      0
      0
      0
      0

      3
      1
      1
      0
      0
      0
      0
      0

      4
      0
      0
      1
      0
      0
      0
      0

      5
      1
      0
      1
      0
      0
      0
      0

      6
      0
      1
      1
      0
      0
      0
      0

      7
      1
      1
      1
      0
      0
      0
      0

      8
      0
      0
      0
      1
      0
      0
      1

      9
      1
      0
      0
      1
      0
      0
      1

      10
      0
      1
      0
      1
      0
      0
      1

      11
      1
      1
      0
      1
      0
      0
      1

      12
      0
      0
      1
      1
      0
      0
      1

      13
      1
      0
      1
      1
      0
      0
      1

      14
      0
      1
      1
      1
      0
      0
      1

      15
      1
      1
      1
      1
      0
      0
      1

      16
      0
      0
      0
      0
      1
      0
      0

      17
      1
      0
      0
      0
      1
      0
      0

      18
      0
      1
      0
      0
      1
      0
      1

      19
      1
      1
      0
      0
      1
      0
      1

      20
      0
      0
      1
      0
      1
      0
      0

      21
      1
      0
      1
      0
      1
      0
      0

      22
      0
      1
      1
      0
      1
      0
      1

      23
      1
      1
      1
      0
      1
      0
      1

      24
      0
      0
      0
      1
      1
      0
      0

      25
      1
      0
      0
      1
      1
      0
      0

      26
      0
      1
      0
      1
      1
      0
      1

      27
      1
      1
      0
      1
      1
      0
      1

      28
      0
      0
      1
      1
      1
      0
      0

      29
      1
      0
      1
      1
      1
      0
      0

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      39
      1
      1
      1
      0
      0
      1
      1

      40
      0
      0
      0
      1
      0
      1
      0

      41
      1
      0
      0
      1
      0
      1
      0

      42
      0
      1
      0
      1
      0
      1
      0

      43
      1
      1
      0
      1
      0
      1
      0

      44
      0
      0
      1
      1
      0
      1
      1

      45
      1
      0
      1
      1
      0
      1
      1

      46
      0
      1
      1
      1
      0
      1
      1

      47
      1
      1
      1
      1
      0
      1
      1

      48
      0
      0
      0
      0
      1
      1
      0

      49
      1
      0
      0
      0
      1
      1
      1

      50
      0
      1
      0
      0
      1
      1
      0

      51
      1
      1
      0
      0
      1
      1
      1

      52
      0
      0
      1
      0
      1
      1
      0

      53
      1
      0
      1
      0
      1
      1
      1

      54
      0
      1
      1
      0
      1
      1
      0

      55
      1
      1
      1
      0
      1
      1
      1

      56
      0
      0
      0
      1
      1
      1
      0

      57
      1
      0
      0
      1
      1
      1
      1

      58
      0
      1
      0
      1
      1
      1
      0

      59
      1
      1
      0
      1
      1
      1
      1

      60
      0
      0
      1
      1
      1
      1
      0

      61
      1
      0
      1
      1
      1
      1
      1

      62
      0
      1
      1
      1
      1
      1
      0

      63
      1
      1
      1
      1
      1
      1
      1

      64
      1
      1
      0
      1
      1
      0
      1

      65
      0
      0
      1
      1
      0
      1
      1

      66
      1
      1
      0
      1
      1
      0
      1

      67
      1
      0
      1
      0
      1
      1
      1

      68
      0
      0
      0
      0
      1
      1
      0

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

```python
Test=MUX4_1_ComboData[['x3', 'x2', 'x1', 'x0', 's1', 's0', 'y']]==MUX4_1_MSData
Test=Test.all().all()
print(f'Module `MUX4_1_MS` works as exspected: {Test}')
```

    Module `MUX4_1_MS` works as exspected: True

## Verilog Conversion

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

    ***Verilog modual from MUX4_1_MS.v***

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

    `timescale 1ns/10ps

    module MUX4_1_MS (
        x0,
        x1,
        x2,
        x3,
        s0,
        s1,
        y
    );
    // 4:1 Multiplexer via 2:1 MUX stacking
    // Input:
    //     x0(bool): input channel 0
    //     x1(bool): input channel 1
    //     x2(bool): input channel 2
    //     x3(bool): input channel 3
    //     s1(bool): channel selection input bit 1
    //     s0(bool): channel selection input bit 0
    // Output:
    //     y(bool): ouput

    input x0;
    input x1;
    input x2;
    input x3;
    input s0;
    input s1;
    output y;
    wire y;

    wire x0x1_yWire;
    wire MUX2_1_Combo1_0_y;

    assign x0x1_yWire = (((!s0) && x0) | (s0 && x1));

    assign MUX2_1_Combo1_0_y = (((!s0) && x2) | (s0 && x3));

    assign y = (((!s1) && x0x1_yWire) | (s1 && MUX2_1_Combo1_0_y));

    endmodule

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

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

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

## myHDL to Verilog Testbench

```python
#create BitVectors
x0TVs=intbv(int(''.join(x0TVs.astype(str)), 2))[TestLen:]
x1TVs=intbv(int(''.join(x1TVs.astype(str)), 2))[TestLen:]
x2TVs=intbv(int(''.join(x2TVs.astype(str)), 2))[TestLen:]
x3TVs=intbv(int(''.join(x3TVs.astype(str)), 2))[TestLen:]

s0TVs=intbv(int(''.join(s0TVs.astype(str)), 2))[TestLen:]
s1TVs=intbv(int(''.join(s1TVs.astype(str)), 2))[TestLen:]

x0TVs, bin(x0TVs), x1TVs, bin(x1TVs), x2TVs, bin(x2TVs), x3TVs, bin(x3TVs), s0TVs, bin(s0TVs), s1TVs, bin(s1TVs)
```

    (intbv(2296870857426870268),
     '1111111100000000111111110000000011111111000000001111111111100',
     intbv(34723282962276803050),
     '11110000111100001111000011110000111100001111000011110000111101010',
     intbv(118059162071741130356),
     '1100110011001100110011001100110011001100110011001100110011001110100',
     intbv(196765270119568550582),
     '10101010101010101010101010101010101010101010101010101010101010110110',
     intbv(137438953451),
     '1111111111111111111111111111111101011',
     intbv(9007061817884663),
     '11111111111111110000000000000000111111111111111110111')

```python
@block
def MUX4_1_MS_TBV():
    """
    myHDL -> Verilog testbench for module `MUX4_1_MS`
    """

    x0=Signal(bool(0))
    x1=Signal(bool(0))
    x2=Signal(bool(0))
    x3=Signal(bool(0))
    y=Signal(bool(0))
    s0=Signal(bool(0))
    s1=Signal(bool(0))

    @always_comb
    def print_data():
        print(x0, x1, x2, x3, s0, s1, y)

    #Test Signal Bit Vectors
    x0TV=Signal(x0TVs)
    x1TV=Signal(x1TVs)
    x2TV=Signal(x2TVs)
    x3TV=Signal(x3TVs)
    s0TV=Signal(s0TVs)
    s1TV=Signal(s1TVs)

    DUT=MUX4_1_MS(x0, x1, x2, x3, s0, s1, y)

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TV[i])
            x1.next=int(x1TV[i])
            x2.next=int(x2TV[i])
            x3.next=int(x3TV[i])
            s0.next=int(s0TV[i])
            s1.next=int(s1TV[i])
            yield delay(1)

        raise StopSimulation()
    return instances()

TB=MUX4_1_MS_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('MUX4_1_MS_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 MUX4_1_MS_TBV.v***

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

    `timescale 1ns/10ps

    module MUX4_1_MS_TBV (

    );
    // myHDL -> Verilog testbench for module `MUX4_1_MS`

    reg x0 = 0;
    reg x1 = 0;
    wire y;
    reg x2 = 0;
    reg x3 = 0;
    reg s0 = 0;
    reg s1 = 0;
    wire [68:0] x0TV;
    wire [68:0] x1TV;
    wire [68:0] x2TV;
    wire [68:0] x3TV;
    wire [68:0] s0TV;
    wire [68:0] s1TV;
    wire MUX4_1_MS0_0_x0x1_yWire;
    wire MUX4_1_MS0_0_MUX2_1_Combo1_0_1_y;

    assign x0TV = 69'd2296870857426870268;
    assign x1TV = 69'd34723282962276803050;
    assign x2TV = 69'd118059162071741130356;
    assign x3TV = 69'd196765270119568550582;
    assign s0TV = 69'd137438953451;
    assign s1TV = 69'd9007061817884663;

    always @(x0, x3, s0, x2, y, x1, s1) begin: MUX4_1_MS_TBV_PRINT_DATA
        $write("%h", x0);
        $write(" ");
        $write("%h", x1);
        $write(" ");
        $write("%h", x2);
        $write(" ");
        $write("%h", x3);
        $write(" ");
        $write("%h", s0);
        $write(" ");
        $write("%h", s1);
        $write(" ");
        $write("%h", y);
        $write("\n");
    end

    assign MUX4_1_MS0_0_x0x1_yWire = (((!s0) && x0) | (s0 && x1));

    assign MUX4_1_MS0_0_MUX2_1_Combo1_0_1_y = (((!s0) && x2) | (s0 && x3));

    assign y = (((!s1) && MUX4_1_MS0_0_x0x1_yWire) | (s1 && MUX4_1_MS0_0_MUX2_1_Combo1_0_1_y));

    initial begin: MUX4_1_MS_TBV_STIMULES
        integer i;
        for (i=0; i<69; i=i+1) begin
            x0 <= x0TV[i];
            x1 <= x1TV[i];
            x2 <= x2TV[i];
            x3 <= x3TV[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: x0TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x1TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x2TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x3TV
      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 "4 Channel Input : 1 Channel Output multiplexer in Gate Level Logic"

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

### Video of Deployment
MUX4_1_MS myHDL PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=uO7VZ8ow_Yg))

# Introduction to HDL Behavioral Modeling

HDL behavioral modeling is a "High" level, though not at the HLS level, HDL syntax where the intended hardware element is modeled via its intended abstract algorithm behavior. Thus the common computer science (and mathematician)tool of abstraction is borrowed and incorporated into the HDL syntax. The abstraction that follows has, like all things, its pros and cons.

As a pro, this means that the Hard Ware Designer is no longer consumed by the manuchia of implementing boolean algebra for every device and can instead focus on implementing the intended algorithm in hardware. And it is thanks to this blending of Software and Hardware that the design of digital devices has grown as prolific as it has. However, there is quite a cache for using behavioral modeling. First off HDL now absolutely requires synthesis tools that can map the behavioral statements to hardware. And even when the behavioral logic is mapped at least to the RTL level there is no escaping two points. 1. At the end of the day, the RTL will be implemented via Gate level devices in some form or another. 2. the way the synthesis tool has mapped the abstract behavioral to RTL may not be physical implementable especially in ASIC implementations.

For these reasons it as Hardware Developers using Behavioral HDL we have to be able to still be able to implement the smallest indivisible units of our HDL at the gate level. Must know what physical limits our target architecture (FPGA, ASIC, etc) has and keep within these limits when writing our HDL code. And lastly, we can not grow lazy in writing behavioral HDL, but must always see at least down to the major RTL elements that our behavioral statements are embodying.

# 2:1 MUX via Behavioral IF

## myHDL Module

```python
@block
def MUX2_1_B(x0, x1, s, y):
    """
    2:1 Multiplexer written via behavioral if
    Input:
        x0(bool): input channel 0
        x1(bool): input channel 1
        s(bool): channel selection input
    Output:
        y(bool): ouput
    """

    @always_comb
    def logic():
        if s:
            y.next=x1
        else:
            y.next=x0

    return instances()
```

## myHDL Testing

```python
#generate systmatic and random test values
TestLen=10
SystmaticVals=list(itertools.product([0,1], repeat=3))

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

x1TVs=np.array([i[2] 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)
x1TVs=np.append(x1TVs, 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(17)
sTVs=np.append(sTVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(x0TVs)
x0TVs, x1TVs, sTVs, TestLen
```

    (array([0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1]),
     array([0, 1, 0, 1, 0, 1, 0, 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]),
     18)

```python
Peeker.clear()
x0=Signal(bool(0)); Peeker(x0, 'x0')
x1=Signal(bool(0)); Peeker(x1, 'x1')
s=Signal(bool(0)); Peeker(s, 's')
y=Signal(bool(0)); Peeker(y, 'y')

DUT=MUX2_1_B(x0, x1, s, y)

def MUX2_1_B_TB():
    """
    myHDL only testbench for module `MUX2_1_B`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TVs[i])
            x1.next=int(x1TVs[i])
            s.next=int(sTVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

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

```python
Peeker.to_wavedrom('x1', 'x0', 's', 'y')
```

```python
MUX2_1_BData=Peeker.to_dataframe()
MUX2_1_BData=MUX2_1_BData[['x1', 'x0', 's', 'y']]
MUX2_1_BData
```

      x1
      x0
      s
      y

      0
      0
      0
      0
      0

      1
      1
      0
      0
      0

      2
      0
      1
      0
      1

      3
      1
      1
      0
      1

      4
      0
      0
      1
      0

      5
      1
      0
      1
      1

      6
      0
      1
      1
      0

      7
      1
      1
      1
      1

      8
      1
      0
      1
      1

      9
      0
      1
      1
      0

      10
      1
      0
      1
      1

      11
      1
      1
      0
      1

      13
      1
      0
      1
      1

      14
      0
      0
      0
      0

      15
      1
      1
      1
      1

      16
      1
      1
      0
      1

      17
      0
      1
      1
      0

```python
Test=MUX2_1_ComboData[['x1', 'x0', 's', 'y']]==MUX2_1_BData
Test=Test.all().all()
print(f'`MUX2_1_B` Behavioral is Eqivlint to `MUX2_1_Combo`: {Test}')
```

    `MUX2_1_B` Behavioral is Eqivlint to `MUX2_1_Combo`: True

## Verilog Conversion

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

    ***Verilog modual from MUX2_1_B.v***

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

    `timescale 1ns/10ps

    module MUX2_1_B (
        x0,
        x1,
        s,
        y
    );
    // 2:1 Multiplexer written via behavioral if
    // Input:
    //     x0(bool): input channel 0
    //     x1(bool): input channel 1
    //     s(bool): channel selection input
    // Output:
    //     y(bool): ouput

    input x0;
    input x1;
    input s;
    output y;
    reg y;

    always @(s, x0, x1) begin: MUX2_1_B_LOGIC
        if (s) begin
            y = x1;
        end
        else begin
            y = x0;
        end
    end

    endmodule

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

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

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

## myHDL to Verilog Testbench

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

x0TVs, bin(x0TVs), x1TVs, bin(x1TVs), sTVs, bin(sTVs)
```

    (intbv(52583),
     '1100110101100111',
     intbv(87798),
     '10101011011110110',
     intbv(16277),
     '11111110010101')

```python
@block
def MUX2_1_B_TBV():
    """
    myHDL -> Verilog testbench for module `MUX2_1_B`
    """
    x0=Signal(bool(0))
    x1=Signal(bool(0))
    s=Signal(bool(0))
    y=Signal(bool(0))

    @always_comb
    def print_data():
        print(x0, x1, s, y)

    #Test Signal Bit Vectors
    x0TV=Signal(x0TVs)
    x1TV=Signal(x1TVs)
    sTV=Signal(sTVs)

    DUT=MUX2_1_B(x0, x1, s, y)

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TV[i])
            x1.next=int(x1TV[i])
            s.next=int(sTV[i])
            yield delay(1)

        raise StopSimulation()
    return instances()

TB=MUX2_1_B_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('MUX2_1_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 MUX2_1_B_TBV.v***

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

    `timescale 1ns/10ps

    module MUX2_1_B_TBV (

    );
    // myHDL -> Verilog testbench for module `MUX2_1_B`

    reg x0 = 0;
    reg x1 = 0;
    reg s = 0;
    reg y = 0;
    wire [17:0] x0TV;
    wire [17:0] x1TV;
    wire [17:0] sTV;

    assign x0TV = 18'd52583;
    assign x1TV = 18'd87798;
    assign sTV = 18'd16277;

    always @(s, y, x0, x1) begin: MUX2_1_B_TBV_PRINT_DATA
        $write("%h", x0);
        $write(" ");
        $write("%h", x1);
        $write(" ");
        $write("%h", s);
        $write(" ");
        $write("%h", y);
        $write("\n");
    end

    always @(s, x0, x1) begin: MUX2_1_B_TBV_MUX2_1_B0_0_LOGIC
        if (s) begin
            y = x1;
        end
        else begin
            y = x0;
        end
    end

    initial begin: MUX2_1_B_TBV_STIMULES
        integer i;
        for (i=0; i<18; i=i+1) begin
            x0 <= x0TV[i];
            x1 <= x1TV[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: x0TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x1TV
      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 "2 Channel Input:1 Channel Output multiplexer in Gate Level Logic"

### Board Constraint
uses the same ` MUX2_1.xdc` as "2 Channel Input:1 Channel Output multiplexer in Gate Level Logic"

### Video of Deployment
MUX2_1_B myHDL PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=QrHQfx_Sjnw))

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

## myHDL Module

```python
@block
def MUX4_1_B(x0, x1, x2, x3, s0, s1, y):
    """
    4:1 Multiblexer written in if-elif-else Behavioral
    Input:
        x0(bool): input channel 0
        x1(bool): input channel 1
        x2(bool): input channel 2
        x3(bool): input channel 3
        s1(bool): channel selection input bit 1
        s0(bool): channel selection input bit 0
    Output:
        y(bool): ouput
    """

    @always_comb
    def logic():
        if s0==0 and s1==0:
            y.next=x0
        elif s0==1 and s1==0:
            y.next=x1
        elif s0==0 and s1==1:
            y.next=x2
        else:
            y.next=x3

    return instances()
```

## myHDL Testing

```python
#generate systmatic and random test values
TestLen=5
SystmaticVals=list(itertools.product([0,1], repeat=6))

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

s1TVs=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)
s1TVs=np.append(s1TVs, np.random.randint(0,2, TestLen)).astype(int)

x0TVs=np.array([i[2] 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)
x0TVs=np.append(x0TVs, np.random.randint(0,2, TestLen)).astype(int)

x1TVs=np.array([i[3] 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(18)
x1TVs=np.append(x1TVs, np.random.randint(0,2, TestLen)).astype(int)

x2TVs=np.array([i[4] 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(19)
x2TVs=np.append(x2TVs, np.random.randint(0,2, TestLen)).astype(int)

x3TVs=np.array([i[5] 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(20)
x3TVs=np.append(x3TVs, np.random.randint(0,2, TestLen)).astype(int)

TestLen=len(x0TVs)
SystmaticVals, s0TVs, s1TVs, x3TVs, x2TVs, x1TVs, x0TVs, TestLen
```

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

```python
Peeker.clear()
x0=Signal(bool(0)); Peeker(x0, 'x0')
x1=Signal(bool(0)); Peeker(x1, 'x1')
x2=Signal(bool(0)); Peeker(x2, 'x2')
x3=Signal(bool(0)); Peeker(x3, 'x3')

s0=Signal(bool(0)); Peeker(s0, 's0')
s1=Signal(bool(0)); Peeker(s1, 's1')
y=Signal(bool(0)); Peeker(y, 'y')

DUT=MUX4_1_B(x0, x1, x2, x3, s0, s1, y)

def MUX4_1_B_TB():
    """
    myHDL only testbench for module `MUX4_1_B`
    """

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TVs[i])
            x1.next=int(x1TVs[i])
            x2.next=int(x2TVs[i])
            x3.next=int(x3TVs[i])
            s0.next=int(s0TVs[i])
            s1.next=int(s1TVs[i])

            yield delay(1)

        raise StopSimulation()

    return instances()

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

```python
Peeker.to_wavedrom()
```

```python
MUX4_1_BData=Peeker.to_dataframe()
MUX4_1_BData=MUX4_1_BData[['x3', 'x2', 'x1', 'x0', 's1', 's0', 'y']]
MUX4_1_BData
```

      x3
      x2
      x1
      x0
      s1
      s0
      y

      0
      0
      0
      0
      0
      0
      0
      0

      1
      1
      0
      0
      0
      0
      0
      0

      2
      0
      1
      0
      0
      0
      0
      0

      3
      1
      1
      0
      0
      0
      0
      0

      4
      0
      0
      1
      0
      0
      0
      0

      5
      1
      0
      1
      0
      0
      0
      0

      6
      0
      1
      1
      0
      0
      0
      0

      7
      1
      1
      1
      0
      0
      0
      0

      8
      0
      0
      0
      1
      0
      0
      1

      9
      1
      0
      0
      1
      0
      0
      1

      10
      0
      1
      0
      1
      0
      0
      1

      11
      1
      1
      0
      1
      0
      0
      1

      12
      0
      0
      1
      1
      0
      0
      1

      13
      1
      0
      1
      1
      0
      0
      1

      14
      0
      1
      1
      1
      0
      0
      1

      15
      1
      1
      1
      1
      0
      0
      1

      16
      0
      0
      0
      0
      1
      0
      0

      17
      1
      0
      0
      0
      1
      0
      0

      18
      0
      1
      0
      0
      1
      0
      1

      19
      1
      1
      0
      0
      1
      0
      1

      20
      0
      0
      1
      0
      1
      0
      0

      21
      1
      0
      1
      0
      1
      0
      0

      22
      0
      1
      1
      0
      1
      0
      1

      23
      1
      1
      1
      0
      1
      0
      1

      24
      0
      0
      0
      1
      1
      0
      0

      25
      1
      0
      0
      1
      1
      0
      0

      26
      0
      1
      0
      1
      1
      0
      1

      27
      1
      1
      0
      1
      1
      0
      1

      28
      0
      0
      1
      1
      1
      0
      0

      29
      1
      0
      1
      1
      1
      0
      0

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      39
      1
      1
      1
      0
      0
      1
      1

      40
      0
      0
      0
      1
      0
      1
      0

      41
      1
      0
      0
      1
      0
      1
      0

      42
      0
      1
      0
      1
      0
      1
      0

      43
      1
      1
      0
      1
      0
      1
      0

      44
      0
      0
      1
      1
      0
      1
      1

      45
      1
      0
      1
      1
      0
      1
      1

      46
      0
      1
      1
      1
      0
      1
      1

      47
      1
      1
      1
      1
      0
      1
      1

      48
      0
      0
      0
      0
      1
      1
      0

      49
      1
      0
      0
      0
      1
      1
      1

      50
      0
      1
      0
      0
      1
      1
      0

      51
      1
      1
      0
      0
      1
      1
      1

      52
      0
      0
      1
      0
      1
      1
      0

      53
      1
      0
      1
      0
      1
      1
      1

      54
      0
      1
      1
      0
      1
      1
      0

      55
      1
      1
      1
      0
      1
      1
      1

      56
      0
      0
      0
      1
      1
      1
      0

      57
      1
      0
      0
      1
      1
      1
      1

      58
      0
      1
      0
      1
      1
      1
      0

      59
      1
      1
      0
      1
      1
      1
      1

      60
      0
      0
      1
      1
      1
      1
      0

      61
      1
      0
      1
      1
      1
      1
      1

      62
      0
      1
      1
      1
      1
      1
      0

      63
      1
      1
      1
      1
      1
      1
      1

      64
      1
      1
      0
      1
      1
      0
      1

      65
      0
      0
      1
      1
      0
      1
      1

      66
      1
      1
      0
      1
      1
      0
      1

      67
      1
      0
      1
      0
      1
      1
      1

      68
      0
      0
      0
      0
      1
      1
      0

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

```python
Test=MUX4_1_ComboData[['x3', 'x2', 'x1', 'x0', 's1', 's0', 'y']]==MUX4_1_BData
Test=Test.all().all()
print(f'Module `MUX4_1_B` works as exspected: {Test}')
```

    Module `MUX4_1_B` works as exspected: True

## Verilog Conversion

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

    ***Verilog modual from MUX4_1_B.v***

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

    `timescale 1ns/10ps

    module MUX4_1_B (
        x0,
        x1,
        x2,
        x3,
        s0,
        s1,
        y
    );
    // 4:1 Multiblexer written in if-elif-else Behavioral
    // Input:
    //     x0(bool): input channel 0
    //     x1(bool): input channel 1
    //     x2(bool): input channel 2
    //     x3(bool): input channel 3
    //     s1(bool): channel selection input bit 1
    //     s0(bool): channel selection input bit 0
    // Output:
    //     y(bool): ouput

    input x0;
    input x1;
    input x2;
    input x3;
    input s0;
    input s1;
    output y;
    reg y;

    always @(x0, s0, x3, x2, x1, s1) begin: MUX4_1_B_LOGIC
        if (((s0 == 0) && (s1 == 0))) begin
            y = x0;
        end
        else if (((s0 == 1) && (s1 == 0))) begin
            y = x1;
        end
        else if (((s0 == 0) && (s1 == 1))) begin
            y = x2;
        end
        else begin
            y = x3;
        end
    end

    endmodule

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

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

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

## myHDL to Verilog Testbench

```python
#create BitVectors
x0TVs=intbv(int(''.join(x0TVs.astype(str)), 2))[TestLen:]
x1TVs=intbv(int(''.join(x1TVs.astype(str)), 2))[TestLen:]
x2TVs=intbv(int(''.join(x2TVs.astype(str)), 2))[TestLen:]
x3TVs=intbv(int(''.join(x3TVs.astype(str)), 2))[TestLen:]

s0TVs=intbv(int(''.join(s0TVs.astype(str)), 2))[TestLen:]
s1TVs=intbv(int(''.join(s1TVs.astype(str)), 2))[TestLen:]

x0TVs, bin(x0TVs), x1TVs, bin(x1TVs), x2TVs, bin(x2TVs), x3TVs, bin(x3TVs), s0TVs, bin(s0TVs), s1TVs, bin(s1TVs)
```

    (intbv(2296870857426870268),
     '1111111100000000111111110000000011111111000000001111111111100',
     intbv(34723282962276803050),
     '11110000111100001111000011110000111100001111000011110000111101010',
     intbv(118059162071741130356),
     '1100110011001100110011001100110011001100110011001100110011001110100',
     intbv(196765270119568550582),
     '10101010101010101010101010101010101010101010101010101010101010110110',
     intbv(137438953451),
     '1111111111111111111111111111111101011',
     intbv(9007061817884663),
     '11111111111111110000000000000000111111111111111110111')

```python
@block
def MUX4_1_B_TBV():
    """
    myHDL -> Verilog testbench for module `MUX4_1_B`
    """

    x0=Signal(bool(0))
    x1=Signal(bool(0))
    x2=Signal(bool(0))
    x3=Signal(bool(0))
    y=Signal(bool(0))
    s0=Signal(bool(0))
    s1=Signal(bool(0))

    @always_comb
    def print_data():
        print(x0, x1, x2, x3, s0, s1, y)

    #Test Signal Bit Vectors
    x0TV=Signal(x0TVs)
    x1TV=Signal(x1TVs)
    x2TV=Signal(x2TVs)
    x3TV=Signal(x3TVs)
    s0TV=Signal(s0TVs)
    s1TV=Signal(s1TVs)

    DUT=MUX4_1_B(x0, x1, x2, x3, s0, s1, y)

    @instance
    def stimules():
        for i in range(TestLen):
            x0.next=int(x0TV[i])
            x1.next=int(x1TV[i])
            x2.next=int(x2TV[i])
            x3.next=int(x3TV[i])
            s0.next=int(s0TV[i])
            s1.next=int(s1TV[i])
            yield delay(1)

        raise StopSimulation()
    return instances()

TB=MUX4_1_B_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('MUX4_1_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 MUX4_1_B_TBV.v***

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

    `timescale 1ns/10ps

    module MUX4_1_B_TBV (

    );
    // myHDL -> Verilog testbench for module `MUX4_1_B`

    reg x0 = 0;
    reg x1 = 0;
    reg y = 0;
    reg x2 = 0;
    reg x3 = 0;
    reg s0 = 0;
    reg s1 = 0;
    wire [68:0] x0TV;
    wire [68:0] x1TV;
    wire [68:0] x2TV;
    wire [68:0] x3TV;
    wire [68:0] s0TV;
    wire [68:0] s1TV;

    assign x0TV = 69'd2296870857426870268;
    assign x1TV = 69'd34723282962276803050;
    assign x2TV = 69'd118059162071741130356;
    assign x3TV = 69'd196765270119568550582;
    assign s0TV = 69'd137438953451;
    assign s1TV = 69'd9007061817884663;

    always @(x0, x3, s0, x2, y, x1, s1) begin: MUX4_1_B_TBV_PRINT_DATA
        $write("%h", x0);
        $write(" ");
        $write("%h", x1);
        $write(" ");
        $write("%h", x2);
        $write(" ");
        $write("%h", x3);
        $write(" ");
        $write("%h", s0);
        $write(" ");
        $write("%h", s1);
        $write(" ");
        $write("%h", y);
        $write("\n");
    end

    always @(x0, s0, x3, x2, x1, s1) begin: MUX4_1_B_TBV_MUX4_1_B0_0_LOGIC
        if (((s0 == 0) && (s1 == 0))) begin
            y = x0;
        end
        else if (((s0 == 1) && (s1 == 0))) begin
            y = x1;
        end
        else if (((s0 == 0) && (s1 == 1))) begin
            y = x2;
        end
        else begin
            y = x3;
        end
    end

    initial begin: MUX4_1_B_TBV_STIMULES
        integer i;
        for (i=0; i<69; i=i+1) begin
            x0 <= x0TV[i];
            x1 <= x1TV[i];
            x2 <= x2TV[i];
            x3 <= x3TV[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: x0TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x1TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x2TV
      category=ToVerilogWarning
    /home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: x3TV
      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 "4 Channel Input : 1 Channel Output multiplexer in Gate Level Logic"

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

### Video of Deployment
MUX4_1_B myHDL PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=UKXx4PYS1xI))

# Multiplexer 4:1 Behavioral via Bitvectors

## myHDL Module

```python
@block
def MUX4_1_BV(X, S, y):
    """
    4:1 Multiblexerwritten in behvioral "if-elif-else"(case)
    with BitVector inputs
    Input:
        X(4bitBV):input bit vector; min=0, max=15
        S(2bitBV):selection bit vector; min=0, max=3
    Output:
        y(bool): ouput
    """

    @always_comb
    def logic():
        if S==0:
            y.next=X[0]
        elif S==1:
            y.next=X[1]
        elif S==2:
            y.next=X[2]
        else:
            y.next=X[3]

    return instances()
```

## myHDL Testing

```python
XTVs=np.array([1,2,4,8])
XTVs=np.append(XTVs, np.random.choice([1,2,4,8], 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
```

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

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

DUT=MUX4_1_BV(X, S, y)

def MUX4_1_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, MUX4_1_BV_TB(), *Peeker.instances()).run()
```

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

```python
MUX4_1_BVData=Peeker.to_dataframe()
MUX4_1_BVData=MUX4_1_BVData[['X', 'S', 'y']]
MUX4_1_BVData
```

      X
      S
      y

      0
      1
      0
      1

      1
      2
      0
      0

      2
      4
      0
      0

      3
      8
      0
      0

      4
      4
      0
      0

      5
      2
      0
      0

      6
      1
      0
      1

      7
      8
      0
      0

      8
      4
      0
      0

      9
      8
      0
      0

      10
      1
      1
      0

      11
      2
      1
      1

      12
      4
      1
      0

      13
      8
      1
      0

      14
      4
      1
      0

      15
      2
      1
      1

      16
      1
      1
      0

      17
      8
      1
      0

      18
      4
      1
      0

      19
      8
      1
      0

      20
      1
      2
      0

      21
      2
      2
      0

      22
      4
      2
      1

      23
      8
      2
      0

      24
      4
      2
      1

      25
      2
      2
      0

      26
      1
      2
      0

      27
      8
      2
      0

      28
      4
      2
      1

      29
      8
      2
      0

      ...
      ...
      ...
      ...

      60
      1
      2
      0

      61
      2
      2
      0

      62
      4
      2
      1

      63
      8
      2
      0

      64
      4
      2
      1

      65
      2
      2
      0

      66
      1
      2
      0

      67
      8
      2
      0

      68
      4
      2
      1

      69
      8
      2
      0

      70
      1
      1
      0

      71
      2
      1
      1

      72
      4
      1
      0

      73
      8
      1
      0

      74
      4
      1
      0

      75
      2
      1
      1

      76
      1
      1
      0

      77
      8
      1
      0

      78
      4
      1
      0

      79
      8
      1
      0

      80
      1
      1
      0

      81
      2
      1
      1

      82
      4
      1
      0

      83
      8
      1
      0

      84
      4
      1
      0

      85
      2
      1
      1

      86
      1
      1
      0

      87
      8
      1
      0

      88
      4
      1
      0

      89
      8
      1
      0

90 rows × 3 columns

```python
MUX4_1_BVData['x0']=None; MUX4_1_BVData['x1']=None; MUX4_1_BVData['x2']=None; MUX4_1_BVData['x3']=None
MUX4_1_BVData[['x3', 'x2', 'x1', 'x0']]=MUX4_1_BVData[['X']].apply(lambda bv: [int(i) for i in bin(bv, 4)], axis=1, result_type='expand')

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

MUX4_1_BVData=MUX4_1_BVData[['X', 'x0', 'x1', 'x2', 'x3', 'S', 's0', 's1', 'y']]
MUX4_1_BVData
```

      X
      x0
      x1
      x2
      x3
      S
      s0
      s1
      y

      0
      1
      1
      0
      0
      0
      0
      0
      0
      1

      1
      2
      0
      1
      0
      0
      0
      0
      0
      0

      2
      4
      0
      0
      1
      0
      0
      0
      0
      0

      3
      8
      0
      0
      0
      1
      0
      0
      0
      0

      4
      4
      0
      0
      1
      0
      0
      0
      0
      0

      5
      2
      0
      1
      0
      0
      0
      0
      0
      0

      6
      1
      1
      0
      0
      0
      0
      0
      0
      1

      7
      8
      0
      0
      0
      1
      0
      0
      0
      0

      8
      4
      0
      0
      1
      0
      0
      0
      0
      0

      9
      8
      0
      0
      0
      1
      0
      0
      0
      0

      10
      1
      1
      0
      0
      0
      1
      1
      0
      0

      11
      2
      0
      1
      0
      0
      1
      1
      0
      1

      12
      4
      0
      0
      1
      0
      1
      1
      0
      0

      13
      8
      0
      0
      0
      1
      1
      1
      0
      0

      14
      4
      0
      0
      1
      0
      1
      1
      0
      0

      15
      2
      0
      1
      0
      0
      1
      1
      0
      1

      16
      1
      1
      0
      0
      0
      1
      1
      0
      0

      17
      8
      0
      0
      0
      1
      1
      1
      0
      0

      18
      4
      0
      0
      1
      0
      1
      1
      0
      0

      19
      8
      0
      0
      0
      1
      1
      1
      0
      0

      20
      1
      1
      0
      0
      0
      2
      0
      1
      0

      21
      2
      0
      1
      0
      0
      2
      0
      1
      0

      22
      4
      0
      0
      1
      0
      2
      0
      1
      1

      23
      8
      0
      0
      0
      1
      2
      0
      1
      0

      24
      4
      0
      0
      1
      0
      2
      0
      1
      1

      25
      2
      0
      1
      0
      0
      2
      0
      1
      0

      26
      1
      1
      0
      0
      0
      2
      0
      1
      0

      27
      8
      0
      0
      0
      1
      2
      0
      1
      0

      28
      4
      0
      0
      1
      0
      2
      0
      1
      1

      29
      8
      0
      0
      0
      1
      2
      0
      1
      0

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      60
      1
      1
      0
      0
      0
      2
      0
      1
      0

      61
      2
      0
      1
      0
      0
      2
      0
      1
      0

      62
      4
      0
      0
      1
      0
      2
      0
      1
      1

      63
      8
      0
      0
      0
      1
      2
      0
      1
      0

      64
      4
      0
      0
      1
      0
      2
      0
      1
      1

      65
      2
      0
      1
      0
      0
      2
      0
      1
      0

      66
      1
      1
      0
      0
      0
      2
      0
      1
      0

      67
      8
      0
      0
      0
      1
      2
      0
      1
      0

      68
      4
      0
      0
      1
      0
      2
      0
      1
      1

      69
      8
      0
      0
      0
      1
      2
      0
      1
      0

      70
      1
      1
      0
      0
      0
      1
      1
      0
      0

      71
      2
      0
      1
      0
      0
      1
      1
      0
      1

      72
      4
      0
      0
      1
      0
      1
      1
      0
      0

      73
      8
      0
      0
      0
      1
      1
      1
      0
      0

      74
      4
      0
      0
      1
      0
      1
      1
      0
      0

      75
      2
      0
      1
      0
      0
      1
      1
      0
      1

      76
      1
      1
      0
      0
      0
      1
      1
      0
      0

      77
      8
      0
      0
      0
      1
      1
      1
      0
      0

      78
      4
      0
      0
      1
      0
      1
      1
      0

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

```python
MUX4_1_BVData['yRef']=MUX4_1_BVData.apply(lambda row:y41EqN(row['x0'], row['x1'], row['x2'], row['x3'], row['s0'], row['s1']), axis=1).astype(int)
MUX4_1_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.

      X
      x0
      x1
      x2
      x3
      S
      s0
      s1
      y
      yRef

      0
      1
      1
      0
      0
      0
      0
      0
      0
      1
      1

      1
      2
      0
      1
      0
      0
      0
      0
      0
      0
      0

      2
      4
      0
      0
      1
      0
      0
      0
      0
      0
      0

      3
      8
      0
      0
      0
      1
      0
      0
      0
      0
      0

      4
      4
      0
      0
      1
      0
      0
      0
      0
      0
      0

      5
      2
      0
      1
      0
      0
      0
      0
      0
      0
      0

      6
      1
      1
      0
      0
      0
      0
      0
      0
      1
      1

      7
      8
      0
      0
      0
      1
      0
      0
      0
      0
      0

      8
      4
      0
      0
      1
      0
      0
      0
      0
      0
      0

      9
      8
      0
      0
      0
      1
      0
      0
      0
      0
      0

      10
      1
      1
      0
      0
      0
      1
      1
      0
      0
      0

      11
      2
      0
      1
      0
      0
      1
      1
      0
      1
      1

      12
      4
      0
      0
      1
      0
      1
      1
      0
      0
      0

      13
      8
      0
      0
      0
      1
      1
      1
      0
      0
      0

      14
      4
      0
      0
      1
      0
      1
      1
      0
      0
      0

      15
      2
      0
      1
      0
      0
      1
      1
      0
      1
      1

      16
      1
      1
      0
      0
      0
      1
      1
      0
      0
      0

      17
      8
      0
      0
      0
      1
      1
      1
      0
      0
      0

      18
      4
      0
      0
      1
      0
      1
      1
      0
      0
      0

      19
      8
      0
      0
      0
      1
      1
      1
      0
      0
      0

      20
      1
      1
      0
      0
      0
      2
      0
      1
      0
      0

      21
      2
      0
      1
      0
      0
      2
      0
      1
      0
      0

      22
      4
      0
      0
      1
      0
      2
      0
      1
      1
      1

      23
      8
      0
      0
      0
      1
      2
      0
      1
      0
      0

      24
      4
      0
      0
      1
      0
      2
      0
      1
      1
      1

      25
      2
      0
      1
      0
      0
      2
      0
      1
      0
      0

      26
      1
      1
      0
      0
      0
      2
      0
      1
      0
      0

      27
      8
      0
      0
      0
      1
      2
      0
      1
      0
      0

      28
      4
      0
      0
      1
      0
      2
      0
      1
      1
      1

      29
      8
      0
      0
      0
      1
      2
      0
      1
      0
      0

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      60
      1
      1
      0
      0
      0
      2
      0
      1
      0
      0

      61
      2
      0
      1
      0
      0
      2
      0
      1
      0
      0

      62
      4
      0
      0
      1
      0
      2
      0
      1
      1
      1

      63
      8
      0
      0
      0
      1
      2
      0
      1
      0
      0

      64
      4
      0
      0
      1
      0
      2
      0
      1
      1
      1

      65
      2
      0
      1
      0
      0
      2
      0
      1
      0
      0

      66
      1
      1
      0
      0
      0
      2
      0
      1
      0
      0

      67
      8
      0
      0
      0
      1
      2
      0
      1
      0
      0

      68
      4
      0
      0
      1
      0
      2
      0
      1
      1
      1

      69
      8
      0
      0
      0
      1
      2
      0
      1
      0
      0

      70
      1
      1
      0
      0
      0
      1
      1
      0
      0
      0

      71
      2
      0
      1
      0
      0
      1
      1
      0
      1
      1

      72
      4
      0
      0
      1
      0
      1
      1

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

```python
Test=(MUX4_1_BVData['y']==MUX4_1_BVData['yRef']).all()
print(f'Module `MUX4_1_BVData` works as exspected: {Test}')
```

    Module `MUX4_1_BVData` works as exspected: True

## Verilog Conversion

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

    ***Verilog modual from MUX4_1_BV.v***

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

    `timescale 1ns/10ps

    module MUX4_1_BV (
        X,
        S,
        y
    );
    // 4:1 Multiblexerwritten in behvioral "if-elif-else"(case)
    // with BitVector inputs
    // Input:
    //     X(4bitBV):input bit vector; min=0, max=15
    //     S(2bitBV):selection bit vector; min=0, max=3
    // Output:
    //     y(bool): ouput

    input [3:0] X;
    input [1:0] S;
    output y;
    reg y;

    always @(X, S) begin: MUX4_1_BV_LOGIC
        case (S)
            'h0: begin
                y = X[0];
            end
            'h1: begin
                y = X[1];
            end
            'h2: begin
                y = X[2];
            end
            default: begin
                y = X[3];
            end
        endcase
    end

    endmodule

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

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

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

## myHDL to Verilog Testbench
Will Do later

## PYNQ-Z1 Deployment

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

### Board Constraint
notice that in `get_ports` the pin is set to the a single bit of the bitvector via bitvector indexing

```python
ConstraintXDCTextReader('MUX4_1_BV');
```

    ***Constraint file from MUX4_1_BV.xdc***

     ## PYNQ-Z1 Constraint File for MUX4_1_BV
    ## Based on https://github.com/Xilinx/PYNQ/blob/master/boards/Pynq-Z1/base/vivado/constraints/base.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 D19 IOSTANDARD LVCMOS33} [get_ports {X[0]}]; ## BT0
    set_property -dict {PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports {X[1]}]; ## BT1
    set_property -dict {PACKAGE_PIN L20 IOSTANDARD LVCMOS33} [get_ports {X[2]}]; ## BT2
    set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS33} [get_ports {X[3]}]; ## BT3

    ## LEDs
    set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports {y}]; ## Led 0

### Video of Deployment
MUX4_1_BV myHDL PYNQ-Z1 ([YouTube](https://www.youtube.com/watch?v=vFG9kgLXJek))