#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 random

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

#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

CountVal=17
BitSize=int(np.log2(CountVal))+1; BitSize

"""
Explanation: \title{Shift Registers in myHDL}
\author{Steven K Armour}
\maketitle
Shift registers are common structures that move around data in primitive memory by rearranging the bit order. While shift registers are built as needed they typically fall into five categories. The four conversion types: PIPO, PISO, SISO, SIPO; and cyclic shift registers such as the ring and Johnson counters. Wich can be used as counters but are in reality shift registers since they reorder the bits in the modules internal memory
<h1>Table of Contents<span class="tocSkip"></span></h1>
<div class="toc" style="margin-top: 1em;"><ul class="toc-item"><li><span><a href="#Refrances" data-toc-modified-id="Refrances-1"><span class="toc-item-num">1&nbsp;&nbsp;</span>Refrances</a></span></li><li><span><a href="#Libraries-and-Helper-functions" data-toc-modified-id="Libraries-and-Helper-functions-2"><span class="toc-item-num">2&nbsp;&nbsp;</span>Libraries and Helper functions</a></span></li><li><span><a href="#Parallel-In-Parallel-Out-(PIPO)-Shift-Register" data-toc-modified-id="Parallel-In-Parallel-Out-(PIPO)-Shift-Register-3"><span class="toc-item-num">3&nbsp;&nbsp;</span>Parallel-In Parallel-Out (PIPO) Shift Register</a></span><ul class="toc-item"><li><span><a href="#Asynchronous" data-toc-modified-id="Asynchronous-3.1"><span class="toc-item-num">3.1&nbsp;&nbsp;</span>Asynchronous</a></span><ul class="toc-item"><li><span><a href="#myHDL-Testing" data-toc-modified-id="myHDL-Testing-3.1.1"><span class="toc-item-num">3.1.1&nbsp;&nbsp;</span>myHDL Testing</a></span></li><li><span><a href="#Verilog-Code" data-toc-modified-id="Verilog-Code-3.1.2"><span class="toc-item-num">3.1.2&nbsp;&nbsp;</span>Verilog Code</a></span></li><li><span><a href="#Verilog-Testbench-(!ToDo)" data-toc-modified-id="Verilog-Testbench-(!ToDo)-3.1.3"><span class="toc-item-num">3.1.3&nbsp;&nbsp;</span>Verilog Testbench (!ToDo)</a></span></li></ul></li><li><span><a href="#Synchronous-1" data-toc-modified-id="Synchronous-1-3.2"><span class="toc-item-num">3.2&nbsp;&nbsp;</span>Synchronous 1</a></span><ul class="toc-item"><li><span><a href="#myHDL-Module" data-toc-modified-id="myHDL-Module-3.2.1"><span class="toc-item-num">3.2.1&nbsp;&nbsp;</span>myHDL Module</a></span></li><li><span><a href="#myHDL-Testing" data-toc-modified-id="myHDL-Testing-3.2.2"><span class="toc-item-num">3.2.2&nbsp;&nbsp;</span>myHDL Testing</a></span></li><li><span><a href="#Verilog-Code" data-toc-modified-id="Verilog-Code-3.2.3"><span class="toc-item-num">3.2.3&nbsp;&nbsp;</span>Verilog Code</a></span></li></ul></li><li><span><a href="#Synchronous-2" data-toc-modified-id="Synchronous-2-3.3"><span class="toc-item-num">3.3&nbsp;&nbsp;</span>Synchronous 2</a></span><ul class="toc-item"><li><span><a href="#myHDL-Module" data-toc-modified-id="myHDL-Module-3.3.1"><span class="toc-item-num">3.3.1&nbsp;&nbsp;</span>myHDL Module</a></span></li><li><span><a href="#myHDL-Testing" data-toc-modified-id="myHDL-Testing-3.3.2"><span class="toc-item-num">3.3.2&nbsp;&nbsp;</span>myHDL Testing</a></span></li><li><span><a href="#Verilog-Code" data-toc-modified-id="Verilog-Code-3.3.3"><span class="toc-item-num">3.3.3&nbsp;&nbsp;</span>Verilog Code</a></span></li></ul></li><li><span><a href="#Comparison-of-the-three-designs" data-toc-modified-id="Comparison-of-the-three-designs-3.4"><span class="toc-item-num">3.4&nbsp;&nbsp;</span>Comparison of the three designs</a></span></li></ul></li><li><span><a href="#Parallel-In-Serial-Out-(PISO)" data-toc-modified-id="Parallel-In-Serial-Out-(PISO)-4"><span class="toc-item-num">4&nbsp;&nbsp;</span>Parallel-In Serial-Out (PISO)</a></span><ul class="toc-item"><li><span><a href="#myHDL-Module" data-toc-modified-id="myHDL-Module-4.1"><span class="toc-item-num">4.1&nbsp;&nbsp;</span>myHDL Module</a></span></li><li><span><a href="#myHDL-Testing" data-toc-modified-id="myHDL-Testing-4.2"><span class="toc-item-num">4.2&nbsp;&nbsp;</span>myHDL Testing</a></span></li><li><span><a href="#Verilog-Code" data-toc-modified-id="Verilog-Code-4.3"><span class="toc-item-num">4.3&nbsp;&nbsp;</span>Verilog Code</a></span></li><li><span><a href="#Verilog-Testbench-(!ToDo)" data-toc-modified-id="Verilog-Testbench-(!ToDo)-4.4"><span class="toc-item-num">4.4&nbsp;&nbsp;</span>Verilog Testbench (!ToDo)</a></span></li></ul></li><li><span><a href="#Serial-In-Serial-Out-(SISO)" data-toc-modified-id="Serial-In-Serial-Out-(SISO)-5"><span class="toc-item-num">5&nbsp;&nbsp;</span>Serial-In Serial-Out (SISO)</a></span><ul class="toc-item"><li><span><a href="#myHDL-Module" data-toc-modified-id="myHDL-Module-5.1"><span class="toc-item-num">5.1&nbsp;&nbsp;</span>myHDL Module</a></span></li><li><span><a href="#myHDL-Testing" data-toc-modified-id="myHDL-Testing-5.2"><span class="toc-item-num">5.2&nbsp;&nbsp;</span>myHDL Testing</a></span></li><li><span><a href="#Verilog-Code" data-toc-modified-id="Verilog-Code-5.3"><span class="toc-item-num">5.3&nbsp;&nbsp;</span>Verilog Code</a></span></li><li><span><a href="#Verilog-Testbench" data-toc-modified-id="Verilog-Testbench-5.4"><span class="toc-item-num">5.4&nbsp;&nbsp;</span>Verilog Testbench</a></span></li></ul></li><li><span><a href="#Serial-In-Parallel-Out-(SIPO)" data-toc-modified-id="Serial-In-Parallel-Out-(SIPO)-6"><span class="toc-item-num">6&nbsp;&nbsp;</span>Serial-In Parallel-Out (SIPO)</a></span><ul class="toc-item"><li><span><a href="#myHDL-Module" data-toc-modified-id="myHDL-Module-6.1"><span class="toc-item-num">6.1&nbsp;&nbsp;</span>myHDL Module</a></span></li><li><span><a href="#myHDL-Testing" data-toc-modified-id="myHDL-Testing-6.2"><span class="toc-item-num">6.2&nbsp;&nbsp;</span>myHDL Testing</a></span></li><li><span><a href="#Verilog-Code" data-toc-modified-id="Verilog-Code-6.3"><span class="toc-item-num">6.3&nbsp;&nbsp;</span>Verilog Code</a></span></li><li><span><a href="#Verilog-Testbench" data-toc-modified-id="Verilog-Testbench-6.4"><span class="toc-item-num">6.4&nbsp;&nbsp;</span>Verilog Testbench</a></span></li></ul></li><li><span><a href="#Cyclic-Shift-Register-Johnson-Counter" data-toc-modified-id="Cyclic-Shift-Register-Johnson-Counter-7"><span class="toc-item-num">7&nbsp;&nbsp;</span>Cyclic Shift Register Johnson Counter</a></span><ul class="toc-item"><li><span><a href="#myHDL-Module" data-toc-modified-id="myHDL-Module-7.1"><span class="toc-item-num">7.1&nbsp;&nbsp;</span>myHDL Module</a></span></li><li><span><a href="#myHDL-Testing" data-toc-modified-id="myHDL-Testing-7.2"><span class="toc-item-num">7.2&nbsp;&nbsp;</span>myHDL Testing</a></span></li><li><span><a href="#Verilog--Code" data-toc-modified-id="Verilog--Code-7.3"><span class="toc-item-num">7.3&nbsp;&nbsp;</span>Verilog  Code</a></span></li><li><span><a href="#Verilog-Testbench" data-toc-modified-id="Verilog-Testbench-7.4"><span class="toc-item-num">7.4&nbsp;&nbsp;</span>Verilog Testbench</a></span></li><li><span><a href="#PYNQ-Z1-Deployment" data-toc-modified-id="PYNQ-Z1-Deployment-7.5"><span class="toc-item-num">7.5&nbsp;&nbsp;</span>PYNQ-Z1 Deployment</a></span><ul class="toc-item"><li><span><a href="#Board-Constraints" data-toc-modified-id="Board-Constraints-7.5.1"><span class="toc-item-num">7.5.1&nbsp;&nbsp;</span>Board Constraints</a></span></li><li><span><a href="#Deployment-Results" data-toc-modified-id="Deployment-Results-7.5.2"><span class="toc-item-num">7.5.2&nbsp;&nbsp;</span>Deployment Results</a></span></li></ul></li></ul></li><li><span><a href="#Cyclic-Shift-Register-Ring-Counter" data-toc-modified-id="Cyclic-Shift-Register-Ring-Counter-8"><span class="toc-item-num">8&nbsp;&nbsp;</span>Cyclic Shift Register Ring Counter</a></span><ul class="toc-item"><li><span><a href="#myHDL-Module" data-toc-modified-id="myHDL-Module-8.1"><span class="toc-item-num">8.1&nbsp;&nbsp;</span>myHDL Module</a></span></li><li><span><a href="#myHDL-testing" data-toc-modified-id="myHDL-testing-8.2"><span class="toc-item-num">8.2&nbsp;&nbsp;</span>myHDL testing</a></span></li><li><span><a href="#Verilog-Code" data-toc-modified-id="Verilog-Code-8.3"><span class="toc-item-num">8.3&nbsp;&nbsp;</span>Verilog Code</a></span></li><li><span><a href="#Verilog-Testbench" data-toc-modified-id="Verilog-Testbench-8.4"><span class="toc-item-num">8.4&nbsp;&nbsp;</span>Verilog Testbench</a></span></li><li><span><a href="#PYNQ-Z1-Deployment" data-toc-modified-id="PYNQ-Z1-Deployment-8.5"><span class="toc-item-num">8.5&nbsp;&nbsp;</span>PYNQ-Z1 Deployment</a></span><ul class="toc-item"><li><span><a href="#Block-Design" data-toc-modified-id="Block-Design-8.5.1"><span class="toc-item-num">8.5.1&nbsp;&nbsp;</span>Block Design</a></span></li><li><span><a href="#Board-Constraints" data-toc-modified-id="Board-Constraints-8.5.2"><span class="toc-item-num">8.5.2&nbsp;&nbsp;</span>Board Constraints</a></span></li><li><span><a href="#RTL,-Synthesis,-&amp;-Implementation" data-toc-modified-id="RTL,-Synthesis,-&amp;-Implementation-8.5.3"><span class="toc-item-num">8.5.3&nbsp;&nbsp;</span>RTL, Synthesis, &amp; Implementation</a></span></li><li><span><a href="#Deployment-Results" data-toc-modified-id="Deployment-Results-8.5.4"><span class="toc-item-num">8.5.4&nbsp;&nbsp;</span>Deployment Results</a></span></li></ul></li></ul></li></ul></div>

Refrances
@misc{myhdl_2017,
title={Johnson Counter},
url={http://www.myhdl.org/docs/examples/jc2.html},
journal={Myhdl.org},
author={myHDL},
year={2017}
}
@misc{the shift register,
url={https://www.electronics-tutorials.ws/sequential/seq_5.html},
journal={Electronics Tutorials}
},
@misc{petrescu,
title={Shift Registers},
url={http://www.csit-sun.pub.ro/courses/Masterat/Xilinx%20Synthesis%20Technology/toolbox.xilinx.com/docsan/xilinx4/data/docs/xst/hdlcode8.html},
journal={Csit-sun.pub.ro},
author={Petrescu, Adrian}
},
@misc{reddy_2014,
title={verilog code for ALU,SISO,PIPO,SIPO,PISO},
url={http://thrinadhreddy.blogspot.com/2014/01/verilog-code-for-alusisopiposipopiso.html},
journal={Thrinadhreddy.blogspot.com},
author={Reddy, Trinadh},
year={2014}
}
Libraries and Helper functions
End of explanation
"""


TestData=np.random.randint(0, 2**4, 15); TestData

"""
Explanation: Parallel-In Parallel-Out (PIPO) Shift Register
A PIPO shift Register is one of the most redundant of the four classic shift registers when used as a One Bus In, One Bus Out, thus the PIPO here is implemented as a One Bus In, Two Bus Out. Further, this opportunity is taken here to talk about HDL algorithms vs HDL Implementation by presenting the same One In, Two Out PIPO but implemented as an asynchronous case and two synchronous cases. While there are obvious differences algorithmically due to the asynchronous vs synchronous. The hardware implementation is even more strikingly different and serves as case in point that HDL programming is neither hardware or software but an intermedte between the worlds.  But with grave consequences when translated into hardware that the HDL must keep in perspective when writing Hardware Descriptive Language code.
End of explanation
"""


@block
def PIPO_AS1(DataIn, DataOut1, DataOut2):
    """
    1:2 PIPO shift regestor with no clock (Asynchronous) 
    
    Input:
        DataIn(bitvec)
    Output:
        DataOut1(bitVec): ouput one bitvec len should be same as 
            `DataIn`
        DataOut2(bitVec):ouput two bitvec len should be same as 
            `DataIn`
    """
    @always_comb
    def logic():
        DataOut1.next=DataIn
        DataOut2.next=DataIn
    
    return instances()


"""
Explanation: Asynchronous
End of explanation
"""


Peeker.clear()
clk=Signal(bool(0)); Peeker(clk, 'clk')
rst=Signal(bool(0)); Peeker(rst, 'rst')
DataIn=Signal(intbv(0)[4:]); Peeker(DataIn, 'DataIn')
DataOut1=Signal(intbv(0)[4:]); Peeker(DataOut1, 'DataOut1')
DataOut2=Signal(intbv(0)[4:]); Peeker(DataOut2, 'DataOut2')

DUT=PIPO_AS1(DataIn, DataOut1, DataOut2)

def PIPO_TB():
    """
    myHDL only Testbench for `PIPO_*` module
    """
    @always(delay(1))
    def ClkGen():
        clk.next=not clk
    
    @instance
    def stimules():
        i=0
        while True:
            
            DataIn.next=int(TestData[i])
            
            if i==14:
                raise StopSimulation()
                
            
            i+=1
            yield clk.posedge
    
    return instances()

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

Peeker.to_wavedrom()

PIPO_AS1Data=Peeker.to_dataframe(); 
PIPO_AS1Data=PIPO_AS1Data[PIPO_AS1Data['clk']==1]
PIPO_AS1Data.drop(['clk', 'rst'], axis=1, inplace=True)
PIPO_AS1Data.reset_index(drop=True, inplace=True)
PIPO_AS1Data

"""
Explanation: myHDL Testing
End of explanation
"""


DUT.convert()
VerilogTextReader('PIPO_AS1');

"""
Explanation: Verilog Code
End of explanation
"""


@block
def PIPO_S1(DataIn, DataOut1, DataOut2, clk, rst):
    """
    one-in two-out PIPO typicaly found in the lititure
    lacking buffering
    
    Inputs:
        DataIn(bitVec): one-in Parallel data int
        clk(bool): clock
        rst(bool): reset
        
    Ouputs:
        DataOut1(bitVec): Parallel out 1
        DataOut2(bitVec): Parallel out 1
        
    """

    
    @always(clk.posedge, rst.negedge)
    def logic():
        if rst:
            DataOut1.next=0
            DataOut2.next=0
        else:
            DataOut1.next=DataIn
            DataOut2.next=DataIn
    
    return instances()


"""
Explanation: \begin{figure}
\centerline{\includegraphics[width=10cm]{PIPO_AS1_RTL.png}}
\caption{\label{fig:APIPORTL} PIPO_AS1 Shift Register RTL schematic; Xilinx Vivado 2017.4}
\end{figure}
\begin{figure}
\centerline{\includegraphics[width=10cm]{PIPO_AS1_SYN.png}}
\caption{\label{fig:APIPOSYN} PIPO_AS1 Shift Register Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}
Verilog Testbench (!ToDo)
Synchronous 1
myHDL Module
End of explanation
"""


Peeker.clear()
clk=Signal(bool(0)); Peeker(clk, 'clk')
rst=Signal(bool(0)); Peeker(rst, 'rst')
DataIn=Signal(intbv(0)[4:]); Peeker(DataIn, 'DataIn')
DataOut1=Signal(intbv(0)[4:]); Peeker(DataOut1, 'DataOut1')
DataOut2=Signal(intbv(0)[4:]); Peeker(DataOut2, 'DataOut2')

DUT=PIPO_S1(DataIn, DataOut1, DataOut2, clk, rst)

def PIPO_TB():
    """
    myHDL only Testbench for `RingCounter` module
    """
    @always(delay(1))
    def ClkGen():
        clk.next=not clk
    
    @instance
    def stimules():
        i=0
        while True:
            
            DataIn.next=int(TestData[i])
            
            if i==14:
                raise StopSimulation()
                
            
            i+=1
            yield clk.posedge
    
    return instances()

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

Peeker.to_wavedrom()

PIPO_S1Data=Peeker.to_dataframe(); 
PIPO_S1Data=PIPO_S1Data[PIPO_S1Data['clk']==1]
PIPO_S1Data.drop(['clk', 'rst'], axis=1, inplace=True)
PIPO_S1Data.reset_index(drop=True, inplace=True)
PIPO_S1Data

"""
Explanation: myHDL Testing
End of explanation
"""


DUT.convert()
VerilogTextReader('PIPO_S1');

"""
Explanation: Verilog Code
End of explanation
"""


@block
def PIPO_S2(DataIn, DataOut1, DataOut2, clk, rst):
    """
    one-in two-out PIPO with buffering
    
    Inputs:
        DataIn(bitVec): one-in Parallel data int
        clk(bool): clock
        rst(bool): reset
        
    Ouputs:
        DataOut1(bitVec): Parallel out 1
        DataOut2(bitVec): Parallel out 1
        
    """
    
    Buffer=Signal(modbv(0)[len(DataIn):])
    @always(clk.posedge, rst.negedge)
    def logic():
        if rst:
            Buffer.next=0
        else:
            Buffer.next=DataIn
            
    
    #not normaly found in PIPO; but is better practice since buffers help 
    #with isolation for ASIC desighn
    @always_comb
    def OuputBuffer():
        DataOut1.next=Buffer
        DataOut2.next=Buffer
    
    return instances()


"""
Explanation: \begin{figure}
\centerline{\includegraphics[width=10cm]{PIPO_S1_RTL.png}}
\caption{\label{fig:S1PIPORTL} PIPO_S1 Shift Register RTL schematic; Xilinx Vivado 2017.4}
\end{figure}
\begin{figure}
\centerline{\includegraphics[width=10cm]{PIPO_S1_SYN.png}}
\caption{\label{fig:S1PIPOSYN} PIPO_S1 Shift Register Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}
Synchronous 2
myHDL Module
End of explanation
"""


Peeker.clear()
clk=Signal(bool(0)); Peeker(clk, 'clk')
rst=Signal(bool(0)); Peeker(rst, 'rst')
DataIn=Signal(intbv(0)[4:]); Peeker(DataIn, 'DataIn')
DataOut1=Signal(intbv(0)[4:]); Peeker(DataOut1, 'DataOut1')
DataOut2=Signal(intbv(0)[4:]); Peeker(DataOut2, 'DataOut2')

DUT=PIPO_S2(DataIn, DataOut1, DataOut2, clk, rst)

def PIPO_TB():
    """
    myHDL only Testbench for `PIPO_*` module
    """
    @always(delay(1))
    def ClkGen():
        clk.next=not clk
    
    @instance
    def stimules():
        i=0
        while True:
            
            DataIn.next=int(TestData[i])
            
            if i==14:
                raise StopSimulation()
                
            
            i+=1
            yield clk.posedge
    
    return instances()

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

Peeker.to_wavedrom()

PIPO_S2Data=Peeker.to_dataframe(); 
PIPO_S2Data=PIPO_S2Data[PIPO_S2Data['clk']==1]
PIPO_S2Data.drop(['clk', 'rst'], axis=1, inplace=True)
PIPO_S2Data.reset_index(drop=True, inplace=True)
PIPO_S2Data

"""
Explanation: myHDL Testing
End of explanation
"""


DUT.convert()
VerilogTextReader('PIPO_S2');

"""
Explanation: Verilog Code
End of explanation
"""


@block
def PISO(ReadBus, BusIn, SerialOut, clk, rst):
    """
    Parallel In Serial Out right shift regestor
    
    Input:
        ReadBus(bool): read bus flag
        BusIn(bool): Serial wire input
        clk(bool): clock
        rst(bool): reset
        
    Output:
        SerialOut(bool): Serial(wire) output data from `BusIn`
    Note:
        Does not have a finsh serial write indicator 
    """
   
    Buffer=Signal(intbv(0)[len(BusIn):])
    @always(clk.posedge, rst.negedge)
    def logic():
        if rst:
            Buffer.next=0
        elif ReadBus:
            Buffer.next=BusIn
        else:
            Buffer.next=Buffer>>1
    
    #A more robust PISO would have a counter to trigger
    #a finish serial write flag here
    
    @always_comb
    def SerialWriteOut():
        SerialOut.next=Buffer[0]
    
    return instances()
        

"""
Explanation: \begin{figure}
\centerline{\includegraphics[width=10cm]{PIPO_S2_RTL.png}}
\caption{\label{fig:S2PIPORTL} PIPO_S2 Shift Register RTL schematic; Xilinx Vivado 2017.4}
\end{figure}
\begin{figure}
\centerline{\includegraphics[width=10cm]{PIPO_S2_SYN.png}}
\caption{\label{fig:S2PIPOSYN} PIPO_S2 Shift Register Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}
Comparison of the three designs
In the asynchronous case, it can be seen in the RTL that incoming Bus is passed through a buffer and then the Bus is then junctioned to two outputs. This , therefore, does not have any synchronicity to a clock and is the HDL equivalent of taping the wires of the incoming bus to create a copy of the signal. What this design lacks in clock support it gains in resource saving and instantaneous interchange of the input signal to output signals
For the two synchronous cases the incoming signal is buffered by a register set, therefore any signal on the bus will not be present on the output buses for at least one clock cycle. Wich for clocked designs is a good thing but for signals that needs an instantaneous transmission, this is a failing in tradeoff. And while Vivado (and most other FPGA synthesis tools) recognized that the two designs are the same we should not take this for granted. Since other tools may not. Since at the RTL level the implementations are clearly different. 
In the first case, the incoming signals is recorded by two registers that then feeds each of the respective output busses. While this means that we gain redundancy in parallel registers. The parallel memories could also become out of sync for any number of reasons. Further, this is a huge amount of resource if it were to be synthesized this way. In comparison, the second design uses a single register that then feeds each of the outputs where this design has better resource allocation and would not suffer from any asynchronicity between parallel registers. It now suffers in lacking redundancy since any issues in the one register effect both outputs. 
The lesson here is that HDL should never be thought of as of programming. Instead, it is a sophisticated abstraction description of Hardware! And therefore HDL should always be written to satisfy the hardware constraints. 
Parallel-In Serial-Out (PISO)
Used to translate bus(parallel) data to a single output wire (serial) data a common example is the transmit line of a UART
myHDL Module
End of explanation
"""


TestData=np.random.randint(0, 2**4, 3)
print(TestData)
#reverse bit order since right shift
TestDataBin="".join([bin(i, 4)[::-1] for i in TestData])
TestDataBin=[int(i) for i in TestDataBin]
TestDataBin

Peeker.clear()
ReadBus=Signal(bool(0)); Peeker(ReadBus, 'ReadBus') 
BusIn=Signal(intbv(0)[4:]); Peeker(BusIn, 'BusIn')
SerialOut=Signal(bool(0)); Peeker(SerialOut, 'SerialOut')
clk=Signal(bool(0)); Peeker(clk, 'clk')
rst=Signal(bool(0)); Peeker(rst, 'rst')

DUT=PISO(ReadBus, BusIn, SerialOut, clk, rst)

def PISO_TB():
    """
    myHDL only Testbench for `SIPO` module
    """
    @always(delay(1))
    def ClkGen():
        clk.next=not clk
    
    @instance
    def stimules():
        yield clk.posedge
        
        for i in TestData:
            BusIn.next=int(i)
            ReadBus.next=True
            yield clk.posedge
            
            ReadBus.next=False
            for j in range(len(bin(i, 4))):
                yield clk.posedge
            


        
        raise StopSimulation()
        
    
    return instances()

sim=Simulation(DUT, PISO_TB(), *Peeker.instances()).run()
print(TestData)
print(TestDataBin)

Peeker.to_wavedrom()

PISOData=Peeker.to_dataframe(); 
PISOData=PISOData[PISOData['clk']==1]
PISOData.drop(['clk', 'rst'], axis=1, inplace=True)
PISOData['BusBits']=PISOData['BusIn'].apply(lambda x:bin(x, 4))
PISOData.reset_index(drop=True, inplace=True)
PISOData

"""
Explanation: myHDL Testing
End of explanation
"""


DUT.convert()
VerilogTextReader('PISO');

"""
Explanation: Verilog Code
End of explanation
"""


@block
def SISO(SerialIn, SerialOut, clk, rst, BufferSize):
    """
    SISO Left Shift registor
    
    Input:
        SerialIn(bool): serial input feed
        clk(bool): clock signal
        rst(bool):reset signal
    
    Output:
        SerialOut(bool): serial out delayed by BufferSize
    
    Paramter:
        BufferSize(int): size of SISO buffer, aka delay amount
    """
    Buffer=Signal(modbv(0)[BufferSize:])
    @always(clk.posedge, rst.negedge)
    def logic():
        if rst:
            Buffer.next=0
        else:
            Buffer.next=concat(Buffer[BufferSize-1:0], SerialIn)
    
    @always_comb
    def ReadLeftMostToSer():
        SerialOut.next=Buffer[BufferSize-1]
    
    return instances()
    

"""
Explanation: \begin{figure}
\centerline{\includegraphics[width=10cm]{PISO_RTL.png}}
\caption{\label{fig:PISORTL} PISO Shift Register RTL schematic; Xilinx Vivado 2017.4}
\end{figure}
\begin{figure}
\centerline{\includegraphics[width=10cm]{PISO_SYN.png}}
\caption{\label{fig:PISOSYN} PISO Shift Register Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}
Verilog Testbench (!ToDo)
Serial-In Serial-Out (SISO)
SISO are used to buffer input data like a primitive serial version of the First In First Out (FIFO) Memory. Or can be used for sampling of a wire input that not clock synced to an output that is clock sync
myHDL Module
End of explanation
"""


SerialInTVLen=20
np.random.seed(71)
SerialInTV=np.random.randint(0,2,20).astype(int)
SerialInTV

Peeker.clear()
SerialIn=Signal(bool(0)); Peeker(SerialIn, 'SerialIn')
SerialOut=Signal(bool(0)); Peeker(SerialOut, 'SerialOut')
clk=Signal(bool(0)); Peeker(clk, 'clk')
rst=Signal(bool(0)); Peeker(rst, 'rst')
BufferSize=4

DUT=SISO(SerialIn, SerialOut, clk, rst, BufferSize)

def SISO_TB():
    """
    myHDL only Testbench for `SISO` module
    """
    @always(delay(1))
    def ClkGen():
        clk.next=not clk
    
    @instance
    def stimules():
        for i in range(SerialInTVLen):
            SerialIn.next=int(SerialInTV[i])
            yield clk.posedge
        
        for i in range(2):
            if i==0:
                SerialIn.next=0
                rst.next=1
            else:
                rst.next=0
            yield clk.posedge
        
        for i in range(BufferSize+1):
            SerialIn.next=1
            yield clk.posedge
        
        raise StopSimulation()
    
    return instances()
        
sim=Simulation(DUT, SISO_TB(), *Peeker.instances()).run()

Peeker.to_wavedrom()

SISOData=Peeker.to_dataframe()
SISOData

SISOData=SISOData[SISOData['clk']==1]
SISOData.drop('clk', inplace=True, axis=1)
SISOData.reset_index(drop=True, inplace=True)
SISOData

SISOData['SerialOutS4']=SISOData['SerialOut'].shift(-4)
SISOData

SISOCheck=(SISOData[:16]['SerialIn'] == SISOData[:16]['SerialOutS4'].astype(int)).all()
print(f'SISO Check:{SISOCheck}')

"""
Explanation: myHDL Testing
End of explanation
"""


DUT.convert()
VerilogTextReader('SISO');

"""
Explanation: Verilog Code
End of explanation
"""


#create BitVector for BufferGate_TBV
SerialInTVs=intbv(int(''.join(SerialInTV.astype(str)), 2))[SerialInTVLen:]
SerialInTVs, bin(SerialInTVs)

BufferSize=4

@block
def SISO_TBV():
    """
    myHDL -> Verilog Testbench for `SISO` module
    """
    
    SerialIn=Signal(bool(0))
    SerialOut=Signal(bool(0))
    clk=Signal(bool(0))
    rst=Signal(bool(0))
    
    @always_comb
    def print_data():
        print(SerialIn, SerialOut, clk, rst)
        
    SerialInTV=Signal(SerialInTVs)

    DUT=SISO(SerialIn, SerialOut, clk, rst, BufferSize)

    @instance
    def clk_signal():
        while True:
            clk.next = not clk
            yield delay(1)
    
    @instance
    def stimules():
        for i in range(SerialInTVLen):
            SerialIn.next=int(SerialInTV[i])
            yield clk.posedge
        
        for i in range(2):
            if i==0:
                SerialIn.next=0
                rst.next=1
            else:
                rst.next=0
            yield clk.posedge
        
        for i in range(BufferSize+1):
            SerialIn.next=1
            yield clk.posedge
        
        raise StopSimulation()
    
    return instances()
        
TB=SISO_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('SISO_TBV');

"""
Explanation: \begin{figure}
\centerline{\includegraphics[width=10cm]{SISO_RTL.png}}
\caption{\label{fig:SISORTL} SISO Shift Register RTL schematic; Xilinx Vivado 2017.4}
\end{figure}
\begin{figure}
\centerline{\includegraphics[width=10cm]{SISO_SYN.png}}
\caption{\label{fig:SISOSYN} SISO Shift Register Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}
Verilog Testbench
End of explanation
"""


@block
def SIPO(SerialIn, BusOut, clk, rst):
    """
    Serial In Parallel Out right shift regestor
    
    Input:
        SerialIn(bool): Serial wire input
        clk(bool): clock
        rst(bool): reset
        
    Output:
        BusOut(bitVec): Parallel(Bus) output data from `SerialWire`
    """
    
    Buffer=Signal(modbv(0)[len(BusOut):])
    @always(clk.posedge, rst.negedge)
    def logic():
        if rst:
            Buffer.next=0
        else:
            Buffer.next=concat(Buffer[len(Buffer):0],SerialIn)
    
    @always_comb
    def OuputBuffer():
        BusOut.next=Buffer
    
    return instances()

"""
Explanation: Serial-In Parallel-Out (SIPO)
used to translate single wire (serial) data to but (parallel) data, a common example is the read line of a UART
myHDL Module
End of explanation
"""


TestData=np.random.randint(0, 2**4, 3)
print(TestData)
TestDataBin="".join([bin(i, 4) for i in TestData])
TestDataBin=[int(i) for i in TestDataBin]
TestDataBin

Peeker.clear()
SerialIn=Signal(bool(0)); Peeker(SerialIn, 'SerialIn')
BusOut=Signal(intbv(0)[4:]); Peeker(BusOut, 'BusOut')
clk=Signal(bool(0)); Peeker(clk, 'clk')
rst=Signal(bool(0)); Peeker(rst, 'rst')

DUT=SIPO(SerialIn, BusOut, clk, rst)

def SIPO_TB():
    """
    myHDL only Testbench for `SIPO` module
    """
    @always(delay(1))
    def ClkGen():
        clk.next=not clk
    
    @instance
    def stimules():
        i=0
        while True:
            if i<len(TestDataBin):
                SerialIn.next=TestDataBin[i]
            elif i==len(TestDataBin):
                pass
            elif i>len(TestDataBin):
                raise StopSimulation()
            i+=1
            yield clk.posedge


        
        raise StopSimulation()
        
    
    return instances()

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

Peeker.to_wavedrom()

SIPOData=Peeker.to_dataframe(); 
SIPOData=SIPOData[SIPOData['clk']==1]
SIPOData.drop(['clk', 'rst'], axis=1, inplace=True)
SIPOData['BusBits']=SIPOData['BusOut'].apply(lambda x:bin(x, 4))
SIPOData.reset_index(drop=True, inplace=True)
SIPOData

TestData, TestDataBin

"""
Explanation: myHDL Testing
End of explanation
"""


DUT.convert()
VerilogTextReader('SIPO');

"""
Explanation: Verilog Code
End of explanation
"""


V=int(''.join([str(i) for i in TestDataBin]), 2)
SerialVal=intbv(V)[len(TestDataBin):]
SerialVal

@block
def SIPO_TBV():
    """
    myHDL -> Verilog Testbench for `SIPO` module
    """
    SerialVals=Signal(SerialVal)
    SerialIn=Signal(bool(0))
    BusOut=Signal(intbv(0)[4:])
    clk=Signal(bool(0))
    rst=Signal(bool(0))
    
    @always_comb
    def print_data():
        print(SerialIn, BusOut, clk, rst)


    
    DUT=SIPO(SerialIn, BusOut, clk, rst)

    @instance
    def clk_signal():
        while True:
            clk.next = not clk
            yield delay(1)
    
    @instance
    def stimules():
        i=0
        while True:
            if i<len(TestDataBin):
                SerialIn.next=SerialVals[i]
            elif i==len(TestDataBin):
                pass
            elif i>len(TestDataBin):
                raise StopSimulation()
            i+=1
            yield clk.posedge


        
        raise StopSimulation()
        
    
    return instances()

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

"""
Explanation: \begin{figure}
\centerline{\includegraphics[width=10cm]{SIPO_RTL.png}}
\caption{\label{fig:SIPORTL} SIPO Shift Register RTL schematic; Xilinx Vivado 2017.4}
\end{figure}
\begin{figure}
\centerline{\includegraphics[width=10cm]{SIPO_SYN.png}}
\caption{\label{fig:SIPOSYN} SIPO Shift Register Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}
Verilog Testbench
End of explanation
"""


#Create the Direction States for Johnson Counter
DirStates=enum('Left','Halt','Right')
print(f"`Left` state repersentation is {bin(DirStates.Left)}")
print(f"`Halt` state repersentation is {bin(DirStates.Halt)}")
print(f"`Right` state repersentation is {bin(DirStates.Right)}")

@block
def JohnsonCount3(Dir, q, clk, rst):
    """
    Based of the `jc2` exsample from the myHDL website 
    http://www.myhdl.org/docs/examples/jc2.html
    
    Input:
        Dir(state): Left,Right, Halt Direction States
        clk(bool): input clock
        rst(bool): reset signal
    
    Ouput:
        q(bitVec): the values in the D flip flops(aka counter)
    """
    
    q_i=Signal(intbv(0)[len(q):])
    @always(clk.posedge, rst.negedge)
    def JCStateMachine():
        #moore state machine
        if rst:
            q_i.next=0
        
        elif Dir==DirStates.Left:
            #set bit slice from left most to one from the right
            #from bit slice from one to the left to the right most
            q_i.next[len(q_i):1]=q_i[len(q_i)-1:]
            #set next right most bit to negated one to the left bit
            q_i.next[0]=not q_i[len(q_i)-1]
        
        elif Dir==DirStates.Halt:
            #create circular stop
            q_i.next=q_i
        
        elif Dir==DirStates.Right:
            #set bit slice from one from the left to right most
            #from bit slice left most bit to one from the right
            q_i.next[len(q_i)-1:]=q_i[len(q_i):1]
            #set next one bit from the right to be negated left most bit  
            q_i.next[len(q_i)-1]=not q_i[0]
            
            
    
    @always_comb
    def OuputBuffer():
        q.next=q_i
    
    return instances()
    

"""
Explanation: Cyclic Shift Register Johnson Counter
The Johnson Counter is implemented in this notebook about shift registers since in reality, a Johnson Counter is a cyclic shift register with single bit inversion. Hence the Johnson Counter, which goes by the other name of a Mobius Ring Counter. The following are aspects of Johnson Counter by Sougata Bhattacharjee [https://www.quora.com/What-is-the-difference-between-a-Johnson-counter-and-a-ring-counter]
\begin{itemize}
\item In a Johnson Counter the output bar or Q(bar) of the last flip-flop is connected to the input of the first flip-flop
\item If $n$ is the number of the flip-flop used, then the total number of states used is $2n$.
\item The Johnson Counter is also known as walking counter, switching tail counter and is mostly used in phase shift or function generator.
\item The decoding circuit is complex as compared to a ring counter.
\item If input frequency is $f$ in Johnson Counter,then the output is $\dfrac{f}{2n}$.
\item The total number of unused states in Johnson Counter is $(2^n - 2n)$
\item The main problem with Johnson counter is that once it enters into an unused state it is in a lockout state
\end{itemize}
For a four-bit Johnson Counter, the next state diagram is given by the following table from wikipedga
\begin{figure}
\centerline{\includegraphics[width=1cm]{JohnsonCounterTable.png}}
\caption{\label{fig:JohnsonTable} 4-bit Ring Counter next state table from wikipedia}
\end{figure}
whereupon examining the next state table for the Johnson counter we can see why a Johnson counter is also called a Mobius counter
myHDL Module
End of explanation
"""


BitSize=4
Peeker.clear()
clk=Signal(bool(0)); Peeker(clk, 'clk')
rst=Signal(bool(0)); Peeker(rst, 'rst')
q=Signal(intbv(0)[BitSize:]); Peeker(q, 'q')
Dir=Signal(DirStates.Right); Peeker(Dir, 'Dir')

DUT=JohnsonCount3(Dir, q, clk, rst)

def JohnsonCount3_TB():
    """
    myHDL only Testbench for `RingCounter` module
    """
    @always(delay(1))
    def ClkGen():
        clk.next=not clk
    
    @instance
    def stimules():
        i=0
        while True:
            if i==2*2*BitSize:
                Dir.next=DirStates.Left
            elif i==4*2*BitSize:
                rst.next=1
            elif i==4*2*BitSize+1:
                rst.next=0
            elif i==4*2*BitSize+2:
                Dir.next=DirStates.Halt
            
            
            if i==5*2*BitSize:
                raise StopSimulation()
                
            i+=1
            yield clk.posedge
    
    return instances()

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

Peeker.to_wavedrom()

JohnsonCount3Data=Peeker.to_dataframe()
JohnsonCount3Data=JohnsonCount3Data[JohnsonCount3Data['clk']==1]
JohnsonCount3Data.drop('clk', axis=1, inplace=True)
JohnsonCount3Data.reset_index(drop=True, inplace=True)
JohnsonCount3Data

JohnsonCount3Data['q']=JohnsonCount3Data['q'].apply(lambda x:bin(x, BitSize))
JohnsonCount3Data

JohnsonCount3Data[JohnsonCount3Data['Dir']==DirStates.Right]

JohnsonCount3Data[JohnsonCount3Data['Dir']==DirStates.Left]

JohnsonCount3Data[JohnsonCount3Data['Dir']==DirStates.Halt]

"""
Explanation: myHDL Testing
End of explanation
"""


DUT.convert()
VerilogTextReader('JohnsonCount3');

"""
Explanation: Verilog  Code
End of explanation
"""


@block
def JohnsonCount3_TBV():
    """
    myHDL -> Verilog Testbench for `UpDown_Counter` module
    """
    
    clk=Signal(bool(0))
    rst=Signal(bool(0))
    q=Signal(intbv(0)[BitSize:])
    Dir=Signal(DirStates.Right)
    
    @always_comb
    def print_data():
        print(clk, rst, q, Dir)

    DUT=JohnsonCount3(Dir, q, clk, rst)

    @instance
    def clk_signal():
        while True:
            clk.next = not clk
            yield delay(1)
    
    @instance
    def stimules():
        i=0
        while True:
            if i==2*2*BitSize:
                Dir.next=DirStates.Left
            elif i==4*2*BitSize:
                rst.next=1
            elif i==4*2*BitSize+1:
                rst.next=0
            elif i==4*2*BitSize+2:
                Dir.next=DirStates.Halt
            else:
                pass
            
            
            if i==5*2*BitSize:
                raise StopSimulation()
                
            i+=1
            yield clk.posedge
    
    return instances()

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

"""
Explanation: \begin{figure}
\centerline{\includegraphics[width=10cm]{JohnsonCount3_RTL.png}}
\caption{\label{fig:JC3RTL} JohnsonCount3 RTL schematic; Xilinx Vivado 2017.4}
\end{figure}
\begin{figure}
\centerline{\includegraphics[width=10cm]{JohnsonCount3_SYN.png}}
\caption{\label{fig:JC3SYN} JohnsonCount3 Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}
\begin{figure}
\centerline{\includegraphics[width=10cm]{JohnsonCount3_IMP.png}}
\caption{\label{fig:BGIMP} JohnsonCount3 Implementated Schematic; Xilinx Vivado 2017.4}
\end{figure}
Verilog Testbench
End of explanation
"""


ConstraintXDCTextReader('PYNQ_Z1Constraints_JohnsonCount3');

"""
Explanation: PYNQ-Z1 Deployment
Board Constraints
End of explanation
"""


#Create the Direction States for Ring Counter
DirStates=enum('Left','Halt','Right')
print(f"`Left` state repersentation is {bin(DirStates.Left)}")
print(f"`Halt` state repersentation is {bin(DirStates.Halt)}")
print(f"`Right` state repersentation is {bin(DirStates.Right)}")

@block
def RingCounter(seed, Dir, q, clk, rst):
    """
    Seedable and direction controlable ring counter in myHDL
    
    Input:
        seed(bitvec): intial value for ring counter
        Dir(enum): Direction contorl signal
        clk(bool): clock
        rst(bool): reset
    Output
    """
    q_i=Signal(intbv(int(seed))[len(q):])
    @always(clk.posedge, rst.negedge)
    def RCStateMachine():
        #moore state machine
        if rst:
            q_i.next=seed
        elif Dir==DirStates.Left:
            q_i.next=concat(q_i[len(q_i)-1:0],q_i[len(q_i)-1])

        elif Dir==DirStates.Halt:
            #create circular stop
            q_i.next=q_i
            
        elif Dir==DirStates.Right:
            q_i.next=concat(q_i[0], q_i[len(q_i):1])
    
    @always_comb
    def OuputBuffer():
        q.next=q_i
    
    return instances()

    
    

"""
Explanation: Pay attention to line 22 that follows of setting the clk input signal to Button 3
```
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets {clk}];
``
This is needed in the constraint file in order for the Implementation and Bitstream to work. What this line says to Vivado is "I know that a clock signal is hooked up to a nonstandard clock source, go ahead and make the connection so". This is because the internal rule checking in vivado will raise errors if one attempts to connect a nonclock source to what it perceives (in this case correctly) should be a clock input. Normally this should not be done this way. But because this is for teaching and theJohnsonCount3` was to be implemented as a stand-alone module without a clock divider at a clock speed of Hertz (FPGAs typically have Megahertz built-in clocks) this had to be done. 
Deployment Results
YouTube:Bi-Directional Johnson Counter from myHDL on the PYNQ-Z1

Cyclic Shift Register Ring Counter
Like the Johnson Counter, which is the Mobius ring version of the Ring Counter, a Ring Counter is, in reality, a cyclic shift register since it simply shift the bits in its memory left or right. The following are 
aspects of Ring Counter by Sougata Bhattacharjee [https://www.quora.com/What-is-the-difference-between-a-Johnson-counter-and-a-ring-counter]
\begin{itemize}
\item In a ring counter, the output of the last flip-flop is connected to the input of the first flip-flop.
\item If $n$ is the number of flip-flops that are used in ring counter, the number of possible states are also $n$.That means the number of states is equal to the number of flip-flops used.
\item A Ring counter is mostly used in Successive approximation type ADC and stepper motor control. 
\item Decoding is easy in a ring counter as the number of states is equal to the number of flip-flops.
\item If the input frequency to a ring counter is $f$ then the output frequency $\dfrac{f}{n}$.
\item The total number of unused states in the ring counter is $(2^n - n)$.
\end{itemize}
For a four-bit ring counter, the next state diagram is given by the following table from wikipedga
\begin{figure}
\centerline{\includegraphics[width=1cm]{RingCounterTable.png}}
\caption{\label{fig:RingTable} 4-bit Ring Counter next state table from wikipedia}
\end{figure}
myHDL Module
End of explanation
"""


BitSize=4; seedval=3
Peeker.clear()
seed=Signal(intbv(seedval)[BitSize:]); Peeker(seed, 'seed')
clk=Signal(bool(0)); Peeker(clk, 'clk')
rst=Signal(bool(0)); Peeker(rst, 'rst')
q=Signal(intbv(0)[BitSize:]); Peeker(q, 'q')
Dir=Signal(DirStates.Right); Peeker(Dir, 'Dir')

DUT=RingCounter(seed, Dir, q, clk, rst)

def RingCounter_TB():
    """
    myHDL only Testbench for `RingCounter` module
    """
    @always(delay(1))
    def ClkGen():
        clk.next=not clk
    
    @instance
    def stimules():
        i=0
        while True:
            if i==2*BitSize:
                Dir.next=DirStates.Left
            elif i==3*BitSize:
                rst.next=1
            elif i==3*BitSize+1:
                rst.next=0
            elif i==3*BitSize+2:
                Dir.next=DirStates.Halt
            
            
            if i==5*BitSize:
                raise StopSimulation()
                
            i+=1
            yield clk.posedge
    
    return instances()

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

Peeker.to_wavedrom()

RingCountData=Peeker.to_dataframe()
RingCountData=RingCountData[RingCountData['clk']==1]
RingCountData.drop('clk', axis=1, inplace=True)
RingCountData.reset_index(drop=True, inplace=True)
RingCountData

RingCountData['q']=RingCountData['q'].apply(lambda x:bin(x, BitSize))
RingCountData

RingCountData[RingCountData['Dir']==DirStates.Right]

RingCountData[RingCountData['Dir']==DirStates.Left]

RingCountData[RingCountData['Dir']==DirStates.Halt]

"""
Explanation: myHDL testing
End of explanation
"""


DUT.convert()
VerilogTextReader('RingCounter');

"""
Explanation: Verilog Code
End of explanation
"""


BitSize=4; seedval=3
@block
def RingCounter_TBV():
    """
    myHDL -> verilog Testbench for `RingCounter` module
    """
    seed=Signal(intbv(seedval)[BitSize:])
    clk=Signal(bool(0))
    rst=Signal(bool(0))
    q=Signal(intbv(0)[BitSize:])
    Dir=Signal(DirStates.Right)

    @always_comb
    def print_data():
        print(seed, Dir, q, clk, rst)

    DUT=RingCounter(seed, Dir, q, clk, rst)

    @instance
    def clk_signal():
        while True:
            clk.next = not clk
            yield delay(1)
    
    @instance
    def stimules():
        i=0
        while True:
            if i==2*BitSize:
                Dir.next=DirStates.Left
            elif i==3*BitSize:
                rst.next=1
            elif i==3*BitSize+1:
                rst.next=0
            elif i==3*BitSize+2:
                Dir.next=DirStates.Halt
            
            
            if i==5*BitSize:
                raise StopSimulation()
                
            i+=1
            yield clk.posedge
    
    return instances()



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

"""
Explanation: \begin{figure}
\centerline{\includegraphics[width=10cm]{RingCounter_RTL.png}}
\caption{\label{fig:RCRTL} RingCounter RTL schematic; Xilinx Vivado 2017.4}
\end{figure}
\begin{figure}
\centerline{\includegraphics[width=10cm]{RingCounter_SYN.png}}
\caption{\label{fig:RCSYN} RingCounter Synthesized Schematic; Xilinx Vivado 2017.4}
\end{figure}
Verilog Testbench
End of explanation
"""


ConstraintXDCTextReader('PYNQ_Z1Constraints_RingCounterBlock');

"""
Explanation: PYNQ-Z1 Deployment
Block Design
Video on how Block Design was made found here: YouTube:Seeded Ring Counter RTL IP Hookup in Vivado from myHDL to PYNQ-Z1

\begin{figure}
\centerline{\includegraphics[width=10cm]{RingBlockDesign.png}}
\caption{\label{fig:RCBD} RingCounter Block IP Block Design; Xilinx Vivado 2017.4}
\end{figure}
The Constant IP in the top left corner of the Block Design has the following internal parameterizations, accessed by right clicking on the IP and selecting "Customize Block"
\begin{figure}
\centerline{\includegraphics[width=10cm]{ConstIPSettings.png}}
\caption{\label{fig:ConstSetting} Xilinx IP Constant 1.1 Internal Settings for  Ring Counter Block design ; Xilinx Vivado 2017.4}
\end{figure}
Board Constraints
End of explanation
"""


