Four bit adder: Difference between revisions

1,832 bytes removed ,  2 years ago
(Added Groovy)
Line 3,950:
 
=={{header|MyHDL}}==
To interpret and run this code you will need a recent copy of PythonPython3, and the MyHDL library from myhdl.org. Both examples integrate test code, and export Verilog and VHDL for hardware synthesis.
 
The test code simulates the adder and exports trace wave file for debug support. Verilog and VHDL files are exported for hardware synthesis.
Verbose Code - With integrated Test & Demo
 
<lang python>#!/usr/bin/env""" python
To run:
 
python3 Four_bit_adder_011.py
""" http://rosettacode.org/wiki/Four_bit_adder
Demonstrate theoretical four bit adder simulation
using And, Or & Invert primitives
2011-05-10 jc
"""
 
from myhdl import always_comb, ConcatSignal, delay, intbv, Signal, \*
Simulation, toVerilog, toVHDL
from random import randrange
 
# define set of primitives
 
@block
""" define set of primitives
def NOTgate( a, q ): # define component name & interface
------------------------ """
""" q <- not(a) """
def inverter(z, a): # define component name & interface
""" z <- not(a) """
@always_comb # define asynchronous logic
def logicNOTgateLogic():
zq.next = not a
 
return logic # return defined logic, named 'inverter'
return NOTgateLogic # return defined logic function, named 'NOTgate'
 
 
@block
def and2(z, a, b):
def ANDgate( a, b, q ):
""" z <- a and b """
""" q <- a and b """
@always_comb
def logicANDgateLogic():
zq.next = a and b
return logic
 
return ANDgateLogic
def or2(z, a, b):
 
""" z <- a or b """
 
@block
def ORgate( a, b, q ):
""" q <- a or b """
@always_comb
def logicORgateLogic():
zq.next = a or b
 
return logic
return ORgateLogic
 
 
"""# build components using defined primitive set
 
-------------------------------------------- """
@block
def xor2 (z, a, b):
def """ z <-XORgate( a xor, b """, q ):
""" q <- a xor b """
# define interconnect signals
# define internal signals
nota, notb, annotb, bnnota = [Signal(bool(0)) for i in range(4)]
# name sub-components, and their interconnect
inv0 = inverterNOTgate(nota a, anota )
inv1 = inverterNOTgate(notb b, bnotb )
and2a = and2ANDgate(annotb, a, notb, annotb )
and2b = and2ANDgate(bnnota, b, nota, bnnota )
or2a = or2ORgate(z, annotb, bnnota, q )
 
return inv0, inv1, and2a, and2b, or2a
 
 
def halfAdder(carry, summ, in_a, in_b):
@block
def HalfAdder( in_a, in_b, summ, carry ):
""" carry,sum is the sum of in_a, in_b """
and2a = and2(carry, ANDgate(in_a, in_b, carry)
xor2a = xor2XORgate(summin_a, in_b, in_a, in_bsumm)
 
return and2a, xor2a
 
def fullAdder(fa_c1, fa_s, fa_c0, fa_a, fa_b):
""" fa_c0,fa_s is the sum of fa_c0, fa_a, fa_b """
ha1_s, ha1_c1, ha2_c1 = [Signal(bool(0)) for i in range(3)]
halfAdder01 = halfAdder(ha1_c1, ha1_s, fa_c0, fa_a)
halfAdder02 = halfAdder(ha2_c1, fa_s, ha1_s, fa_b)
or2a = or2(fa_c1, ha1_c1, ha2_c1)
return halfAdder01, halfAdder02, or2a
 
@block
def Adder4b_ST(co,sum4, ina,inb):
def FullAdder( fa_c0, fa_a, fa_b, fa_s, fa_c1 ):
''' assemble 4 full adders '''
""" fa_c1,fa_s is the sum of fa_c0, fa_a, fa_b """
c = [Signal(bool()) for i in range(0,4)]
sl = [Signal(bool()) for i in range(4)] # sum list
halfAdder_0 = halfAdder(c[1],sl[0], ina(0),inb(0))
fullAdder_1 = fullAdder(c[2],sl[1], c[1],ina(1),inb(1))
fullAdder_2 = fullAdder(c[3],sl[2], c[2],ina(2),inb(2))
fullAdder_3 = fullAdder(co, sl[3], c[3],ina(3),inb(3))
# create an internal bus for the output list
sc = ConcatSignal(*reversed(sl)) # create internal bus for output list
@always_comb
def list2intbv():
sum4.next = sc # assign internal bus to actual output
 
ha1_s, ha1_c1, ha2_c1 = [Signal(bool(0)) for i in range(3)]
return halfAdder_0, fullAdder_1, fullAdder_2, fullAdder_3, list2intbv
 
HalfAdder01 = HalfAdder( fa_c0, fa_a, ha1_s, ha1_c1 )
HalfAdder02 = HalfAdder( ha1_s, fa_b, fa_s, ha2_c1 )
or2a = ORgate(ha1_c1, ha2_c1, fa_c1)
 
return HalfAdder01, HalfAdder02, or2a
""" define signals and code for testing
----------------------------------- """
t_co, t_s, t_a, t_b, dbug = [Signal(bool(0)) for i in range(5)]
ina4, inb4, sum4 = [Signal(intbv(0)[4:]) for i in range(3)]
 
def test():
print "\n b a | c1 s \n -------------------"
for i in range(15):
ina4.next, inb4.next = randrange(2**4), randrange(2**4)
yield delay(5)
print " %2d %2d | %2d %2d " \
% (ina4,inb4, t_co,sum4)
assert t_co * 16 + sum4 == ina4 + inb4
print
 
@block
def Adder4b( ina, inb, cOut, sum4):
''' assemble 4 full adders '''
 
cl = [Signal(bool()) for i in range(0,4)] # carry signal list
""" instantiate components and run test
sl = [Signal(bool()) for i in range(4)] # sum signal list
----------------------------------- """
Adder4b_01 = Adder4b_ST(t_co,sum4, ina4,inb4)
test_1 = test()
 
HalfAdder0 = HalfAdder( ina(0), inb(0), sl[0], cl[1] )
def main():
FullAdder1 = FullAdder( cl[1], ina(1), inb(1), sl[1], cl[2] )
sim = Simulation(Adder4b_01, test_1)
FullAdder2 = FullAdder( cl[2], ina(2), inb(2), sl[2], cl[3] )
sim.run()
FullAdder3 = FullAdder( cl[3], ina(3), inb(3), sl[3], cOut )
toVHDL(Adder4b_ST, t_co,sum4, ina4,inb4)
toVerilog(Adder4b_ST, t_co,sum4, ina4,inb4)
if __name__ == '__main__':
main()
</lang>
 
sc = ConcatSignal(*reversed(sl)) # create internal bus for output list
 
@always_comb
Professional Code - with test bench
def list2intbv():
sum4.next = sc # assign internal bus to actual output
 
return HalfAdder0, FullAdder1, FullAdder2, FullAdder3, list2intbv
<lang python>#!/usr/bin/env python
 
from myhdl import *
 
""" define signals and code for testing
def Half_adder(a, b, s, c):
----------------------------------- """
t_co, t_s, t_a, t_b, dbug = [Signal(bool(0)) for i in range(5)]
ina4, inb4, sum4 = [Signal(intbv(0)[4:]) for i in range(3)]
 
from random import randrange
@always_comb
def logic():
s.next = a ^ b
c.next = a & b
 
@block
return logic
def Test_Adder4b():
''' Test Bench for Adder4b '''
dut = Adder4b( ina4, inb4, t_co, sum4 )
 
@instance
def check():
print( "\n b a | c1 s \n -------------------" )
for i in range(15):
ina4.next, inb4.next = randrange(2**4), randrange(2**4)
yield delay(5)
print( " %2d %2d | %2d %2d " \
% (ina4,inb4, t_co,sum4) )
assert t_co * 16 + sum4 == ina4 + inb4 # test result
print()
 
return dut, check
def Full_Adder(a, b, cin, s, c_out):
s_ha1, c_ha1, c_ha2 = [Signal(bool()) for i in range(3)]
ha1 = Half_adder(a=cin, b=a, s=s_ha1, c=c_ha1)
ha2 = Half_adder(a=s_ha1, b=b, s=s, c=c_ha2)
 
@always_comb
def logic():
c_out.next = c_ha1 | c_ha2
 
""" instantiate components and run test
return ha1, ha2, logic
----------------------------------- """
 
def main():
simInst = Test_Adder4b()
simInst.name = "mySimInst"
simInst.config_sim(trace=True) # waveform trace turned on
simInst.run_sim(duration=None)
 
def inst = Adder4b( ina4, inb4, t_co, sum4 ) #Multibit_Adder( a, b, s):
inst.convert(hdl='VHDL') # export VHDL
N = len(s)-1
# inst.convert(hdl='Verilog') input busses# toexport listsVerilog
al = [a(i) for i in range(N)]
bl = [b(i) for i in range(N)]
# set up lists for carry and output
cl = [Signal(bool()) for i in range(N+1)]
sl = [Signal(bool()) for i in range(N+1)]
# boundaries for carry and output
cl[0] = 0
sl[N] = cl[N]
# create an internal bus for the output list
sc = ConcatSignal(*reversed(sl))
 
# assign internal bus to actual output
@always_comb
def assign():
s.next = sc
if __name__ == '__main__':
# create a list of adders
main()
add = [None] * N
for i in range(N):
add[i] = Full_Adder(a=al[i], b=bl[i], s=sl[i], cin=cl[i], c_out=cl[i+1])
 
return add, assign
 
 
# declare I/O for a four-bit adder
N=4
a = Signal(intbv(0)[N:])
b = Signal(intbv(0)[N:])
s = Signal(intbv(0)[N+1:])
 
# convert to Verilog and VHDL
toVerilog(Multibit_Adder, a, b, s)
toVHDL(Multibit_Adder, a, b, s)
# set up a test bench
from random import randrange
def tb():
dut = Multibit_Adder(a, b, s)
 
@instance
def check():
yield delay(10)
for i in range(100):
p, q = randrange(2**N), randrange(2**N)
a.next = p
b.next = q
yield delay(10)
assert s == p + q
 
return dut, check
 
# the entry point for the py.test unit test framework
def test_Adder():
sim = Simulation(tb())
sim.run()
</lang>