frontend/ecc: Add optional Write errors detection (checking granularity).
Write granularity has been recently reduced from DRAM's full burst data-width to DRAM's data-width. This can avoid read-modify-write pattern from User logic, but we also need to be sure the User logic will not generate partial access or adjust the granularity correctly. The new with_we_error_detection paramter can be set to True to enable Write granularity errors and can ease debug.
This commit is contained in:
parent
5ce6bf7824
commit
d16aaa7456
|
@ -34,6 +34,7 @@ class LiteDRAMNativePortECCW(Module):
|
|||
def __init__(self, data_width_from, data_width_to, burst_cycles=8):
|
||||
self.sink = sink = Endpoint(wdata_description(data_width_from))
|
||||
self.source = source = Endpoint(wdata_description(data_width_to))
|
||||
self.we_error = Signal()
|
||||
|
||||
# # #
|
||||
|
||||
|
@ -42,8 +43,8 @@ class LiteDRAMNativePortECCW(Module):
|
|||
|
||||
# Data Path.
|
||||
for i in range(burst_cycles):
|
||||
ecc_width_from = data_width_from//burst_cycles
|
||||
ecc_width_to = data_width_to//burst_cycles
|
||||
ecc_width_from = data_width_from // burst_cycles
|
||||
ecc_width_to = data_width_to // burst_cycles
|
||||
|
||||
# Encoder.
|
||||
self.submodules.encoder = encoder = ECCEncoder(ecc_width_from)
|
||||
|
@ -54,9 +55,13 @@ class LiteDRAMNativePortECCW(Module):
|
|||
# We always have to store the full ECC-Word so byte enable is not supported within
|
||||
# an ECC word. If any of the byte enable is set, the full ECC-Word is written.
|
||||
If(sink.we[i*ecc_width_from//8:(i+1)*ecc_width_from//8] != 0,
|
||||
source.we[i*ecc_width_to//8:(i+1)*ecc_width_to//8].eq(2**ecc_width_to-1)
|
||||
source.we[i*ecc_width_to//8:(i+1)*ecc_width_to//8].eq(2**ecc_width_to//8-1)
|
||||
),
|
||||
source.data[i*ecc_width_to:(i+1)*ecc_width_to].eq(encoder.o)
|
||||
source.data[i*ecc_width_to:(i+1)*ecc_width_to].eq(encoder.o),
|
||||
# Byte enable granularity error detection.
|
||||
If(sink.valid & (sink.we[i*ecc_width_from//8:(i+1)*ecc_width_from//8] != (2**ecc_width_from//8-1)),
|
||||
self.we_error.eq(1)
|
||||
)
|
||||
]
|
||||
|
||||
# LiteDRAMNativePortECCR ---------------------------------------------------------------------------
|
||||
|
@ -76,8 +81,8 @@ class LiteDRAMNativePortECCR(Module):
|
|||
|
||||
# Data Path.
|
||||
for i in range(burst_cycles):
|
||||
ecc_width_to = data_width_to//burst_cycles
|
||||
ecc_width_from = data_width_from//burst_cycles
|
||||
ecc_width_to = data_width_to // burst_cycles
|
||||
ecc_width_from = data_width_from // burst_cycles
|
||||
|
||||
# Decoder.
|
||||
self.submodules.decoder = decoder = ECCDecoder(ecc_width_from)
|
||||
|
@ -98,7 +103,7 @@ class LiteDRAMNativePortECCR(Module):
|
|||
# LiteDRAMNativePortECC ----------------------------------------------------------------------------
|
||||
|
||||
class LiteDRAMNativePortECC(Module, AutoCSR):
|
||||
def __init__(self, port_from, port_to, burst_cycles=8, with_error_injection=False):
|
||||
def __init__(self, port_from, port_to, burst_cycles=8, with_error_injection=False, with_we_error_detection=False):
|
||||
_ , n = compute_m_n(port_from.data_width//burst_cycles)
|
||||
assert port_to.data_width >= (n + 1)*burst_cycles
|
||||
|
||||
|
@ -110,6 +115,8 @@ class LiteDRAMNativePortECC(Module, AutoCSR):
|
|||
self.ded_detected = ded_detected = Signal()
|
||||
if with_error_injection:
|
||||
self.flip = CSRStorage(8)
|
||||
if with_we_error_detection:
|
||||
self.we_errors = CSRStatus(32)
|
||||
|
||||
# # #
|
||||
|
||||
|
@ -163,3 +170,16 @@ class LiteDRAMNativePortECC(Module, AutoCSR):
|
|||
)
|
||||
)
|
||||
]
|
||||
if with_we_error_detection:
|
||||
we_errors = self.we_errors.status
|
||||
self.sync += [
|
||||
If(self.clear.re,
|
||||
we_errors.eq(0),
|
||||
).Else(
|
||||
If(we_errors != (2**len(we_errors) - 1),
|
||||
If(ecc_wdata.we_error,
|
||||
we_errors.eq(we_errors + 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue