videostream: add compacter and packer
This commit is contained in:
parent
25acf17312
commit
b6a00e86e4
|
@ -1,5 +1,7 @@
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.genlib.fsm import *
|
from migen.genlib.fsm import *
|
||||||
|
from migen.genlib.record import Record
|
||||||
|
from migen.genlib.misc import optree
|
||||||
from migen.sim.generic import run_simulation
|
from migen.sim.generic import run_simulation
|
||||||
|
|
||||||
class Chopper(Module):
|
class Chopper(Module):
|
||||||
|
@ -93,6 +95,59 @@ class Chopper(Module):
|
||||||
# initialize Np
|
# initialize Np
|
||||||
fsm.act(N, load_np.eq(1))
|
fsm.act(N, load_np.eq(1))
|
||||||
|
|
||||||
|
class Compacter(Module):
|
||||||
|
def __init__(self, base_layout, N):
|
||||||
|
self.i = Record([("w"+str(i), base_layout) for i in range(N)])
|
||||||
|
self.sel = Signal(N)
|
||||||
|
|
||||||
|
self.o = Record([("w"+str(i), base_layout) for i in range(N)])
|
||||||
|
self.count = Signal(max=N+1)
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
def set_word(wn, selstart):
|
||||||
|
if wn >= N or selstart >= N:
|
||||||
|
return
|
||||||
|
r = None
|
||||||
|
for i in reversed(range(selstart, N)):
|
||||||
|
r = If(self.sel[i],
|
||||||
|
getattr(self.o, "w"+str(wn)).eq(getattr(self.i, "w"+str(i))),
|
||||||
|
set_word(wn+1, i+1)
|
||||||
|
).Else(r)
|
||||||
|
return r
|
||||||
|
self.sync += set_word(0, 0)
|
||||||
|
self.sync += self.count.eq(optree("+", [self.sel[i] for i in range(N)]))
|
||||||
|
|
||||||
|
class Packer(Module):
|
||||||
|
def __init__(self, base_layout, N):
|
||||||
|
assert(N & (N - 1) == 0) # only support powers of 2
|
||||||
|
|
||||||
|
self.i = Record([("w"+str(i), base_layout) for i in range(N)])
|
||||||
|
self.count = Signal(max=N+1)
|
||||||
|
|
||||||
|
self.o = Record([("w"+str(i), base_layout) for i in range(N)])
|
||||||
|
self.stb = Signal()
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
buf = Record([("w"+str(i), base_layout) for i in range(2*N)])
|
||||||
|
|
||||||
|
wrp = Signal(max=2*N)
|
||||||
|
wrp_next = Signal(max=2*N)
|
||||||
|
self.comb += wrp_next.eq(wrp + self.count)
|
||||||
|
self.sync += [
|
||||||
|
wrp.eq(wrp_next), self.stb.eq(wrp_next[-1] ^ wrp[-1]),
|
||||||
|
Case(wrp, {i: [getattr(buf, "w"+str(j + i & 2*N - 1)).eq(getattr(self.i, "w"+str(j))) for j in range(N)] for i in range(2*N)})
|
||||||
|
]
|
||||||
|
|
||||||
|
rdp = Signal()
|
||||||
|
self.sync += If(self.stb, rdp.eq(~rdp))
|
||||||
|
self.comb += If(rdp,
|
||||||
|
[getattr(self.o, "w"+str(i)).eq(getattr(buf, "w"+str(i+N))) for i in range(N)]
|
||||||
|
).Else(
|
||||||
|
[getattr(self.o, "w"+str(i)).eq(getattr(buf, "w"+str(i))) for i in range(N)]
|
||||||
|
)
|
||||||
|
|
||||||
def _count_ones(n):
|
def _count_ones(n):
|
||||||
r = 0
|
r = 0
|
||||||
while n:
|
while n:
|
||||||
|
@ -108,6 +163,7 @@ class _ChopperTB(Module):
|
||||||
def gen_simulation(self, selfp):
|
def gen_simulation(self, selfp):
|
||||||
dut = selfp.dut
|
dut = selfp.dut
|
||||||
|
|
||||||
|
print("initializing chopper...")
|
||||||
dut.init = 1
|
dut.init = 1
|
||||||
dut.p = 320
|
dut.p = 320
|
||||||
dut.q = 681
|
dut.q = 681
|
||||||
|
@ -115,7 +171,6 @@ class _ChopperTB(Module):
|
||||||
dut.init = 0
|
dut.init = 0
|
||||||
yield
|
yield
|
||||||
while not dut.ready:
|
while not dut.ready:
|
||||||
print("waiting")
|
|
||||||
yield
|
yield
|
||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
|
@ -124,10 +179,57 @@ class _ChopperTB(Module):
|
||||||
ones = 0
|
ones = 0
|
||||||
niter = 681
|
niter = 681
|
||||||
for i in range(niter):
|
for i in range(niter):
|
||||||
print("{:04b}".format(dut.chopper))
|
#print("{:04b}".format(dut.chopper))
|
||||||
ones += _count_ones(dut.chopper)
|
ones += _count_ones(dut.chopper)
|
||||||
yield
|
yield
|
||||||
print("Ones: {} (expected: {})".format(ones, dut.p*niter*4//dut.q))
|
print("Ones: {} (expected: {})".format(ones, dut.p*niter*4//dut.q))
|
||||||
|
|
||||||
|
class _CompacterPackerTB(Module):
|
||||||
|
def __init__(self, input_it):
|
||||||
|
self.input_it = input_it
|
||||||
|
self.output = []
|
||||||
|
self.end_cycle = -1
|
||||||
|
|
||||||
|
self.submodules.compacter = Compacter(16, 4)
|
||||||
|
self.submodules.packer = Packer(16, 4)
|
||||||
|
self.comb += self.packer.i.eq(self.compacter.o), self.packer.count.eq(self.compacter.count)
|
||||||
|
|
||||||
|
def do_simulation(self, selfp):
|
||||||
|
if selfp.simulator.cycle_counter == self.end_cycle:
|
||||||
|
raise StopSimulation
|
||||||
|
|
||||||
|
# push values
|
||||||
|
sel = 0
|
||||||
|
for i in range(4):
|
||||||
|
try:
|
||||||
|
value, keep = next(self.input_it)
|
||||||
|
except StopIteration:
|
||||||
|
value, keep = 0, 0
|
||||||
|
if self.end_cycle == -1:
|
||||||
|
self.end_cycle = selfp.simulator.cycle_counter + 3
|
||||||
|
sel |= int(keep) << i
|
||||||
|
setattr(selfp.compacter.i, "w"+str(i), value)
|
||||||
|
selfp.compacter.sel = sel
|
||||||
|
|
||||||
|
# pull values
|
||||||
|
if selfp.packer.stb:
|
||||||
|
for i in range(4):
|
||||||
|
self.output.append(getattr(selfp.packer.o, "w"+str(i)))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
print("*** Testing chopper ***")
|
||||||
run_simulation(_ChopperTB())
|
run_simulation(_ChopperTB())
|
||||||
|
|
||||||
|
print("*** Testing compacter and packer ***")
|
||||||
|
test_seq = [
|
||||||
|
(42, 0), (32, 1), ( 4, 1), (21, 0),
|
||||||
|
(43, 1), (11, 1), ( 5, 1), (18, 0),
|
||||||
|
(71, 0), (70, 1), (30, 1), (12, 1),
|
||||||
|
( 3, 1), (12, 1), (21, 1), (10, 0),
|
||||||
|
( 1, 1), (87, 0), (72, 0), (12, 0)
|
||||||
|
]
|
||||||
|
tb = _CompacterPackerTB(iter(test_seq))
|
||||||
|
run_simulation(tb)
|
||||||
|
print("got: " + str(tb.output))
|
||||||
|
print("expected: " + str([value for value, keep in test_seq if keep]))
|
||||||
|
|
Loading…
Reference in New Issue