<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 \title{Combinational-Circuit Building Blocks aka medium scale integrated circuit (MSI) in myHDL}
\author{Steven K Armour}
\maketitle
Table of Contents
<p><div class="lev1 toc-item"><a href="#Refs" data-toc-modified-id="Refs-1"><span class="toc-item-num">1&nbsp;&nbsp;</span>Refs</a></div><div class="lev1 toc-item"><a href="#Python-Libraries-Utilized" data-toc-modified-id="Python-Libraries-Utilized-2"><span class="toc-item-num">2&nbsp;&nbsp;</span>Python Libraries Utilized</a></div><div class="lev1 toc-item"><a href="#Multiplexers-(mux)" data-toc-modified-id="Multiplexers-(mux)-3"><span class="toc-item-num">3&nbsp;&nbsp;</span>Multiplexers (mux)</a></div><div class="lev2 toc-item"><a href="#Shannon’s-Expansion-Theorem" data-toc-modified-id="Shannon’s-Expansion-Theorem-31"><span class="toc-item-num">3.1&nbsp;&nbsp;</span>Shannon’s Expansion Theorem</a></div><div class="lev2 toc-item"><a href="#2
Step2:  Multiplexers (mux)
a junction switch between one of n inputs to a single output; equivalent to a "if" or "case" statement
let $Z$ be its output $m_k$ the minterms of the controls to the mux and $I_k$ be the input feeds to the mux; then the expression for the mux in terms of boolean algebra becomes
$$Z=\sum^{2^k-1}_{k=0} m_k \cdot I_k= \text{OR}(m_k \& I_k) $$
Shannon’s Expansion Theorem
The above is Shannon's theorem
it can be written more sincintly as
Step3:  ## 2
Step4:  let $f(m_1, m_2, m_3)$ be the total set of minterms for a 3-bit then let $m_1$ be designated the select terms then by shannon's theorem states
$$f(m_1, m_2, m_3)=\bar{m_1} \cdot f_1'(0, m_2, m_3)+m_1 \cdot f_1(1, m_2, m_3)$$
in other words we want select the two subset of the f where $m_1$ is 1 or 0 and call thouse two subsets $f_1'$, $f_1$
Step5:  $$f(m_1, m_2, m_3)$$
Step6:  $$\bar{m_1} \cdot f_1'(0, m_2, m_3)$$
Step7:  $$m_1 \cdot f_1(1, m_2, m_3)$$
Step8:  and since this is the lowest order mux this case use of shannon's theorem is kind of trivial
myHDL 2
Step9:  myHDL 2
Step10:  The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL 2
Step11:  myHDL 2
Step12:  The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL behavioral level 2
Step13:  myHDL 4
Step14:  The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL 4
Step15:  myHDL 4
Step16:  The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL behavioral level 4
Step17:  myHDL 4
Step18:  myHDL 4
Step19:  The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL behavioral level 4
Step20:  myHDL Generic Expression via MUXs and Testing
Step21:  myHDL Generic Expression via MUXs HDL Synthesis
<ASSISTANT_TASK:>
Python Code:
import numpy as np
import pandas as pd
from sympy import *
init_printing()
from myhdl import *
from myhdlpeek import *
import random
from sympy_myhdl_tools import *
pass
Explanation: \title{Combinational-Circuit Building Blocks aka medium scale integrated circuit (MSI) in myHDL}
\author{Steven K Armour}
\maketitle
Table of Contents
<p><div class="lev1 toc-item"><a href="#Refs" data-toc-modified-id="Refs-1"><span class="toc-item-num">1&nbsp;&nbsp;</span>Refs</a></div><div class="lev1 toc-item"><a href="#Python-Libraries-Utilized" data-toc-modified-id="Python-Libraries-Utilized-2"><span class="toc-item-num">2&nbsp;&nbsp;</span>Python Libraries Utilized</a></div><div class="lev1 toc-item"><a href="#Multiplexers-(mux)" data-toc-modified-id="Multiplexers-(mux)-3"><span class="toc-item-num">3&nbsp;&nbsp;</span>Multiplexers (mux)</a></div><div class="lev2 toc-item"><a href="#Shannon’s-Expansion-Theorem" data-toc-modified-id="Shannon’s-Expansion-Theorem-31"><span class="toc-item-num">3.1&nbsp;&nbsp;</span>Shannon’s Expansion Theorem</a></div><div class="lev2 toc-item"><a href="#2:1-MultiPlexer" data-toc-modified-id="2:1-MultiPlexer-32"><span class="toc-item-num">3.2&nbsp;&nbsp;</span>2:1 MultiPlexer</a></div><div class="lev3 toc-item"><a href="#myHDL-2:1-MUX-Gate-Level-and-Testing" data-toc-modified-id="myHDL-2:1-MUX-Gate-Level-and-Testing-321"><span class="toc-item-num">3.2.1&nbsp;&nbsp;</span>myHDL 2:1 MUX Gate Level and Testing</a></div><div class="lev3 toc-item"><a href="#myHDL-2:1-MUX-Gate-Level-HDL-Synthesis" data-toc-modified-id="myHDL-2:1-MUX-Gate-Level-HDL-Synthesis-322"><span class="toc-item-num">3.2.2&nbsp;&nbsp;</span>myHDL 2:1 MUX Gate Level HDL Synthesis</a></div><div class="lev2 toc-item"><a href="#2:1-Multiplexer-Behavioral" data-toc-modified-id="2:1-Multiplexer-Behavioral-33"><span class="toc-item-num">3.3&nbsp;&nbsp;</span>2:1 Multiplexer Behavioral</a></div><div class="lev3 toc-item"><a href="#myHDL-2:1-MUX-Behavioral-Level-and-Testing" data-toc-modified-id="myHDL-2:1-MUX-Behavioral-Level-and-Testing-331"><span class="toc-item-num">3.3.1&nbsp;&nbsp;</span>myHDL 2:1 MUX Behavioral Level and Testing</a></div><div class="lev3 toc-item"><a href="#myHDL-2:1-MUX-Behavioral-Level-HDL-Synthesis" data-toc-modified-id="myHDL-2:1-MUX-Behavioral-Level-HDL-Synthesis-332"><span class="toc-item-num">3.3.2&nbsp;&nbsp;</span>myHDL 2:1 MUX Behavioral Level HDL Synthesis</a></div><div class="lev2 toc-item"><a href="#4:1-MUX" data-toc-modified-id="4:1-MUX-34"><span class="toc-item-num">3.4&nbsp;&nbsp;</span>4:1 MUX</a></div><div class="lev3 toc-item"><a href="#!?-Insert-Digram-below" data-toc-modified-id="!?-Insert-Digram-below-341"><span class="toc-item-num">3.4.1&nbsp;&nbsp;</span>!? Insert Digram below</a></div><div class="lev3 toc-item"><a href="#myHDL-4:1-MUX-Gate-Level-and-Testing" data-toc-modified-id="myHDL-4:1-MUX-Gate-Level-and-Testing-342"><span class="toc-item-num">3.4.2&nbsp;&nbsp;</span>myHDL 4:1 MUX Gate Level and Testing</a></div><div class="lev3 toc-item"><a href="#myHDL-4:1-MUX-Gate-Level-HDL-Synthesis" data-toc-modified-id="myHDL-4:1-MUX-Gate-Level-HDL-Synthesis-343"><span class="toc-item-num">3.4.3&nbsp;&nbsp;</span>myHDL 4:1 MUX Gate Level HDL Synthesis</a></div><div class="lev2 toc-item"><a href="#4:1-Multiplexer-Behavioral" data-toc-modified-id="4:1-Multiplexer-Behavioral-35"><span class="toc-item-num">3.5&nbsp;&nbsp;</span>4:1 Multiplexer Behavioral</a></div><div class="lev3 toc-item"><a href="#myHDL-4:1-MUX-Behavioral-Level-and-Testing" data-toc-modified-id="myHDL-4:1-MUX-Behavioral-Level-and-Testing-351"><span class="toc-item-num">3.5.1&nbsp;&nbsp;</span>myHDL 4:1 MUX Behavioral Level and Testing</a></div><div class="lev3 toc-item"><a href="#myHDL-4:1-MUX-Behavioral-Level-HDL-Synthesis" data-toc-modified-id="myHDL-4:1-MUX-Behavioral-Level-HDL-Synthesis-352"><span class="toc-item-num">3.5.2&nbsp;&nbsp;</span>myHDL 4:1 MUX Behavioral Level HDL Synthesis</a></div><div class="lev2 toc-item"><a href="#4:1-Multiplexer-Behavioral-with-bitvectors" data-toc-modified-id="4:1-Multiplexer-Behavioral-with-bitvectors-36"><span class="toc-item-num">3.6&nbsp;&nbsp;</span>4:1 Multiplexer Behavioral with bitvectors</a></div><div class="lev3 toc-item"><a href="#How-bit-vectors-work-in-myHDL-and-in-Verilog/VHDL" data-toc-modified-id="How-bit-vectors-work-in-myHDL-and-in-Verilog/VHDL-361"><span class="toc-item-num">3.6.1&nbsp;&nbsp;</span>How bit vectors work in myHDL and in Verilog/VHDL</a></div><div class="lev3 toc-item"><a href="#Understanding-BitVector-bit-selection-in-myHDL" data-toc-modified-id="Understanding-BitVector-bit-selection-in-myHDL-362"><span class="toc-item-num">3.6.2&nbsp;&nbsp;</span>Understanding BitVector bit selection in myHDL</a></div><div class="lev3 toc-item"><a href="#myHDL-4:1-MUX-Behavioral-with-BitVecters-and-Testing" data-toc-modified-id="myHDL-4:1-MUX-Behavioral-with-BitVecters-and-Testing-363"><span class="toc-item-num">3.6.3&nbsp;&nbsp;</span>myHDL 4:1 MUX Behavioral with BitVecters and Testing</a></div><div class="lev4 toc-item"><a href="#!?-This-needs-to-be-checked" data-toc-modified-id="!?-This-needs-to-be-checked-3631"><span class="toc-item-num">3.6.3.1&nbsp;&nbsp;</span>!? This needs to be checked</a></div><div class="lev3 toc-item"><a href="#myHDL-4:1-MUX-Behavioral-with-BitVecters-HDL-Synthesis" data-toc-modified-id="myHDL-4:1-MUX-Behavioral-with-BitVecters-HDL-Synthesis-364"><span class="toc-item-num">3.6.4&nbsp;&nbsp;</span>myHDL 4:1 MUX Behavioral with BitVecters HDL Synthesis</a></div><div class="lev2 toc-item"><a href="#Generic-Expressions-via-MUXs" data-toc-modified-id="Generic-Expressions-via-MUXs-37"><span class="toc-item-num">3.7&nbsp;&nbsp;</span>Generic Expressions via MUXs</a></div><div class="lev3 toc-item"><a href="#myHDL-Generic-Expression-via-MUXs-and-Testing" data-toc-modified-id="myHDL-Generic-Expression-via-MUXs-and-Testing-371"><span class="toc-item-num">3.7.1&nbsp;&nbsp;</span>myHDL Generic Expression via MUXs and Testing</a></div><div class="lev3 toc-item"><a href="#myHDL-Generic-Expression-via-MUXs-HDL-Synthesis" data-toc-modified-id="myHDL-Generic-Expression-via-MUXs-HDL-Synthesis-372"><span class="toc-item-num">3.7.2&nbsp;&nbsp;</span>myHDL Generic Expression via MUXs HDL Synthesis</a></div><div class="lev1 toc-item"><a href="#Demultiplexers" data-toc-modified-id="Demultiplexers-4"><span class="toc-item-num">4&nbsp;&nbsp;</span>Demultiplexers</a></div><div class="lev1 toc-item"><a href="#Encoders" data-toc-modified-id="Encoders-5"><span class="toc-item-num">5&nbsp;&nbsp;</span>Encoders</a></div><div class="lev1 toc-item"><a href="#Decoders" data-toc-modified-id="Decoders-6"><span class="toc-item-num">6&nbsp;&nbsp;</span>Decoders</a></div>
# Refs
@book{brown_vranesic_2014,
place={New York, NY},
edition={3},
title={Fundamentals of digital logic with Verilog design},
publisher={McGraw-Hill},
author={Brown, Stephen and Vranesic, Zvonko G},
year={2014}
},
@book{lameres_2017,
title={Introduction to logic circuits & logic design with Verilog},
publisher={springer},
author={LaMeres, Brock J},
year={2017}
},
@misc{peeker_simple_mux,
url={http://www.xess.com/static/media/pages/peeker_simple_mux.html},
journal={Xess.com},
year={2017}
},
# Python Libraries Utilized
End of explanation
def shannon_exspanson(f, term):
    
    f is not a full equation
    
    cof0=simplify(f.subs(term, 0)); cof1=simplify(f.subs(term, 1))
    return ((~term & cof0 | (term & cof1))), cof0, cof1
Explanation: Multiplexers (mux)
a junction switch between one of n inputs to a single output; equivalent to a "if" or "case" statement
let $Z$ be its output $m_k$ the minterms of the controls to the mux and $I_k$ be the input feeds to the mux; then the expression for the mux in terms of boolean algebra becomes
$$Z=\sum^{2^k-1}_{k=0} m_k \cdot I_k= \text{OR}(m_k \& I_k) $$
Shannon’s Expansion Theorem
The above is Shannon's theorem
it can be written more sincintly as:
$$f(x_1, x_2, ..., x_n)=\bar{x_1}f(0, x_2, ..., x_n)+x_1 f(x_1, x_2, ..., x_n)$$
and then each $f(0, x_2, ..., x_n)$ \& $f(x_1, x_2, ..., x_n)$ is broken down as the above till the maximum  number of control statement and minim inputs are needed
End of explanation
sel, x_1in, x_2in=symbols('sel, x_1in, x_2in')
Explanation: ## 2:1 MultiPlexer
End of explanation
x_1in, x_2in, sel=symbols('x_1in, x_2in, sel')
Explanation: let $f(m_1, m_2, m_3)$ be the total set of minterms for a 3-bit then let $m_1$ be designated the select terms then by shannon's theorem states
$$f(m_1, m_2, m_3)=\bar{m_1} \cdot f_1'(0, m_2, m_3)+m_1 \cdot f_1(1, m_2, m_3)$$
in other words we want select the two subset of the f where $m_1$ is 1 or 0 and call thouse two subsets $f_1'$, $f_1$
End of explanation
ConversionTable=pd.DataFrame()
Terms=[bin(i, 3) for i in np.arange(0, 2**3)]
ConversionTable['sel']=[int(j[0]) for j in Terms]
ConversionTable['x_1in']=[int(j[1]) for j in Terms]
ConversionTable['x_2in']=[int(j[2]) for j in Terms]
#this is shannos theorm
ConversionTable['f']=list(ConversionTable.loc[ConversionTable['sel'] == 0]['x_1in'])+list(ConversionTable.loc[ConversionTable['sel'] == 1]['x_2in'])
ConversionTable.index.name='MinMaxTerm'
ConversionTable
POS=list(ConversionTable.loc[ConversionTable['f'] == 0].index)
SOP=list(ConversionTable.loc[ConversionTable['f'] == 1].index)
f"POS: {POS}, SOP:{SOP}"
f, _=POS_SOPformCalcater([sel, x_1in, x_2in], SOP, POS)
f
a, b, c=shannon_exspanson(f, sel)
f,'= via shannaon', a
Explanation: $$f(m_1, m_2, m_3)$$
End of explanation
m1bar_f0=~sel&x_1in; m1bar_f0
f0Table=ConversionTable.loc[ConversionTable['sel'] == 0].copy()
f0Table['f0']=[m1bar_f0.subs({sel:i, x_1in:j}) for i, j in zip(f0Table['sel'], f0Table['x_1in'])]
f0Table
Explanation: $$\bar{m_1} \cdot f_1'(0, m_2, m_3)$$
End of explanation
m1_f1=sel&x_2in; m1_f1
f1Table=ConversionTable.loc[ConversionTable['sel'] == 1].copy()
f1Table['f1']=[m1_f1.subs({sel:i, x_2in:j}) for i, j in zip(f1Table['sel'], f1Table['x_2in'])]
f1Table
Explanation: $$m_1 \cdot f_1(1, m_2, m_3)$$
End of explanation
def mux21_gates(sel, x_1in, x_2in,  f_out):
    @always_comb
    def logic():
        f_out.next=(sel and x_2in) or (x_1in and not sel)
    return logic
Peeker.clear()
sel, x_1in, x_2in,  f_out=[Signal(bool(0)) for _ in range(4)]
Peeker(sel, 'sel'); Peeker(x_1in, 'x_1in'); Peeker(x_2in, 'x_2in')
Peeker(f_out, 'f_out')
DUT=mux21_gates(sel, x_1in, x_2in,  f_out)
inputs=[sel, x_1in, x_2in]
sim=Simulation(DUT, Combo_TB(inputs), *Peeker.instances()).run()        
Peeker.to_wavedrom(start_time=0, stop_time=2*2**len(inputs), tock=True,
                  title='MUX 2:1 gate type simulation',
                  caption=f'after clock cycle {2**len(inputs)-1} ->random input')
 
MakeDFfromPeeker(Peeker.to_wavejson(start_time=0, stop_time=2**len(inputs) -1))
Explanation: and since this is the lowest order mux this case use of shannon's theorem is kind of trivial
myHDL 2:1 MUX Gate Level and Testing
End of explanation
sel, x_1in, x_2in,  f_out=[Signal(bool(0)) for _ in range(4)]
toVerilog(mux21_gates, sel, x_1in, x_2in,  f_out)
#toVHDL(mux21_gates sel, x_1in, x_2in,  f_out)
_=VerilogTextReader('mux21_gates')
Explanation: myHDL 2:1 MUX Gate Level HDL Synthesis
End of explanation
def mux21_behavioral(sel, x_1in, x_2in,  f_out):
    @always_comb
    def logic():
            if sel:
                f_out.next=x_1in
            else:
                f_out.next=x_2in
    return logic
Peeker.clear()
sel, x_1in, x_2in,  f_out=[Signal(bool(0)) for _ in range(4)]
Peeker(sel, 'sel'); Peeker(x_1in, 'x_1in'); Peeker(x_2in, 'x_2in')
Peeker(f_out, 'f_out')
DUT=mux21_behavioral(sel, x_1in, x_2in,  f_out)
inputs=[sel, x_1in, x_2in]
sim=Simulation(DUT, Combo_TB(inputs), *Peeker.instances()).run()        
Peeker.to_wavedrom(start_time=0, stop_time=2*2**len(inputs), tock=True,
                  title='MUX 2:1 behaviroal type simulation',
                  caption=f'after clock cycle {2**len(inputs)-1} ->random input')
 
MakeDFfromPeeker(Peeker.to_wavejson(start_time=0, stop_time=2**len(inputs) -1))
Explanation: The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL 2:1 MUX Gate level verilog code
<img style="float: center;" src="MUX21GateRTLSch.PNG">
however as will be shown doing gate implementation of MUXs is not sustainable in HDL code and this we will have to implement behavioral syntax as follows, thouse the caveat is that this only works for standard MUXs
2:1 Multiplexer Behavioral
myHDL 2:1 MUX Behavioral Level and Testing
End of explanation
sel, x_1in, x_2in,  f_out=[Signal(bool(0)) for _ in range(4)]
toVerilog(mux21_behavioral, sel, x_1in, x_2in,  f_out)
#toVHDL(mux21_behavioral sel, x_1in, x_2in,  f_out)
_=VerilogTextReader('mux21_behavioral')
Explanation: myHDL 2:1 MUX Behavioral Level HDL Synthesis
End of explanation
def MUX41_gates(sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out):
    @always_comb
    def logic():
        f_out.next=((not sel_1) and (not sel_2) and x_1in) or ((not sel_1) and ( sel_2) and x_2in) or (( sel_1) and (not sel_2) and x_3in) or (( sel_1) and ( sel_2) and x_4in)
    return logic
Peeker.clear()
sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out=[Signal(bool(0)) for _ in range(7)]
Peeker(sel_1, 'sel_1'); Peeker(sel_2, 'sel_2');
Peeker(x_1in, 'x_1in'); Peeker(x_2in, 'x_2in'); Peeker(x_3in, 'x_3in'); Peeker(x_4in, 'x_4in')
Peeker(f_out, 'f_out')
DUT=MUX41_gates(sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out)
inputs=[sel_1, sel_2, x_1in, x_2in, x_3in, x_4in]
sim=Simulation(DUT, Combo_TB(inputs), *Peeker.instances()).run()        
Peeker.to_wavedrom(start_time=0, stop_time=2*2**len(inputs), tock=True,
                  title='MUX 4:1 gate type simulation',
                  caption=f'after clock cycle {2**len(inputs)-1} ->random input')
 
MakeDFfromPeeker(Peeker.to_wavejson(start_time=0, stop_time=2**len(inputs) -1))
Explanation: The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL behavioral level 2:1 MUX's verilog code
<img style="float: center;" src="MUX21BehavioralRTLSch.PNG">
4:1 MUX
If you try to repeat the above using a 4:1 which has four input lines and needs two select lines you can become overwhelmed quickly instead it is easier to use the following diagram to than synthesis the gate level architecture
!? Insert Digram below
myHDL 4:1 MUX Gate Level and Testing
End of explanation
sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out=[Signal(bool(0)) for _ in range(7)]
toVerilog(MUX41_gates, sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out)
#toVHDL(MUX41_gates, sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out)
_=VerilogTextReader('MUX41_gates')
Explanation: myHDL 4:1 MUX Gate Level HDL Synthesis
End of explanation
def MUX41_behavioral(sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out):
    @always_comb
    def logic():
        if (not sel_1) and (not sel_2):
            f_out.next=x_1in
        
        elif (not sel_1) and sel_2:
            f_out.next=x_2in
        
        elif sel_1 and (not sel_2):
            f_out.next=x_3in
        
        else:
            f_out.next=x_4in
    
    return logic
Peeker.clear()
sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out=[Signal(bool(0)) for _ in range(7)]
Peeker(sel_1, 'sel_1'); Peeker(sel_2, 'sel_2');
Peeker(x_1in, 'x_1in'); Peeker(x_2in, 'x_2in'); Peeker(x_3in, 'x_3in'); Peeker(x_4in, 'x_4in')
Peeker(f_out, 'f_out')
DUT=MUX41_behavioral(sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out)
inputs=[sel_1, sel_2, x_1in, x_2in, x_3in, x_4in]
sim=Simulation(DUT, Combo_TB(inputs), *Peeker.instances()).run()        
Peeker.to_wavedrom(start_time=0, stop_time=2*2**len(inputs), tock=True,
                  title='MUX 4:1 behavioral type simulation',
                  caption=f'after clock cycle {2**len(inputs)-1} ->random input')
 
MakeDFfromPeeker(Peeker.to_wavejson(start_time=0, stop_time=2**len(inputs) -1))
Explanation: The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL 4:1 MUX Gate level verilog code 
<img style="float: center;" src="MUX41GateRTLSch.PNG">
4:1 Multiplexer Behavioral
As one can clearly see this is not sustainable and thus 'if' Statements need to be used via behavioral logic modeling 
myHDL 4:1 MUX Behavioral Level and Testing
End of explanation
sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out=[Signal(bool(0)) for _ in range(7)]
toVerilog(MUX41_behavioral, sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out)
#toVHDL(MUX41_behavioral, sel_1, sel_2, x_1in, x_2in, x_3in, x_4in,  f_out)
_=VerilogTextReader('MUX41_behavioral')
Explanation: myHDL 4:1 MUX Behavioral Level HDL Synthesis
End of explanation
sel=intbv(1)[2:]; x_in=intbv(7)[4:]; f_out=bool(0)
for i in x_in:
    print(i)
for i in range(4):
    print(x_in[i])
Explanation: The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL behavioral level 4:1 MUX's verilog code 
<img style="float: center;" src="MUX41BehaviroalRTLSch.PNG">
4:1 Multiplexer Behavioral with bitvectors
taking this a step further using bytes we can implement the behavioral using vector inputs instead of single bit inputs as follows
How bit vectors work in myHDL and in Verilog/VHDL
Understanding BitVector bit selection in myHDL
End of explanation
def MUX41_behavioralVec(sel, x_in, f_out):
    @always_comb
    def logic():
        f_out.next=x_in[sel]
    return logic
Peeker.clear()
sel=Signal(intbv(0)[2:]); Peeker(sel, 'sel')
x_in=Signal(intbv(0)[4:]); Peeker(x_in, 'x_in')
f_out=Signal(bool(0)); Peeker(f_out, 'f_out')
DUT=MUX41_behavioralVec(sel, x_in, f_out)
def MUX41_behavioralVec_TB(sel, x_in):
    
    selLen=len(sel); x_inLen=len(x_in)
    
    for i in range(2**x_inLen):
        x_in.next=i
        for j in range(selLen):
            sel.next=j
            
            yield delay(1)
            now()
    
        
im=Simulation(DUT, MUX41_behavioralVec_TB(sel, x_in), *Peeker.instances()).run()        
Peeker.to_wavedrom(tock=True,
                  title='MUX 4:1 behavioral vectype simulation') 
MakeDFfromPeeker(Peeker.to_wavejson())
Explanation: myHDL 4:1 MUX Behavioral with BitVecters and Testing
!? This needs to be checked
End of explanation
sel=Signal(intbv(0)[2:]); x_in=Signal(intbv(0)[4:]); 
f_out=Signal(bool(0))
toVerilog(MUX41_behavioralVec,sel, x_in, f_out)
#toVHDL(MUX41_behavioralVec,sel, x_in, f_out)
_=VerilogTextReader('MUX41_behavioralVec')
Explanation: myHDL 4:1 MUX Behavioral with BitVecters HDL Synthesis
End of explanation
w1, w2, w3=symbols('w_1, w_2, w_3')
f=(~w1&~w3)|(w1&w2)|(w1&w3)
f
s1=w1
fp, fp0, fp1=shannon_exspanson(f, s1)
fp, fp0, fp1
s2=w2
fpp0, fpp00, fpp01=shannon_exspanson(fp0, s2)
fpp1, fpp10, fpp11=shannon_exspanson(fp1, s2)
fpp0, fpp00, fpp01, fpp1, fpp10, fpp11
Explanation: The following shows the Xilinx's Vivado 2016.1 RTL generated schematic of our myHDL behavioral level 4:1 MUX using Bitvecters verilog code 
<img style="float: center;" src="MUX41BehaviroalVecRTLSch.PNG">
Generic Expressions via MUXs
(clean this and find harder exsample)
while shannon's theorem did not prove very much  useful in designing a 4:1 MUX it's true power lies converting boolean logic expression from and or gates to MUX's
using example 4.5 from Brown & Vranesic 3rd Ed
End of explanation
def Shannon21MUX(s1, s2, w_3in, f_out):
    @always_comb
    def logic():
        if (not s1) and (not s2):
            f_out.next=not w_3in
        elif (not s1) and ( s2):
            f_out.next=not w_3in
        elif ( s1) and (not s2):
            f_out.next= w_3in
        else:
            f_out.next=1
    return logic
            
Peeker.clear()
s1, s2, w_3in,  f_out=[Signal(bool(0)) for _ in range(4)]
Peeker(s1, 's1'); Peeker(s2, 's2');
Peeker(w_3in, 'w_3in')
Peeker(f_out, 'f_out')
DUT=Shannon21MUX(s1, s2, w_3in, f_out)
inputs=[s1, s2, w_3in, f_out]
sim=Simulation(DUT, Combo_TB(inputs), *Peeker.instances()).run()        
Peeker.to_wavedrom(start_time=0, stop_time=2*2**len(inputs), tock=True,
                  title='Shannon 2:1 MUX gate type simulation',
                  caption=f'after clock cycle {2**len(inputs)-1} ->random input')
 
MakeDFfromPeeker(Peeker.to_wavejson(start_time=0, stop_time=2**len(inputs) -1))
Explanation: myHDL Generic Expression via MUXs and Testing
End of explanation
s1, s2, w_3in,  f_out=[Signal(bool(0)) for _ in range(4)]
toVerilog(Shannon21MUX,s1, s2, w_3in, f_out)
#toVHDL(Shannon21MUX, s1, s2, w_3in, f_out)
_=VerilogTextReader('Shannon21MUX')
Explanation: myHDL Generic Expression via MUXs HDL Synthesis
End of explanation
<END_TASK>