\title{Addition in myHDL (In Progress)} \author{Steven K Armour} \maketitle
In [1]:
    
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, random, itertools
    
    Out[1]:
In [2]:
    
#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
    
In [3]:
    
BitVals=[0,1]
    
In [4]:
    
@block
def HalfAdder(x1, x2, s, c):
    """
    Half Adder
    Input:
        x1(bool): bit signal to be added
        x2(bool): bit signal to be added
    
    Output:
        s(bool): Half Adder Sum
        c(bool): Half Adder Carry
    """
    @always_comb
    def logic():
        s.next=x1 ^ x2
        c.next=x1 & x2
    
    return instances()
    
In [5]:
    
Peeker.clear()
x1=Signal(bool(0)); Peeker(x1, 'x1')
x2=Signal(bool(0)); Peeker(x2, 'x2')
s=Signal(bool(0)); Peeker(s, 's')
c=Signal(bool(0)); Peeker(c, 'c')
#generate test values
x1TVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals))]
x2TVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals))]
DUT=HalfAdder(x1, x2, s, c)
def HalfAdder_TB():
    """
    myHDL only Testbench for module "HalfAdder"
    """
    @instance
    def stimules():
        for i, j in zip(x1TVals, x2TVals):
            x1.next=i; x2.next=j
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
sim=Simulation(DUT, HalfAdder_TB(), *Peeker.instances()).run()
    
In [6]:
    
Peeker.to_wavedrom('x1', 'x2', 's', 'c')
    
    
    
In [7]:
    
HalfAdderData=Peeker.to_dataframe()
HalfAdderData=HalfAdderData[['x1', 'x2', 's', 'c']]
HalfAdderData
    
    Out[7]:
In [8]:
    
HalfAdderData['sCheck']=HalfAdderData.apply(lambda row: row['x1']^row['x2'], axis=1)
HalfAdderData['cCheck']=HalfAdderData.apply(lambda row: row['x1']&row['x2'], axis=1)
HalfAdderData
    
    Out[8]:
In [9]:
    
SumCheck=(HalfAdderData['s']==HalfAdderData['sCheck']).all()
CarryCheck=(HalfAdderData['c']==HalfAdderData['cCheck']).all()
print(f'Sum Result Check: {SumCheck}; Carry Result Check: {CarryCheck}')
    
    
In [10]:
    
DUT.convert()
VerilogTextReader('HalfAdder');
    
    
In [11]:
    
#generate test values
x1TVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals))]
x2TVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals))]
#create single value representation of Test Inputs
x1TVal=intbv(int(''.join([str(i) for i in x1TVals]), 2))[len(x1TVals):]
x2TVal=intbv(int(''.join([str(i) for i in x2TVals]), 2))[len(x2TVals):]
    
In [12]:
    
print(f'x1Test: {x1TVals}, {x1TVal}, {[int(i) for i in x1TVal]}')
print(f'x2Test: {x2TVals}, {x2TVal}, {[int(i) for i in x2TVal]}')
    
    
In [13]:
    
@block
def HalfAdder_TBV():
    """
    myHDL -> Verilog Testbench for module "HalfAdder"
    """
    x1=Signal(bool(0))
    x2=Signal(bool(0))
    s=Signal(bool(0))
    c=Signal(bool(0))
    
    #test stimuli
    x1TVals=Signal(x1TVal)
    x2TVals=Signal(x2TVal)
    
    @always_comb
    def print_data():
        print(x1, x2, s, c)
    DUT=HalfAdder(x1, x2, s, c)
    @instance
    def stimules():
        for i in range(len(x1TVal)):
            x1.next=x1TVals[i]; x2.next=x2TVals[i]
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
TB=HalfAdder_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('HalfAdder_TBV');
    
    
    
In [14]:
    
@block
def FullAdder(x1, x2, cin, s, c):
    """
    Full Adder 2bit+1 input from exspresion
    Input:
        x1(bool): bit signal to be added
        x2(bool): bit signal to be added
        cin(bool): carry in bit signal
    
    Output:
        s(bool): Full Adder Sum
        c(bool): Full Adder Carry
    """
    @always_comb
    def logic():
        s.next=x1^x2^cin
        c.next=(x1&x2) | (x1&cin) | (x2&cin)
    
    return instances()
    
In [15]:
    
Peeker.clear()
x1=Signal(bool(0)); Peeker(x1, 'x1')
x2=Signal(bool(0)); Peeker(x2, 'x2')
cin=Signal(bool(0)); Peeker(cin, 'cin')
s=Signal(bool(0)); Peeker(s, 's')
c=Signal(bool(0)); Peeker(c, 'c')
#generate test values
x1TVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
x2TVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
cinTVals=[i[2] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
DUT=FullAdder(x1, x2, cin, s, c)
def FullAdder_TB():
    """
    myHDL only Testbench for module "FullAdder"
    """
    @instance
    def stimules():
        for i, j, k in zip(x1TVals, x2TVals, cinTVals):
            x1.next=i; x2.next=j; cin.next=k
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
sim=Simulation(DUT, FullAdder_TB(), *Peeker.instances()).run()
    
In [16]:
    
Peeker.to_wavedrom('x1', 'x2', 'cin', 's', 'c')
    
    
    
In [17]:
    
FullAdderData=Peeker.to_dataframe()
FullAdderData=FullAdderData[['x1', 'x2', 'cin', 's', 'c']]
FullAdderData
    
    Out[17]:
In [18]:
    
FullAdderData['sCheck']=FullAdderData.apply(lambda row: row['x1']^row['x2']^row['cin'], axis=1)
FullAdderData['cCheck']=FullAdderData.apply(lambda row: (row['x1']&row['x2'])|(row['cin']*(row['x1']^row['x2'])), axis=1)
FullAdderData
    
    Out[18]:
In [19]:
    
SumCheck=(FullAdderData['s']==FullAdderData['sCheck']).all()
CarryCheck=(FullAdderData['c']==FullAdderData['cCheck']).all()
print(f'Sum Result Check: {SumCheck}; Carry Result Check: {CarryCheck}')
    
    
In [20]:
    
DUT.convert()
VerilogTextReader('FullAdder');
    
    
In [21]:
    
#generate test values
x1TVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
x2TVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
cinTVals=[i[2] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
#create single value representation of Test Inputs
x1TVal=intbv(int(''.join([str(i) for i in x1TVals]), 2))[len(x1TVals):]
x2TVal=intbv(int(''.join([str(i) for i in x2TVals]), 2))[len(x2TVals):]
cinTVal=intbv(int(''.join([str(i) for i in cinTVals]), 2))[len(cinTVals):]
    
In [22]:
    
print(f'x1Test: {x1TVals}, {x1TVal}, {[int(i) for i in x1TVal]}')
print(f'x2Test: {x2TVals}, {x2TVal}, {[int(i) for i in x2TVal]}')
print(f'cinTest: {cinTVals}, {cinTVal}, {[int(i) for i in cinTVal]}')
    
    
In [23]:
    
@block
def FullAdder_TBV():
    """
    myHDL -> Verilog Testbench for module "FullAdder"
    """
    x1=Signal(bool(0))
    x2=Signal(bool(0))
    cin=Signal(bool(0))
    s=Signal(bool(0))
    c=Signal(bool(0))
    
    #test stimuli
    x1TVals=Signal(x1TVal)
    x2TVals=Signal(x2TVal)
    cinTVals=Signal(cinTVal)
    
    @always_comb
    def print_data():
        print(x1, x2, cin, s, c)
    DUT=FullAdder(x1, x2, cin, s, c)
    @instance
    def stimules():
        for i in range(len(x1TVal)):
            x1.next=x1TVals[i]; x2.next=x2TVals[i]; cin.next=cinTVals[i]
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
TB=FullAdder_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('FullAdder_TBV');
    
    
    
In [24]:
    
@block
def FullAdderViaHAs(x1, x2, cin, s, c):
    """
    Full Adder 2bit+1 input from Half Adders
    Input:
        x1(bool): bit signal to be added
        x2(bool): bit signal to be added
        cin(bool): carry in bit signal
    
    Output:
        s(bool): Full Adder Sum
        c(bool): Full Adder Carry
    """
    #create ouput wires from first HA (HA1) to next HA and 
    #`CarryLogic`
    s_HA1HA2=Signal(bool(0)); c_HA1CL=Signal(bool(0))
    #create first HA and wire it
    HA1_x1x2=HalfAdder(x1=x1, x2=x2, s=s_HA1HA2, c=c_HA1CL)
    
    #create output wire for seconed HA (HA2) to `CarryLogic`
    c_HA2CL=Signal(bool(0))
    HA2_HA1cin=HalfAdder(x1=cin, x2=s_HA1HA2, s=s, c=c_HA2CL)
    @always_comb
    def CarryLogic():
        c.next= c_HA1CL|c_HA2CL
    
    return instances()
    
In [25]:
    
Peeker.clear()
x1=Signal(bool(0)); Peeker(x1, 'x1')
x2=Signal(bool(0)); Peeker(x2, 'x2')
cin=Signal(bool(0)); Peeker(cin, 'cin')
s=Signal(bool(0)); Peeker(s, 's')
c=Signal(bool(0)); Peeker(c, 'c')
#generate test values
x1TVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
x2TVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
cinTVals=[i[2] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
DUT=FullAdderViaHAs(x1, x2, cin, s, c)
def FullAdderViaHAs_TB():
    """
    myHDL only Testbench for module "FullAdderViaHAs"
    """
    @instance
    def stimules():
        for i, j, k in zip(x1TVals, x2TVals, cinTVals):
            x1.next=i; x2.next=j; cin.next=k
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
sim=Simulation(DUT, FullAdder_TB(), *Peeker.instances()).run()
    
In [26]:
    
Peeker.to_wavedrom('x1', 'x2', 'cin', 's', 'c')
    
    
    
In [27]:
    
FullAdderHAData=Peeker.to_dataframe()
FullAdderHAData=FullAdderHAData[['x1', 'x2', 'cin', 's', 'c']]
FullAdderHAData
    
    Out[27]:
In [28]:
    
FullAdderHAData['sCheck']=FullAdderHAData.apply(lambda row: row['x1']^row['x2']^row['cin'], axis=1)
FullAdderHAData['cCheck']=FullAdderHAData.apply(lambda row: (row['x1']&row['x2'])|(row['cin']*(row['x1']^row['x2'])), axis=1)
FullAdderHAData
    
    Out[28]:
In [29]:
    
SumCheck=(FullAdderHAData['s']==FullAdderHAData['sCheck']).all()
CarryCheck=(FullAdderHAData['c']==FullAdderHAData['cCheck']).all()
print(f'Sum Result Check: {SumCheck}; Carry Result Check: {CarryCheck}')
    
    
In [30]:
    
(FullAdderData==FullAdderHAData).all()
    
    Out[30]:
In [31]:
    
DUT.convert()
VerilogTextReader('FullAdderViaHAs');
    
    
In [32]:
    
#generate test values
x1TVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
x2TVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
cinTVals=[i[2] for i in itertools.product(BitVals, repeat=len(BitVals)+1)]
#create single value representation of Test Inputs
x1TVal=intbv(int(''.join([str(i) for i in x1TVals]), 2))[len(x1TVals):]
x2TVal=intbv(int(''.join([str(i) for i in x2TVals]), 2))[len(x2TVals):]
cinTVal=intbv(int(''.join([str(i) for i in cinTVals]), 2))[len(cinTVals):]
    
In [33]:
    
print(f'x1Test: {x1TVals}, {x1TVal}, {[int(i) for i in x1TVal]}')
print(f'x2Test: {x2TVals}, {x2TVal}, {[int(i) for i in x2TVal]}')
print(f'cinTest: {cinTVals}, {cinTVal}, {[int(i) for i in cinTVal]}')
    
    
In [34]:
    
@block
def FullAdderViaHAs_TBV():
    """
    myHDL -> Verilog Testbench for module "FullAdderViaHAs"
    """
    x1=Signal(bool(0))
    x2=Signal(bool(0))
    cin=Signal(bool(0))
    s=Signal(bool(0))
    c=Signal(bool(0))
    
    #test stimuli
    x1TVals=Signal(x1TVal)
    x2TVals=Signal(x2TVal)
    cinTVals=Signal(cinTVal)
    
    @always_comb
    def print_data():
        print(x1, x2, cin, s, c)
    DUT=FullAdderViaHAs(x1, x2, cin, s, c)
    @instance
    def stimules():
        for i in range(len(x1TVal)):
            x1.next=x1TVals[i]; x2.next=x2TVals[i]; cin.next=cinTVals[i]
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
TB=FullAdderViaHAs_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('FullAdderViaHAs_TBV');
    
    
    
In [35]:
    
@block
def RippleCarry4Bit(X1, X2, cin, S, c):
    """
    4 Bit Ripple Carray Adder
    Input:
    Output:
    """
    
    S_i = [Signal(bool(0)) for _ in range(len(S))]   # Sum bit for each stage.
    
    #create intercontect wire between FA0 and FA1 and intialze FA0 and wire up
    c_FA0FA1=Signal(bool(0))
    FA0=FullAdder(x1=X1(0), x2=X2(0), cin=cin, s=S_i[0], c=c_FA0FA1)
    
    c_FA1FA2=Signal(bool(0))
    FA1=FullAdder(x1=X1(1), x2=X2(1), cin=c_FA0FA1, s=S_i[1], c=c_FA1FA2)
    
    c_FA2FA3=Signal(bool(0))
    FA2=FullAdder(x1=X1(2), x2=X2(2), cin=c_FA1FA2, s=S_i[2], c=c_FA2FA3)
    
    FA3=FullAdder(x1=X1(3), x2=X2(3), cin=c_FA2FA3, s=S_i[3], c=c)
    #concat bus wires to single bitvec wire
    @always_comb
    def ConCatSum():
        S.next=concat(S_i[3], S_i[2], S_i[1], S_i[0])
    
    return instances()
    
In [36]:
    
BitSize=4
np.random.seed(12)
X1TVals=np.random.randint(0, 2**BitSize, 2**BitSize)
X2TVals=np.random.randint(0, 2**BitSize, 2**BitSize)
cinTVals=np.random.randint(0,2,2**BitSize)
print(X1TVals)
print(X2TVals)
print(cinTVals)
    
    
In [37]:
    
Peeker.clear()
X1=Signal(intbv(0)[BitSize:]); Peeker(X1, 'X1')
X2=Signal(intbv(0)[BitSize:]); Peeker(X2, 'X2')
cin=Signal(bool(0)); Peeker(cin, 'cin')
S=Signal(intbv(0)[BitSize:]); Peeker(S, 'S')
c=Signal(bool(0)); Peeker(c, 'c')
DUT = RippleCarry4Bit(X1=X1, X2=X2, cin=cin, S=S, c=c)
def RippleCarry4Bit_TB():
    @instance
    def stimules():
        for i in range(len(X1TVals)):
            X1.next=int(X1TVals[i])
            X2.next=int(X2TVals[i])
            cin.next=int(cinTVals[i])
            yield delay(1)
        
        raise StopSimulation()
    return instances()
    
    
sim=Simulation(DUT, RippleCarry4Bit_TB(), *Peeker.instances()).run()
    
In [38]:
    
Peeker.to_wavedrom('cin', 'X1', 'X2', 'S', 'c')
    
    
    
In [39]:
    
RC4BData=Peeker.to_dataframe()
RC4BData=RC4BData[['cin', 'X1', 'X2', 'S', 'c']]
RC4BData
    
    Out[39]:
In [40]:
    
def RC4B_SCheck(cin, X1, X2):
    S=cin+X1+X2
    if S<16:
        return S
    else:
        return S-16
def RC4B_cCheck(cin, X1, X2):
    S=cin+X1+X2
    if S<16:
        return 0
    else:
        return 1
RC4BData['SCheck']=RC4BData.apply(lambda row: RC4B_SCheck(row['cin'], row['X1'], row['X2']), axis=1)
RC4BData['cCheck']=RC4BData.apply(lambda row: RC4B_cCheck(row['cin'], row['X1'], row['X2']), axis=1)
RC4BData
    
    Out[40]:
In [41]:
    
SumCheck=(RC4BData['S']==RC4BData['SCheck']).all()
CarryCheck=(RC4BData['c']==RC4BData['cCheck']).all()
print(f'Sum Result Check: {SumCheck}; Carry Result Check: {CarryCheck}')
    
    
In [42]:
    
DUT.convert()
VerilogTextReader('RippleCarry4Bit');
    
    
In [43]:
    
X1TVal=[intbv(int(i))[BitSize:] for i in X1TVals]
X2TVal=[intbv(int(i))[BitSize:] for i in X2TVals]
cinTVal=intbv(int(''.join([str(i) for i in cinTVals]), 2))[len(cinTVals):]
print(X1TVal)
print(X2TVal)
print(cinTVal)
    
    
In [44]:
    
@block
def RippleCarry4Bit_TBV():
    """
    myHDL -> Verilog Testbench for module "FullAdderViaHAs"
    """
    X1=Signal(intbv(0)[BitSize:])
    X2=Signal(intbv(0)[BitSize:])
    cin=Signal(bool(0))
    S=Signal(intbv(0)[BitSize:])
    c=Signal(bool(0))
    
    #test stimuli
    X1TVals=[Signal(i) for i in X1TVal]
    X2TVals=[Signal(i) for i in X2TVal]
    cinTVals=Signal(cinTVal)
    
    @always_comb
    def print_data():
        print(X1, X2, cin, S, c)
    DUT=RippleCarry4Bit(X1=X1, X2=X2, cin=cin, S=S, c=c)
    @instance
    def stimules():
        for i in range(len(X1TVals)):
            X1.next=X1TVals[i]
            X2.next=X2TVals[i]
            cin.next=cinTVals[i]
            yield delay(1)
        
        raise StopSimulation()
    return instances()
TB=RippleCarry4Bit_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('RippleCarry4Bit_TBV');
    
    
    
In [45]:
    
@block
def RippleCarryNBit(X1, X2, cin, S, c):
    """
    N Bit Ripple Carray Adder
    Input:
    Output:
    """
    
    S_i = [Signal(bool(0)) for _ in range(len(S))]   # Sum bit for each stage.
    c_FAiFAj=[Signal(bool(0)) for _ in range(len(S)-1)]
    
    FAStages=[]
    
    for i in range(len(S)):
        if i==0:
            FAStages.append(FullAdder(x1=X1(i), x2=X2(i), cin=cin, s=S_i[i], c=c_FAiFAj[i]))
        elif i<(len(S)-1):
            FAStages.append(FullAdder(x1=X1(i), x2=X2(i), cin=c_FAiFAj[i-1], s=S_i[i], c=c_FAiFAj[i]))
        else:
            FAStages.append(FullAdder(x1=X1(i), x2=X2(i), cin=c_FAiFAj[i-1], s=S_i[i], c=c))
    #concat bus wires to single bitvec wire
    @always_comb
    def ConCatSum():
        S.next=concat(*reversed(S_i))
    
    return instances()
    
In [46]:
    
BitSize=16
np.random.seed(12)
X1TVals=np.random.randint(0, 2**BitSize, 2**4)
X2TVals=np.random.randint(0, 2**BitSize, 2**4)
cinTVals=np.random.randint(0,2,2**4)
print(X1TVals)
print(X2TVals)
print(cinTVals)
    
    
In [47]:
    
Peeker.clear()
X1=Signal(intbv(0)[BitSize:]); Peeker(X1, 'X1')
X2=Signal(intbv(0)[BitSize:]); Peeker(X2, 'X2')
cin=Signal(bool(0)); Peeker(cin, 'cin')
S=Signal(intbv(0)[BitSize:]); Peeker(S, 'S')
c=Signal(bool(0)); Peeker(c, 'c')
DUT = RippleCarryNBit(X1=X1, X2=X2, cin=cin, S=S, c=c)
def RippleCarryNBit_TB():
    @instance
    def stimules():
        for i in range(len(X1TVals)):
            X1.next=int(X1TVals[i])
            X2.next=int(X2TVals[i])
            cin.next=int(cinTVals[i])
            yield delay(1)
        
        raise StopSimulation()
    return instances()
    
    
sim=Simulation(DUT, RippleCarryNBit_TB(), *Peeker.instances()).run()
    
In [48]:
    
Peeker.to_wavedrom('cin', 'X1', 'X2', 'S', 'c')
    
    
    
In [49]:
    
RCNBData=Peeker.to_dataframe()
RCNBData=RCNBData[['cin', 'X1', 'X2', 'S', 'c']]
RCNBData
    
    Out[49]:
In [50]:
    
def RCNB_SCheck(cin, X1, X2):
    S=cin+X1+X2
    if S<2**BitSize:
        return S
    else:
        return S-(2**BitSize)
def RCNB_cCheck(cin, X1, X2):
    S=cin+X1+X2
    if S<2**BitSize:
        return 0
    else:
        return 1
RCNBData['SCheck']=RCNBData.apply(lambda row: RCNB_SCheck(row['cin'], row['X1'], row['X2']), axis=1)
RCNBData['cCheck']=RCNBData.apply(lambda row: RCNB_cCheck(row['cin'], row['X1'], row['X2']), axis=1)
RCNBData
    
    Out[50]:
In [51]:
    
SumCheck=(RCNBData['S']==RCNBData['SCheck']).all()
CarryCheck=(RCNBData['c']==RCNBData['cCheck']).all()
print(f'Sum Result Check: {SumCheck}; Carry Result Check: {CarryCheck}')
    
    
there is a conversion error in that the converter does not know how to translate as least the * unpacking operator in line 27  of RippleCarryNBit
S.next=ConcatSignal(*reversed(S_i))
There is also a high liklyhood that the converter also does not know how to handle the reversed operator
In [52]:
    
#DUT.convert()
#VerilogTextReader('RippleCarryNBit');
    
In [53]:
    
@block
def CLAS1(x1, x2, p, g):
    """
    Carry Look Ahead Adder Stage One
    Input:
        x1(bool): x1 input
        x2(bool): x2 input
    
    Output:
        p(bool):carry propagate
        g(bool):carry generate
    
    """
    @always_comb
    def logic():
        p.next=x1^x2
        g.next=x1&x2
    return instances()
    
In [54]:
    
Peeker.clear()
x1=Signal(bool(0)); Peeker(x1, 'x1')
x2=Signal(bool(0)); Peeker(x2, 'x2')
p=Signal(bool(0)); Peeker(p, 'p')
g=Signal(bool(0)); Peeker(g, 'g')
#generate test values
x1TVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals))]
x2TVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals))]
DUT=CLAS1(x1, x2, p, g)
def CLAS1_TB():
    """
    myHDL only Testbench for module "CL"
    """
    @instance
    def stimules():
        for i, j in zip(x1TVals, x2TVals):
            x1.next=i; x2.next=j
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
sim=Simulation(DUT, CLAS1_TB(), *Peeker.instances()).run()
    
In [55]:
    
Peeker.to_wavedrom('x1', 'x2', 'p', 'g')
    
    
    
In [56]:
    
CLAS1Data=Peeker.to_dataframe()
CLAS1Data=CLAS1Data[['x1', 'x2', 'p', 'g']]
CLAS1Data
    
    Out[56]:
In [57]:
    
CLAS1Data['pCheck']=CLAS1Data.apply(lambda row: row['x1']^row['x2'], axis=1)
CLAS1Data['gCheck']=CLAS1Data.apply(lambda row: row['x1']&row['x2'], axis=1)
CLAS1Data
    
    Out[57]:
In [58]:
    
pCheck=(CLAS1Data['p']==CLAS1Data['pCheck']).all()
gCheck=(CLAS1Data['g']==CLAS1Data['gCheck']).all()
print(f'p Result Check: {pCheck}; g Result Check: {gCheck}')
    
    
In [59]:
    
DUT.convert()
VerilogTextReader('CLAS1');
    
    
In [60]:
    
#generate test values
x1TVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals))]
x2TVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals))]
#create single value representation of Test Inputs
x1TVal=intbv(int(''.join([str(i) for i in x1TVals]), 2))[len(x1TVals):]
x2TVal=intbv(int(''.join([str(i) for i in x2TVals]), 2))[len(x2TVals):]
    
In [61]:
    
print(f'x1Test: {x1TVals}, {x1TVal}, {[int(i) for i in x1TVal]}')
print(f'x2Test: {x2TVals}, {x2TVal}, {[int(i) for i in x2TVal]}')
    
    
In [62]:
    
@block
def CLAS1_TBV():
    """
    myHDL -> Verilog Testbench for module "CLAS1"
    """
    x1=Signal(bool(0))
    x2=Signal(bool(0))
    p=Signal(bool(0))
    g=Signal(bool(0))
    
    #test stimuli
    x1TVals=Signal(x1TVal)
    x2TVals=Signal(x2TVal)
    
    @always_comb
    def print_data():
        print(x1, x2, p, g)
    DUT=CLAS1(x1, x2, p, g)
    @instance
    def stimules():
        for i in range(len(x1TVal)):
            x1.next=x1TVals[i]; x2.next=x2TVals[i]
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
TB=CLAS1_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('CLAS1_TBV');
    
    
    
In [63]:
    
@block
def CLAS3(p, c, s):
    """
    Carrry Look Ahead Adder Stage 3
    Input:
        p(bool):carry propagate
        c(bool): carry
    Output:
        s(bool): sum
    """
    @always_comb
    def logic():
        s.next=p^c
    return instances()
    
In [64]:
    
Peeker.clear()
p=Signal(bool(0)); Peeker(p, 'p')
c=Signal(bool(0)); Peeker(c, 'c')
s=Signal(bool(0)); Peeker(s, 's')
#generate test values
pTVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals))]
cTVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals))]
DUT=CLAS3(p, c, s)
def CLAS3_TB():
    """
    myHDL only Testbench for module "CLAS3"
    """
    @instance
    def stimules():
        for i, j in zip(pTVals, cTVals):
            p.next=i; c.next=j
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
sim=Simulation(DUT, CLAS3_TB(), *Peeker.instances()).run()
    
In [65]:
    
Peeker.to_wavedrom('p', 'c', 's')
    
    
    
In [66]:
    
CLAS3Data=Peeker.to_dataframe()
CLAS3Data=CLAS3Data[['p', 'c', 's']]
CLAS3Data
    
    Out[66]:
In [67]:
    
CLAS3Data['sCheck']=CLAS3Data.apply(lambda row: row['p']^row['c'], axis=1)
CLAS3Data
    
    Out[67]:
In [68]:
    
sCheck=(CLAS3Data['s']==CLAS3Data['sCheck']).all()
print(f's Result Check: {sCheck}')
    
    
In [69]:
    
DUT.convert()
VerilogTextReader('CLAS3');
    
    
In [70]:
    
#generate test values
pTVals=[i[0] for i in itertools.product(BitVals, repeat=len(BitVals))]
cTVals=[i[1] for i in itertools.product(BitVals, repeat=len(BitVals))]
#create single value representation of Test Inputs
pTVal=intbv(int(''.join([str(i) for i in pTVals]), 2))[len(pTVals):]
cTVal=intbv(int(''.join([str(i) for i in cTVals]), 2))[len(cTVals):]
    
In [71]:
    
print(f'pTest: {pTVals}, {pTVal}, {[int(i) for i in pTVal]}')
print(f'cTest: {cTVals}, {cTVal}, {[int(i) for i in cTVal]}')
    
    
In [72]:
    
@block
def CLAS3_TBV():
    """
    myHDL -> Verilog Testbench for module "CLAS3"
    """
    p=Signal(bool(0))
    c=Signal(bool(0))
    s=Signal(bool(0))
    
    #test stimuli
    pTVals=Signal(pTVal)
    cTVals=Signal(cTVal)
    
    @always_comb
    def print_data():
        print(p, c, s)
    DUT=CLAS3(p, c, s)
    @instance
    def stimules():
        for i in range(len(pTVal)):
            p.next=pTVals[i]; c.next=cTVals[i]
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
TB=CLAS3_TBV()
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('CLAS3_TBV');
    
    
    
And is thus a recursion formula, so for a exsample a 4 bit Carray Lock Ahead Adder would have the following carry exspersions
$$C_1=G_0+P_0\cdot C_{in}$$$$C_2=G_1+P_1\cdot C_1=G_1+P_1G_0+P_1P_0C_{in}$$$$C_3=G_2+P_2\cdot C_2=G_2+P_2G_1+P_2P_1G_0+P_2P_1P_0C_{in}$$$$C_4=G_3+P_3\cdot C_3=G_3+P_3G_2+P_3P_2G_1+P_3P_2P_1G_0+P_3P_2P_1P_0C_{in}$$
In [73]:
    
def CLAS2B4_TestFunc(P, G, cin):
    P=[int(i) for i in reversed(bin(P,4))]
    G=[int(i) for i in reversed(bin(G,4))]
    C=[]
    for i in range(4):
        if i==0:
            C.append(int(G[i]) | (P[i]&cin))
        else:
            C.append(int(G[i]) | (P[i] &C[i-1]))
        
    C=int(''.join(str(i) for i in C[::-1]),2)
    return C
CLAS2B4_TestFunc(8,6,1)
    
    Out[73]:
In [ ]: