soc/cores: add initial simple hyperram core

This commit is contained in:
Antti Lukats 2019-08-16 09:46:15 +02:00 committed by Florent Kermarrec
parent 6e6fe83af3
commit d1502d4195
1 changed files with 125 additions and 0 deletions

View File

@ -0,0 +1,125 @@
# This file is Copyright (c) 2019 Antti Lukats <antti.lukats@gmail.com>
# This file is Copyright (c) 2016-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
#
#
#
from migen import *
from migen.genlib.misc import timeline
from litex.gen import *
from litex.soc.interconnect import wishbone
from litex.soc.interconnect.csr import *
class HyperMemporyCommon(Module):
def __init__(self, pads):
self.pads = pads
class HyperRAM(HyperMemporyCommon):
def __init__(self, pads):
"""
HyperRAM simple core for LiteX
This core should always just work on any FPGA platorm it is fully vendor neutral
No configuration, no software setup, ready after poweron, fixed latency
"""
HyperMemporyCommon.__init__(self, pads)
if hasattr(pads, "rst_n"):
self.comb += pads.rst_n.eq(1)
if hasattr(pads, "cs1_n"):
self.comb += pads.cs1_n.eq(1)
# Tristate pads
dq = TSTriple(8)
self.specials.dq = dq.get_tristate(pads.dq)
rwds = TSTriple(1)
self.specials.rwds = rwds.get_tristate(pads.rwds)
# Wishbone
self.bus = bus = wishbone.Interface()
sr = Signal(48)
dq_oe = Signal(reset=0)
rwds_oe = Signal(reset=0)
cs_int = Signal(reset=1)
self.comb += [
bus.dat_r.eq(sr),
dq.oe.eq(dq_oe),
dq.o.eq(sr[-8:]),
rwds.oe.eq(rwds_oe),
pads.cs0_n.eq(cs_int)
]
# we generate complementaty clk out for emulated differential output
clk_p = Signal(1)
clk_n = Signal(1)
self.comb += pads.clk.eq(clk_p)
# if negative is defined drive complementary clock out
if hasattr(pads, "clk_n"):
self.comb += pads.clk_n.eq(clk_n)
# 1 sys clock delay needed to adjust input timings?
dqi = Signal(8)
self.sync += [
dqi.eq(dq.i)
]
# hyper RAM clock generator and 48 bit byte shifter
i = Signal(max=4)
self.sync += [
If(i == 0,
sr.eq(Cat(dqi, sr[:-8])),
),
If(i == 1,
clk_p.eq(~cs_int), # 1
clk_n.eq(cs_int) # 0
),
If(i == 2,
sr.eq(Cat(dqi, sr[:-8]))
),
If(i == 3,
i.eq(0),
clk_p.eq(0), # 1
clk_n.eq(1) # 0
).Else(
i.eq(i + 1)
)
]
# signals to use CA or data to write
CA = Signal(48)
# combine bits to create CA bytes
self.comb += [
CA[47].eq(~self.bus.we),
CA[45].eq(1),
CA[16:35].eq(self.bus.adr[2:21]),
CA[1:3].eq(self.bus.adr[0:2]),
CA[0].eq(0),
]
z = Replicate(0, 16)
seq = [
(3, []),
(12, [cs_int.eq(0), dq_oe.eq(1), sr.eq(CA)]), # 6 clock edges for command transmit
(44, [dq_oe.eq(0)]), # 6+6 latency default
(2, [dq_oe.eq(self.bus.we), rwds_oe.eq(self.bus.we), rwds.o.eq(~bus.sel[0]), sr.eq(Cat(z, self.bus.dat_w))]), # 4 edges to write data
(2, [rwds.o.eq(~bus.sel[1])]), # 4 edges to write data
(2, [rwds.o.eq(~bus.sel[2])]), # 4 edges to write data
(2, [rwds.o.eq(~bus.sel[3])]), # 4 edges to write data
(2, [cs_int.eq(1), rwds_oe.eq(0), dq_oe.eq(0)]),
(1, [bus.ack.eq(1)]), # is 1 also OK?
(1, [bus.ack.eq(0)]), #
(0, []),
]
t, tseq = 0, []
for dt, a in seq:
tseq.append((t, a))
t += dt
self.sync += timeline(bus.cyc & bus.stb & (i == 1), tseq)