phy/utils: automatically determine number of cycles in ConstBitSlip

This commit is contained in:
Jędrzej Boczar 2021-05-31 10:56:45 +02:00
parent 1543fa4ace
commit 4b16dd994a
1 changed files with 17 additions and 8 deletions

View File

@ -5,6 +5,7 @@
# SPDX-License-Identifier: BSD-2-Clause # SPDX-License-Identifier: BSD-2-Clause
import re import re
import math
from fractions import Fraction from fractions import Fraction
from functools import reduce from functools import reduce
from operator import or_ from operator import or_
@ -43,11 +44,14 @@ def edge(mod, cond):
return ~cond_d & cond return ~cond_d & cond
class ConstBitSlip(Module): class ConstBitSlip(Module):
def __init__(self, dw, i=None, o=None, slp=None, cycles=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.i = Signal(dw, name='i') if i is None else i
self.o = Signal(dw, name='o') if o is None else o self.o = Signal(dw, name='o') if o is None else o
assert cycles >= 1 if cycles is None:
assert 0 <= slp <= cycles*dw-1 cycles = self.min_cycles(slp, dw)
assert cycles >= 1, cycles
assert 0 <= slp <= cycles*dw-1, (slp, cycles, dw)
slp = (cycles*dw-1) - slp slp = (cycles*dw-1) - slp
# # # # # #
@ -56,6 +60,11 @@ class ConstBitSlip(Module):
self.sync += r.eq(Cat(r[dw:], self.i)) self.sync += r.eq(Cat(r[dw:], self.i))
self.comb += self.o.eq(r[slp+1:dw+slp+1]) 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 # TODO: rewrite DQSPattern in litedram/common.py to support different data widths
class DQSPattern(Module): class DQSPattern(Module):
def __init__(self, preamble=None, postamble=None, wlevel_en=0, wlevel_strobe=0, register=False): 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 n_previous = cmd_nphases_span - 1
# Create a history of valid adapters used for masking overlapping ones # 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.submodules += valids
self.comb += valids.i.eq(Cat(a.valid for a in adapters)) self.comb += valids.i.eq(Cat(a.valid for a in adapters))
valids_hist = valids.r valids_hist = valids.r
@ -204,7 +213,7 @@ class CommandsPipeline(Module):
allowed = ~reduce(or_, valids_hist[nphases+phase - n_previous:nphases+phase]) allowed = ~reduce(or_, valids_hist[nphases+phase - n_previous:nphases+phase])
# Use CS and CA of given adapter slipped by `phase` bits # 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.submodules += cs_bs
self.comb += cs_bs.i.eq(Cat(adapter.cs)), self.comb += cs_bs.i.eq(Cat(adapter.cs)),
cs_mask = Replicate(allowed, len(cs_bs.o)) 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 # For CA we need to do the same for each bit
ca_bits = [] ca_bits = []
for bit in range(ca_nbits): 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 self.submodules += ca_bs
ca_bit_hist = [adapter.ca[i][bit] for i in range(cmd_nphases_span)] ca_bit_hist = [adapter.ca[i][bit] for i in range(cmd_nphases_span)]
self.comb += ca_bs.i.eq(Cat(*ca_bit_hist)), self.comb += ca_bs.i.eq(Cat(*ca_bit_hist)),