Lesson 2 - Creating a behavioural 1 bit Full Adder¶

In the previous lesson we have seen how to implement a 1 bit full adder using structural design. In this lesson we will see how to implement it behaviouraly

In [1]:
import sys
import platform
if (platform.uname().node == 'TPY14'):
    print('Dev machine')
    sys.path.append('..\\..\\..\\py4hw')
Dev machine
In [2]:
import py4hw
In [3]:
class FullAdder(py4hw.Logic):
    
    def __init__(self, parent, name, x, y, ci, s, co):
        super().__init__(parent, name)
        
        self.x = self.addIn('x', x)
        self.y = self.addIn('y', y)
        self.ci = self.addIn('ci', ci)
        self.s = self.addOut('s', s)
        self.co = self.addOut('co', co)

    def propagate(self):
        self.s.put((self.x.get() ^ self.y.get()) ^ self.ci.get())
        self.co.put((self.x.get() & self.y.get()) | ( (self.x.get() ^ self.y.get())  & self.ci.get()))

Testing the circuit¶

In this case the circuit has no schematic to provide, then it will raise an exception if you try to draw it

In [4]:
sys = py4hw.HWSystem()

x = sys.wire('x')
y = sys.wire('y')
ci = sys.wire('ci')
s = sys.wire('s')
co = sys.wire('co')
fa = FullAdder(sys, 'fa', x, y, ci, s, co)
In [5]:
sch = py4hw.Schematic(fa)
sch.draw()
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_17236\1901126793.py in <module>
----> 1 sch = py4hw.Schematic(fa)
      2 sch.draw()

C:\Projects\Research\INT_Py4hw\py4hw\py4hw\schematic.py in __init__(self, obj, render, parent, placeAndRoute)
    247 
    248         if not(obj.isStructural()):
--> 249             raise Exception('Schematics are only available to structural circuits')
    250 
    251         self.sys = obj

Exception: Schematics are only available to structural circuits

Simulating¶

However, you can simulate it. If you have a look at previous results you will see that the behaviour is equivalent.

In [6]:
sys = py4hw.HWSystem()

x = sys.wire('x')
y = sys.wire('y')
ci = sys.wire('ci')
s = sys.wire('s')
co = sys.wire('co')

py4hw.Sequence(sys, 'ci', [0,1], ci)
py4hw.Sequence(sys, 'y', [0,0,1,1], y)
py4hw.Sequence(sys, 'x', [0,0,0,0,1,1,1,1], x)

fa = FullAdder(sys, 'fa', x, y, ci, s, co)

wf = py4hw.Waveform(sys, 'wf', [x, y, ci, s, co])
sys.getSimulator().clk(20)
wf.draw_wavedrom(shortNames=True)
Out[6]:

How to synthesize this?¶

What about synthesis?

In [7]:
rtlgen = py4hw.VerilogGenerator(fa)

print(rtlgen.getVerilog(noInstanceNumber=True))
transpiling /HWSystem[HWSystem]/FullAdder[fa]
// This file was automatically created by py4hw RTL generator
module FullAdder (
	input  x,
	input  y,
	input  ci,
	output  reg  s,
	output  reg  co);
// Code generated from propagate method
// variable declaration 
reg i0;
reg i1;
reg i2;
reg i3;
// process 
always @(*)
begin
s<=i0^ci;
co<=i1|i2;
i0<=x^y;
i1<=x&y;
i2<=i3&ci;
i3<=x^y;
end
endmodule

In [ ]:
 
In [ ]: