118 lines
8.2 KiB
Python
118 lines
8.2 KiB
Python
from ariths_gen.wire_components import (
|
|
ConstantWireValue0,
|
|
Bus
|
|
)
|
|
from ariths_gen.core.arithmetic_circuits import (
|
|
GeneralCircuit
|
|
)
|
|
from ariths_gen.one_bit_circuits.one_bit_components import (
|
|
TwoOneMultiplexer,
|
|
FullSubtractor
|
|
)
|
|
from ariths_gen.one_bit_circuits.logic_gates import (
|
|
NotGate
|
|
)
|
|
|
|
|
|
class ArrayDivider(GeneralCircuit):
|
|
"""Class representing array divider.
|
|
|
|
Array divider performs division between two N bit numbers and stores their
|
|
quotient in the output bus (remainder bits are not returned).
|
|
|
|
Design is based on series of iterative subtractions.
|
|
|
|
```
|
|
0 B3 0 B2 0 B1 A3 B0
|
|
│ │ │ │ │ │ │ │
|
|
│ │ │ │ │ │ │ │
|
|
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
|
│ │ │ │ │ │ │ │
|
|
┌─┤ FS │◄─┤ FS │◄─┤ FS │◄─┤ FS │◄─ 0
|
|
│ │ │ │ │ │ │ │ │
|
|
│ └──────┘ └───┬──┘ └───┬──┘ └───┬──┘
|
|
│ │ │0 │ │0 │ │A3
|
|
│ ┌─▼───▼┐ ┌─▼───▼┐ ┌─▼───▼┐
|
|
├────────────►│2:1MUX├─►│2:1MUX├─►│2:1MUX│
|
|
│ └───┬──┘ └───┬──┘ └───┬──┘
|
|
│ MX0│ B3 MX1│ B2 MX2│ B1 A2 B0
|
|
│ │ │ │ │ │ │ │ │
|
|
│ ┌─▼─▼──┐ ┌─▼─▼──┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
|
│ │ │ │ │ │ │ │ │
|
|
│ ┌─┤ FS │◄─┤ FS │◄─┤ FS │◄─┤ FS │◄─ 0
|
|
│ │ │ │ │ │ │ │ │ │
|
|
│ │ └──────┘ └───┬──┘ └───┬──┘ └───┬──┘
|
|
│ │ │ │MX1 │ │MX2 │ │A2
|
|
│ │ ┌─▼───▼┐ ┌─▼───▼┐ ┌─▼───▼┐
|
|
│ ├────────────►│2:1MUX├─►│2:1MUX│─►│2:1MUX│
|
|
│ │ └───┬──┘ └───┬──┘ └───┬──┘
|
|
│ │ MX3│ B3 MX4│ B2 MX5│ B1 A1 B0
|
|
│ │ │ │ │ │ │ │ │ │
|
|
│ │ ┌─▼─▼──┐ ┌─▼─▼──┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
|
│ │ │ │ │ │ │ │ │ │
|
|
│ │ ┌─┤ FS │◄─┤ FS │◄─┤ FS │◄─┤ FS │◄─ 0
|
|
│ │ │ │ │ │ │ │ │ │ │
|
|
│ │ │ └──────┘ └───┬──┘ └───┬──┘ └───┬──┘
|
|
│ │ │ │ │MX4 │ │MX5 │ │A1
|
|
│ │ │ ┌─▼───▼┐ ┌─▼───▼┐ ┌─▼───▼┐
|
|
│ │ │────────────►│2:1MUX├─►│2:1MUX│─►│2:1MUX│
|
|
│ │ │ └───┬──┘ └───┬──┘ └───┬──┘
|
|
│ │ │ MX6│ B3 MX7│ B2 MX8│ B1 A0 B0
|
|
│ │ │ │ │ │ │ │ │ │ │
|
|
│ │ │ ┌─▼─▼──┐ ┌─▼─▼──┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
|
│ │ │ │ │ │ │ │ │ │ │
|
|
│ │ │ ┌─┤ FS │◄─┤ FS │◄─┤ FS │◄─┤ FS │◄─ 0
|
|
│ │ │ │ │ │ │ │ │ │ │ │
|
|
│ │ │ │ └──────┘ └──────┘ └──────┘ └──────┘
|
|
│ │ │ │
|
|
│ │ │ │
|
|
┌──▼──┐ ┌──▼──┐ ┌──▼──┐ ┌──▼──┐
|
|
│ │ │ │ │ │ │ │
|
|
│ NOT │ │ NOT │ │ NOT │ │ NOT │
|
|
│ │ │ │ │ │ │ │
|
|
└──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘
|
|
▼ ▼ ▼ ▼
|
|
Q3 Q2 Q1 Q0
|
|
```
|
|
|
|
Description of the __init__ method.
|
|
|
|
Args:
|
|
a (Bus): First input bus.
|
|
b (Bus): Second input bus.
|
|
prefix (str, optional): Prefix name of array divider. Defaults to "".
|
|
name (str, optional): Name of array divider. Defaults to "arrdiv".
|
|
"""
|
|
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "arrdiv", **kwargs):
|
|
self.N = max(a.N, b.N)
|
|
super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N, **kwargs)
|
|
|
|
# Bus sign extension in case buses have different lengths
|
|
self.a.bus_extend(N=self.N, prefix=a.prefix)
|
|
self.b.bus_extend(N=self.N, prefix=b.prefix)
|
|
|
|
# Performing series of iterative subtractions
|
|
# Gradually shifting the divisor
|
|
for a_index in reversed(range(self.N)):
|
|
# Series of subtractions to obtain quotient bit
|
|
for b_index in range(self.N):
|
|
# First full subtractor is formed from divisor's LSB bit (b_index) and divident's MSB bit (a_index)
|
|
if b_index == 0:
|
|
adder_object = FullSubtractor(a=self.a.get_wire(a_index), b=self.b.get_wire(b_index), c=ConstantWireValue0(), prefix=self.prefix+"_fs"+str(self.get_instance_num(cls=FullSubtractor)))
|
|
elif a_index == self.N-1:
|
|
adder_object = FullSubtractor(a=ConstantWireValue0(), b=self.b.get_wire(b_index), c=self.get_previous_component().get_borrow_wire(), prefix=self.prefix+"_fs"+str(self.get_instance_num(cls=FullSubtractor)))
|
|
else:
|
|
adder_object = FullSubtractor(a=self.get_previous_component(self.N+1).out.get_wire(), b=self.b.get_wire(b_index), c=self.get_previous_component().get_borrow_wire(), prefix=self.prefix+"_fs"+str(self.get_instance_num(cls=FullSubtractor)))
|
|
self.add_component(adder_object)
|
|
|
|
# Don't generate multiplexers for divison remainders
|
|
if a_index != 0:
|
|
for mux_index in range(self.N-1):
|
|
mux_object = TwoOneMultiplexer(a=self.get_previous_component(self.N).get_difference_wire(), b=self.get_previous_component(self.N).a, c=self.get_previous_component(1+mux_index).get_borrow_wire(), prefix=self.prefix+"_mux2to1"+str(self.get_instance_num(cls=TwoOneMultiplexer)))
|
|
self.add_component(mux_object)
|
|
|
|
# Every borrow out obtained from each iteration of subtractions needs to be negated to represent the quotient output bit
|
|
quotient = NotGate(a=adder_object.get_borrow_wire(), prefix=self.prefix+"_not"+str(self.get_instance_num(cls=NotGate)), parent_component=self)
|
|
self.add_component(quotient)
|
|
self.out.connect(a_index, quotient.out)
|