frontend/ecc: Reduce write byte enable granularity from DRAM's full burst data-width to DRAM's data-width.

Also add comments.
This commit is contained in:
Florent Kermarrec 2021-06-08 16:57:39 +02:00
parent 377d6fac6c
commit c5d70114b5
1 changed files with 34 additions and 13 deletions

View File

@ -16,7 +16,7 @@ Features:
- Errors reporting. - Errors reporting.
Limitations: Limitations:
- Byte enable not supported for writes. - Write byte enable granularity of DRAM's data-width.
""" """
from migen import * from migen import *
@ -37,15 +37,27 @@ class LiteDRAMNativePortECCW(Module):
# # # # # #
# Control (ECC encoding is combinatorial).
self.comb += sink.connect(source, omit={"data", "we"}),
# Data Path.
for i in range(8): for i in range(8):
encoder = ECCEncoder(data_width_from//8) ecc_width_from = data_width_from//8
self.submodules += encoder ecc_width_to = data_width_to//8
# Encoder.
self.submodules.encoder = encoder = ECCEncoder(ecc_width_from)
self.comb += [ self.comb += [
sink.connect(source, omit={"data", "we"}), # Input.
encoder.i.eq(sink.data[i*data_width_from//8:(i+1)*data_width_from//8]), encoder.i.eq(sink.data[i*ecc_width_from:(i+1)*ecc_width_from]),
source.data[i*data_width_to//8:(i+1)*data_width_to//8].eq(encoder.o) # Output.
# 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.data[i*ecc_width_to:(i+1)*ecc_width_to].eq(encoder.o)
] ]
self.comb += If(sink.we != 0, source.we.eq(2**len(source.we)-1))
# LiteDRAMNativePortECCR --------------------------------------------------------------------------- # LiteDRAMNativePortECCR ---------------------------------------------------------------------------
@ -59,15 +71,24 @@ class LiteDRAMNativePortECCR(Module):
# # # # # #
# Control Path (ECC encoding is combinatorial).
self.comb += sink.connect(source, omit={"data"}) self.comb += sink.connect(source, omit={"data"})
# Data Path.
for i in range(8): for i in range(8):
decoder = ECCDecoder(data_width_from//8) ecc_width_to = data_width_to//8
self.submodules += decoder ecc_width_from = data_width_from//8
# Decoder.
self.submodules.decoder = decoder = ECCDecoder(ecc_width_from)
self.comb += [ self.comb += [
# Enable.
decoder.enable.eq(self.enable), decoder.enable.eq(self.enable),
decoder.i.eq(sink.data[i*data_width_to//8:(i+1)*data_width_to//8]), # Input.
source.data[i*data_width_from//8:(i+1)*data_width_from//8].eq(decoder.o), decoder.i.eq(sink.data[i*ecc_width_to:(i+1)*ecc_width_to]),
# Output.
source.data[i*ecc_width_from:(i+1)*ecc_width_from].eq(decoder.o),
# Bitflip/Error reporting.
If(source.valid, If(source.valid,
self.sec[i].eq(decoder.sec), self.sec[i].eq(decoder.sec),
self.ded[i].eq(decoder.ded) self.ded[i].eq(decoder.ded)
@ -95,7 +116,7 @@ class LiteDRAMNativePortECC(Module, AutoCSR):
# Cmd -------------------------------------------------------------------------------------- # Cmd --------------------------------------------------------------------------------------
self.comb += port_from.cmd.connect(port_to.cmd) self.comb += port_from.cmd.connect(port_to.cmd)
# Wdata (ecc encoding) --------------------------------------------------------------------- # Wdata (ECC) encoding) --------------------------------------------------------------------
ecc_wdata = LiteDRAMNativePortECCW(port_from.data_width, port_to.data_width) ecc_wdata = LiteDRAMNativePortECCW(port_from.data_width, port_to.data_width)
ecc_wdata = BufferizeEndpoints({"source": DIR_SOURCE})(ecc_wdata) ecc_wdata = BufferizeEndpoints({"source": DIR_SOURCE})(ecc_wdata)
self.submodules += ecc_wdata self.submodules += ecc_wdata
@ -106,7 +127,7 @@ class LiteDRAMNativePortECC(Module, AutoCSR):
if with_error_injection: if with_error_injection:
self.comb += port_to.wdata.data[:8].eq(self.flip.storage ^ ecc_wdata.source.data[:8]) self.comb += port_to.wdata.data[:8].eq(self.flip.storage ^ ecc_wdata.source.data[:8])
# Rdata (ecc decoding) --------------------------------------------------------------------- # Rdata (ECC decoding) ---------------------------------------------------------------------
sec = Signal() sec = Signal()
ded = Signal() ded = Signal()
ecc_rdata = LiteDRAMNativePortECCR(port_from.data_width, port_to.data_width) ecc_rdata = LiteDRAMNativePortECCR(port_from.data_width, port_to.data_width)