From 6f8f0d2346afe5194b690438bf784065e6bbf674 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 19 May 2020 15:49:25 +0200 Subject: [PATCH] litex_setup: add litehyperbus and remove hyperbus core/test. --- litex/soc/cores/hyperbus.py | 108 ------------------------------------ litex_setup.py | 1 + test/test_hyperbus.py | 83 --------------------------- 3 files changed, 1 insertion(+), 191 deletions(-) delete mode 100644 litex/soc/cores/hyperbus.py delete mode 100644 test/test_hyperbus.py diff --git a/litex/soc/cores/hyperbus.py b/litex/soc/cores/hyperbus.py deleted file mode 100644 index cfc813104..000000000 --- a/litex/soc/cores/hyperbus.py +++ /dev/null @@ -1,108 +0,0 @@ -# This file is Copyright (c) 2019 Antti Lukats -# This file is Copyright (c) 2019 Florent Kermarrec -# License: BSD - -from migen import * -from migen.genlib.misc import timeline - -from litex.build.io import DifferentialOutput - -from litex.soc.interconnect import wishbone - -# HyperRAM ----------------------------------------------------------------------------------------- - -class HyperRAM(Module): - """HyperRAM - - Provides a very simple/minimal HyperRAM core that should work with all FPGA/HyperRam chips: - - FPGA vendor agnostic. - - no setup/chip configuration (use default latency). - - This core favrors portability and ease of use over performance. - """ - def __init__(self, pads): - self.pads = pads - self.bus = bus = wishbone.Interface() - - # # # - - clk = Signal() - clk_phase = Signal(2) - cs = Signal() - ca = Signal(48) - sr = Signal(48) - dq = self.add_tristate(pads.dq) if not hasattr(pads.dq, "oe") else pads.dq - rwds = self.add_tristate(pads.rwds) if not hasattr(pads.rwds, "oe") else pads.rwds - - # Drive rst_n, cs_n, clk from internal signals --------------------------------------------- - if hasattr(pads, "rst_n"): - self.comb += pads.rst_n.eq(1) - self.comb += pads.cs_n[0].eq(~cs) - assert len(pads.cs_n) <= 2 - if len(pads.cs_n) == 2: - self.comb += pads.cs_n[1].eq(1) - if hasattr(pads, "clk"): - self.comb += pads.clk.eq(clk) - else: - self.specials += DifferentialOutput(clk, pads.clk_p, pads.clk_n) - - # Clock Generation (sys_clk/4) ------------------------------------------------------------- - self.sync += clk_phase.eq(clk_phase + 1) - cases = {} - cases[1] = clk.eq(cs) # Set pads clk on 90° (if cs is set) - cases[3] = clk.eq(0) # Clear pads clk on 270° - self.sync += Case(clk_phase, cases) - - # Data Shift Register (for write and read) ------------------------------------------------- - dqi = Signal(8) - self.sync += dqi.eq(dq.i) # Sample on 90° and 270° - cases = {} - cases[0] = sr.eq(Cat(dqi, sr[:-8])) # Shift on 0° - cases[2] = sr.eq(Cat(dqi, sr[:-8])) # Shift on 180° - self.sync += Case(clk_phase, cases) - self.comb += [ - bus.dat_r.eq(sr), # To Wisbone - dq.o.eq(sr[-8:]), # To HyperRAM - ] - - # Command generation ----------------------------------------------------------------------- - self.comb += [ - ca[47].eq(~self.bus.we), # R/W# - ca[45].eq(1), # Burst Type (Linear) - ca[16:35].eq(self.bus.adr[2:21]), # Row & Upper Column Address - ca[1:3].eq(self.bus.adr[0:2]), # Lower Column Address - ca[0].eq(0), # Lower Column Address - ] - - # Sequencer -------------------------------------------------------------------------------- - dt_seq = [ - # DT, Action - (3, []), - (12, [cs.eq(1), dq.oe.eq(1), sr.eq(ca)]), # Command: 6 clk - (44, [dq.oe.eq(0)]), # Latency(default): 2*6 clk - (2, [dq.oe.eq(self.bus.we), # Write/Read data byte: 2 clk - sr[:16].eq(0), - sr[16:].eq(self.bus.dat_w), - rwds.oe.eq(self.bus.we), - rwds.o.eq(~bus.sel[0])]), - (2, [rwds.o.eq(~bus.sel[1])]), # Write/Read data byte: 2 clk - (2, [rwds.o.eq(~bus.sel[2])]), # Write/Read data byte: 2 clk - (2, [rwds.o.eq(~bus.sel[3])]), # Write/Read data byte: 2 clk - (2, [cs.eq(0), rwds.oe.eq(0), dq.oe.eq(0)]), - (1, [bus.ack.eq(1)]), - (1, [bus.ack.eq(0)]), - (0, []), - ] - # Convert delta-time sequencer to time sequencer - t_seq = [] - t_seq_start = (clk_phase == 1) - t = 0 - for dt, a in dt_seq: - t_seq.append((t, a)) - t += dt - self.sync += timeline(bus.cyc & bus.stb & t_seq_start, t_seq) - - def add_tristate(self, pad): - t = TSTriple(len(pad)) - self.specials += t.get_tristate(pad) - return t diff --git a/litex_setup.py b/litex_setup.py index d8705e72e..85a6d5909 100755 --- a/litex_setup.py +++ b/litex_setup.py @@ -34,6 +34,7 @@ repos = [ ("litescope", ("https://github.com/enjoy-digital/", False, True, None)), ("litejesd204b", ("https://github.com/enjoy-digital/", False, True, None)), ("litespi", ("https://github.com/litex-hub/", False, True, None)), + ("litehyperbus", ("https://github.com/litex-hub/", False, True, None)), # LiteX boards support ("litex-boards", ("https://github.com/litex-hub/", False, True, None)), diff --git a/test/test_hyperbus.py b/test/test_hyperbus.py deleted file mode 100644 index b9209ad2d..000000000 --- a/test/test_hyperbus.py +++ /dev/null @@ -1,83 +0,0 @@ -# This file is Copyright (c) 2019 Florent Kermarrec -# License: BSD - -import unittest - -from migen import * - -from litex.soc.cores.hyperbus import HyperRAM - -def c2bool(c): - return {"-": 1, "_": 0}[c] - - -class Pads: pass - - -class HyperRamPads: - def __init__(self): - self.clk = Signal() - self.cs_n = Signal() - self.dq = Record([("oe", 1), ("o", 8), ("i", 8)]) - self.rwds = Record([("oe", 1), ("o", 1), ("i", 1)]) - - -class TestHyperBus(unittest.TestCase): - def test_hyperram_syntax(self): - pads = Record([("clk", 1), ("cs_n", 1), ("dq", 8), ("rwds", 1)]) - hyperram = HyperRAM(pads) - - pads = Record([("clk_p", 1), ("clk_n", 1), ("cs_n", 1), ("dq", 8), ("rwds", 1)]) - hyperram = HyperRAM(pads) - - def test_hyperram_write(self): - def fpga_gen(dut): - yield from dut.bus.write(0x1234, 0xdeadbeef) - yield - - def hyperram_gen(dut): - clk = "___--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_______" - cs_n = "--________________________________________________________________------" - dq_oe = "__------------____________________________________________--------______" - dq_o = "002000048d000000000000000000000000000000000000000000000000deadbeef000000" - rwds_oe = "__________________________________________________________--------______" - rwds_o = "________________________________________________________________________" - for i in range(3): - yield - for i in range(len(clk)): - self.assertEqual(c2bool(clk[i]), (yield dut.pads.clk)) - self.assertEqual(c2bool(cs_n[i]), (yield dut.pads.cs_n)) - self.assertEqual(c2bool(dq_oe[i]), (yield dut.pads.dq.oe)) - self.assertEqual(int(dq_o[2*(i//2):2*(i//2)+2], 16), (yield dut.pads.dq.o)) - self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) - self.assertEqual(c2bool(rwds_o[i]), (yield dut.pads.rwds.o)) - yield - - dut = HyperRAM(HyperRamPads()) - run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)]) - - def test_hyperram_read(self): - def fpga_gen(dut): - dat = yield from dut.bus.read(0x1234) - self.assertEqual(dat, 0xdeadbeef) - - def hyperram_gen(dut): - clk = "___--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_______" - cs_n = "--________________________________________________________________------" - dq_oe = "__------------__________________________________________________________" - dq_o = "00a000048d00000000000000000000000000000000000000000000000000000000000000" - dq_i = "0000000000000000000000000000000000000000000000000000000000deadbeef000000" - rwds_oe = "________________________________________________________________________" - for i in range(3): - yield - for i in range(len(clk)): - yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) - self.assertEqual(c2bool(clk[i]), (yield dut.pads.clk)) - self.assertEqual(c2bool(cs_n[i]), (yield dut.pads.cs_n)) - self.assertEqual(c2bool(dq_oe[i]), (yield dut.pads.dq.oe)) - self.assertEqual(int(dq_o[2*(i//2):2*(i//2)+2], 16), (yield dut.pads.dq.o)) - self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) - yield - - dut = HyperRAM(HyperRamPads()) - run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)])