Add an hacked no we memory for Efinix
Efinity synthesizer cannot infer RAM blocks with write enable. In order to workaround this (at least for the Litex SoC intergrated RAM/ROM) a dirty modified Memory class has been created. This class needs to be rewrite !
This commit is contained in:
parent
bd71dc663f
commit
b24475b07d
|
@ -0,0 +1,175 @@
|
|||
from migen.fhdl.structure import *
|
||||
from migen.fhdl.module import *
|
||||
from migen.fhdl.bitcontainer import bits_for
|
||||
from migen.fhdl.tools import *
|
||||
from migen.fhdl.tracer import get_obj_var_name
|
||||
from migen.fhdl.verilog import _printexpr as verilog_printexpr
|
||||
from migen.fhdl.specials import Special, _MemoryPort, _MemoryLocation
|
||||
|
||||
(READ_FIRST, WRITE_FIRST, NO_CHANGE) = range(3)
|
||||
|
||||
class Memory(Special):
|
||||
def __init__(self, width, depth, init=None, name=None):
|
||||
Special.__init__(self)
|
||||
self.width = width
|
||||
self.depth = depth
|
||||
self.ports = []
|
||||
self.init = init
|
||||
self.name_override = get_obj_var_name(name, "mem")
|
||||
|
||||
def __getitem__(self, index):
|
||||
# simulation only
|
||||
return _MemoryLocation(self, index)
|
||||
|
||||
def get_port(self, write_capable=False, async_read=False,
|
||||
has_re=False, we_granularity=0, mode=WRITE_FIRST,
|
||||
clock_domain="sys"):
|
||||
if we_granularity >= self.width:
|
||||
we_granularity = 0
|
||||
adr = Signal(max=self.depth)
|
||||
dat_r = Signal(self.width)
|
||||
if write_capable:
|
||||
if we_granularity:
|
||||
we = Signal(self.width//we_granularity)
|
||||
else:
|
||||
we = Signal()
|
||||
dat_w = Signal(self.width)
|
||||
else:
|
||||
we = None
|
||||
dat_w = None
|
||||
if has_re:
|
||||
re = Signal()
|
||||
else:
|
||||
re = None
|
||||
mp = _MemoryPort(adr, dat_r, we, dat_w,
|
||||
async_read, re, we_granularity, mode,
|
||||
clock_domain)
|
||||
self.ports.append(mp)
|
||||
return mp
|
||||
|
||||
@staticmethod
|
||||
def emit_verilog(memory, ns, add_data_file):
|
||||
r = ""
|
||||
def gn(e):
|
||||
if isinstance(e, Memory):
|
||||
return ns.get_name(e)
|
||||
else:
|
||||
return verilog_printexpr(ns, e)[0]
|
||||
adrbits = bits_for(memory.depth-1)
|
||||
|
||||
for i in range(memory.width // 8):
|
||||
r += "reg [" + str((memory.width//4)-1) + ":0] " \
|
||||
+ gn(memory) + '_' + str(i) \
|
||||
+ "[0:" + str(memory.depth-1) + "];\n"
|
||||
|
||||
adr_regs = {}
|
||||
data_regs = {}
|
||||
for port in memory.ports:
|
||||
if not port.async_read:
|
||||
if port.mode == WRITE_FIRST:
|
||||
adr_reg = Signal(name_override="memadr")
|
||||
r += "reg [" + str(adrbits-1) + ":0] " \
|
||||
+ gn(adr_reg) + ";\n"
|
||||
adr_regs[id(port)] = adr_reg
|
||||
else:
|
||||
data_reg = Signal(name_override="memdat")
|
||||
r += "reg [" + str(memory.width-1) + ":0] " \
|
||||
+ gn(data_reg) + ";\n"
|
||||
data_regs[id(port)] = data_reg
|
||||
|
||||
for port in memory.ports:
|
||||
r += "always @(posedge " + gn(port.clock) + ") begin\n"
|
||||
if port.we is not None:
|
||||
if port.we_granularity:
|
||||
n = memory.width//port.we_granularity
|
||||
for i in range(n):
|
||||
if (i > 0):
|
||||
r += "always @(posedge " + gn(port.clock) + ") begin\n"
|
||||
m = i*port.we_granularity
|
||||
M = (i+1)*port.we_granularity-1
|
||||
sl = "[" + str(M) + ":" + str(m) + "]"
|
||||
r += "\tif (" + gn(port.we) + "[" + str(i) + "])\n"
|
||||
r += "\t\t" + gn(memory) + '_' + str(i) + "[" + gn(port.adr) + "]" + " <= " + gn(port.dat_w) + sl + ";\n"
|
||||
r += "end\n"
|
||||
else:
|
||||
r += "\tif (" + gn(port.we) + ")\n"
|
||||
r += "\t\t" + gn(memory) + "[" + gn(port.adr) + "] <= " + gn(port.dat_w) + ";\n"
|
||||
if not port.async_read:
|
||||
if port.mode == WRITE_FIRST:
|
||||
r += "always @(posedge " + gn(port.clock) + ") begin\n"
|
||||
rd = "\t" + gn(adr_regs[id(port)]) + " <= " + gn(port.adr) + ";\n"
|
||||
else:
|
||||
bassign = ""
|
||||
for i in range(memory.width // 8):
|
||||
m = i*port.we_granularity
|
||||
M = (i+1)*port.we_granularity-1
|
||||
sl = "[" + str(M) + ":" + str(m) + "]"
|
||||
bassign += gn(data_regs[id(port)]) + sl + " <= " + gn(memory) + "_" + str(i) + "[" + gn(port.adr) + "];\n"
|
||||
if port.mode == READ_FIRST:
|
||||
rd = "\t" + bassign
|
||||
elif port.mode == NO_CHANGE:
|
||||
rd = "\tif (!" + gn(port.we) + ")\n" \
|
||||
+ "\t\t" + bassign
|
||||
if port.re is None:
|
||||
r += rd
|
||||
else:
|
||||
r += "\tif (" + gn(port.re) + ")\n"
|
||||
r += "\t" + rd.replace("\n\t", "\n\t\t")
|
||||
r += "end\n\n"
|
||||
|
||||
for port in memory.ports:
|
||||
if port.async_read:
|
||||
r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(port.adr) + "];\n"
|
||||
else:
|
||||
if port.mode == WRITE_FIRST:
|
||||
for i in range(memory.width // 8):
|
||||
m = i*port.we_granularity
|
||||
M = (i+1)*port.we_granularity-1
|
||||
sl = "[" + str(M) + ":" + str(m) + "]"
|
||||
r += "assign " + gn(port.dat_r) + sl + " = " + gn(memory) + "_" + str(i) + "[" + gn(adr_regs[id(port)]) + "];\n"
|
||||
else:
|
||||
r += "assign " + gn(port.dat_r) + " = " + gn(data_regs[id(port)]) + ";\n"
|
||||
r += "\n"
|
||||
|
||||
if memory.init is not None:
|
||||
content_7_0 = ""
|
||||
content_15_8 = ""
|
||||
content_23_16 = ""
|
||||
content_31_24 = ""
|
||||
formatter = "{:0" + str(int(memory.width / 4)) + "X}\n"
|
||||
|
||||
init_7_0 = []
|
||||
init_15_8 = []
|
||||
init_23_16 = []
|
||||
init_31_24 = []
|
||||
|
||||
for w in memory.init:
|
||||
init_7_0.append(w & 0xff)
|
||||
init_15_8.append((w >> 8) & 0xff)
|
||||
init_23_16.append((w >> 16) & 0xff)
|
||||
init_31_24.append((w >> 24) & 0xff)
|
||||
|
||||
for d in init_7_0:
|
||||
content_7_0 += formatter.format(d)
|
||||
|
||||
for d in init_15_8:
|
||||
content_15_8 += formatter.format(d)
|
||||
|
||||
for d in init_23_16:
|
||||
content_23_16 += formatter.format(d)
|
||||
|
||||
for d in init_31_24:
|
||||
content_31_24 += formatter.format(d)
|
||||
|
||||
memory_filename1 = add_data_file(gn(memory) + "1.init", content_7_0)
|
||||
memory_filename2 = add_data_file(gn(memory) + "2.init", content_15_8)
|
||||
memory_filename3 = add_data_file(gn(memory) + "3.init", content_23_16)
|
||||
memory_filename4 = add_data_file(gn(memory) + "4.init", content_31_24)
|
||||
r += "initial begin\n"
|
||||
r += "\t$readmemh(\"" + memory_filename1 + "\", " + gn(memory)+ "_0" + ");\n"
|
||||
r += "\t$readmemh(\"" + memory_filename2 + "\", " + gn(memory)+ "_1" + ");\n"
|
||||
r += "\t$readmemh(\"" + memory_filename3 + "\", " + gn(memory)+ "_2" + ");\n"
|
||||
r += "\t$readmemh(\"" + memory_filename4 + "\", " + gn(memory)+ "_3" + ");\n"
|
||||
r += "end\n\n"
|
||||
|
||||
return r
|
|
@ -815,7 +815,7 @@ class SoC(Module):
|
|||
self.check_if_exists(name)
|
||||
setattr(self.submodules, name, SoCController(**kwargs))
|
||||
|
||||
def add_ram(self, name, origin, size, contents=[], mode="rw"):
|
||||
def add_ram(self, name, origin, size, contents=[], mode="rw", no_we=False):
|
||||
ram_cls = {
|
||||
"wishbone": wishbone.SRAM,
|
||||
"axi-lite": axi.AXILiteSRAM,
|
||||
|
@ -825,7 +825,7 @@ class SoC(Module):
|
|||
"axi-lite": axi.AXILiteInterface,
|
||||
}[self.bus.standard]
|
||||
ram_bus = interface_cls(data_width=self.bus.data_width)
|
||||
ram = ram_cls(size, bus=ram_bus, init=contents, read_only=(mode == "r"))
|
||||
ram = ram_cls(size, bus=ram_bus, init=contents, read_only=(mode == "r"), no_we=no_we)
|
||||
self.bus.add_slave(name, ram.bus, SoCRegion(origin=origin, size=size, mode=mode))
|
||||
self.check_if_exists(name)
|
||||
self.logger.info("RAM {} {} {}.".format(
|
||||
|
@ -834,8 +834,8 @@ class SoC(Module):
|
|||
self.bus.regions[name]))
|
||||
setattr(self.submodules, name, ram)
|
||||
|
||||
def add_rom(self, name, origin, size, contents=[], mode="r"):
|
||||
self.add_ram(name, origin, size, contents, mode=mode)
|
||||
def add_rom(self, name, origin, size, contents=[], mode="r", no_we=False):
|
||||
self.add_ram(name, origin, size, contents, mode=mode, no_we=no_we)
|
||||
|
||||
def init_rom(self, name, contents=[], auto_size=True):
|
||||
self.logger.info("Initializing ROM {} with contents (Size: {}).".format(
|
||||
|
|
|
@ -79,10 +79,12 @@ class SoCCore(LiteXSoC):
|
|||
integrated_rom_size = 0,
|
||||
integrated_rom_mode = "r",
|
||||
integrated_rom_init = [],
|
||||
integrated_rom_no_we = False,
|
||||
|
||||
# SRAM parameters
|
||||
integrated_sram_size = 0x2000,
|
||||
integrated_sram_init = [],
|
||||
integrated_sram_no_we = False,
|
||||
|
||||
# MAIN_RAM parameters
|
||||
integrated_main_ram_size = 0,
|
||||
|
@ -197,11 +199,11 @@ class SoCCore(LiteXSoC):
|
|||
|
||||
# Add integrated ROM
|
||||
if integrated_rom_size:
|
||||
self.add_rom("rom", self.cpu.reset_address, integrated_rom_size, integrated_rom_init, integrated_rom_mode)
|
||||
self.add_rom("rom", self.cpu.reset_address, integrated_rom_size, integrated_rom_init, integrated_rom_mode, no_we=integrated_rom_no_we)
|
||||
|
||||
# Add integrated SRAM
|
||||
if integrated_sram_size:
|
||||
self.add_ram("sram", self.mem_map["sram"], integrated_sram_size)
|
||||
self.add_ram("sram", self.mem_map["sram"], integrated_sram_size, no_we=integrated_sram_no_we)
|
||||
|
||||
# Add integrated MAIN_RAM (only useful when no external SRAM/SDRAM is available)
|
||||
if integrated_main_ram_size:
|
||||
|
|
|
@ -783,7 +783,7 @@ class AXILite2CSR(Module):
|
|||
# AXILite SRAM -------------------------------------------------------------------------------------
|
||||
|
||||
class AXILiteSRAM(Module):
|
||||
def __init__(self, mem_or_size, read_only=None, init=None, bus=None):
|
||||
def __init__(self, mem_or_size, read_only=None, init=None, bus=None, no_we=False):
|
||||
if bus is None:
|
||||
bus = AXILiteInterface()
|
||||
self.bus = bus
|
||||
|
|
|
@ -329,7 +329,7 @@ class Converter(Module):
|
|||
# Wishbone SRAM ------------------------------------------------------------------------------------
|
||||
|
||||
class SRAM(Module):
|
||||
def __init__(self, mem_or_size, read_only=None, init=None, bus=None):
|
||||
def __init__(self, mem_or_size, read_only=None, init=None, bus=None, no_we=False):
|
||||
if bus is None:
|
||||
bus = Interface()
|
||||
self.bus = bus
|
||||
|
@ -337,8 +337,13 @@ class SRAM(Module):
|
|||
if isinstance(mem_or_size, Memory):
|
||||
assert(mem_or_size.width <= bus_data_width)
|
||||
self.mem = mem_or_size
|
||||
else:
|
||||
if no_we:
|
||||
from litex.gen.fhdl.memory import Memory as NoWeMemory
|
||||
self.mem = NoWeMemory(bus_data_width, mem_or_size//(bus_data_width//8), init=init)
|
||||
else:
|
||||
self.mem = Memory(bus_data_width, mem_or_size//(bus_data_width//8), init=init)
|
||||
|
||||
if read_only is None:
|
||||
if hasattr(self.mem, "bus_read_only"):
|
||||
read_only = self.mem.bus_read_only
|
||||
|
|
Loading…
Reference in New Issue