gen/genlib/cdc: add gearbox

This commit is contained in:
Florent Kermarrec 2017-04-19 09:54:28 +02:00
parent e27bc936ef
commit b708b9cfba

View file

@ -1,6 +1,7 @@
"""
Clock domain crossing module
"""
from fractions import gcd
from litex.gen.fhdl.structure import *
from litex.gen.fhdl.module import Module
@ -193,3 +194,59 @@ class ElasticBuffer(Module):
rdport.adr.eq(rdpointer),
self.dout.eq(rdport.dat_r)
]
def lcm(a, b):
"""Compute the lowest common multiple of a and b"""
return int(a * b / gcd(a, b))
class Gearbox(Module):
def __init__(self, iwidth, idomain, owidth, odomain):
self.i = Signal(iwidth)
self.o = Signal(owidth)
# # #
reset = Signal()
cd_write = ClockDomain()
cd_read = ClockDomain()
self.comb += [
cd_write.clk.eq(ClockSignal(idomain)),
cd_read.clk.eq(ClockSignal(odomain)),
reset.eq(ResetSignal(idomain) | ResetSignal(odomain))
]
self.specials += [
AsyncResetSynchronizer(cd_write, reset),
AsyncResetSynchronizer(cd_read, reset)
]
self.clock_domains += cd_write, cd_read
storage = Signal(lcm(iwidth, owidth))
wrchunks = len(storage)//iwidth
rdchunks = len(storage)//owidth
wrpointer = Signal(max=wrchunks, reset=0 if iwidth > owidth else wrchunks-1)
rdpointer = Signal(max=rdchunks, reset=rdchunks-1 if iwidth > owidth else 0)
self.sync.write += \
If(wrpointer == wrchunks-1,
wrpointer.eq(0)
).Else(
wrpointer.eq(wrpointer + 1)
)
cases = {}
for i in range(wrchunks):
cases[i] = [storage[iwidth*i:iwidth*(i+1)].eq(self.i)]
self.sync.write += Case(wrpointer, cases)
self.sync.read += \
If(rdpointer == rdchunks-1,
rdpointer.eq(0)
).Else(
rdpointer.eq(rdpointer + 1)
)
cases = {}
for i in range(rdchunks):
cases[i] = [self.o.eq(storage[owidth*i:owidth*(i+1)])]
self.sync.read += Case(rdpointer, cases)