From 461b076624ae497d49f4498922f3bdcd7e80995c Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sun, 16 Sep 2018 00:39:33 +0200 Subject: [PATCH] frontend/ecc: add ecc adapter --- litedram/frontend/ecc.py | 55 ++++++++++++++++++++++++++++++++++++++++ test/test_ecc.py | 12 +++++++++ 2 files changed, 67 insertions(+) diff --git a/litedram/frontend/ecc.py b/litedram/frontend/ecc.py index 4c098be..5ca9773 100644 --- a/litedram/frontend/ecc.py +++ b/litedram/frontend/ecc.py @@ -140,3 +140,58 @@ class ECCDecoder(SECDEC, Module): ) ) ] + + +class LiteDRAMNativePortECC(Module): + def __init__(self, port_from, port_to): + _ , n = compute_m_n(port_from.data_width//8) + assert port_to.data_width >= n + 1 + + self.clear_errors = clear_errors = Signal() + self.sec_errors = sec_errors = Signal(32) + self.dec_errors = dec_errors = Signal(32) + + # # # + + # cmd + self.comb += port_from.cmd.connect(port_to.cmd) + + # wdata (ecc encoding) + for i in range(8): + encoder = ECCEncoder(port_from.data_width//8) + self.submodules += encoder + self.comb += [ + port_from.wdata.connect(port_to.wdata, omit={"data", "we"}), + encoder.i.eq(port_from.wdata.data[i*port_from.data_width//8:(i+1)*port_from.data_width//8]), + port_to.wdata.data[i*port_to.data_width//8:(i+1)*port_to.data_width//8].eq(encoder.o) + ] + self.comb += port_to.wdata.we.eq(2**len(port_to.wdata.we)-1) # FIXME: how to handle we? + + # rdata (ecc decoding) + sec = Signal(8) + dec = Signal(8) + for i in range(8): + decoder = ECCDecoder(port_from.data_width//8) + self.submodules += decoder + self.comb += [ + port_to.rdata.connect(port_from.rdata, omit={"data", "we"}), + decoder.i.eq(port_to.rdata.data[i*port_to.data_width//8:(i+1)*port_to.data_width//8]), + port_from.rdata.data[i*port_from.data_width//8:(i+1)*port_from.data_width//8].eq(decoder.o), + sec[i].eq(decoder.sec), + dec[i].eq(decoder.dec) + ] + + # errors count + self.sync += [ + If(clear_errors, + sec_errors.eq(0), + dec_errors.eq(0) + ).Else( + If(sec_errors != (2**len(sec_errors) - 1), + If(sec != 0, sec_errors.eq(sec_errors + 1)) + ), + If(dec_errors != (2**len(dec_errors) - 1), + If(dec != 0, dec_errors.eq(dec_errors + 1)) + ) + ) + ] diff --git a/test/test_ecc.py b/test/test_ecc.py index c3aa62c..c560917 100644 --- a/test/test_ecc.py +++ b/test/test_ecc.py @@ -3,6 +3,7 @@ import random from migen import * +from litedram.common import * from litedram.frontend.ecc import * from litex.gen.sim import * @@ -93,3 +94,14 @@ class TestECC(unittest.TestCase): dut = DUT(k) run_simulation(dut, generator(dut, k, 128, i)) self.assertEqual(dut.errors, 0) + + def test_ecc_wrapper(self): + # 32 bits + 8 bits ecc + port_from = LiteDRAMNativePort("both", 24, 32*8) + port_to = LiteDRAMNativePort("both", 24, 40*8) + ecc = LiteDRAMNativePortECC(port_from, port_to) + + # 64 bits + 8 bits ecc + port_from = LiteDRAMNativePort("both", 24, 64*8) + port_to = LiteDRAMNativePort("both", 24, 72*8) + ecc = LiteDRAMNativePortECC(port_from, port_to)