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:
parent
377d6fac6c
commit
c5d70114b5
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue