# This file is Copyright (c) 2016-2019 Florent Kermarrec <florent@enjoy-digital.fr>
+# This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
# License: BSD
-from migen import *
+from nmigen import *
+from nmigen.compat import Case
-from litex.soc.interconnect import stream
-
-from litedram.common import *
+from gram.common import *
+import gram.stream as stream
# LiteDRAMNativePortCDC ----------------------------------------------------------------------------
-class LiteDRAMNativePortCDC(Module):
+class gramNativePortCDC(Elaboratable):
def __init__(self, port_from, port_to,
cmd_depth = 4,
wdata_depth = 16,
assert port_from.data_width == port_to.data_width
assert port_from.mode == port_to.mode
- address_width = port_from.address_width
- data_width = port_from.data_width
- mode = port_from.mode
- clock_domain_from = port_from.clock_domain
- clock_domain_to = port_to.clock_domain
+ self._port_from = port_from
+ self._port_to = port_to
+ self._cmd_depth = cmd_depth
+ self._wdata_depth = wdata_depth
+ self._rdata_depth = rdata_depth
+
+ def elaborate(self, platform):
+ m = Module()
- # # #
+ port_from = self._port_from
+ port_to = self._port_to
+ cmd_depth = self._cmd_depth
+ wdata_depth = self._wdata_depth
+ rdata_depth = self._rdata_depth
+
+ address_width = port_from.address_width
+ data_width = port_from.data_width
+ mode = port_from.mode
+ clock_domain_from = port_from.clock_domain
+ clock_domain_to = port_to.clock_domain
cmd_fifo = stream.AsyncFIFO(
[("we", 1), ("addr", address_width)], cmd_depth)
cmd_fifo = ClockDomainsRenamer(
{"write": clock_domain_from,
"read": clock_domain_to})(cmd_fifo)
- self.submodules += cmd_fifo
- self.submodules += stream.Pipeline(
+ m.submodules += cmd_fifo
+ m.submodules += stream.Pipeline(
port_from.cmd, cmd_fifo, port_to.cmd)
if mode == "write" or mode == "both":
wdata_fifo = ClockDomainsRenamer(
{"write": clock_domain_from,
"read": clock_domain_to})(wdata_fifo)
- self.submodules += wdata_fifo
- self.submodules += stream.Pipeline(
+ m.submodules += wdata_fifo
+ m.submodules += stream.Pipeline(
port_from.wdata, wdata_fifo, port_to.wdata)
if mode == "read" or mode == "both":
rdata_fifo = ClockDomainsRenamer(
{"write": clock_domain_to,
"read": clock_domain_from})(rdata_fifo)
- self.submodules += rdata_fifo
- self.submodules += stream.Pipeline(
+ m.submodules += rdata_fifo
+ m.submodules += stream.Pipeline(
port_to.rdata, rdata_fifo, port_from.rdata)
+ return m
+
# LiteDRAMNativePortDownConverter ------------------------------------------------------------------
-class LiteDRAMNativePortDownConverter(Module):
+class gramNativePortDownConverter(Elaboratable):
"""LiteDRAM port DownConverter
This module reduces user port data width to fit controller data width.
if port_from.data_width % port_to.data_width:
raise ValueError("Ratio must be an int")
- # # #
+ self._port_from = port_from
+ self._port_to = port_to
+ self._reverse = reverse
+
+ def elaborate(self, platform):
+ m = Module()
+
+ port_from = self._port_from
+ port_to = self._port_to
+ reverse = self._reverse
ratio = port_from.data_width//port_to.data_width
mode = port_from.mode
counter = Signal(max=ratio)
counter_reset = Signal()
counter_ce = Signal()
- self.sync += \
- If(counter_reset,
- counter.eq(0)
- ).Elif(counter_ce,
- counter.eq(counter + 1)
- )
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- counter_reset.eq(1),
- If(port_from.cmd.valid,
- NextState("CONVERT")
- )
- )
- fsm.act("CONVERT",
- port_to.cmd.valid.eq(1),
- port_to.cmd.we.eq(port_from.cmd.we),
- port_to.cmd.addr.eq(port_from.cmd.addr*ratio + counter),
- If(port_to.cmd.ready,
- counter_ce.eq(1),
- If(counter == ratio - 1,
- port_from.cmd.ready.eq(1),
- NextState("IDLE")
- )
- )
- )
+ with m.If(counter_reset):
+ m.d.sync += counter.eq(0)
+ with m.Elif(counter_ce):
+ m.d.sync += counter.eq(counter+1)
+
+ with m.FSM():
+ with m.State("Idle"):
+ m.d.comb += counter_reset.eq(1)
+ with m.If(port_from.cmd.valid):
+ m.next = "Convert"
+
+ with m.State("Convert"):
+ m.d.comb += [
+ port_to.cmd.valid.eq(1),
+ port_to.cmd.we.eq(port_from.cmd.we),
+ port_to.cmd.addr.eq(port_from.cmd.addr*ratio + counter),
+ ]
+ with m.If(port_to.cmd.ready):
+ m.d.comb += counter_ce.eq(1)
+ with m.If(counter == ratio - 1):
+ m.d.comb += port_from.cmd.ready.eq(1)
+ m.next = "Idle"
if mode == "write" or mode == "both":
wdata_converter = stream.StrideConverter(
port_from.wdata.description,
port_to.wdata.description,
reverse=reverse)
- self.submodules += wdata_converter
- self.submodules += stream.Pipeline(
+ m.submodules += wdata_converter
+ m.submodules += stream.Pipeline(
port_from.wdata, wdata_converter, port_to.wdata)
if mode == "read" or mode == "both":
port_to.rdata.description,
port_from.rdata.description,
reverse=reverse)
- self.submodules += rdata_converter
- self.submodules += stream.Pipeline(
+ m.submodules += rdata_converter
+ m.submodules += stream.Pipeline(
port_to.rdata, rdata_converter, port_from.rdata)
+ return m
+
# LiteDRAMNativeWritePortUpConverter ---------------------------------------------------------------
-class LiteDRAMNativeWritePortUpConverter(Module):
+class gramNativeWritePortUpConverter(Elaboratable):
# TODO: finish and remove hack
"""LiteDRAM write port UpConverter
if port_to.data_width % port_from.data_width:
raise ValueError("Ratio must be an int")
- # # #
+ self._port_from = port_from
+ self._port_to = port_to
+ self._reverse = reverse
+
+ def elaborate(self, platform):
+ m = Module()
+
+ port_from = self._port_from
+ port_to = self._port_to
+ reverse = self._reverse
ratio = port_to.data_width//port_from.data_width
counter.eq(counter + 1)
)
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- port_from.cmd.ready.eq(1),
- If(port_from.cmd.valid,
- counter_ce.eq(1),
- NextValue(we, port_from.cmd.we),
- NextValue(address, port_from.cmd.addr),
- NextState("RECEIVE")
- )
- )
- fsm.act("RECEIVE",
- port_from.cmd.ready.eq(1),
- If(port_from.cmd.valid,
- counter_ce.eq(1),
- If(counter == ratio-1,
- NextState("GENERATE")
- )
- )
- )
- fsm.act("GENERATE",
- port_to.cmd.valid.eq(1),
- port_to.cmd.we.eq(we),
- port_to.cmd.addr.eq(address[log2_int(ratio):]),
- If(port_to.cmd.ready,
- NextState("IDLE")
- )
- )
+ with m.FSM():
+ with m.State("Idle"):
+ m.d.comb += port_from.cmd.ready.eq(1)
+ with m.If(port_from.cmd.valid):
+ m.d.sync += [
+ we.eq(port_from.cmd.we),
+ address.eq(port_from.cmd.addr),
+ ]
+ m.next = "Receive"
+
+ with m.State("Receive"):
+ m.d.comb += port_from.cmd.ready.eq(1)
+ with m.If(port_from.cmd.valid):
+ m.d.comb += counter_ce.eq(1)
+ with m.If(counter == ratio-1):
+ m.next = "Generate"
+
+ with m.State("Generate"):
+ m.d.comb += [
+ port_to.cmd.valid.eq(1),
+ port_to.cmd.we.eq(we),
+ port_to.cmd.addr.eq(address[log2_int(ratio):]),
+ ]
+ with m.If(port_to.cmd.ready):
+ m.next = "Idle"
wdata_converter = stream.StrideConverter(
port_from.wdata.description,
port_to.wdata.description,
reverse=reverse)
- self.submodules += wdata_converter
- self.submodules += stream.Pipeline(
+ m.submodules += wdata_converter
+ m.submodules += stream.Pipeline(
port_from.wdata,
wdata_converter,
port_to.wdata)
+ return m
+
# LiteDRAMNativeReadPortUpConverter ----------------------------------------------------------------
-class LiteDRAMNativeReadPortUpConverter(Module):
+class gramNativeReadPortUpConverter(Elaboratable):
"""LiteDRAM port UpConverter
This module increase user port data width to fit controller data width.
if port_to.data_width % port_from.data_width:
raise ValueError("Ratio must be an int")
- # # #
+ self._port_from = port_from
+ self._port_to = port_to
+ self._reverse = reverse
- ratio = port_to.data_width//port_from.data_width
+ def elaborate(self, platform):
+ m = Module()
+ port_from = self._port_from
+ port_to = self._port_to
+ reverse = self._reverse
+
+ ratio = port_to.data_width//port_from.data_width
# Command ----------------------------------------------------------------------------------
cmd_buffer = stream.SyncFIFO([("sel", ratio)], 4)
- self.submodules += cmd_buffer
+ m.submodules += cmd_buffer
- counter = Signal(max=ratio)
+ counter = Signal(range(ratio))
counter_ce = Signal()
- self.sync += \
- If(counter_ce,
- counter.eq(counter + 1)
- )
+ with m.If(counter_ce):
+ m.d.sync += counter.eq(counter+1)
- self.comb += \
- If(port_from.cmd.valid,
- If(counter == 0,
+ with m.If(port_from.cmd.valid):
+ with m.If(counter == 0):
+ m.d.comb += [
port_to.cmd.valid.eq(1),
port_to.cmd.addr.eq(port_from.cmd.addr[log2_int(ratio):]),
port_from.cmd.ready.eq(port_to.cmd.ready),
- counter_ce.eq(port_to.cmd.ready)
- ).Else(
+ counter_ce.eq(port_to.cmd.ready),
+ ]
+ with m.Else():
+ m.d.comb += [
port_from.cmd.ready.eq(1),
- counter_ce.eq(1)
- )
- )
+ counter_ce.eq(1),
+ ]
# TODO: fix sel
- self.comb += \
- If(port_to.cmd.valid & port_to.cmd.ready,
+ with m.If(port_to.cmd.valid & port_to.cmd.ready):
+ m.d.comb += [
cmd_buffer.sink.valid.eq(1),
- cmd_buffer.sink.sel.eq(2**ratio-1)
- )
+ cmd_buffer.sink.sel.eq(2**ratio-1),
+ ]
# Datapath ---------------------------------------------------------------------------------
port_to.rdata.description,
port_from.rdata.description,
reverse=reverse)
- self.submodules += rdata_buffer, rdata_converter
+ m.submodules += rdata_buffer, rdata_converter
rdata_chunk = Signal(ratio, reset=1)
rdata_chunk_valid = Signal()
- self.sync += \
- If(rdata_converter.source.valid &
- rdata_converter.source.ready,
- rdata_chunk.eq(Cat(rdata_chunk[ratio-1], rdata_chunk[:ratio-1]))
- )
+ with m.If(rdata_converter.source.valid & rdata_converter.source.ready):
+ m.d.sync += rdata_chunk.eq(Cat(rdata_chunk[ratio-1], rdata_chunk[:ratio-1]))
- self.comb += [
+ m.d.comb += [
port_to.rdata.connect(rdata_buffer.sink),
rdata_buffer.source.connect(rdata_converter.sink),
rdata_chunk_valid.eq((cmd_buffer.source.sel & rdata_chunk) != 0),
- If(port_from.flush,
- rdata_converter.source.ready.eq(1)
- ).Elif(cmd_buffer.source.valid,
- If(rdata_chunk_valid,
+ cmd_buffer.source.ready.eq(rdata_converter.source.ready & rdata_chunk[ratio-1]),
+ ]
+
+ with m.If(port_from.flush):
+ m.d.comb += rdata_converter.source.ready.eq(1)
+ with m.Elif(cmd_buffer.source.valid):
+ with m.If(rdata_chunk_valid):
+ m.d.comb += [
port_from.rdata.valid.eq(rdata_converter.source.valid),
port_from.rdata.data.eq(rdata_converter.source.data),
- rdata_converter.source.ready.eq(port_from.rdata.ready)
- ).Else(
- rdata_converter.source.ready.eq(1)
- )
- ),
- cmd_buffer.source.ready.eq(
- rdata_converter.source.ready & rdata_chunk[ratio-1])
- ]
+ rdata_converter.source.ready.eq(port_from.rdata.ready),
+ ]
+ with m.Else():
+ m.d.comb += rdata_converter.source.ready.eq(1)
+
+ return m
# LiteDRAMNativePortConverter ----------------------------------------------------------------------
-class LiteDRAMNativePortConverter(Module):
+class LiteDRAMNativePortConverter(Elaboratable):
def __init__(self, port_from, port_to, reverse=False):
assert port_from.clock_domain == port_to.clock_domain
assert port_from.mode == port_to.mode
- # # #
+ self._port_from = port_from
+ self._port_to = port_to
+ self._reverse = reverse
+
+ def elaborate(self, platform):
+ m = Module()
+
+ port_from = self._port_from
+ port_to = self._port_to
+ reverse = self._reverse
mode = port_from.mode
if port_from.data_width > port_to.data_width:
- converter = LiteDRAMNativePortDownConverter(port_from, port_to, reverse)
- self.submodules += converter
+ converter = gramNativePortDownConverter(port_from, port_to, reverse)
+ m.submodules += converter
elif port_from.data_width < port_to.data_width:
if mode == "write":
- converter = LiteDRAMNativeWritePortUpConverter(port_from, port_to, reverse)
+ converter = gramNativeWritePortUpConverter(port_from, port_to, reverse)
elif mode == "read":
- converter = LiteDRAMNativeReadPortUpConverter(port_from, port_to, reverse)
+ converter = gramNativeReadPortUpConverter(port_from, port_to, reverse)
else:
raise NotImplementedError
- self.submodules += converter
+ m.submodules += converter
else:
- self.comb += [
+ m.d.comb += [
port_from.cmd.connect(port_to.cmd),
port_from.wdata.connect(port_to.wdata),
port_to.rdata.connect(port_from.rdata)
]
+
+ return m