# Wiki

### Site Tools

nmigen:nmigen_sim_testbench_sync

# Creating a multiplier

Here we do a multiplication of 'a' * 'b' using a shifter with n step. n being the amount of bits. example a = 1101, b = 0101. (a=13 , b=5) we shift 'a' to the left by 1 bit at each step, and if the coresponding bit of 'b' is 1, we add 'a' shifted to the result:

``` b * (a << 0)
+
b * (a << 1)
+
b * (a << 2)
+
b * (a << 3)
--------------
o = 00001101 + 00110100 = 13+52 = 65```

So let's implement our multiplier

```class Multiplier(Elaboratable):
def __init__(self, width):

# o = a * b
self.a = Signal(width)
self.b = Signal(width)

# result has 2x more bits
self.o = Signal(2*width)

# used to start our multiplication
self.start = Signal()

# notify us when done
self.done = Signal()

self.width = width

def elaborate(self, platform):
m = Module()

#tmp holds 'a' shifted at each step of 1 bit
tmp = Signal(2*self.width)

# counter will count the amount of addition we are doing
cnt = Signal.range(0, self.width)

#we are done when the cnt has reached 'width-1' steps
m.d.comb += self.done.eq(cnt == self.width-1)

#check if we got 'start' asserted, if so reset the output and counter
with m.If(self.start):
m.d.sync += [
tmp.eq(self.a),
cnt.eq(0),
self.o.eq(0)
]

with m.Elif(~self.done):
#as long as we are not done, let's shift tmp (which is a copy of 'a') and increment counter
m.d.sync += [
tmp.eq(tmp << 1),
cnt.eq(cnt + 1)
]

#if the bit at position 'cnt' of 'b' is 1, then add 'a' shifted 'cnt' times (which is tmp)
with m.If(self.b.bit_select(cnt, 1)):
m.d.sync += self.o.eq(self.o + tmp)

return m```

We then need a testbench that will take 2 values, tick once with 'start'=1 then a couple of times with 'start'=0 otherwise the core will remain in the start position

```if __name__ == "__main__":
dut = Multiplier(4)
with Simulator(dut, vcd_file=open("multiplier.vcd", "w")) as sim:
def process():
# set a, b, and start
yield dut.a.eq(13)
yield dut.b.eq(5)
yield dut.start.eq(1)
# one clock tick here
yield Tick()
# deassert just 'start'
yield dut.start.eq(0)
# 10 tick here
for i in range(10):
yield Tick()

# Add a clock to our design
# Add 'process' as a testbench process
# Run the simulation
sim.run()```

Here is the entire code

mult.py
```from nmigen import *
from nmigen.cli import main
from nmigen.back.pysim import *
from nmigen.test.tools import *

class Multiplier(Elaboratable):
def __init__(self, width):
self.a = Signal(width)
self.b = Signal(width)
self.o = Signal(2*width)
self.start = Signal()
self.done = Signal()

self.width = width

def elaborate(self, platform):
m = Module()

tmp = Signal(2*self.width)
cnt = Signal.range(0, self.width)

m.d.comb += self.done.eq(cnt == self.width-1)

with m.If(self.start):
m.d.sync += [
tmp.eq(self.a),
cnt.eq(0),
self.o.eq(0)
]

with m.Elif(~self.done):
m.d.sync += tmp.eq(tmp << 1)
m.d.sync += cnt.eq(cnt + 1)
with m.If(self.b.bit_select(cnt, 1)):
m.d.sync += self.o.eq(self.o + tmp)

return m

if __name__ == "__main__":
dut = Multiplier(4)
with Simulator(dut, vcd_file=open("multiplier.vcd", "w")) as sim:
def process():
yield dut.a.eq(13)
yield dut.b.eq(5)
yield dut.start.eq(1)
yield Tick()
yield dut.start.eq(0)
for i in range(10):
yield Tick()

This testbench has generated a vcd file we can look at with gtkwave As we can see, after a couple of clock tick, we have 'o' that is 65, which is our multiplication value 