From 4b16dd994ab38b6a8adda8fed7155bcb6e800a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Boczar?= Date: Mon, 31 May 2021 10:56:45 +0200 Subject: [PATCH] phy/utils: automatically determine number of cycles in ConstBitSlip --- litedram/phy/utils.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/litedram/phy/utils.py b/litedram/phy/utils.py index c168c0f..801cc1e 100644 --- a/litedram/phy/utils.py +++ b/litedram/phy/utils.py @@ -5,6 +5,7 @@ # SPDX-License-Identifier: BSD-2-Clause import re +import math from fractions import Fraction from functools import reduce from operator import or_ @@ -43,11 +44,14 @@ def edge(mod, cond): return ~cond_d & cond class ConstBitSlip(Module): - def __init__(self, dw, i=None, o=None, slp=None, cycles=1): - self.i = Signal(dw, name='i') if i is None else i - self.o = Signal(dw, name='o') if o is None else o - assert cycles >= 1 - assert 0 <= slp <= cycles*dw-1 + def __init__(self, dw, slp, i=None, o=None, cycles=None): + self.i = Signal(dw, name='i') if i is None else i + self.o = Signal(dw, name='o') if o is None else o + if cycles is None: + cycles = self.min_cycles(slp, dw) + + assert cycles >= 1, cycles + assert 0 <= slp <= cycles*dw-1, (slp, cycles, dw) slp = (cycles*dw-1) - slp # # # @@ -56,6 +60,11 @@ class ConstBitSlip(Module): self.sync += r.eq(Cat(r[dw:], self.i)) self.comb += self.o.eq(r[slp+1:dw+slp+1]) + @staticmethod + def min_cycles(slp, dw): + """Minimum number of cycles to be able to use given bitslip values""" + return math.ceil((slp + 1) / dw) + # TODO: rewrite DQSPattern in litedram/common.py to support different data widths class DQSPattern(Module): def __init__(self, preamble=None, postamble=None, wlevel_en=0, wlevel_strobe=0, register=False): @@ -186,7 +195,7 @@ class CommandsPipeline(Module): n_previous = cmd_nphases_span - 1 # Create a history of valid adapters used for masking overlapping ones - valids = ConstBitSlip(dw=nphases, cycles=1, slp=0) + valids = ConstBitSlip(dw=nphases, slp=0) self.submodules += valids self.comb += valids.i.eq(Cat(a.valid for a in adapters)) valids_hist = valids.r @@ -204,7 +213,7 @@ class CommandsPipeline(Module): allowed = ~reduce(or_, valids_hist[nphases+phase - n_previous:nphases+phase]) # Use CS and CA of given adapter slipped by `phase` bits - cs_bs = ConstBitSlip(dw=cs_ser_width, cycles=1, slp=phase) + cs_bs = ConstBitSlip(dw=cs_ser_width, slp=phase) self.submodules += cs_bs self.comb += cs_bs.i.eq(Cat(adapter.cs)), cs_mask = Replicate(allowed, len(cs_bs.o)) @@ -214,7 +223,7 @@ class CommandsPipeline(Module): # For CA we need to do the same for each bit ca_bits = [] for bit in range(ca_nbits): - ca_bs = ConstBitSlip(dw=ca_ser_width, cycles=1, slp=phase) + ca_bs = ConstBitSlip(dw=ca_ser_width, slp=phase) self.submodules += ca_bs ca_bit_hist = [adapter.ca[i][bit] for i in range(cmd_nphases_span)] self.comb += ca_bs.i.eq(Cat(*ca_bit_hist)),