Switch to LASMI, bug pandemonium

This commit is contained in:
Sebastien Bourdeauducq 2013-06-11 14:18:16 +02:00
parent 6f2c05d436
commit 91d7b656a9
16 changed files with 321 additions and 530 deletions

View file

@ -1,62 +0,0 @@
from migen.fhdl.std import *
from migen.bus import dfi, asmibus
from milkymist.asmicon.refresher import *
from milkymist.asmicon.bankmachine import *
from milkymist.asmicon.multiplexer import *
class PhySettings:
def __init__(self, dfi_d, nphases, rdphase, wrphase):
self.dfi_d = dfi_d
self.nphases = nphases
self.rdphase = rdphase
self.wrphase = wrphase
class GeomSettings:
def __init__(self, bank_a, row_a, col_a):
self.bank_a = bank_a
self.row_a = row_a
self.col_a = col_a
self.mux_a = max(row_a, col_a)
class TimingSettings:
def __init__(self, tRP, tRCD, tWR, tREFI, tRFC, CL, rd_delay, read_time, write_time, slot_time=0):
self.tRP = tRP
self.tRCD = tRCD
self.tWR = tWR
self.tREFI = tREFI
self.tRFC = tRFC
self.CL = CL
self.rd_delay = rd_delay
self.read_time = read_time
self.write_time = write_time
self.slot_time = slot_time
class ASMIcon(Module):
def __init__(self, phy_settings, geom_settings, timing_settings, full_selector=False):
self.phy_settings = phy_settings
self.geom_settings = geom_settings
self.timing_settings = timing_settings
self.full_selector = full_selector
self.dfi = dfi.Interface(self.geom_settings.mux_a,
self.geom_settings.bank_a,
self.phy_settings.dfi_d,
self.phy_settings.nphases)
burst_length = self.phy_settings.nphases*2
self.address_align = log2_int(burst_length)
aw = self.geom_settings.bank_a + self.geom_settings.row_a + self.geom_settings.col_a - self.address_align
dw = self.phy_settings.dfi_d*self.phy_settings.nphases
self.submodules.hub = asmibus.Hub(aw, dw, self.timing_settings.slot_time)
def do_finalize(self):
slots = self.hub.get_slots()
self.submodules.refresher = Refresher(self.geom_settings.mux_a, self.geom_settings.bank_a,
self.timing_settings.tRP, self.timing_settings.tREFI, self.timing_settings.tRFC)
self.submodules.bank_machines = [BankMachine(self.geom_settings, self.timing_settings, self.address_align, i, slots, self.full_selector)
for i in range(2**self.geom_settings.bank_a)]
self.submodules.multiplexer = Multiplexer(self.phy_settings, self.geom_settings, self.timing_settings,
self.bank_machines, self.refresher,
self.dfi, self.hub)

View file

@ -1,273 +0,0 @@
from migen.fhdl.std import *
from migen.bus.asmibus import *
from migen.genlib.roundrobin import *
from migen.genlib.fsm import FSM
from migen.genlib.misc import optree
from milkymist.asmicon.multiplexer import *
# Row:Bank:Col address mapping
class _AddressSlicer:
def __init__(self, geom_settings, address_align):
self.geom_settings = geom_settings
self.address_align = address_align
self._b1 = self.geom_settings.col_a - self.address_align
self._b2 = self._b1 + self.geom_settings.bank_a
def row(self, address):
if isinstance(address, int):
return address >> self._b2
else:
return address[self._b2:]
def bank(self, address):
if isinstance(address, int):
return (address & (2**self._b2 - 1)) >> self._b1
else:
return address[self._b1:self._b2]
def col(self, address):
if isinstance(address, int):
return (address & (2**self._b1 - 1)) << self.address_align
else:
return Cat(Replicate(0, self.address_align), address[:self._b1])
class _Selector(Module):
def __init__(self, slicer, bankn, slots):
nslots = len(slots)
self.stb = Signal()
self.ack = Signal()
self.tag = Signal(max=nslots)
self.adr = Signal(slots[0].adr.nbits)
self.we = Signal()
# derived classes should drive rr.request
self.submodules.rr = RoundRobin(nslots, SP_CE)
###
# Multiplex
rr = self.rr
state = Signal(2)
self.comb += [
state.eq(Array(slot.state for slot in slots)[rr.grant]),
self.adr.eq(Array(slot.adr for slot in slots)[rr.grant]),
self.we.eq(Array(slot.we for slot in slots)[rr.grant]),
self.stb.eq(
(slicer.bank(self.adr) == bankn) \
& (state == SLOT_PENDING)),
rr.ce.eq(self.ack | ~self.stb),
self.tag.eq(rr.grant)
]
self.comb += [If((rr.grant == i) & self.stb & self.ack, slot.process.eq(1))
for i, slot in enumerate(slots)]
self.complete_selector(slicer, bankn, slots)
class _SimpleSelector(_Selector):
def complete_selector(self, slicer, bankn, slots):
for i, slot in enumerate(slots):
self.comb += self.rr.request[i].eq(
(slicer.bank(slot.adr) == bankn) & \
(slot.state == SLOT_PENDING))
class _FullSelector(_Selector):
def complete_selector(self, slicer, bankn, slots):
rr = self.rr
# List outstanding requests for our bank
outstandings = []
for slot in slots:
outstanding = Signal()
self.comb += outstanding.eq(
(slicer.bank(slot.adr) == bankn) & \
(slot.state == SLOT_PENDING))
outstandings.append(outstanding)
# Row tracking
openrow_r = Signal(slicer.geom_settings.row_a)
openrow_n = Signal(slicer.geom_settings.row_a)
openrow = Signal(slicer.geom_settings.row_a)
self.comb += [
openrow_n.eq(slicer.row(self.adr)),
If(self.stb,
openrow.eq(openrow_n)
).Else(
openrow.eq(openrow_r)
)
]
self.sync += If(self.stb & self.ack, openrow_r.eq(openrow_n))
hits = []
for slot, os in zip(slots, outstandings):
hit = Signal()
self.comb += hit.eq((slicer.row(slot.adr) == openrow) & os)
hits.append(hit)
# Determine best request
rr = RoundRobin(self.nslots, SP_CE)
has_hit = Signal()
self.comb += has_hit.eq(optree("|", hits))
best_hit = [rr.request[i].eq(hit)
for i, hit in enumerate(hits)]
best_fallback = [rr.request[i].eq(os)
for i, os in enumerate(outstandings)]
select_stmt = If(has_hit,
*best_hit
).Else(
*best_fallback
)
if slots[0].time:
# Implement anti-starvation timer
matures = []
for slot, os in zip(slots, outstandings):
mature = Signal()
comb.append(mature.eq(slot.mature & os))
matures.append(mature)
has_mature = Signal()
self.comb += has_mature.eq(optree("|", matures))
best_mature = [rr.request[i].eq(mature)
for i, mature in enumerate(matures)]
select_stmt = If(has_mature, *best_mature).Else(select_stmt)
self.comb += select_stmt
class _Buffer(Module):
def __init__(self, source):
self.stb = Signal()
self.ack = Signal()
self.tag = Signal(source.tag.bv)
self.adr = Signal(source.adr.bv)
self.we = Signal()
###
en = Signal()
self.comb += [
en.eq(self.ack | ~self.stb),
source.ack.eq(en)
]
self.sync += [
If(en,
self.stb.eq(source.stb),
self.tag.eq(source.tag),
self.adr.eq(source.adr),
self.we.eq(source.we)
)
]
class BankMachine(Module):
def __init__(self, geom_settings, timing_settings, address_align, bankn, slots, full_selector):
self.refresh_req = Signal()
self.refresh_gnt = Signal()
self.cmd = CommandRequestRW(geom_settings.mux_a, geom_settings.bank_a,
bits_for(len(slots)-1))
###
# Sub components
slicer = _AddressSlicer(geom_settings, address_align)
if full_selector:
selector = _FullSelector(slicer, bankn, slots)
self.submodules.buf = _Buffer(selector)
cmdsource = self.buf
else:
selector = _SimpleSelector(slicer, bankn, slots)
cmdsource = selector
self.submodules += selector
# Row tracking
has_openrow = Signal()
openrow = Signal(geom_settings.row_a)
hit = Signal()
self.comb += hit.eq(openrow == slicer.row(cmdsource.adr))
track_open = Signal()
track_close = Signal()
self.sync += [
If(track_open,
has_openrow.eq(1),
openrow.eq(slicer.row(cmdsource.adr))
),
If(track_close,
has_openrow.eq(0)
)
]
# Address generation
s_row_adr = Signal()
self.comb += [
self.cmd.ba.eq(bankn),
If(s_row_adr,
self.cmd.a.eq(slicer.row(cmdsource.adr))
).Else(
self.cmd.a.eq(slicer.col(cmdsource.adr))
)
]
self.comb += self.cmd.tag.eq(cmdsource.tag)
# Respect write-to-precharge specification
precharge_ok = Signal()
t_unsafe_precharge = 2 + timing_settings.tWR - 1
unsafe_precharge_count = Signal(max=t_unsafe_precharge+1)
self.comb += precharge_ok.eq(unsafe_precharge_count == 0)
self.sync += [
If(self.cmd.stb & self.cmd.ack & self.cmd.is_write,
unsafe_precharge_count.eq(t_unsafe_precharge)
).Elif(~precharge_ok,
unsafe_precharge_count.eq(unsafe_precharge_count-1)
)
]
# Control and command generation FSM
fsm = FSM("REGULAR", "PRECHARGE", "ACTIVATE", "REFRESH", delayed_enters=[
("TRP", "ACTIVATE", timing_settings.tRP-1),
("TRCD", "REGULAR", timing_settings.tRCD-1)
])
self.submodules += fsm
fsm.act(fsm.REGULAR,
If(self.refresh_req,
fsm.next_state(fsm.REFRESH)
).Elif(cmdsource.stb,
If(has_openrow,
If(hit,
# NB: write-to-read specification is enforced by multiplexer
self.cmd.stb.eq(1),
cmdsource.ack.eq(self.cmd.ack),
self.cmd.is_read.eq(~cmdsource.we),
self.cmd.is_write.eq(cmdsource.we),
self.cmd.cas_n.eq(0),
self.cmd.we_n.eq(~cmdsource.we)
).Else(
fsm.next_state(fsm.PRECHARGE)
)
).Else(
fsm.next_state(fsm.ACTIVATE)
)
)
)
fsm.act(fsm.PRECHARGE,
# Notes:
# 1. we are presenting the column address, A10 is always low
# 2. since we always go to the ACTIVATE state, we do not need
# to assert track_close.
If(precharge_ok,
self.cmd.stb.eq(1),
If(self.cmd.ack, fsm.next_state(fsm.TRP)),
self.cmd.ras_n.eq(0),
self.cmd.we_n.eq(0)
)
)
fsm.act(fsm.ACTIVATE,
s_row_adr.eq(1),
track_open.eq(1),
self.cmd.stb.eq(1),
If(self.cmd.ack, fsm.next_state(fsm.TRCD)),
self.cmd.ras_n.eq(0)
)
fsm.act(fsm.REFRESH,
self.refresh_gnt.eq(precharge_ok),
track_close.eq(1),
If(~self.refresh_req, fsm.next_state(fsm.REGULAR))
)

View file

@ -1,28 +0,0 @@
from migen.fhdl.std import *
from migen.bank.description import *
class ASMIprobe(Module):
def __init__(self, hub, trace_depth=16):
slots = hub.get_slots()
slot_count = len(slots)
self._slot_count = CSRStatus(bits_for(slot_count))
self._trace_depth = CSRStatus(bits_for(trace_depth))
self._slot_status = [CSRStatus(2, name="slot_status" + str(i)) for i in range(slot_count)]
self._trace = [CSRStatus(bits_for(slot_count-1), name="trace" + str(i)) for i in range(trace_depth)]
###
self.comb += [
self._slot_count.status.eq(slot_count),
self._trace_depth.status.eq(trace_depth)
]
for slot, status in zip(slots, self._slot_status):
self.sync += status.status.eq(slot.state)
shift_tags = [self._trace[n].status.eq(self._trace[n+1].status)
for n in range(len(self._trace) - 1)]
shift_tags.append(self._trace[-1].status.eq(hub.tag_call))
self.sync += If(hub.call, *shift_tags)
def get_csrs(self):
return [self._slot_count, self._trace_depth] + self._slot_status + self._trace

View file

@ -13,6 +13,7 @@ class PhaseInjector(Module, AutoCSR):
### ###
wrdata_en_adv = Signal()
self.comb += [ self.comb += [
If(self._command_issue.re, If(self._command_issue.re,
phase.cs_n.eq(~self._command.storage[0]), phase.cs_n.eq(~self._command.storage[0]),
@ -27,12 +28,15 @@ class PhaseInjector(Module, AutoCSR):
), ),
phase.address.eq(self._address.storage), phase.address.eq(self._address.storage),
phase.bank.eq(self._baddress.storage), phase.bank.eq(self._baddress.storage),
phase.wrdata_en.eq(self._command_issue.re & self._command.storage[4]), wrdata_en_adv.eq(self._command_issue.re & self._command.storage[4]),
phase.rddata_en.eq(self._command_issue.re & self._command.storage[5]), phase.rddata_en.eq(self._command_issue.re & self._command.storage[5]),
phase.wrdata.eq(self._wrdata.storage), phase.wrdata.eq(self._wrdata.storage),
phase.wrdata_mask.eq(0) phase.wrdata_mask.eq(0)
] ]
self.sync += If(phase.rddata_valid, self._rddata.status.eq(phase.rddata)) self.sync += [
phase.wrdata_en.eq(wrdata_en_adv),
If(phase.rddata_valid, self._rddata.status.eq(phase.rddata))
]
class DFIInjector(Module, AutoCSR): class DFIInjector(Module, AutoCSR):
def __init__(self, a, ba, d, nphases=1): def __init__(self, a, ba, d, nphases=1):

View file

@ -2,7 +2,7 @@ from migen.fhdl.std import *
from migen.genlib.fifo import AsyncFIFO from migen.genlib.fifo import AsyncFIFO
from migen.genlib.record import layout_len from migen.genlib.record import layout_len
from migen.bank.description import AutoCSR from migen.bank.description import AutoCSR
from migen.actorlib import structuring, dma_asmi, spi from migen.actorlib import structuring, dma_lasmi, spi
from milkymist.dvisampler.edid import EDID from milkymist.dvisampler.edid import EDID
from milkymist.dvisampler.clocking import Clocking from milkymist.dvisampler.clocking import Clocking
@ -35,7 +35,7 @@ class RawDVISampler(Module, AutoCSR):
pack_factor = asmiport.hub.dw//16 pack_factor = asmiport.hub.dw//16
self.submodules.packer = structuring.Pack([("word", 10), ("pad", 6)], pack_factor) self.submodules.packer = structuring.Pack([("word", 10), ("pad", 6)], pack_factor)
self.submodules.cast = structuring.Cast(self.packer.source.payload.layout, asmiport.hub.dw) self.submodules.cast = structuring.Cast(self.packer.source.payload.layout, asmiport.hub.dw)
self.submodules.dma = spi.DMAWriteController(dma_asmi.Writer(asmiport), spi.MODE_SINGLE_SHOT, free_flow=True) self.submodules.dma = spi.DMAWriteController(dma_lasmi.Writer(lasmim), spi.MODE_SINGLE_SHOT)
self.comb += [ self.comb += [
self.packer.sink.stb.eq(fifo.readable), self.packer.sink.stb.eq(fifo.readable),
fifo.re.eq(self.packer.sink.ack), fifo.re.eq(self.packer.sink.ack),

View file

@ -3,7 +3,7 @@ from migen.genlib.fsm import FSM
from migen.bank.description import * from migen.bank.description import *
from migen.bank.eventmanager import * from migen.bank.eventmanager import *
from migen.flow.actor import * from migen.flow.actor import *
from migen.actorlib import dma_asmi from migen.actorlib import dma_lasmi
from milkymist.dvisampler.common import frame_layout from milkymist.dvisampler.common import frame_layout
@ -55,9 +55,9 @@ class _SlotArray(Module, AutoCSR):
self.comb += [slot.address_done.eq(self.address_done & (current_slot == n)) for n, slot in enumerate(slots)] self.comb += [slot.address_done.eq(self.address_done & (current_slot == n)) for n, slot in enumerate(slots)]
class DMA(Module): class DMA(Module):
def __init__(self, asmiport, nslots): def __init__(self, lasmim, nslots):
bus_aw = asmiport.hub.aw bus_aw = lasmim.aw
bus_dw = asmiport.hub.dw bus_dw = lasmim.dw
alignment_bits = bits_for(bus_dw//8) - 1 alignment_bits = bits_for(bus_dw//8) - 1
self.frame = Sink(frame_layout) self.frame = Sink(frame_layout)
@ -112,7 +112,7 @@ class DMA(Module):
) )
# bus accessor # bus accessor
self.submodules._bus_accessor = dma_asmi.Writer(asmiport) self.submodules._bus_accessor = dma_lasmi.Writer(lasmim)
self.comb += [ self.comb += [
self._bus_accessor.address_data.payload.a.eq(current_address), self._bus_accessor.address_data.payload.a.eq(current_address),
self._bus_accessor.address_data.payload.d.eq(cur_memory_word) self._bus_accessor.address_data.payload.d.eq(cur_memory_word)

View file

@ -2,18 +2,18 @@ from migen.fhdl.std import *
from migen.flow.actor import * from migen.flow.actor import *
from migen.flow.network import * from migen.flow.network import *
from migen.bank.description import CSRStorage, AutoCSR from migen.bank.description import CSRStorage, AutoCSR
from migen.actorlib import dma_asmi, structuring, sim, spi from migen.actorlib import dma_lasmi, structuring, sim, spi
from milkymist.framebuffer.lib import bpp, pixel_layout, dac_layout, FrameInitiator, VTG, FIFO from milkymist.framebuffer.lib import bpp, pixel_layout, dac_layout, FrameInitiator, VTG, FIFO
class Framebuffer(Module): class Framebuffer(Module):
def __init__(self, pads, asmiport, simulation=False): def __init__(self, pads, lasmim, simulation=False):
pack_factor = asmiport.hub.dw//(2*bpp) pack_factor = lasmim.dw//(2*bpp)
packed_pixels = structuring.pack_layout(pixel_layout, pack_factor) packed_pixels = structuring.pack_layout(pixel_layout, pack_factor)
fi = FrameInitiator() fi = FrameInitiator()
dma = spi.DMAReadController(dma_asmi.Reader(asmiport), spi.MODE_EXTERNAL, length_reset=640*480*4) dma = spi.DMAReadController(dma_lasmi.Reader(lasmim), spi.MODE_EXTERNAL, length_reset=640*480*4)
cast = structuring.Cast(asmiport.hub.dw, packed_pixels, reverse_to=True) cast = structuring.Cast(lasmim.dw, packed_pixels, reverse_to=True)
unpack = structuring.Unpack(pack_factor, pixel_layout) unpack = structuring.Unpack(pack_factor, pixel_layout)
vtg = VTG() vtg = VTG()
if simulation: if simulation:
@ -93,19 +93,19 @@ class Blender(PipelinedActor, AutoCSR):
self.comb += self.source.payload.eq(outval) self.comb += self.source.payload.eq(outval)
class MixFramebuffer(Module, AutoCSR): class MixFramebuffer(Module, AutoCSR):
def __init__(self, pads, *asmiports, blender_latency=5): def __init__(self, pads, *lasmims, blender_latency=5):
pack_factor = asmiports[0].hub.dw//(2*bpp) pack_factor = lasmims[0].dw//(2*bpp)
packed_pixels = structuring.pack_layout(pixel_layout, pack_factor) packed_pixels = structuring.pack_layout(pixel_layout, pack_factor)
self._enable = CSRStorage() self._enable = CSRStorage()
self.fi = FrameInitiator() self.fi = FrameInitiator()
self.blender = Blender(len(asmiports), blender_latency) self.blender = Blender(len(lasmims), blender_latency)
self.comb += self.fi.trigger.eq(self._enable.storage) self.comb += self.fi.trigger.eq(self._enable.storage)
g = DataFlowGraph() g = DataFlowGraph()
for n, asmiport in enumerate(asmiports): for n, lasmim in enumerate(lasmims):
dma = spi.DMAReadController(dma_asmi.Reader(asmiport), spi.MODE_EXTERNAL, length_reset=640*480*4) dma = spi.DMAReadController(dma_lasmi.Reader(lasmim), spi.MODE_EXTERNAL, length_reset=640*480*4)
cast = structuring.Cast(asmiport.hub.dw, packed_pixels, reverse_to=True) cast = structuring.Cast(lasmim.dw, packed_pixels, reverse_to=True)
unpack = structuring.Unpack(pack_factor, pixel_layout) unpack = structuring.Unpack(pack_factor, pixel_layout)
g.add_connection(dma, cast) g.add_connection(dma, cast)

View file

@ -0,0 +1,64 @@
from migen.fhdl.std import *
from migen.bus import dfi, lasmibus
from milkymist.lasmicon.refresher import *
from milkymist.lasmicon.bankmachine import *
from milkymist.lasmicon.multiplexer import *
class PhySettings:
def __init__(self, dfi_d, nphases, rdphase, wrphase):
self.dfi_d = dfi_d
self.nphases = nphases
self.rdphase = rdphase
self.wrphase = wrphase
class GeomSettings:
def __init__(self, bank_a, row_a, col_a):
self.bank_a = bank_a
self.row_a = row_a
self.col_a = col_a
self.mux_a = max(row_a, col_a)
class TimingSettings:
def __init__(self, tRP, tRCD, tWR, tWTR, tREFI, tRFC, CL, read_latency, write_latency, read_time, write_time):
self.tRP = tRP
self.tRCD = tRCD
self.tWR = tWR
self.tWTR = tWTR
self.tREFI = tREFI
self.tRFC = tRFC
self.CL = CL
self.read_latency = read_latency
self.write_latency = write_latency
self.read_time = read_time
self.write_time = write_time
class LASMIcon(Module):
def __init__(self, phy_settings, geom_settings, timing_settings):
burst_length = phy_settings.nphases*2 # command multiplication*DDR
address_align = log2_int(burst_length)
self.dfi = dfi.Interface(geom_settings.mux_a,
geom_settings.bank_a,
phy_settings.dfi_d,
phy_settings.nphases)
self.lasmic = lasmibus.Interface(
aw=geom_settings.row_a + geom_settings.col_a - address_align,
dw=phy_settings.dfi_d*phy_settings.nphases,
nbanks=2**geom_settings.bank_a,
read_latency=timing_settings.read_latency,
write_latency=timing_settings.write_latency)
self.nrowbits = geom_settings.col_a - address_align
###
self.submodules.refresher = Refresher(geom_settings.mux_a, geom_settings.bank_a,
timing_settings.tRP, timing_settings.tREFI, timing_settings.tRFC)
self.submodules.bank_machines = [BankMachine(geom_settings, timing_settings, address_align, i,
getattr(self.lasmic, "bank"+str(i)))
for i in range(2**geom_settings.bank_a)]
self.submodules.multiplexer = Multiplexer(phy_settings, geom_settings, timing_settings,
self.bank_machines, self.refresher,
self.dfi, self.lasmic)

View file

@ -0,0 +1,129 @@
from migen.fhdl.std import *
from migen.bus.asmibus import *
from migen.genlib.roundrobin import *
from migen.genlib.fsm import FSM
from migen.genlib.misc import optree
from milkymist.lasmicon.multiplexer import *
class _AddressSlicer:
def __init__(self, col_a, address_align):
self.col_a = col_a
self.address_align = address_align
def row(self, address):
split = self.col_a - self.address_align
if isinstance(address, int):
return address >> split
else:
return address[split:]
def col(self, address):
split = self.col_a - self.address_align
if isinstance(address, int):
return (address & (2**split - 1)) << self.address_align
else:
return Cat(Replicate(0, self.address_align), address[:split])
class BankMachine(Module):
def __init__(self, geom_settings, timing_settings, address_align, bankn, req):
self.refresh_req = Signal()
self.refresh_gnt = Signal()
self.cmd = CommandRequestRW(geom_settings.mux_a, geom_settings.bank_a)
###
slicer = _AddressSlicer(geom_settings.col_a, address_align)
# Row tracking
has_openrow = Signal()
openrow = Signal(geom_settings.row_a)
hit = Signal()
self.comb += hit.eq(openrow == slicer.row(req.adr))
track_open = Signal()
track_close = Signal()
self.sync += [
If(track_open,
has_openrow.eq(1),
openrow.eq(slicer.row(req.adr))
),
If(track_close,
has_openrow.eq(0)
)
]
# Address generation
s_row_adr = Signal()
self.comb += [
self.cmd.ba.eq(bankn),
If(s_row_adr,
self.cmd.a.eq(slicer.row(req.adr))
).Else(
self.cmd.a.eq(slicer.col(req.adr))
)
]
# Respect write-to-precharge specification
precharge_ok = Signal()
t_unsafe_precharge = 2 + timing_settings.tWR - 1
unsafe_precharge_count = Signal(max=t_unsafe_precharge+1)
self.comb += precharge_ok.eq(unsafe_precharge_count == 0)
self.sync += [
If(self.cmd.stb & self.cmd.ack & self.cmd.is_write,
unsafe_precharge_count.eq(t_unsafe_precharge)
).Elif(~precharge_ok,
unsafe_precharge_count.eq(unsafe_precharge_count-1)
)
]
# Control and command generation FSM
fsm = FSM("REGULAR", "PRECHARGE", "ACTIVATE", "REFRESH", delayed_enters=[
("TRP", "ACTIVATE", timing_settings.tRP-1),
("TRCD", "REGULAR", timing_settings.tRCD-1)
])
self.submodules += fsm
fsm.act(fsm.REGULAR,
If(self.refresh_req,
fsm.next_state(fsm.REFRESH)
).Elif(req.stb,
If(has_openrow,
If(hit,
# NB: write-to-read specification is enforced by multiplexer
self.cmd.stb.eq(1),
req.ack.eq(self.cmd.ack),
self.cmd.is_read.eq(~req.we),
self.cmd.is_write.eq(req.we),
self.cmd.cas_n.eq(0),
self.cmd.we_n.eq(~req.we)
).Else(
fsm.next_state(fsm.PRECHARGE)
)
).Else(
fsm.next_state(fsm.ACTIVATE)
)
)
)
fsm.act(fsm.PRECHARGE,
# Notes:
# 1. we are presenting the column address, A10 is always low
# 2. since we always go to the ACTIVATE state, we do not need
# to assert track_close.
If(precharge_ok,
self.cmd.stb.eq(1),
If(self.cmd.ack, fsm.next_state(fsm.TRP)),
self.cmd.ras_n.eq(0),
self.cmd.we_n.eq(0)
)
)
fsm.act(fsm.ACTIVATE,
s_row_adr.eq(1),
track_open.eq(1),
self.cmd.stb.eq(1),
If(self.cmd.ack, fsm.next_state(fsm.TRCD)),
self.cmd.ras_n.eq(0)
)
fsm.act(fsm.REFRESH,
self.refresh_gnt.eq(precharge_ok),
track_close.eq(1),
If(~self.refresh_req, fsm.next_state(fsm.REGULAR))
)

View file

@ -12,20 +12,19 @@ class CommandRequest:
self.we_n = Signal(reset=1) self.we_n = Signal(reset=1)
class CommandRequestRW(CommandRequest): class CommandRequestRW(CommandRequest):
def __init__(self, a, ba, tagbits): def __init__(self, a, ba):
CommandRequest.__init__(self, a, ba) CommandRequest.__init__(self, a, ba)
self.stb = Signal() self.stb = Signal()
self.ack = Signal() self.ack = Signal()
self.is_read = Signal() self.is_read = Signal()
self.is_write = Signal() self.is_write = Signal()
self.tag = Signal(tagbits)
class _CommandChooser(Module): class _CommandChooser(Module):
def __init__(self, requests, tagbits): def __init__(self, requests):
self.want_reads = Signal() self.want_reads = Signal()
self.want_writes = Signal() self.want_writes = Signal()
# NB: cas_n/ras_n/we_n are 1 when stb is inactive # NB: cas_n/ras_n/we_n are 1 when stb is inactive
self.cmd = CommandRequestRW(flen(requests[0].a), flen(requests[0].ba), tagbits) self.cmd = CommandRequestRW(flen(requests[0].a), flen(requests[0].ba))
### ###
@ -37,7 +36,7 @@ class _CommandChooser(Module):
stb = Signal() stb = Signal()
self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant]) self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant])
for name in ["a", "ba", "is_read", "is_write", "tag"]: for name in ["a", "ba", "is_read", "is_write"]:
choices = Array(getattr(req, name) for req in requests) choices = Array(getattr(req, name) for req in requests)
self.comb += getattr(self.cmd, name).eq(choices[rr.grant]) self.comb += getattr(self.cmd, name).eq(choices[rr.grant])
for name in ["cas_n", "ras_n", "we_n"]: for name in ["cas_n", "ras_n", "we_n"]:
@ -66,6 +65,7 @@ class _Steerer(Module):
else: else:
return cmd.stb & getattr(cmd, attr) return cmd.stb & getattr(cmd, attr)
for phase, sel in zip(dfi.phases, self.sel): for phase, sel in zip(dfi.phases, self.sel):
wrdata_en_adv = Signal()
self.comb += [ self.comb += [
phase.cke.eq(1), phase.cke.eq(1),
phase.cs_n.eq(0) phase.cs_n.eq(0)
@ -77,67 +77,20 @@ class _Steerer(Module):
phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]), phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]),
phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]), phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]),
phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in commands)[sel]), phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in commands)[sel]),
phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in commands)[sel]) wrdata_en_adv.eq(Array(stb_and(cmd, "is_write") for cmd in commands)[sel]),
phase.wrdata_en.eq(wrdata_en_adv)
] ]
class _Datapath(Module):
def __init__(self, timing_settings, command, dfi, hub):
tagbits = flen(hub.tag_call)
rd_valid = Signal()
rd_tag = Signal(tagbits)
wr_valid = Signal()
wr_tag = Signal(tagbits)
self.comb += [
hub.call.eq(rd_valid | wr_valid),
If(wr_valid,
hub.tag_call.eq(wr_tag)
).Else(
hub.tag_call.eq(rd_tag)
)
]
rd_delay = timing_settings.rd_delay + 1
rd_valid_d = [Signal() for i in range(rd_delay)]
rd_tag_d = [Signal(tagbits) for i in range(rd_delay)]
for i in range(rd_delay):
if i:
self.sync += [
rd_valid_d[i].eq(rd_valid_d[i-1]),
rd_tag_d[i].eq(rd_tag_d[i-1])
]
else:
self.sync += [
rd_valid_d[i].eq(command.stb & command.ack & command.is_read),
rd_tag_d[i].eq(command.tag)
]
self.comb += [
rd_valid.eq(rd_valid_d[-1]),
rd_tag.eq(rd_tag_d[-1]),
wr_valid.eq(command.stb & command.ack & command.is_write),
wr_tag.eq(command.tag),
]
all_rddata = [p.rddata for p in dfi.phases]
all_wrdata = [p.wrdata for p in dfi.phases]
all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
self.comb += [
hub.dat_r.eq(Cat(*all_rddata)),
Cat(*all_wrdata).eq(hub.dat_w),
Cat(*all_wrdata_mask).eq(hub.dat_wm)
]
class Multiplexer(Module): class Multiplexer(Module):
def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, hub): def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, lasmic):
assert(phy_settings.nphases == len(dfi.phases)) assert(phy_settings.nphases == len(dfi.phases))
if phy_settings.nphases != 2: if phy_settings.nphases != 2:
raise NotImplementedError("TODO: multiplexer only supports 2 phases") raise NotImplementedError("TODO: multiplexer only supports 2 phases")
# Command choosing # Command choosing
requests = [bm.cmd for bm in bank_machines] requests = [bm.cmd for bm in bank_machines]
tagbits = flen(hub.tag_call) choose_cmd = _CommandChooser(requests)
choose_cmd = _CommandChooser(requests, tagbits) choose_req = _CommandChooser(requests)
choose_req = _CommandChooser(requests, tagbits)
self.comb += [ self.comb += [
choose_cmd.want_reads.eq(0), choose_cmd.want_reads.eq(0),
choose_cmd.want_writes.eq(0) choose_cmd.want_writes.eq(0)
@ -183,13 +136,19 @@ class Multiplexer(Module):
self.comb += go_to_refresh.eq(optree("&", [bm.refresh_gnt for bm in bank_machines])) self.comb += go_to_refresh.eq(optree("&", [bm.refresh_gnt for bm in bank_machines]))
# Datapath # Datapath
datapath = _Datapath(timing_settings, choose_req.cmd, dfi, hub) all_rddata = [p.rddata for p in dfi.phases]
self.submodules += datapath all_wrdata = [p.wrdata for p in dfi.phases]
all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
self.comb += [
lasmic.dat_r.eq(Cat(*all_rddata)),
Cat(*all_wrdata).eq(lasmic.dat_w),
Cat(*all_wrdata_mask).eq(~lasmic.dat_we)
]
# Control FSM # Control FSM
fsm = FSM("READ", "WRITE", "REFRESH", delayed_enters=[ fsm = FSM("READ", "WRITE", "REFRESH", delayed_enters=[
("RTW", "WRITE", timing_settings.rd_delay), ("RTW", "WRITE", timing_settings.read_latency),
("WTR", "READ", timing_settings.tWR) ("WTR", "READ", timing_settings.tWTR)
]) ])
self.submodules += fsm self.submodules += fsm
fsm.act(fsm.READ, fsm.act(fsm.READ,

View file

@ -2,7 +2,7 @@ from migen.fhdl.std import *
from migen.genlib.misc import timeline from migen.genlib.misc import timeline
from migen.genlib.fsm import FSM from migen.genlib.fsm import FSM
from milkymist.asmicon.multiplexer import * from milkymist.lasmicon.multiplexer import *
class Refresher(Module): class Refresher(Module):
def __init__(self, a, ba, tRP, tREFI, tRFC): def __init__(self, a, ba, tRP, tREFI, tRFC):

View file

@ -367,7 +367,6 @@ static void do_command(char *c)
else if(strcmp(token, "ddrwr") == 0) ddrwr(get_token(&c)); else if(strcmp(token, "ddrwr") == 0) ddrwr(get_token(&c));
else if(strcmp(token, "memtest") == 0) memtest(); else if(strcmp(token, "memtest") == 0) memtest();
else if(strcmp(token, "ddrinit") == 0) ddrinit(); else if(strcmp(token, "ddrinit") == 0) ddrinit();
else if(strcmp(token, "asmiprobe") == 0) asmiprobe();
else if(strcmp(token, "dfs") == 0) dfs(get_token(&c)); else if(strcmp(token, "dfs") == 0) dfs(get_token(&c));

View file

@ -127,9 +127,9 @@ void ddrrd(char *startaddr)
cdelay(15); cdelay(15);
for(i=0;i<8;i++) for(i=0;i<8;i++)
printf("%02x", MMPTR(0xe0000834+4*i)); printf("%02x", MMPTR(0xe0001038+4*i));
for(i=0;i<8;i++) for(i=0;i<8;i++)
printf("%02x", MMPTR(0xe0000884+4*i)); printf("%02x", MMPTR(0xe000108c+4*i));
printf("\n"); printf("\n");
} }
@ -150,8 +150,8 @@ void ddrwr(char *startaddr)
} }
for(i=0;i<8;i++) { for(i=0;i<8;i++) {
MMPTR(0xe0000814+4*i) = i; MMPTR(0xe0001018+4*i) = i;
MMPTR(0xe0000864+4*i) = 0xf0 + i; MMPTR(0xe000106c+4*i) = 0xf0 + i;
} }
dfii_pi1_address_write(addr); dfii_pi1_address_write(addr);
@ -209,32 +209,3 @@ int ddrinit(void)
return 1; return 1;
} }
static const char *format_slot_state(int state)
{
switch(state) {
case 0: return "Empty";
case 1: return "Pending";
case 2: return "Processing";
default: return "UNEXPECTED VALUE";
}
}
void asmiprobe(void)
{
volatile unsigned int *regs = (unsigned int *)ASMIPROBE_BASE;
int slot_count;
int trace_depth;
int i;
int offset;
offset = 0;
slot_count = regs[offset++];
trace_depth = regs[offset++];
for(i=0;i<slot_count;i++)
printf("Slot #%d: %s\n", i, format_slot_state(regs[offset++]));
printf("Latest tags:\n");
for(i=0;i<trace_depth;i++)
printf("%d ", regs[offset++]);
printf("\n");
}

View file

@ -10,6 +10,4 @@ int memtest_silent(void);
int memtest(void); int memtest(void);
int ddrinit(void); int ddrinit(void);
void asmiprobe(void);
#endif /* __SDRAM_H */ #endif /* __SDRAM_H */

57
top.py
View file

@ -3,11 +3,12 @@ from math import ceil
from operator import itemgetter from operator import itemgetter
from migen.fhdl.std import * from migen.fhdl.std import *
from migen.bus import wishbone, wishbone2asmi, csr, wishbone2csr, dfi from migen.bus import wishbone, csr, lasmibus, dfi
from migen.bus import wishbone2lasmi, wishbone2csr
from migen.bank import csrgen from migen.bank import csrgen
from milkymist import m1crg, lm32, norflash, uart, s6ddrphy, dfii, asmicon, \ from milkymist import m1crg, lm32, norflash, uart, s6ddrphy, dfii, lasmicon, \
identifier, timer, minimac3, framebuffer, asmiprobe, dvisampler, \ identifier, timer, minimac3, framebuffer, dvisampler, \
counteradc, gpio counteradc, gpio
from milkymist.cif import get_macros from milkymist.cif import get_macros
@ -23,26 +24,28 @@ def ns(t, margin=True):
t += clk_period_ns/2 t += clk_period_ns/2
return ceil(t/clk_period_ns) return ceil(t/clk_period_ns)
sdram_phy = asmicon.PhySettings( sdram_phy = lasmicon.PhySettings(
dfi_d=64, dfi_d=64,
nphases=2, nphases=2,
rdphase=0, rdphase=0,
wrphase=1 wrphase=1
) )
sdram_geom = asmicon.GeomSettings( sdram_geom = lasmicon.GeomSettings(
bank_a=2, bank_a=2,
row_a=13, row_a=13,
col_a=10 col_a=10
) )
sdram_timing = asmicon.TimingSettings( sdram_timing = lasmicon.TimingSettings(
tRP=ns(15), tRP=ns(15),
tRCD=ns(15), tRCD=ns(15),
tWR=ns(15), tWR=ns(15),
tWTR=2,
tREFI=ns(7800, False), tREFI=ns(7800, False),
tRFC=ns(70), tRFC=ns(70),
CL=3, CL=3,
rd_delay=4, read_latency=5,
write_latency=1,
read_time=32, read_time=32,
write_time=16 write_time=16
@ -72,14 +75,13 @@ class SoC(Module):
"timer0": 4, "timer0": 4,
"minimac": 5, "minimac": 5,
"fb": 6, "fb": 6,
"asmiprobe": 7, "dvisampler0": 7,
"dvisampler0": 8, "dvisampler0_edid_mem": 8,
"dvisampler0_edid_mem": 9, "dvisampler1": 9,
"dvisampler1": 10, "dvisampler1_edid_mem": 10,
"dvisampler1_edid_mem": 11, "pots": 11,
"pots": 12, "buttons": 12,
"buttons": 13, "leds": 13
"leds": 14
} }
interrupt_map = { interrupt_map = {
@ -92,15 +94,11 @@ class SoC(Module):
def __init__(self, platform): def __init__(self, platform):
# #
# ASMI # LASMI
# #
self.submodules.asmicon = asmicon.ASMIcon(sdram_phy, sdram_geom, sdram_timing) self.submodules.lasmicon = lasmicon.LASMIcon(sdram_phy, sdram_geom, sdram_timing)
asmiport_wb = self.asmicon.hub.get_port() self.submodules.lasmixbar = lasmibus.Crossbar([self.lasmicon.lasmic], 5, self.lasmicon.nrowbits)
asmiport_fb0 = self.asmicon.hub.get_port(4) lasmim_wb, lasmim_fb0, lasmim_fb1, lasmim_dvi0, lasmim_dvi1 = self.lasmixbar.masters
asmiport_fb1 = self.asmicon.hub.get_port(4)
asmiport_dvi0 = self.asmicon.hub.get_port(4)
asmiport_dvi1 = self.asmicon.hub.get_port(4)
self.asmicon.finalize()
# #
# DFI # DFI
@ -109,7 +107,7 @@ class SoC(Module):
self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a, sdram_phy.dfi_d, self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a, sdram_phy.dfi_d,
sdram_phy.nphases) sdram_phy.nphases)
self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, self.ddrphy.dfi) self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, self.ddrphy.dfi)
self.submodules.dficon1 = dfi.Interconnect(self.asmicon.dfi, self.dfii.slave) self.submodules.dficon1 = dfi.Interconnect(self.lasmicon.dfi, self.dfii.slave)
# #
# WISHBONE # WISHBONE
@ -118,7 +116,7 @@ class SoC(Module):
self.submodules.norflash = norflash.NorFlash(platform.request("norflash"), 12) self.submodules.norflash = norflash.NorFlash(platform.request("norflash"), 12)
self.submodules.sram = wishbone.SRAM(sram_size) self.submodules.sram = wishbone.SRAM(sram_size)
self.submodules.minimac = minimac3.MiniMAC(platform.request("eth")) self.submodules.minimac = minimac3.MiniMAC(platform.request("eth"))
self.submodules.wishbone2asmi = wishbone2asmi.WB2ASMI(l2_size//4, asmiport_wb) self.submodules.wishbone2lasmi = wishbone2lasmi.WB2LASMI(l2_size//4, lasmim_wb)
self.submodules.wishbone2csr = wishbone2csr.WB2CSR() self.submodules.wishbone2csr = wishbone2csr.WB2CSR()
# norflash 0x00000000 (shadow @0x80000000) # norflash 0x00000000 (shadow @0x80000000)
@ -135,7 +133,7 @@ class SoC(Module):
(lambda a: a[26:29] == 0, self.norflash.bus), (lambda a: a[26:29] == 0, self.norflash.bus),
(lambda a: a[26:29] == 1, self.sram.bus), (lambda a: a[26:29] == 1, self.sram.bus),
(lambda a: a[26:29] == 3, self.minimac.membus), (lambda a: a[26:29] == 3, self.minimac.membus),
(lambda a: a[27:29] == 2, self.wishbone2asmi.wishbone), (lambda a: a[27:29] == 2, self.wishbone2lasmi.wishbone),
(lambda a: a[27:29] == 3, self.wishbone2csr.wishbone) (lambda a: a[27:29] == 3, self.wishbone2csr.wishbone)
], ],
register=True) register=True)
@ -147,10 +145,9 @@ class SoC(Module):
self.submodules.uart = uart.UART(platform.request("serial"), clk_freq, baud=115200) self.submodules.uart = uart.UART(platform.request("serial"), clk_freq, baud=115200)
self.submodules.identifier = identifier.Identifier(0x4D31, version, int(clk_freq)) self.submodules.identifier = identifier.Identifier(0x4D31, version, int(clk_freq))
self.submodules.timer0 = timer.Timer() self.submodules.timer0 = timer.Timer()
self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga"), asmiport_fb0, asmiport_fb1) self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga"), lasmim_fb0, lasmim_fb1)
self.submodules.asmiprobe = asmiprobe.ASMIprobe(self.asmicon.hub) self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), lasmim_dvi0)
self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), asmiport_dvi0) self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1), lasmim_dvi1)
self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1), asmiport_dvi1)
pots_pads = platform.request("dvi_pots") pots_pads = platform.request("dvi_pots")
self.submodules.pots = counteradc.CounterADC(pots_pads.charge, self.submodules.pots = counteradc.CounterADC(pots_pads.charge,
[pots_pads.blackout, pots_pads.crossfade]) [pots_pads.blackout, pots_pads.crossfade])

View file

@ -2,12 +2,12 @@
* 1:2 frequency-ratio DDR PHY for Spartan-6 * 1:2 frequency-ratio DDR PHY for Spartan-6
* *
* Assert dfi_wrdata_en and present the data * Assert dfi_wrdata_en and present the data
* on dfi_wrdata_mask/dfi_wrdata in the same * on dfi_wrdata_mask/dfi_wrdata in the cycle
* cycle as the write command. * immediately following the write command.
* *
* Assert dfi_rddata_en in the same cycle as the read * Assert dfi_rddata_en in the same cycle as the read
* command. The data will come back on dfi_rddata * command. The data will come back on dfi_rddata
* 4 cycles later, along with the assertion of * 5 cycles later, along with the assertion of
* dfi_rddata_valid. * dfi_rddata_valid.
* *
* This PHY only supports CAS Latency 3. * This PHY only supports CAS Latency 3.
@ -75,6 +75,39 @@ module s6ddrphy #(
* Command/address * Command/address
*/ */
reg [NUM_AD-1:0] r0_dfi_address_p0;
reg [NUM_BA-1:0] r0_dfi_bank_p0;
reg r0_dfi_cs_n_p0;
reg r0_dfi_cke_p0;
reg r0_dfi_ras_n_p0;
reg r0_dfi_cas_n_p0;
reg r0_dfi_we_n_p0;
reg [NUM_AD-1:0] r0_dfi_address_p1;
reg [NUM_BA-1:0] r0_dfi_bank_p1;
reg r0_dfi_cs_n_p1;
reg r0_dfi_cke_p1;
reg r0_dfi_ras_n_p1;
reg r0_dfi_cas_n_p1;
reg r0_dfi_we_n_p1;
always @(posedge sys_clk) begin
r0_dfi_address_p0 <= dfi_address_p0;
r0_dfi_bank_p0 <= dfi_bank_p0;
r0_dfi_cs_n_p0 <= dfi_cs_n_p0;
r0_dfi_cke_p0 <= dfi_cke_p0;
r0_dfi_ras_n_p0 <= dfi_ras_n_p0;
r0_dfi_cas_n_p0 <= dfi_cas_n_p0;
r0_dfi_we_n_p0 <= dfi_we_n_p0;
r0_dfi_address_p1 <= dfi_address_p1;
r0_dfi_bank_p1 <= dfi_bank_p1;
r0_dfi_cs_n_p1 <= dfi_cs_n_p1;
r0_dfi_cke_p1 <= dfi_cke_p1;
r0_dfi_ras_n_p1 <= dfi_ras_n_p1;
r0_dfi_cas_n_p1 <= dfi_cas_n_p1;
r0_dfi_we_n_p1 <= dfi_we_n_p1;
end
reg phase_sel; reg phase_sel;
always @(posedge clk2x_270) always @(posedge clk2x_270)
phase_sel <= sys_clk; phase_sel <= sys_clk;
@ -95,21 +128,21 @@ reg r_dfi_cas_n_p1;
reg r_dfi_we_n_p1; reg r_dfi_we_n_p1;
always @(posedge clk2x_270) begin always @(posedge clk2x_270) begin
r_dfi_address_p0 <= dfi_address_p0; r_dfi_address_p0 <= r0_dfi_address_p0;
r_dfi_bank_p0 <= dfi_bank_p0; r_dfi_bank_p0 <= r0_dfi_bank_p0;
r_dfi_cs_n_p0 <= dfi_cs_n_p0; r_dfi_cs_n_p0 <= r0_dfi_cs_n_p0;
r_dfi_cke_p0 <= dfi_cke_p0; r_dfi_cke_p0 <= r0_dfi_cke_p0;
r_dfi_ras_n_p0 <= dfi_ras_n_p0; r_dfi_ras_n_p0 <= r0_dfi_ras_n_p0;
r_dfi_cas_n_p0 <= dfi_cas_n_p0; r_dfi_cas_n_p0 <= r0_dfi_cas_n_p0;
r_dfi_we_n_p0 <= dfi_we_n_p0; r_dfi_we_n_p0 <= r0_dfi_we_n_p0;
r_dfi_address_p1 <= dfi_address_p1; r_dfi_address_p1 <= r0_dfi_address_p1;
r_dfi_bank_p1 <= dfi_bank_p1; r_dfi_bank_p1 <= r0_dfi_bank_p1;
r_dfi_cs_n_p1 <= dfi_cs_n_p1; r_dfi_cs_n_p1 <= r0_dfi_cs_n_p1;
r_dfi_cke_p1 <= dfi_cke_p1; r_dfi_cke_p1 <= r0_dfi_cke_p1;
r_dfi_ras_n_p1 <= dfi_ras_n_p1; r_dfi_ras_n_p1 <= r0_dfi_ras_n_p1;
r_dfi_cas_n_p1 <= dfi_cas_n_p1; r_dfi_cas_n_p1 <= r0_dfi_cas_n_p1;
r_dfi_we_n_p1 <= dfi_we_n_p1; r_dfi_we_n_p1 <= r0_dfi_we_n_p1;
end end
always @(posedge clk2x_270) begin always @(posedge clk2x_270) begin
@ -334,10 +367,10 @@ end
assign drive_dqs = r2_dfi_wrdata_en; assign drive_dqs = r2_dfi_wrdata_en;
wire rddata_valid; wire rddata_valid;
reg [4:0] rddata_sr; reg [5:0] rddata_sr;
assign dfi_rddata_valid_w0 = rddata_sr[0]; assign dfi_rddata_valid_w0 = rddata_sr[0];
assign dfi_rddata_valid_w1 = rddata_sr[0]; assign dfi_rddata_valid_w1 = rddata_sr[0];
always @(posedge sys_clk) always @(posedge sys_clk)
rddata_sr <= {dfi_rddata_en_p0, rddata_sr[4:1]}; rddata_sr <= {dfi_rddata_en_p0, rddata_sr[5:1]};
endmodule endmodule