From b708b9cfba5a4a3a34fe71d0601a0acda1a15982 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 19 Apr 2017 09:54:28 +0200 Subject: [PATCH] gen/genlib/cdc: add gearbox --- litex/gen/genlib/cdc.py | 57 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/litex/gen/genlib/cdc.py b/litex/gen/genlib/cdc.py index 72efb03f..6e7b0ad8 100644 --- a/litex/gen/genlib/cdc.py +++ b/litex/gen/genlib/cdc.py @@ -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) \ No newline at end of file -- 2.30.2