frontend/bist: simplify and fix CDC using AsyncFIFO.

This commit is contained in:
Florent Kermarrec 2020-04-14 18:13:33 +02:00
parent 378c4419c1
commit 92e34d4d37
1 changed files with 107 additions and 85 deletions

View File

@ -8,10 +8,8 @@ from functools import reduce
from operator import xor from operator import xor
from migen import * from migen import *
from migen.genlib.cdc import MultiReg
from migen.genlib.cdc import PulseSynchronizer
from migen.genlib.cdc import BusSynchronizer
from litex.soc.interconnect import stream
from litex.soc.interconnect.csr import * from litex.soc.interconnect.csr import *
from litedram.common import LiteDRAMNativePort from litedram.common import LiteDRAMNativePort
@ -339,49 +337,63 @@ class LiteDRAMBISTGenerator(Module, AutoCSR):
self.submodules += core self.submodules += core
if clock_domain != "sys": if clock_domain != "sys":
reset_sync = PulseSynchronizer("sys", clock_domain) control_layout = [
start_sync = PulseSynchronizer("sys", clock_domain) ("reset", 1),
self.submodules += reset_sync, start_sync ("start", 1),
self.comb += [ ("base", awidth),
reset_sync.i.eq(self.reset.re), ("end", awidth),
core.reset.eq(reset_sync.o), ("length", awidth),
("random_data", 1),
start_sync.i.eq(self.start.re), ("random_addr", 1),
core.start.eq(start_sync.o)
] ]
status_layout = [
done_sync = BusSynchronizer(1, clock_domain, "sys") ("done", 1),
self.submodules += done_sync ("ticks", 32),
self.comb += [
done_sync.i.eq(core.done),
self.done.status.eq(done_sync.o)
] ]
control_cdc = stream.AsyncFIFO(control_layout)
base_sync = BusSynchronizer(awidth, "sys", clock_domain) control_cdc = ClockDomainsRenamer({"write" : "sys", "read": clock_domain})(control_cdc)
end_sync = BusSynchronizer(awidth, "sys", clock_domain) status_cdc = stream.AsyncFIFO(status_layout)
length_sync = BusSynchronizer(awidth, "sys", clock_domain) status_cdc = ClockDomainsRenamer({"write" : clock_domain, "read": "sys"})(status_cdc)
self.submodules += base_sync, end_sync, length_sync self.submodules += control_cdc, status_cdc
# Control CDC In
self.comb += [ self.comb += [
base_sync.i.eq(self.base.storage), control_cdc.sink.valid.eq(self.reset.re | self.start.re),
core.base.eq(base_sync.o), control_cdc.sink.reset.eq(self.reset.re),
control_cdc.sink.start.eq(self.start.re),
end_sync.i.eq(self.end.storage), control_cdc.sink.base.eq(self.base.storage),
core.end.eq(end_sync.o), control_cdc.sink.end.eq(self.end.storage),
control_cdc.sink.length.eq(self.length.storage),
length_sync.i.eq(self.length.storage), control_cdc.sink.random_data.eq(self.random.fields.data),
core.length.eq(length_sync.o) control_cdc.sink.random_addr.eq(self.random.fields.addr),
] ]
# Control CDC Out
self.specials += [
MultiReg(self.random.fields.data, core.random_data, clock_domain),
MultiReg(self.random.fields.addr, core.random_addr, clock_domain),
]
ticks_sync = BusSynchronizer(32, clock_domain, "sys")
self.submodules += ticks_sync
self.comb += [ self.comb += [
ticks_sync.i.eq(core.ticks), control_cdc.source.ready.eq(1),
self.ticks.status.eq(ticks_sync.o) core.reset.eq(control_cdc.source.valid & control_cdc.source.reset),
core.start.eq(control_cdc.source.valid & control_cdc.source.start),
]
self.sync += [
If(control_cdc.source.valid,
core.base.eq(control_cdc.source.base),
core.end.eq(control_cdc.source.end),
core.length.eq(control_cdc.source.length),
core.random_data.eq(control_cdc.source.random_data),
core.random_addr.eq(control_cdc.source.random_addr),
)
]
# Status CDC In
self.comb += [
status_cdc.sink.valid.eq(1),
status_cdc.sink.done.eq(core.done),
status_cdc.sink.ticks.eq(core.ticks),
]
# Status CDC Out
self.comb += status_cdc.source.ready.eq(1)
self.sync += [
If(status_cdc.source.valid,
self.done.status.eq(status_cdc.source.done),
self.ticks.status.eq(status_cdc.source.ticks),
)
] ]
else: else:
self.comb += [ self.comb += [
@ -671,56 +683,66 @@ class LiteDRAMBISTChecker(Module, AutoCSR):
self.submodules += core self.submodules += core
if clock_domain != "sys": if clock_domain != "sys":
reset_sync = PulseSynchronizer("sys", clock_domain) control_layout = [
start_sync = PulseSynchronizer("sys", clock_domain) ("reset", 1),
self.submodules += reset_sync, start_sync ("start", 1),
self.comb += [ ("base", awidth),
reset_sync.i.eq(self.reset.re), ("end", awidth),
core.reset.eq(reset_sync.o), ("length", awidth),
("random_data", 1),
start_sync.i.eq(self.start.re), ("random_addr", 1),
core.start.eq(start_sync.o)
] ]
status_layout = [
done_sync = BusSynchronizer(1, clock_domain, "sys") ("done", 1),
self.submodules += done_sync ("ticks", 32),
self.comb += [ ("errors", 32),
done_sync.i.eq(core.done),
self.done.status.eq(done_sync.o)
] ]
control_cdc = stream.AsyncFIFO(control_layout)
base_sync = BusSynchronizer(awidth, "sys", clock_domain) control_cdc = ClockDomainsRenamer({"write" : "sys", "read": clock_domain})(control_cdc)
end_sync = BusSynchronizer(awidth, "sys", clock_domain) status_cdc = stream.AsyncFIFO(status_layout)
length_sync = BusSynchronizer(awidth, "sys", clock_domain) status_cdc = ClockDomainsRenamer({"write" : clock_domain, "read": "sys"})(status_cdc)
self.submodules += base_sync, end_sync, length_sync self.submodules += control_cdc, status_cdc
# Control CDC In
self.comb += [ self.comb += [
base_sync.i.eq(self.base.storage), control_cdc.sink.valid.eq(self.reset.re | self.start.re),
core.base.eq(base_sync.o), control_cdc.sink.reset.eq(self.reset.re),
control_cdc.sink.start.eq(self.start.re),
end_sync.i.eq(self.end.storage), control_cdc.sink.base.eq(self.base.storage),
core.end.eq(end_sync.o), control_cdc.sink.end.eq(self.end.storage),
control_cdc.sink.length.eq(self.length.storage),
length_sync.i.eq(self.length.storage), control_cdc.sink.random_data.eq(self.random.fields.data),
core.length.eq(length_sync.o) control_cdc.sink.random_addr.eq(self.random.fields.addr),
] ]
# Control CDC Out
self.specials += [
MultiReg(self.random.fields.data, core.random_data, clock_domain),
MultiReg(self.random.fields.addr, core.random_addr, clock_domain),
]
ticks_sync = BusSynchronizer(32, clock_domain, "sys")
self.submodules += ticks_sync
self.comb += [ self.comb += [
ticks_sync.i.eq(core.ticks), control_cdc.source.ready.eq(1),
self.ticks.status.eq(ticks_sync.o) core.reset.eq(control_cdc.source.valid & control_cdc.source.reset),
core.start.eq(control_cdc.source.valid & control_cdc.source.start),
] ]
self.sync += [
errors_sync = BusSynchronizer(32, clock_domain, "sys") If(control_cdc.source.valid,
self.submodules += errors_sync core.base.eq(control_cdc.source.base),
core.end.eq(control_cdc.source.end),
core.length.eq(control_cdc.source.length),
core.random_data.eq(control_cdc.source.random_data),
core.random_addr.eq(control_cdc.source.random_addr),
)
]
# Status CDC In
self.comb += [ self.comb += [
errors_sync.i.eq(core.errors), status_cdc.sink.valid.eq(1),
self.errors.status.eq(errors_sync.o) status_cdc.sink.done.eq(core.done),
status_cdc.sink.ticks.eq(core.ticks),
status_cdc.sink.errors.eq(core.errors),
]
# Status CDC Out
self.comb += status_cdc.source.ready.eq(1)
self.sync += [
If(status_cdc.source.valid,
self.done.status.eq(status_cdc.source.done),
self.ticks.status.eq(status_cdc.source.ticks),
self.errors.status.eq(status_cdc.source.errors),
)
] ]
else: else:
self.comb += [ self.comb += [
@ -733,5 +755,5 @@ class LiteDRAMBISTChecker(Module, AutoCSR):
core.random_data.eq(self.random.fields.data), core.random_data.eq(self.random.fields.data),
core.random_addr.eq(self.random.fields.addr), core.random_addr.eq(self.random.fields.addr),
self.ticks.status.eq(core.ticks), self.ticks.status.eq(core.ticks),
self.errors.status.eq(core.errors) self.errors.status.eq(core.errors),
] ]