mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
Merge branch 'master' of https://github.com/enjoy-digital/litex
This commit is contained in:
commit
c780fb22b7
29 changed files with 633 additions and 390 deletions
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
Unless otherwise noted, LiteX is copyright (C) 2012-2018 Florent Kermarrec.
|
||||
Unless otherwise noted, LiteX is copyright (C) 2012-2019 Florent Kermarrec.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
|
2
README
2
README
|
@ -5,7 +5,7 @@
|
|||
Migen inside
|
||||
|
||||
Build your hardware, easily!
|
||||
Copyright 2012-2018 / EnjoyDigital
|
||||
Copyright 2012-2019 / EnjoyDigital
|
||||
|
||||
[> Intro
|
||||
--------
|
||||
|
|
|
@ -14,6 +14,9 @@ from litex.soc.integration.builder import *
|
|||
from litedram.modules import EDY4016A
|
||||
from litedram.phy import usddrphy
|
||||
|
||||
from liteeth.phy.ku_1000basex import KU_1000BASEX
|
||||
from liteeth.core.mac import LiteEthMAC
|
||||
|
||||
# CRG ----------------------------------------------------------------------------------------------
|
||||
|
||||
class _CRG(Module):
|
||||
|
@ -92,15 +95,61 @@ class BaseSoC(SoCSDRAM):
|
|||
sdram_module.geom_settings,
|
||||
sdram_module.timing_settings)
|
||||
|
||||
|
||||
# EthernetSoC ------------------------------------------------------------------------------------------
|
||||
|
||||
class EthernetSoC(BaseSoC):
|
||||
csr_map = {
|
||||
"ethphy": 18,
|
||||
"ethmac": 19
|
||||
}
|
||||
csr_map.update(BaseSoC.csr_map)
|
||||
|
||||
interrupt_map = {
|
||||
"ethmac": 3,
|
||||
}
|
||||
interrupt_map.update(BaseSoC.interrupt_map)
|
||||
|
||||
mem_map = {
|
||||
"ethmac": 0x30000000, # (shadow @0xb0000000)
|
||||
}
|
||||
mem_map.update(BaseSoC.mem_map)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
BaseSoC.__init__(self, **kwargs)
|
||||
|
||||
self.comb += self.platform.request("sfp_tx_disable_n", 0).eq(1)
|
||||
self.submodules.ethphy = KU_1000BASEX(self.crg.cd_clk200.clk,
|
||||
self.platform.request("sfp", 0), sys_clk_freq=self.clk_freq)
|
||||
self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32,
|
||||
interface="wishbone", endianness=self.cpu.endianness)
|
||||
self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus)
|
||||
self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000)
|
||||
|
||||
self.crg.cd_sys.clk.attr.add("keep")
|
||||
self.ethphy.cd_eth_rx.clk.attr.add("keep")
|
||||
self.ethphy.cd_eth_tx.clk.attr.add("keep")
|
||||
self.platform.add_period_constraint(self.ethphy.cd_eth_rx.clk, 1e9/125e6)
|
||||
self.platform.add_period_constraint(self.ethphy.cd_eth_tx.clk, 1e9/125e6)
|
||||
self.platform.add_false_path_constraints(
|
||||
self.crg.cd_sys.clk,
|
||||
self.ethphy.cd_eth_rx.clk,
|
||||
self.ethphy.cd_eth_tx.clk)
|
||||
|
||||
self.platform.add_platform_command("set_property SEVERITY {{Warning}} [get_drc_checks REQP-1753]")
|
||||
|
||||
# Build --------------------------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="LiteX SoC on KCU105")
|
||||
builder_args(parser)
|
||||
soc_sdram_args(parser)
|
||||
parser.add_argument("--with-ethernet", action="store_true",
|
||||
help="enable Ethernet support")
|
||||
args = parser.parse_args()
|
||||
|
||||
soc = BaseSoC(**soc_sdram_argdict(args))
|
||||
cls = EthernetSoC if args.with_ethernet else BaseSoC
|
||||
soc = cls(**soc_sdram_argdict(args))
|
||||
builder = Builder(soc, **builder_argdict(args))
|
||||
builder.build()
|
||||
|
||||
|
|
|
@ -13,7 +13,10 @@ from litex.soc.integration.soc_sdram import *
|
|||
from litex.soc.integration.builder import *
|
||||
|
||||
from litedram.modules import MT41K64M16
|
||||
from litedram.phy import ECP5DDRPHY, ECP5DDRPHYInit
|
||||
from litedram.phy import ECP5DDRPHY
|
||||
|
||||
from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII
|
||||
from liteeth.core.mac import LiteEthMAC
|
||||
|
||||
# CRG ----------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -70,7 +73,7 @@ class BaseSoC(SoCSDRAM):
|
|||
csr_map.update(SoCSDRAM.csr_map)
|
||||
def __init__(self, toolchain="diamond", **kwargs):
|
||||
platform = versa_ecp5.Platform(toolchain=toolchain)
|
||||
sys_clk_freq = int(50e6)
|
||||
sys_clk_freq = int(75e6)
|
||||
SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
|
||||
integrated_rom_size=0x8000,
|
||||
**kwargs)
|
||||
|
@ -84,24 +87,61 @@ class BaseSoC(SoCSDRAM):
|
|||
platform.request("ddram"),
|
||||
sys_clk_freq=sys_clk_freq)
|
||||
self.add_constant("ECP5DDRPHY", None)
|
||||
ddrphy_init = ECP5DDRPHYInit(self.crg, self.ddrphy)
|
||||
self.submodules += ddrphy_init
|
||||
self.comb += crg.stop.eq(self.ddrphy.init.stop)
|
||||
sdram_module = MT41K64M16(sys_clk_freq, "1:2")
|
||||
self.register_sdram(self.ddrphy,
|
||||
sdram_module.geom_settings,
|
||||
sdram_module.timing_settings)
|
||||
|
||||
# EthernetSoC --------------------------------------------------------------------------------------
|
||||
|
||||
class EthernetSoC(BaseSoC):
|
||||
csr_map = {
|
||||
"ethphy": 18,
|
||||
"ethmac": 19
|
||||
}
|
||||
csr_map.update(BaseSoC.csr_map)
|
||||
|
||||
interrupt_map = {
|
||||
"ethmac": 3,
|
||||
}
|
||||
interrupt_map.update(BaseSoC.interrupt_map)
|
||||
|
||||
mem_map = {
|
||||
"ethmac": 0x30000000, # (shadow @0xb0000000)
|
||||
}
|
||||
mem_map.update(BaseSoC.mem_map)
|
||||
|
||||
def __init__(self, toolchain="diamond", **kwargs):
|
||||
BaseSoC.__init__(self, toolchain=toolchain, **kwargs)
|
||||
|
||||
self.submodules.ethphy = LiteEthPHYRGMII(
|
||||
self.platform.request("eth_clocks"),
|
||||
self.platform.request("eth"))
|
||||
self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32,
|
||||
interface="wishbone", endianness=self.cpu.endianness)
|
||||
self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus)
|
||||
self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000)
|
||||
|
||||
self.ethphy.crg.cd_eth_rx.clk.attr.add("keep")
|
||||
self.ethphy.crg.cd_eth_tx.clk.attr.add("keep")
|
||||
self.platform.add_period_constraint(self.ethphy.crg.cd_eth_rx.clk, 1e9/125e6)
|
||||
self.platform.add_period_constraint(self.ethphy.crg.cd_eth_tx.clk, 1e9/125e6)
|
||||
|
||||
# Build --------------------------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="LiteX SoC on ECP5")
|
||||
parser = argparse.ArgumentParser(description="LiteX SoC on Versa ECP5")
|
||||
parser.add_argument("--gateware-toolchain", dest="toolchain", default="diamond",
|
||||
help='gateware toolchain to use, diamond (default) or trellis')
|
||||
builder_args(parser)
|
||||
soc_sdram_args(parser)
|
||||
parser.add_argument("--with-ethernet", action="store_true",
|
||||
help="enable Ethernet support")
|
||||
args = parser.parse_args()
|
||||
|
||||
soc = BaseSoC(toolchain=args.toolchain, **soc_sdram_argdict(args))
|
||||
cls = EthernetSoC if args.with_ethernet else BaseSoC
|
||||
soc = cls(args.toolchain, **soc_sdram_argdict(args))
|
||||
builder = Builder(soc, **builder_argdict(args))
|
||||
builder.build()
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from migen.fhdl.module import Module
|
||||
from migen.fhdl.specials import Instance
|
||||
from migen.genlib.io import DifferentialInput, DifferentialOutput
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
|
||||
from migen.fhdl.structure import *
|
||||
|
||||
|
||||
class AlteraDifferentialInputImpl(Module):
|
||||
|
@ -32,8 +35,29 @@ class AlteraDifferentialOutput:
|
|||
def lower(dr):
|
||||
return AlteraDifferentialOutputImpl(dr.i, dr.o_p, dr.o_n)
|
||||
|
||||
class AlteraAsyncResetSynchronizerImpl(Module):
|
||||
def __init__(self, cd, async_reset):
|
||||
if not hasattr(async_reset, "attr"):
|
||||
i, async_reset = async_reset, Signal()
|
||||
self.comb += async_reset.eq(i)
|
||||
rst_meta = Signal()
|
||||
self.specials += [
|
||||
Instance("DFF", i_d=0, i_clk=cd.clk, i_clrn=1,
|
||||
i_prn=async_reset, o_q=rst_meta,
|
||||
attr={"async_reg", "ars_ff1"}),
|
||||
Instance("DFF", i_d=rst_meta, i_clk=cd.clk, i_clrn=1,
|
||||
i_prn=async_reset, o_q=cd.rst,
|
||||
attr={"async_reg", "ars_ff2"})
|
||||
]
|
||||
|
||||
class AlteraAsyncResetSynchronizer:
|
||||
@staticmethod
|
||||
def lower(dr):
|
||||
return AlteraAsyncResetSynchronizerImpl(dr.cd, dr.async_reset)
|
||||
|
||||
|
||||
altera_special_overrides = {
|
||||
DifferentialInput: AlteraDifferentialInput,
|
||||
DifferentialOutput: AlteraDifferentialOutput
|
||||
DifferentialOutput: AlteraDifferentialOutput,
|
||||
AsyncResetSynchronizer: AlteraAsyncResetSynchronizer
|
||||
}
|
||||
|
|
|
@ -25,3 +25,10 @@ class AlteraPlatform(GenericPlatform):
|
|||
if hasattr(clk, "p"):
|
||||
clk = clk.p
|
||||
self.toolchain.add_period_constraint(self, clk, period)
|
||||
|
||||
def add_false_path_constraint(self, from_, to):
|
||||
if hasattr(from_, "p"):
|
||||
from_ = from_.p
|
||||
if hasattr(to, "p"):
|
||||
to = to.p
|
||||
self.toolchain.add_false_path_constraint(self, from_, to)
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
# This file is Copyright (c) 2013 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# This file is Copyright (c) 2013-2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# License: BSD
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import math
|
||||
|
||||
from migen.fhdl.structure import _Fragment
|
||||
|
||||
|
@ -50,7 +51,7 @@ def _format_qsf(signame, pin, others, resname):
|
|||
return '\n'.join(fmt_c)
|
||||
|
||||
|
||||
def _build_qsf(named_sc, named_pc):
|
||||
def _build_qsf(named_sc, named_pc, build_name):
|
||||
lines = []
|
||||
for sig, pins, others, resname in named_sc:
|
||||
if len(pins) > 1:
|
||||
|
@ -64,10 +65,27 @@ def _build_qsf(named_sc, named_pc):
|
|||
lines.append("")
|
||||
lines.append("\n\n".join(named_pc))
|
||||
|
||||
lines.append("set_global_assignment -name top_level_entity top")
|
||||
# Set top level name to "build_name" in .qsf file instead always use "top" name
|
||||
lines.append("set_global_assignment -name top_level_entity " + build_name)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def _build_sdc(clocks, false_paths, vns, build_name):
|
||||
lines = []
|
||||
for clk, period in sorted(clocks.items(), key=lambda x: x[0].duid):
|
||||
lines.append(
|
||||
"create_clock -name {clk} -period ".format(clk=vns.get_name(clk)) + str(period) +
|
||||
" [get_ports {{{clk}}}]".format(clk=vns.get_name(clk)))
|
||||
for from_, to in sorted(false_paths,
|
||||
key=lambda x: (x[0].duid, x[1].duid)):
|
||||
lines.append(
|
||||
"set_false_path "
|
||||
"-from [get_clocks {{{from_}}}] "
|
||||
"-to [get_clocks {{{to}}}]".format(
|
||||
from_=vns.get_name(from_), to=vns.get_name(to)))
|
||||
tools.write_to_file("{}.sdc".format(build_name), "\n".join(lines))
|
||||
|
||||
|
||||
def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name):
|
||||
lines = []
|
||||
for filename, language, library in sources:
|
||||
|
@ -81,12 +99,13 @@ def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name):
|
|||
lang=language.upper(),
|
||||
path=filename.replace("\\", "/"),
|
||||
lib=library))
|
||||
lines.append("set_global_assignment -name SDC_FILE {}.sdc".format(build_name))
|
||||
|
||||
for path in vincpaths:
|
||||
lines.append("set_global_assignment -name SEARCH_PATH {}".format(
|
||||
path.replace("\\", "/")))
|
||||
|
||||
lines.append(_build_qsf(named_sc, named_pc))
|
||||
lines.append(_build_qsf(named_sc, named_pc, build_name))
|
||||
lines.append("set_global_assignment -name DEVICE {}".format(device))
|
||||
tools.write_to_file("{}.qsf".format(build_name), "\n".join(lines))
|
||||
|
||||
|
@ -116,6 +135,10 @@ fi
|
|||
|
||||
|
||||
class AlteraQuartusToolchain:
|
||||
def __init__(self):
|
||||
self.clocks = dict()
|
||||
self.false_paths = set()
|
||||
|
||||
def build(self, platform, fragment, build_dir="build", build_name="top",
|
||||
toolchain_path=None, run=True, **kwargs):
|
||||
if toolchain_path is None:
|
||||
|
@ -139,6 +162,8 @@ class AlteraQuartusToolchain:
|
|||
named_sc,
|
||||
named_pc,
|
||||
build_name)
|
||||
|
||||
_build_sdc(self.clocks, self.false_paths, v_output.ns, build_name)
|
||||
if run:
|
||||
_run_quartus(build_name, toolchain_path)
|
||||
|
||||
|
@ -147,12 +172,11 @@ class AlteraQuartusToolchain:
|
|||
return v_output.ns
|
||||
|
||||
def add_period_constraint(self, platform, clk, period):
|
||||
# TODO: handle differential clk
|
||||
platform.add_platform_command(
|
||||
"set_global_assignment -name duty_cycle 50 -section_id {clk}",
|
||||
clk=clk)
|
||||
platform.add_platform_command(
|
||||
"set_global_assignment -name fmax_requirement \"{freq} MHz\" "
|
||||
"-section_id {clk}".format(freq=(1. / period) * 1000,
|
||||
clk="{clk}"),
|
||||
clk=clk)
|
||||
if clk in self.clocks:
|
||||
raise ValueError("A period constraint already exists")
|
||||
period = math.floor(period*1e3)/1e3 # round to lowest picosecond
|
||||
self.clocks[clk] = period
|
||||
|
||||
def add_false_path_constraint(self, platform, from_, to):
|
||||
if (to, from_) not in self.false_paths:
|
||||
self.false_paths.add((from_, to))
|
||||
|
|
|
@ -143,7 +143,7 @@ class LatticeTrellisToolchain:
|
|||
self.build_template = [
|
||||
"yosys -q -l {build_name}.rpt {build_name}.ys",
|
||||
"nextpnr-ecp5 --json {build_name}.json --lpf {build_name}.lpf --textcfg {build_name}.config --{architecture} --package {package} --freq {freq_constraint}",
|
||||
"ecppack {build_name}.config {build_name}.bit"
|
||||
"ecppack {build_name}.config --svf {build_name}.svf --bit {build_name}.bit"
|
||||
]
|
||||
|
||||
self.freq_constraints = dict()
|
||||
|
|
|
@ -23,6 +23,8 @@ def _format_io_constraint(c):
|
|||
elif isinstance(c, IOStandard):
|
||||
return "-io_std {} ".format(c.name)
|
||||
elif isinstance(c, Misc):
|
||||
return "-RES_PULL {} ".format(c.misc)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
|
@ -183,7 +185,10 @@ def _build_script(build_name, device, toolchain_path, ver=None):
|
|||
copy_stmt = "copy"
|
||||
fail_stmt = " || exit /b"
|
||||
else:
|
||||
raise NotImplementedError
|
||||
script_ext = ".sh"
|
||||
build_script_contents = "# Autogenerated by Migen\n\n"
|
||||
copy_stmt = "cp"
|
||||
fail_stmt = " || exit 1"
|
||||
|
||||
build_script_file = "build_" + build_name + script_ext
|
||||
tools.write_to_file(build_script_file, build_script_contents,
|
||||
|
|
|
@ -203,7 +203,7 @@ static void cb(int sock, short which, void *arg)
|
|||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
void *vdut=NULL;
|
||||
struct timeval tv;
|
||||
|
@ -224,6 +224,7 @@ int main()
|
|||
goto out;
|
||||
}
|
||||
|
||||
litex_sim_init_cmdargs(argc, argv);
|
||||
if(RC_OK != (ret = litex_sim_initialize_all(&vdut, base)))
|
||||
{
|
||||
goto out;
|
||||
|
|
|
@ -17,6 +17,11 @@ extern "C" void litex_sim_eval(void *vdut)
|
|||
dut->eval();
|
||||
}
|
||||
|
||||
extern "C" void litex_sim_init_cmdargs(int argc, char *argv[])
|
||||
{
|
||||
Verilated::commandArgs(argc, argv);
|
||||
}
|
||||
|
||||
extern "C" void litex_sim_init_tracer(void *vdut)
|
||||
{
|
||||
Vdut *dut = (Vdut*)vdut;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define __VERIL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" void litex_sim_init_cmdargs(int argc, char *argv[]);
|
||||
extern "C" void litex_sim_eval(void *vdut);
|
||||
extern "C" void litex_sim_init_tracer(void *vdut);
|
||||
extern "C" void litex_sim_tracer_dump();
|
||||
|
|
|
@ -265,7 +265,7 @@ setattr -set keep 1 a:async_reg=true
|
|||
|
||||
synth_xilinx -top top
|
||||
|
||||
write_edif -attrprop {build_name}.edif
|
||||
write_edif -pvector bra -attrprop {build_name}.edif
|
||||
""".format(build_name=build_name)
|
||||
|
||||
ys_name = build_name + ".ys"
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# This file is Copyright (c) 2014 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# This file is Copyright (c) 2014-2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# License: BSD
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import math
|
||||
|
||||
from migen.fhdl.structure import _Fragment
|
||||
|
||||
|
@ -117,6 +118,7 @@ class XilinxVivadoToolchain:
|
|||
for filename, language, library in sources:
|
||||
filename_tcl = "{" + filename + "}"
|
||||
tcl.append("add_files " + filename_tcl)
|
||||
if language == "vhdl":
|
||||
tcl.append("set_property library {} [get_files {}]"
|
||||
.format(library, filename_tcl))
|
||||
for filename in edifs:
|
||||
|
@ -196,23 +198,23 @@ class XilinxVivadoToolchain:
|
|||
# The asynchronous input to a MultiReg is a false path
|
||||
platform.add_platform_command(
|
||||
"set_false_path -quiet "
|
||||
"-to [get_nets -filter {{mr_ff == TRUE}}]"
|
||||
"-to [get_nets -quiet -filter {{mr_ff == TRUE}}]"
|
||||
)
|
||||
# The asychronous reset input to the AsyncResetSynchronizer is a false
|
||||
# path
|
||||
platform.add_platform_command(
|
||||
"set_false_path -quiet "
|
||||
"-to [get_pins -filter {{REF_PIN_NAME == PRE}} "
|
||||
"-of [get_cells -filter {{ars_ff1 == TRUE || ars_ff2 == TRUE}}]]"
|
||||
"-to [get_pins -quiet -filter {{REF_PIN_NAME == PRE}} "
|
||||
"-of [get_cells -quiet -filter {{ars_ff1 == TRUE || ars_ff2 == TRUE}}]]"
|
||||
)
|
||||
# clock_period-2ns to resolve metastability on the wire between the
|
||||
# AsyncResetSynchronizer FFs
|
||||
platform.add_platform_command(
|
||||
"set_max_delay 2 -quiet "
|
||||
"-from [get_pins -filter {{REF_PIN_NAME == Q}} "
|
||||
"-of [get_cells -filter {{ars_ff1 == TRUE}}]] "
|
||||
"-to [get_pins -filter {{REF_PIN_NAME == D}} "
|
||||
"-of [get_cells -filter {{ars_ff2 == TRUE}}]]"
|
||||
"-from [get_pins -quiet -filter {{REF_PIN_NAME == Q}} "
|
||||
"-of [get_cells -quiet -filter {{ars_ff1 == TRUE}}]] "
|
||||
"-to [get_pins -quiet -filter {{REF_PIN_NAME == D}} "
|
||||
"-of [get_cells -quiet -filter {{ars_ff2 == TRUE}}]]"
|
||||
)
|
||||
|
||||
def build(self, platform, fragment, build_dir="build", build_name="top",
|
||||
|
@ -250,6 +252,7 @@ class XilinxVivadoToolchain:
|
|||
def add_period_constraint(self, platform, clk, period):
|
||||
if clk in self.clocks:
|
||||
raise ValueError("A period constraint already exists")
|
||||
period = math.floor(period*1e3)/1e3 # round to lowest picosecond
|
||||
self.clocks[clk] = period
|
||||
|
||||
def add_false_path_constraint(self, platform, from_, to):
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
"""
|
||||
Clock Abstraction Modules
|
||||
|
||||
|
||||
Made in Paris-CDG while waiting a delayed Air-France KLM flight...
|
||||
"""
|
||||
"""Clock Abstraction Modules"""
|
||||
|
||||
from migen import *
|
||||
from migen.genlib.io import DifferentialInput
|
||||
|
@ -15,13 +10,14 @@ from litex.soc.interconnect.csr import *
|
|||
def period_ns(freq):
|
||||
return 1e9/freq
|
||||
|
||||
# Xilinx / 7-Series
|
||||
# Xilinx / 7-Series --------------------------------------------------------------------------------
|
||||
|
||||
class S7Clocking(Module, AutoCSR):
|
||||
clkfbout_mult_frange = (2, 64+1)
|
||||
clkout_divide_range = (1, 128+1)
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, vco_margin=0):
|
||||
self.vco_margin = vco_margin
|
||||
self.reset = Signal()
|
||||
self.locked = Signal()
|
||||
self.clkin_freq = None
|
||||
|
@ -62,12 +58,14 @@ class S7Clocking(Module, AutoCSR):
|
|||
|
||||
def compute_config(self):
|
||||
config = {}
|
||||
config["divclk_divide"] = 1
|
||||
for divclk_divide in range(*self.divclk_divide_range):
|
||||
config["divclk_divide"] = divclk_divide
|
||||
for clkfbout_mult in range(*self.clkfbout_mult_frange):
|
||||
all_valid = True
|
||||
vco_freq = self.clkin_freq*clkfbout_mult
|
||||
vco_freq = self.clkin_freq*clkfbout_mult/divclk_divide
|
||||
(vco_freq_min, vco_freq_max) = self.vco_freq_range
|
||||
if vco_freq >= vco_freq_min and vco_freq <= vco_freq_max:
|
||||
if (vco_freq >= vco_freq_min*(1 + self.vco_margin) and
|
||||
vco_freq <= vco_freq_max*(1 - self.vco_margin)):
|
||||
for n, (clk, f, p, m) in sorted(self.clkouts.items()):
|
||||
valid = False
|
||||
for d in range(*self.clkout_divide_range):
|
||||
|
@ -127,6 +125,7 @@ class S7PLL(S7Clocking):
|
|||
|
||||
def __init__(self, speedgrade=-1):
|
||||
S7Clocking.__init__(self)
|
||||
self.divclk_divide_range = (1, 56+1)
|
||||
self.vco_freq_range = {
|
||||
-1: (800e6, 2133e6),
|
||||
-2: (800e6, 1866e6),
|
||||
|
@ -157,6 +156,7 @@ class S7MMCM(S7Clocking):
|
|||
|
||||
def __init__(self, speedgrade=-1):
|
||||
S7Clocking.__init__(self)
|
||||
self.divclk_divide_range = (1, 106+1)
|
||||
self.clkin_freq_range = {
|
||||
-1: (10e6, 800e6),
|
||||
-2: (10e6, 933e6),
|
||||
|
@ -204,7 +204,7 @@ class S7IDELAYCTRL(Module):
|
|||
)
|
||||
self.specials += Instance("IDELAYCTRL", i_REFCLK=cd.clk, i_RST=ic_reset)
|
||||
|
||||
# Xilinx / Ultrascale
|
||||
# Xilinx / Ultrascale ------------------------------------------------------------------------------
|
||||
|
||||
# TODO:
|
||||
# - use Ultrascale primitives instead of 7-Series' ones. (Vivado recognize and convert them).
|
||||
|
@ -213,7 +213,8 @@ class USClocking(Module, AutoCSR):
|
|||
clkfbout_mult_frange = (2, 64+1)
|
||||
clkout_divide_range = (1, 128+1)
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, vco_margin=0):
|
||||
self.vco_margin = vco_margin
|
||||
self.reset = Signal()
|
||||
self.locked = Signal()
|
||||
self.clkin_freq = None
|
||||
|
@ -254,12 +255,14 @@ class USClocking(Module, AutoCSR):
|
|||
|
||||
def compute_config(self):
|
||||
config = {}
|
||||
config["divclk_divide"] = 1
|
||||
for divclk_divide in range(*self.divclk_divide_range):
|
||||
config["divclk_divide"] = divclk_divide
|
||||
for clkfbout_mult in range(*self.clkfbout_mult_frange):
|
||||
all_valid = True
|
||||
vco_freq = self.clkin_freq*clkfbout_mult
|
||||
vco_freq = self.clkin_freq*clkfbout_mult/divclk_divide
|
||||
(vco_freq_min, vco_freq_max) = self.vco_freq_range
|
||||
if vco_freq >= vco_freq_min and vco_freq <= vco_freq_max:
|
||||
if (vco_freq >= vco_freq_min*(1 + self.vco_margin) and
|
||||
vco_freq <= vco_freq_max*(1 - self.vco_margin)):
|
||||
for n, (clk, f, p, m) in sorted(self.clkouts.items()):
|
||||
valid = False
|
||||
for d in range(*self.clkout_divide_range):
|
||||
|
@ -318,12 +321,12 @@ class USPLL(USClocking):
|
|||
|
||||
def __init__(self, speedgrade=-1):
|
||||
USClocking.__init__(self)
|
||||
self.divclk_divide_range = (1, 56+1)
|
||||
self.clkin_freq_range = {
|
||||
-1: (70e6, 800e6),
|
||||
-2: (70e6, 933e6),
|
||||
-3: (70e6, 1066e6),
|
||||
}[speedgrade]
|
||||
|
||||
self.vco_freq_range = {
|
||||
-1: (600e6, 1200e6),
|
||||
-2: (600e6, 1335e6),
|
||||
|
@ -354,12 +357,12 @@ class USMMCM(USClocking):
|
|||
|
||||
def __init__(self, speedgrade=-1):
|
||||
USClocking.__init__(self)
|
||||
self.divclk_divide_range = (1, 106+1)
|
||||
self.clkin_freq_range = {
|
||||
-1: (10e6, 800e6),
|
||||
-2: (10e6, 933e6),
|
||||
-3: (10e6, 1066e6),
|
||||
}[speedgrade]
|
||||
|
||||
self.vco_freq_range = {
|
||||
-1: (600e6, 1200e6),
|
||||
-2: (600e6, 1440e6),
|
||||
|
@ -404,7 +407,7 @@ class USIDELAYCTRL(Module):
|
|||
i_REFCLK=cd.clk,
|
||||
i_RST=ic_reset)
|
||||
|
||||
# Lattice / ECP5
|
||||
# Lattice / ECP5 -----------------------------------------------------------------------------------
|
||||
|
||||
# TODO:
|
||||
# - add proper phase support.
|
||||
|
|
|
@ -16,8 +16,11 @@ class VexRiscv(Module, AutoCSR):
|
|||
def __init__(self, platform, cpu_reset_address, variant=None):
|
||||
variant = "std" if variant is None else variant
|
||||
variant = "std_debug" if variant == "debug" else variant
|
||||
variants = ("std", "std_debug", "lite", "lite_debug", "min", "min_debug")
|
||||
variants = ("std", "std_debug", "lite", "lite_debug", "min", "min_debug", "full", "full_debug")
|
||||
assert variant in variants, "Unsupported variant %s" % variant
|
||||
self.platform = platform
|
||||
self.variant = variant
|
||||
self.external_variant = None
|
||||
self.reset = Signal()
|
||||
self.ibus = ibus = wishbone.Interface()
|
||||
self.dbus = dbus = wishbone.Interface()
|
||||
|
@ -60,9 +63,6 @@ class VexRiscv(Module, AutoCSR):
|
|||
if "debug" in variant:
|
||||
self.add_debug()
|
||||
|
||||
# add verilog sources
|
||||
self.add_sources(platform, variant)
|
||||
|
||||
def add_debug(self):
|
||||
debug_reset = Signal()
|
||||
|
||||
|
@ -156,12 +156,20 @@ class VexRiscv(Module, AutoCSR):
|
|||
"std_debug": "VexRiscv_Debug.v",
|
||||
"lite": "VexRiscv_Lite.v",
|
||||
"lite_debug": "VexRiscv_LiteDebug.v",
|
||||
"min": "VexRiscv_Lite.v",
|
||||
"min_debug": "VexRiscv_LiteDebug.v",
|
||||
"min": "VexRiscv_Min.v",
|
||||
"min_debug": "VexRiscv_MinDebug.v",
|
||||
"full": "VexRiscv_Full.v",
|
||||
"full_debug": "VexRiscv_FullDebug.v",
|
||||
}
|
||||
cpu_filename = verilog_variants[variant]
|
||||
vdir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "verilog")
|
||||
platform.add_source(os.path.join(vdir, cpu_filename))
|
||||
|
||||
def use_external_variant(self, variant_filename):
|
||||
self.external_variant = True
|
||||
self.platform.add_source(variant_filename)
|
||||
|
||||
def do_finalize(self):
|
||||
if not self.external_variant:
|
||||
self.add_sources(self.platform, self.variant)
|
||||
self.specials += Instance("VexRiscv", **self.cpu_params)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit d7bbc2c167f1a0886c446d3c305d0ed4388570be
|
||||
Subproject commit ebe4064653bc143bf92a0ccdd1099173620fcbf5
|
|
@ -1,5 +1,7 @@
|
|||
import os
|
||||
import struct
|
||||
import inspect
|
||||
import json
|
||||
from operator import itemgetter
|
||||
|
||||
from migen import *
|
||||
|
@ -36,24 +38,43 @@ def mem_decoder(address, start=26, end=29):
|
|||
|
||||
|
||||
def get_mem_data(filename, endianness="big", mem_size=None):
|
||||
data = []
|
||||
with open(filename, "rb") as mem_file:
|
||||
while True:
|
||||
w = mem_file.read(4)
|
||||
if not w:
|
||||
break
|
||||
if endianness == "little":
|
||||
data.append(struct.unpack("<I", w)[0])
|
||||
# create memory regions
|
||||
_, ext = os.path.splitext(filename)
|
||||
if ext == ".json":
|
||||
f = open(filename, "r")
|
||||
regions = json.load(f)
|
||||
f.close()
|
||||
else:
|
||||
data.append(struct.unpack(">I", w)[0])
|
||||
data_size = len(data)*4
|
||||
regions = {filename: "0x00000000"}
|
||||
|
||||
# determine data_size
|
||||
data_size = 0
|
||||
for filename, base in regions.items():
|
||||
data_size = max(int(base, 16) + os.path.getsize(filename), data_size)
|
||||
assert data_size > 0
|
||||
if mem_size is not None:
|
||||
assert data_size < mem_size, (
|
||||
"file is too big: {}/{} bytes".format(
|
||||
data_size, mem_size))
|
||||
return data
|
||||
|
||||
# fill data
|
||||
data = [0]*(data_size//4)
|
||||
for filename, base in regions.items():
|
||||
with open(filename, "rb") as f:
|
||||
i = 0
|
||||
while True:
|
||||
w = f.read(4)
|
||||
if not w:
|
||||
break
|
||||
if len(w) != 4:
|
||||
for i in range(len(w), 4):
|
||||
w += b'\x00'
|
||||
if endianness == "little":
|
||||
data[i] = struct.unpack("<I", w)[0]
|
||||
else:
|
||||
data[i] = struct.unpack(">I", w)[0]
|
||||
i += 1
|
||||
return data
|
||||
|
||||
class ReadOnlyDict(dict):
|
||||
def __readonly__(self, *args, **kwargs):
|
||||
|
|
|
@ -8,16 +8,29 @@ from litex.soc.integration.cpu_interface import get_csr_header
|
|||
from litex.soc.interconnect import wishbone
|
||||
from litex.soc.interconnect import axi
|
||||
|
||||
# Record layouts -----------------------------------------------------------------------------------
|
||||
|
||||
def axi_fifo_ctrl_layout():
|
||||
return [
|
||||
("racount", 3, DIR_M_TO_S),
|
||||
("rcount", 8, DIR_M_TO_S),
|
||||
("rdissuecapen", 1, DIR_S_TO_M),
|
||||
("wacount", 6, DIR_M_TO_S),
|
||||
("wcount", 8, DIR_M_TO_S),
|
||||
("wrissuecapen", 1, DIR_S_TO_M),
|
||||
]
|
||||
|
||||
# SoC Zync -----------------------------------------------------------------------------------------
|
||||
|
||||
class SoCZynq(SoCCore):
|
||||
SoCCore.mem_map["csr"] = 0x00000000
|
||||
def __init__(self, platform, clk_freq, ps7_name, **kwargs):
|
||||
self.ps7_name = ps7_name
|
||||
SoCCore.__init__(self, platform, clk_freq, cpu_type=None, shadow_base=0x00000000, **kwargs)
|
||||
|
||||
# PS7 --------------------------------------------------------------------------------------
|
||||
self.axi_gp0 = axi_gp0 = axi.AXIInterface(data_width=32, address_width=32, id_width=12)
|
||||
# PS7 (Minimal) ----------------------------------------------------------------------------
|
||||
ps7_ddram_pads = platform.request("ps7_ddram")
|
||||
self.specials += Instance(ps7_name,
|
||||
self.ps7_params = dict(
|
||||
# clk/rst
|
||||
io_PS_CLK=platform.request("ps7_clk"),
|
||||
io_PS_PORB=platform.request("ps7_porb"),
|
||||
|
@ -57,10 +70,17 @@ class SoCZynq(SoCCore):
|
|||
# fabric clk
|
||||
o_FCLK_CLK0=ClockSignal("sys"),
|
||||
|
||||
# axi clk
|
||||
# axi gp0 clk
|
||||
i_M_AXI_GP0_ACLK=ClockSignal("sys"),
|
||||
)
|
||||
platform.add_ip(os.path.join("ip", ps7_name + ".xci"))
|
||||
|
||||
# axi aw
|
||||
# GP0 ------------------------------------------------------------------------------------------
|
||||
|
||||
def add_gp0(self):
|
||||
self.axi_gp0 = axi_gp0 = axi.AXIInterface(data_width=32, address_width=32, id_width=12)
|
||||
self.ps7_params.update(
|
||||
# axi gp0 aw
|
||||
o_M_AXI_GP0_AWVALID=axi_gp0.aw.valid,
|
||||
i_M_AXI_GP0_AWREADY=axi_gp0.aw.ready,
|
||||
o_M_AXI_GP0_AWADDR=axi_gp0.aw.addr,
|
||||
|
@ -68,39 +88,39 @@ class SoCZynq(SoCCore):
|
|||
o_M_AXI_GP0_AWLEN=axi_gp0.aw.len,
|
||||
o_M_AXI_GP0_AWSIZE=axi_gp0.aw.size,
|
||||
o_M_AXI_GP0_AWID=axi_gp0.aw.id,
|
||||
#o_M_AXI_GP0_AWLOCK =,
|
||||
#o_M_AXI_GP0_AWPROT =,
|
||||
#o_M_AXI_GP0_AWCACHE =,
|
||||
#o_M_AXI_GP0_AWQOS =,
|
||||
o_M_AXI_GP0_AWLOCK=axi_gp0.aw.lock,
|
||||
o_M_AXI_GP0_AWPROT=axi_gp0.aw.prot,
|
||||
o_M_AXI_GP0_AWCACHE=axi_gp0.aw.cache,
|
||||
o_M_AXI_GP0_AWQOS=axi_gp0.aw.qos,
|
||||
|
||||
# axi w
|
||||
# axi gp0 w
|
||||
o_M_AXI_GP0_WVALID=axi_gp0.w.valid,
|
||||
o_M_AXI_GP0_WLAST=axi_gp0.w.last,
|
||||
i_M_AXI_GP0_WREADY=axi_gp0.w.ready,
|
||||
#o_M_AXI_GP0_WID=,
|
||||
o_M_AXI_GP0_WID=axi_gp0.w.id,
|
||||
o_M_AXI_GP0_WDATA=axi_gp0.w.data,
|
||||
o_M_AXI_GP0_WSTRB=axi_gp0.w.strb,
|
||||
|
||||
# axi b
|
||||
# axi gp0 b
|
||||
i_M_AXI_GP0_BVALID=axi_gp0.b.valid,
|
||||
o_M_AXI_GP0_BREADY=axi_gp0.b.ready,
|
||||
i_M_AXI_GP0_BID=axi_gp0.b.id,
|
||||
i_M_AXI_GP0_BRESP=axi_gp0.b.resp,
|
||||
|
||||
# axi ar
|
||||
# axi gp0 ar
|
||||
o_M_AXI_GP0_ARVALID=axi_gp0.ar.valid,
|
||||
i_M_AXI_GP0_ARREADY=axi_gp0.ar.ready,
|
||||
o_M_AXI_GP0_ARADDR=axi_gp0.ar.addr,
|
||||
o_M_AXI_GP0_ARBURST=axi_gp0.ar.burst,
|
||||
o_M_AXI_GP0_ARLEN=axi_gp0.ar.len,
|
||||
o_M_AXI_GP0_ARID=axi_gp0.ar.id,
|
||||
#o_M_AXI_GP0_ARLOCK=,
|
||||
#o_M_AXI_GP0_ARSIZE=,
|
||||
#o_M_AXI_GP0_ARPROT=,
|
||||
#o_M_AXI_GP0_ARCACHE=,
|
||||
#o_M_AXI_GP0_ARQOS=,
|
||||
o_M_AXI_GP0_ARLOCK=axi_gp0.ar.lock,
|
||||
o_M_AXI_GP0_ARSIZE=axi_gp0.ar.size,
|
||||
o_M_AXI_GP0_ARPROT=axi_gp0.ar.prot,
|
||||
o_M_AXI_GP0_ARCACHE=axi_gp0.ar.cache,
|
||||
o_M_AXI_GP0_ARQOS=axi_gp0.ar.qos,
|
||||
|
||||
# axi r
|
||||
# axi gp0 r
|
||||
i_M_AXI_GP0_RVALID=axi_gp0.r.valid,
|
||||
o_M_AXI_GP0_RREADY=axi_gp0.r.ready,
|
||||
i_M_AXI_GP0_RLAST=axi_gp0.r.last,
|
||||
|
@ -108,13 +128,79 @@ class SoCZynq(SoCCore):
|
|||
i_M_AXI_GP0_RRESP=axi_gp0.r.resp,
|
||||
i_M_AXI_GP0_RDATA=axi_gp0.r.data,
|
||||
)
|
||||
platform.add_ip(os.path.join("ip", ps7_name + ".xci"))
|
||||
|
||||
# AXI to Wishbone --------------------------------------------------------------------------
|
||||
self.wb_gp0 = wb_gp0 = wishbone.Interface()
|
||||
axi2wishbone = axi.AXI2Wishbone(axi_gp0, wb_gp0, base_address=0x43c00000)
|
||||
# HP0 ------------------------------------------------------------------------------------------
|
||||
|
||||
def add_hp0(self):
|
||||
self.axi_hp0 = axi_hp0 = axi.AXIInterface(data_width=64, address_width=32, id_width=6)
|
||||
self.axi_hp0_fifo_ctrl = axi_hp0_fifo_ctrl = Record(axi_fifo_ctrl_layout())
|
||||
self.ps7_params.update(
|
||||
# axi hp0 aw
|
||||
i_S_AXI_HP0_AWVALID=axi_hp0.aw.valid,
|
||||
o_S_AXI_HP0_AWREADY=axi_hp0.aw.ready,
|
||||
i_S_AXI_HP0_AWADDR=axi_hp0.aw.addr,
|
||||
i_S_AXI_HP0_AWBURST=axi_hp0.aw.burst,
|
||||
i_S_AXI_HP0_AWLEN=axi_hp0.aw.len,
|
||||
i_S_AXI_HP0_AWSIZE=axi_hp0.aw.size,
|
||||
i_S_AXI_HP0_AWID=axi_hp0.aw.id,
|
||||
i_S_AXI_HP0_AWLOCK=axi_hp0.aw.lock,
|
||||
i_S_AXI_HP0_AWPROT=axi_hp0.aw.prot,
|
||||
i_S_AXI_HP0_AWCACHE=axi_hp0.aw.cache,
|
||||
i_S_AXI_HP0_AWQOS=axi_hp0.aw.qos,
|
||||
|
||||
# axi hp0 w
|
||||
i_S_AXI_HP0_WVALID=axi_hp0.w.valid,
|
||||
i_S_AXI_HP0_WLAST=axi_hp0.w.last,
|
||||
o_S_AXI_HP0_WREADY=axi_hp0.w.ready,
|
||||
i_S_AXI_HP0_WID=axi_hp0.w.id,
|
||||
i_S_AXI_HP0_WDATA=axi_hp0.w.data,
|
||||
i_S_AXI_HP0_WSTRB=axi_hp0.w.strb,
|
||||
|
||||
# axi hp0 b
|
||||
o_S_AXI_HP0_BVALID=axi_hp0.b.valid,
|
||||
i_S_AXI_HP0_BREADY=axi_hp0.b.ready,
|
||||
o_S_AXI_HP0_BID=axi_hp0.b.id,
|
||||
o_S_AXI_HP0_BRESP=axi_hp0.b.resp,
|
||||
|
||||
# axi hp0 ar
|
||||
i_S_AXI_HP0_ARVALID=axi_hp0.ar.valid,
|
||||
o_S_AXI_HP0_ARREADY=axi_hp0.ar.ready,
|
||||
i_S_AXI_HP0_ARADDR=axi_hp0.ar.addr,
|
||||
i_S_AXI_HP0_ARBURST=axi_hp0.ar.burst,
|
||||
i_S_AXI_HP0_ARLEN=axi_hp0.ar.len,
|
||||
i_S_AXI_HP0_ARID=axi_hp0.ar.id,
|
||||
i_S_AXI_HP0_ARLOCK=axi_hp0.ar.lock,
|
||||
i_S_AXI_HP0_ARSIZE=axi_hp0.ar.size,
|
||||
i_S_AXI_HP0_ARPROT=axi_hp0.ar.prot,
|
||||
i_S_AXI_HP0_ARCACHE=axi_hp0.ar.cache,
|
||||
i_S_AXI_HP0_ARQOS=axi_hp0.ar.qos,
|
||||
|
||||
# axi hp0 r
|
||||
o_S_AXI_HP0_RVALID=axi_hp0.r.valid,
|
||||
i_S_AXI_HP0_RREADY=axi_hp0.r.ready,
|
||||
o_S_AXI_HP0_RLAST=axi_hp0.r.last,
|
||||
o_S_AXI_HP0_RID=axi_hp0.r.id,
|
||||
o_S_AXI_HP0_RRESP=axi_hp0.r.resp,
|
||||
o_S_AXI_HP0_RDATA=axi_hp0.r.data,
|
||||
|
||||
# axi hp0 fifo ctrl
|
||||
o_S_AXI_HP0_RACOUNT=axi_hp0_fifo_ctrl.racount,
|
||||
o_S_AXI_HP0_RCOUNT=axi_hp0_fifo_ctrl.rcount,
|
||||
i_S_AXI_HP0_RDISSUECAP1_EN=axi_hp0_fifo_ctrl.rdissuecapen,
|
||||
o_S_AXI_HP0_WACOUNT=axi_hp0_fifo_ctrl.wacount,
|
||||
o_S_AXI_HP0_WCOUNT=axi_hp0_fifo_ctrl.wcount,
|
||||
i_S_AXI_HP0_WRISSUECAP1_EN=axi_hp0_fifo_ctrl.wrissuecapen
|
||||
)
|
||||
|
||||
def add_axi_to_wishbone(self, axi_port, base_address=0x43c00000):
|
||||
wb = wishbone.Interface()
|
||||
axi2wishbone = axi.AXI2Wishbone(axi_port, wb, base_address)
|
||||
self.submodules += axi2wishbone
|
||||
self.add_wb_master(wb_gp0)
|
||||
self.add_wb_master(wb)
|
||||
|
||||
def do_finalize(self):
|
||||
SoCCore.do_finalize(self)
|
||||
self.specials += Instance(self.ps7_name, **self.ps7_params)
|
||||
|
||||
def generate_software_header(self, filename):
|
||||
csr_header = get_csr_header(self.get_csr_regions(),
|
||||
|
|
38
litex/soc/interconnect/avalon.py
Normal file
38
litex/soc/interconnect/avalon.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
from migen import *
|
||||
|
||||
from litex.soc.interconnect import stream
|
||||
|
||||
# AvalonST to/from Native --------------------------------------------------------------------------
|
||||
|
||||
class Native2AvalonST(Module):
|
||||
def __init__(self, layout, latency=2):
|
||||
self.sink = sink = stream.Endpoint(layout)
|
||||
self.source = source = stream.Endpoint(layout)
|
||||
|
||||
# # #
|
||||
|
||||
_from = sink
|
||||
for n in range(latency):
|
||||
_to = stream.Endpoint(layout)
|
||||
self.sync += _from.connect(_to, omit={"ready"})
|
||||
if n == 0:
|
||||
self.sync += _to.valid.eq(sink.valid & source.ready)
|
||||
_from = _to
|
||||
self.comb += _to.connect(source, omit={"ready"})
|
||||
self.comb += sink.ready.eq(source.ready)
|
||||
|
||||
|
||||
class AvalonST2Native(Module):
|
||||
def __init__(self, layout, latency=2):
|
||||
self.sink = sink = stream.Endpoint(layout)
|
||||
self.source = source = stream.Endpoint(layout)
|
||||
|
||||
# # #
|
||||
|
||||
buf = stream.SyncFIFO(layout, max(latency, 4))
|
||||
self.submodules += buf
|
||||
self.comb += [
|
||||
sink.connect(buf.sink, omit={"ready"}),
|
||||
sink.ready.eq(source.ready),
|
||||
buf.source.connect(source)
|
||||
]
|
|
@ -20,13 +20,18 @@ def ax_description(address_width, id_width):
|
|||
("burst", 2), # Burst type
|
||||
("len", 8), # Number of data (-1) transfers (up to 256)
|
||||
("size", 4), # Number of bytes (-1) of each data transfer (up to 1024 bits)
|
||||
("lock", 2),
|
||||
("prot", 3),
|
||||
("cache", 4),
|
||||
("qos", 4),
|
||||
("id", id_width)
|
||||
]
|
||||
|
||||
def w_description(data_width):
|
||||
def w_description(data_width, id_width):
|
||||
return [
|
||||
("data", data_width),
|
||||
("strb", data_width//8)
|
||||
("strb", data_width//8),
|
||||
("id", id_width)
|
||||
]
|
||||
|
||||
def b_description(id_width):
|
||||
|
@ -51,7 +56,7 @@ class AXIInterface(Record):
|
|||
self.clock_domain = clock_domain
|
||||
|
||||
self.aw = stream.Endpoint(ax_description(address_width, id_width))
|
||||
self.w = stream.Endpoint(w_description(data_width))
|
||||
self.w = stream.Endpoint(w_description(data_width, id_width))
|
||||
self.b = stream.Endpoint(b_description(id_width))
|
||||
self.ar = stream.Endpoint(ax_description(address_width, id_width))
|
||||
self.r = stream.Endpoint(r_description(data_width, id_width))
|
||||
|
@ -60,12 +65,12 @@ class AXIInterface(Record):
|
|||
|
||||
class AXI2Wishbone(Module):
|
||||
def __init__(self, axi, wishbone, base_address):
|
||||
assert axi.data_width == 32
|
||||
assert axi.address_width == 32
|
||||
assert axi.data_width == len(wishbone.dat_r)
|
||||
assert axi.address_width == len(wishbone.adr) + 2
|
||||
|
||||
_data = Signal(axi.data_width)
|
||||
_read_addr = Signal(32)
|
||||
_write_addr = Signal(32)
|
||||
_read_addr = Signal(axi.address_width)
|
||||
_write_addr = Signal(axi.address_width)
|
||||
|
||||
self.comb += _read_addr.eq(axi.ar.addr - base_address)
|
||||
self.comb += _write_addr.eq(axi.aw.addr - base_address)
|
||||
|
@ -78,8 +83,6 @@ class AXI2Wishbone(Module):
|
|||
NextState("DO-WRITE")
|
||||
)
|
||||
)
|
||||
axi_ar_addr = Signal(32)
|
||||
self.comb += axi_ar_addr.eq(axi.ar.addr - base_address)
|
||||
fsm.act("DO-READ",
|
||||
wishbone.stb.eq(1),
|
||||
wishbone.cyc.eq(1),
|
||||
|
|
|
@ -186,133 +186,18 @@ static void ident(void)
|
|||
printf("Ident: %s\n", buffer);
|
||||
}
|
||||
|
||||
#ifdef __lm32__
|
||||
enum {
|
||||
CSR_IE = 1, CSR_IM, CSR_IP, CSR_ICC, CSR_DCC, CSR_CC, CSR_CFG, CSR_EBA,
|
||||
CSR_DC, CSR_DEBA, CSR_JTX, CSR_JRX, CSR_BP0, CSR_BP1, CSR_BP2, CSR_BP3,
|
||||
CSR_WP0, CSR_WP1, CSR_WP2, CSR_WP3,
|
||||
};
|
||||
|
||||
/* processor registers */
|
||||
static int parse_csr(const char *csr)
|
||||
{
|
||||
if(!strcmp(csr, "ie")) return CSR_IE;
|
||||
if(!strcmp(csr, "im")) return CSR_IM;
|
||||
if(!strcmp(csr, "ip")) return CSR_IP;
|
||||
if(!strcmp(csr, "icc")) return CSR_ICC;
|
||||
if(!strcmp(csr, "dcc")) return CSR_DCC;
|
||||
if(!strcmp(csr, "cc")) return CSR_CC;
|
||||
if(!strcmp(csr, "cfg")) return CSR_CFG;
|
||||
if(!strcmp(csr, "eba")) return CSR_EBA;
|
||||
if(!strcmp(csr, "dc")) return CSR_DC;
|
||||
if(!strcmp(csr, "deba")) return CSR_DEBA;
|
||||
if(!strcmp(csr, "jtx")) return CSR_JTX;
|
||||
if(!strcmp(csr, "jrx")) return CSR_JRX;
|
||||
if(!strcmp(csr, "bp0")) return CSR_BP0;
|
||||
if(!strcmp(csr, "bp1")) return CSR_BP1;
|
||||
if(!strcmp(csr, "bp2")) return CSR_BP2;
|
||||
if(!strcmp(csr, "bp3")) return CSR_BP3;
|
||||
if(!strcmp(csr, "wp0")) return CSR_WP0;
|
||||
if(!strcmp(csr, "wp1")) return CSR_WP1;
|
||||
if(!strcmp(csr, "wp2")) return CSR_WP2;
|
||||
if(!strcmp(csr, "wp3")) return CSR_WP3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rcsr(char *csr)
|
||||
{
|
||||
unsigned int csr2;
|
||||
register unsigned int value;
|
||||
|
||||
if(*csr == 0) {
|
||||
printf("rcsr <csr>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
csr2 = parse_csr(csr);
|
||||
if(csr2 == 0) {
|
||||
printf("incorrect csr\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(csr2) {
|
||||
case CSR_IE: asm volatile ("rcsr %0,ie":"=r"(value)); break;
|
||||
case CSR_IM: asm volatile ("rcsr %0,im":"=r"(value)); break;
|
||||
case CSR_IP: asm volatile ("rcsr %0,ip":"=r"(value)); break;
|
||||
case CSR_CC: asm volatile ("rcsr %0,cc":"=r"(value)); break;
|
||||
case CSR_CFG: asm volatile ("rcsr %0,cfg":"=r"(value)); break;
|
||||
case CSR_EBA: asm volatile ("rcsr %0,eba":"=r"(value)); break;
|
||||
case CSR_DEBA: asm volatile ("rcsr %0,deba":"=r"(value)); break;
|
||||
case CSR_JTX: asm volatile ("rcsr %0,jtx":"=r"(value)); break;
|
||||
case CSR_JRX: asm volatile ("rcsr %0,jrx":"=r"(value)); break;
|
||||
default: printf("csr write only\n"); return;
|
||||
}
|
||||
|
||||
printf("%08x\n", value);
|
||||
}
|
||||
|
||||
static void wcsr(char *csr, char *value)
|
||||
{
|
||||
char *c;
|
||||
unsigned int csr2;
|
||||
register unsigned int value2;
|
||||
|
||||
if((*csr == 0) || (*value == 0)) {
|
||||
printf("wcsr <csr> <address>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
csr2 = parse_csr(csr);
|
||||
if(csr2 == 0) {
|
||||
printf("incorrect csr\n");
|
||||
return;
|
||||
}
|
||||
value2 = strtoul(value, &c, 0);
|
||||
if(*c != 0) {
|
||||
printf("incorrect value\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(csr2) {
|
||||
case CSR_IE: asm volatile ("wcsr ie,%0"::"r"(value2)); break;
|
||||
case CSR_IM: asm volatile ("wcsr im,%0"::"r"(value2)); break;
|
||||
case CSR_ICC: asm volatile ("wcsr icc,%0"::"r"(value2)); break;
|
||||
case CSR_DCC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
|
||||
case CSR_EBA: asm volatile ("wcsr eba,%0"::"r"(value2)); break;
|
||||
case CSR_DC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
|
||||
case CSR_DEBA: asm volatile ("wcsr deba,%0"::"r"(value2)); break;
|
||||
case CSR_JTX: asm volatile ("wcsr jtx,%0"::"r"(value2)); break;
|
||||
case CSR_JRX: asm volatile ("wcsr jrx,%0"::"r"(value2)); break;
|
||||
case CSR_BP0: asm volatile ("wcsr bp0,%0"::"r"(value2)); break;
|
||||
case CSR_BP1: asm volatile ("wcsr bp1,%0"::"r"(value2)); break;
|
||||
case CSR_BP2: asm volatile ("wcsr bp2,%0"::"r"(value2)); break;
|
||||
case CSR_BP3: asm volatile ("wcsr bp3,%0"::"r"(value2)); break;
|
||||
case CSR_WP0: asm volatile ("wcsr wp0,%0"::"r"(value2)); break;
|
||||
case CSR_WP1: asm volatile ("wcsr wp1,%0"::"r"(value2)); break;
|
||||
case CSR_WP2: asm volatile ("wcsr wp2,%0"::"r"(value2)); break;
|
||||
case CSR_WP3: asm volatile ("wcsr wp3,%0"::"r"(value2)); break;
|
||||
default: printf("csr read only\n"); return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __lm32__ */
|
||||
|
||||
/* Init + command line */
|
||||
|
||||
static void help(void)
|
||||
{
|
||||
puts("LiteX SoC BIOS");
|
||||
puts("Available commands:");
|
||||
puts("LiteX BIOS, available commands:");
|
||||
puts("mr - read address space");
|
||||
puts("mw - write address space");
|
||||
puts("mc - copy address space");
|
||||
puts("");
|
||||
puts("crc - compute CRC32 of a part of the address space");
|
||||
puts("ident - display identifier");
|
||||
#ifdef __lm32__
|
||||
puts("rcsr - read processor CSR");
|
||||
puts("wcsr - write processor CSR");
|
||||
#endif
|
||||
puts("");
|
||||
#ifdef CSR_CTRL_BASE
|
||||
puts("reboot - reset processor");
|
||||
#endif
|
||||
|
@ -326,6 +211,7 @@ static void help(void)
|
|||
#ifdef ROM_BOOT_ADDRESS
|
||||
puts("romboot - boot from embedded rom");
|
||||
#endif
|
||||
puts("");
|
||||
#ifdef CSR_SDRAM_BASE
|
||||
puts("memtest - run a memory test");
|
||||
#endif
|
||||
|
@ -385,11 +271,6 @@ static void do_command(char *c)
|
|||
|
||||
else if(strcmp(token, "help") == 0) help();
|
||||
|
||||
#ifdef __lm32__
|
||||
else if(strcmp(token, "rcsr") == 0) rcsr(get_token(&c));
|
||||
else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c));
|
||||
#endif
|
||||
|
||||
#ifdef CSR_SDRAM_BASE
|
||||
else if(strcmp(token, "sdrrow") == 0) sdrrow(get_token(&c));
|
||||
else if(strcmp(token, "sdrsw") == 0) sdrsw();
|
||||
|
@ -399,6 +280,7 @@ static void do_command(char *c)
|
|||
else if(strcmp(token, "sdrrderr") == 0) sdrrderr(get_token(&c));
|
||||
else if(strcmp(token, "sdrwr") == 0) sdrwr(get_token(&c));
|
||||
#ifdef CSR_DDRPHY_BASE
|
||||
else if(strcmp(token, "sdrinit") == 0) sdrinit();
|
||||
#ifdef CSR_DDRPHY_WLEVEL_EN_ADDR
|
||||
else if(strcmp(token, "sdrwlon") == 0) sdrwlon();
|
||||
else if(strcmp(token, "sdrwloff") == 0) sdrwloff();
|
||||
|
@ -406,7 +288,6 @@ static void do_command(char *c)
|
|||
else if(strcmp(token, "sdrlevel") == 0) sdrlevel();
|
||||
#endif
|
||||
else if(strcmp(token, "memtest") == 0) memtest();
|
||||
else if(strcmp(token, "sdrinit") == 0) sdrinit();
|
||||
#endif
|
||||
|
||||
else if(strcmp(token, "") != 0)
|
||||
|
@ -509,12 +390,22 @@ int main(int i, char **c)
|
|||
irq_setmask(0);
|
||||
irq_setie(1);
|
||||
uart_init();
|
||||
|
||||
printf("\n");
|
||||
printf("\e[1m __ _ __ _ __\e[0m\n");
|
||||
printf("\e[1m / / (_) /____ | |/_/\e[0m\n");
|
||||
printf("\e[1m / /__/ / __/ -_)> <\e[0m\n");
|
||||
printf("\e[1m /____/_/\\__/\\__/_/|_|\e[0m\n");
|
||||
printf("\e[1m SoC BIOS / CPU: ");
|
||||
printf("\n");
|
||||
printf(" (c) Copyright 2012-2019 Enjoy-Digital\n");
|
||||
printf(" (c) Copyright 2012-2015 M-Labs Ltd\n");
|
||||
printf("\n");
|
||||
printf(" BIOS built on "__DATE__" "__TIME__"\n");
|
||||
crcbios();
|
||||
printf("\n");
|
||||
|
||||
printf("--============ \e[1mSoC info\e[0m ================--\n");
|
||||
printf("\e[1mCPU\e[0m: ");
|
||||
#ifdef __lm32__
|
||||
printf("LM32");
|
||||
#elif __or1k__
|
||||
|
@ -528,14 +419,19 @@ int main(int i, char **c)
|
|||
#else
|
||||
printf("Unknown");
|
||||
#endif
|
||||
printf(" / %3dMHz\e[0m\n", SYSTEM_CLOCK_FREQUENCY/1000000);
|
||||
printf(" @ %dMHz\n", SYSTEM_CLOCK_FREQUENCY/1000000);
|
||||
printf("\e[1mROM\e[0m: %dKB\n", ROM_SIZE/1024);
|
||||
printf("\e[1mSRAM\e[0m: %dKB\n", SRAM_SIZE/1024);
|
||||
#ifdef L2_SIZE
|
||||
printf("\e[1mL2\e[0m: %dKB\n", L2_SIZE/1024);
|
||||
#endif
|
||||
#ifdef MAIN_RAM_SIZE
|
||||
printf("\e[1mMAIN-RAM\e[0m: %dKB\n", MAIN_RAM_SIZE/1024);
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
puts(
|
||||
"(c) Copyright 2012-2018 Enjoy-Digital\n"
|
||||
"(c) Copyright 2007-2018 M-Labs Limited\n"
|
||||
"Built "__DATE__" "__TIME__"\n");
|
||||
crcbios();
|
||||
#ifdef CSR_ETHMAC_BASE
|
||||
printf("--========= \e[1mPeripherals init\e[0m ===========--\n");
|
||||
#ifdef CSR_ETHPHY_CRG_RESET_ADDR
|
||||
eth_init();
|
||||
#endif
|
||||
#ifdef CSR_SDRAM_BASE
|
||||
|
@ -547,11 +443,17 @@ int main(int i, char **c)
|
|||
sdr_ok = 1;
|
||||
#endif
|
||||
#endif
|
||||
if(sdr_ok)
|
||||
boot_sequence();
|
||||
else
|
||||
if (sdr_ok !=1)
|
||||
printf("Memory initialization failed\n");
|
||||
printf("\n");
|
||||
|
||||
if(sdr_ok) {
|
||||
printf("--========== \e[1mBoot sequence\e[0m =============--\n");
|
||||
boot_sequence();
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("--============= \e[1mConsole\e[0m ================--\n");
|
||||
while(1) {
|
||||
putsnonl("\e[1mBIOS>\e[0m ");
|
||||
readstr(buffer, 64);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#define MAIN_RAM_BASE SRAM_BASE
|
||||
#endif
|
||||
|
||||
static void cdelay(int i)
|
||||
__attribute__((unused)) static void cdelay(int i)
|
||||
{
|
||||
while(i > 0) {
|
||||
#if defined (__lm32__)
|
||||
|
@ -210,16 +210,18 @@ void sdrwr(char *startaddr)
|
|||
|
||||
#if defined (USDDRPHY)
|
||||
#define ERR_DDRPHY_DELAY 512
|
||||
#define ERR_DDRPHY_BITSLIP 8
|
||||
#define NBMODULES DFII_PIX_DATA_SIZE/2
|
||||
#elif defined (ECP5DDRPHY)
|
||||
#define ERR_DDRPHY_DELAY 8
|
||||
#define ERR_DDRPHY_BITSLIP 1
|
||||
#define NBMODULES DFII_PIX_DATA_SIZE/4
|
||||
#else
|
||||
#define ERR_DDRPHY_DELAY 32
|
||||
#define ERR_DDRPHY_BITSLIP 8
|
||||
#define NBMODULES DFII_PIX_DATA_SIZE/2
|
||||
#endif
|
||||
|
||||
#define ERR_DDRPHY_BITSLIP DFII_NPHASES*2
|
||||
|
||||
#define NBMODULES DFII_PIX_DATA_SIZE*DFII_NPHASES/8
|
||||
|
||||
#ifdef CSR_DDRPHY_WLEVEL_EN_ADDR
|
||||
|
||||
void sdrwlon(void)
|
||||
|
@ -461,6 +463,9 @@ static int read_level_scan(int module, int bitslip)
|
|||
int show = 1;
|
||||
#ifdef USDDRPHY
|
||||
show = (j%16 == 0);
|
||||
#endif
|
||||
#ifdef ECP5DDRPHY
|
||||
ddrphy_burstdet_clr_write(1);
|
||||
#endif
|
||||
command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
|
||||
cdelay(15);
|
||||
|
@ -471,6 +476,10 @@ static int read_level_scan(int module, int bitslip)
|
|||
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
|
||||
working = 0;
|
||||
}
|
||||
#ifdef ECP5DDRPHY
|
||||
if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1)
|
||||
working = 0;
|
||||
#endif
|
||||
if (show)
|
||||
printf("%d", working);
|
||||
score += working;
|
||||
|
@ -526,6 +535,9 @@ static void read_level(int module)
|
|||
delay = 0;
|
||||
read_delay_rst(module);
|
||||
while(1) {
|
||||
#ifdef ECP5DDRPHY
|
||||
ddrphy_burstdet_clr_write(1);
|
||||
#endif
|
||||
command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
|
||||
cdelay(15);
|
||||
working = 1;
|
||||
|
@ -535,6 +547,10 @@ static void read_level(int module)
|
|||
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
|
||||
working = 0;
|
||||
}
|
||||
#ifdef ECP5DDRPHY
|
||||
if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1)
|
||||
working = 0;
|
||||
#endif
|
||||
if(working)
|
||||
break;
|
||||
delay++;
|
||||
|
@ -557,6 +573,9 @@ static void read_level(int module)
|
|||
|
||||
/* Find largest working delay */
|
||||
while(1) {
|
||||
#ifdef ECP5DDRPHY
|
||||
ddrphy_burstdet_clr_write(1);
|
||||
#endif
|
||||
command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
|
||||
cdelay(15);
|
||||
working = 1;
|
||||
|
@ -566,6 +585,10 @@ static void read_level(int module)
|
|||
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
|
||||
working = 0;
|
||||
}
|
||||
#ifdef ECP5DDRPHY
|
||||
if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1)
|
||||
working = 0;
|
||||
#endif
|
||||
if(!working)
|
||||
break;
|
||||
delay++;
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef __HW_ETHMAC_MEM_H
|
||||
#define __HW_ETHMAC_MEM_H
|
||||
|
||||
#include <generated/mem.h>
|
||||
|
||||
#define ETHMAC_RX0_BASE ETHMAC_BASE
|
||||
#define ETHMAC_RX1_BASE (ETHMAC_BASE+0x0800)
|
||||
#define ETHMAC_TX0_BASE (ETHMAC_BASE+0x1000)
|
||||
#define ETHMAC_TX1_BASE (ETHMAC_BASE+0x1800)
|
||||
|
||||
#endif
|
|
@ -1,4 +1,6 @@
|
|||
#include <generated/csr.h>
|
||||
#include <generated/mem.h>
|
||||
|
||||
#ifdef CSR_ETHMAC_BASE
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -6,7 +8,6 @@
|
|||
#include <system.h>
|
||||
#include <crc.h>
|
||||
#include <hw/flags.h>
|
||||
#include <hw/ethmac_mem.h>
|
||||
|
||||
#include <net/microudp.h>
|
||||
|
||||
|
@ -110,24 +111,17 @@ struct ethernet_frame {
|
|||
|
||||
typedef union {
|
||||
struct ethernet_frame frame;
|
||||
unsigned char raw[1532];
|
||||
unsigned char raw[ETHMAC_SLOT_SIZE];
|
||||
} ethernet_buffer;
|
||||
|
||||
|
||||
static unsigned int rxslot;
|
||||
static unsigned int rxlen;
|
||||
static ethernet_buffer *rxbuffer;
|
||||
static ethernet_buffer *rxbuffer0;
|
||||
static ethernet_buffer *rxbuffer1;
|
||||
static unsigned int txslot;
|
||||
static unsigned int txlen;
|
||||
static ethernet_buffer *txbuffer;
|
||||
static ethernet_buffer *txbuffer0;
|
||||
static ethernet_buffer *txbuffer1;
|
||||
|
||||
static void send_packet(void)
|
||||
{
|
||||
|
||||
unsigned int txslot;
|
||||
#ifndef HW_PREAMBLE_CRC
|
||||
unsigned int crc;
|
||||
crc = crc32(&txbuffer->raw[8], txlen-8);
|
||||
|
@ -147,15 +141,13 @@ static void send_packet(void)
|
|||
printf("\n");
|
||||
#endif
|
||||
|
||||
ethmac_sram_reader_slot_write(txslot);
|
||||
ethmac_sram_reader_length_write(txlen);
|
||||
while(!(ethmac_sram_reader_ready_read()));
|
||||
ethmac_sram_reader_start_write(1);
|
||||
txslot = (txslot+1)%2;
|
||||
if (txslot)
|
||||
txbuffer = txbuffer1;
|
||||
else
|
||||
txbuffer = txbuffer0;
|
||||
while(!(ethmac_sram_reader_ready_read()));
|
||||
txslot = ethmac_sram_reader_slot_read();
|
||||
txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * (ETHMAC_RX_SLOTS + txslot));
|
||||
txslot = (txslot+1)%ETHMAC_TX_SLOTS;
|
||||
ethmac_sram_reader_slot_write(txslot);
|
||||
}
|
||||
|
||||
static unsigned char my_mac[6];
|
||||
|
@ -415,17 +407,6 @@ void microudp_start(const unsigned char *macaddr, unsigned int ip)
|
|||
ethmac_sram_reader_ev_pending_write(ETHMAC_EV_SRAM_READER);
|
||||
ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
|
||||
|
||||
rxbuffer0 = (ethernet_buffer *)ETHMAC_RX0_BASE;
|
||||
rxbuffer1 = (ethernet_buffer *)ETHMAC_RX1_BASE;
|
||||
txbuffer0 = (ethernet_buffer *)ETHMAC_TX0_BASE;
|
||||
txbuffer1 = (ethernet_buffer *)ETHMAC_TX1_BASE;
|
||||
|
||||
rxslot = 0;
|
||||
txslot = 0;
|
||||
|
||||
rxbuffer = rxbuffer0;
|
||||
txbuffer = txbuffer0;
|
||||
|
||||
for(i=0;i<6;i++)
|
||||
my_mac[i] = macaddr[i];
|
||||
my_ip = ip;
|
||||
|
@ -434,18 +415,21 @@ void microudp_start(const unsigned char *macaddr, unsigned int ip)
|
|||
for(i=0;i<6;i++)
|
||||
cached_mac[i] = 0;
|
||||
|
||||
ethmac_sram_reader_slot_write(0);
|
||||
txbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * ETHMAC_RX_SLOTS);
|
||||
|
||||
|
||||
rxbuffer = (ethernet_buffer *)ETHMAC_BASE;
|
||||
rx_callback = (udp_callback)0;
|
||||
}
|
||||
|
||||
void microudp_service(void)
|
||||
{
|
||||
unsigned int rxslot;
|
||||
if(ethmac_sram_writer_ev_pending_read() & ETHMAC_EV_SRAM_WRITER) {
|
||||
rxslot = ethmac_sram_writer_slot_read();
|
||||
rxbuffer = (ethernet_buffer *)(ETHMAC_BASE + ETHMAC_SLOT_SIZE * rxslot);
|
||||
rxlen = ethmac_sram_writer_length_read();
|
||||
if (rxslot)
|
||||
rxbuffer = rxbuffer1;
|
||||
else
|
||||
rxbuffer = rxbuffer0;
|
||||
process_frame();
|
||||
ethmac_sram_writer_ev_pending_write(ETHMAC_EV_SRAM_WRITER);
|
||||
}
|
||||
|
@ -463,13 +447,12 @@ static void busy_wait(unsigned int ds)
|
|||
|
||||
void eth_init(void)
|
||||
{
|
||||
ethphy_crg_reset_write(0);
|
||||
busy_wait(2);
|
||||
/* that pesky ethernet PHY needs two resets at times... */
|
||||
#ifdef CSR_ETHPHY_CRG_RESET_ADDR
|
||||
ethphy_crg_reset_write(1);
|
||||
busy_wait(2);
|
||||
ethphy_crg_reset_write(0);
|
||||
busy_wait(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR
|
||||
|
|
1
litex/utils/__init__.py
Normal file
1
litex/utils/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import time
|
||||
|
@ -10,22 +12,19 @@ from litex.soc.tools.remote.etherbone import EtherboneIPC
|
|||
|
||||
|
||||
class RemoteServer(EtherboneIPC):
|
||||
def __init__(self, comm, port=1234):
|
||||
def __init__(self, comm, bind_ip, bind_port=1234):
|
||||
self.comm = comm
|
||||
self.port = port
|
||||
self.bind_ip = bind_ip
|
||||
self.bind_port = bind_port
|
||||
self.lock = False
|
||||
|
||||
def open(self):
|
||||
if hasattr(self, "socket"):
|
||||
return
|
||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
for i in range(32):
|
||||
try:
|
||||
self.socket.bind(("localhost", self.port + i))
|
||||
break
|
||||
except:
|
||||
pass
|
||||
print("tcp port: {:d}".format(self.port + i))
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
||||
self.socket.bind((self.bind_ip, self.bind_port))
|
||||
print("tcp port: {:d}".format(self.bind_port))
|
||||
self.socket.listen(1)
|
||||
self.comm.open()
|
||||
|
||||
|
@ -95,46 +94,65 @@ class RemoteServer(EtherboneIPC):
|
|||
|
||||
def main():
|
||||
print("LiteX remote server")
|
||||
if len(sys.argv) < 2 or len(sys.argv) > 4:
|
||||
print("usages:")
|
||||
print("litex_server uart [port] [baudrate]")
|
||||
print("litex_server udp [server] [server_port]")
|
||||
print("litex_server pcie [bar]")
|
||||
sys.exit()
|
||||
comm = sys.argv[1]
|
||||
if comm == "uart":
|
||||
parser = argparse.ArgumentParser()
|
||||
# Common arguments
|
||||
parser.add_argument("--bind-ip", default="localhost",
|
||||
help="Host bind address")
|
||||
parser.add_argument("--bind-port", default=1234,
|
||||
help="Host bind port")
|
||||
|
||||
# UART arguments
|
||||
parser.add_argument("--uart", action="store_true",
|
||||
help="Select UART interface")
|
||||
parser.add_argument("--uart-port", default=None,
|
||||
help="Set UART port")
|
||||
parser.add_argument("--uart-baudrate", default=115200,
|
||||
help="Set UART baudrate")
|
||||
|
||||
# UDP arguments
|
||||
parser.add_argument("--udp", action="store_true",
|
||||
help="Select UDP interface")
|
||||
parser.add_argument("--udp-ip", default="192.168.1.50",
|
||||
help="Set UDP remote IP address")
|
||||
parser.add_argument("--udp-port", default=1234,
|
||||
help="Set UDP remote port")
|
||||
|
||||
# PCIe arguments
|
||||
parser.add_argument("--pcie", action="store_true",
|
||||
help="Select PCIe interface")
|
||||
parser.add_argument("--pcie-bar", default=None,
|
||||
help="Set PCIe BAR")
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
if args.uart:
|
||||
from litex.soc.tools.remote import CommUART
|
||||
uart_port = None
|
||||
uart_baudrate = 115200
|
||||
if len(sys.argv) > 2:
|
||||
uart_port = sys.argv[2]
|
||||
if len(sys.argv) > 3:
|
||||
uart_baudrate = int(float(sys.argv[3]))
|
||||
if args.uart_port is None:
|
||||
print("Need to specify --uart-port, exiting.")
|
||||
exit()
|
||||
uart_port = args.uart_port
|
||||
uart_baudrate = int(float(args.uart_baudrate))
|
||||
print("[CommUART] port: {} / baudrate: {} / ".format(uart_port, uart_baudrate), end="")
|
||||
comm = CommUART(uart_port, uart_baudrate)
|
||||
elif comm == "udp":
|
||||
elif args.udp:
|
||||
from litex.soc.tools.remote import CommUDP
|
||||
server = "192.168.1.50"
|
||||
server_port = 1234
|
||||
if len(sys.argv) > 2:
|
||||
server = sys.argv[2]
|
||||
if len(sys.argv) > 3:
|
||||
server_port = int(sys.argv[3])
|
||||
print("[CommUDP] server: {} / port: {} / ".format(server, server_port), end="")
|
||||
comm = CommUDP(server, server_port)
|
||||
elif comm == "pcie":
|
||||
udp_ip = args.udp_ip
|
||||
udp_port = int(args.udp_port)
|
||||
print("[CommUDP] ip: {} / port: {} / ".format(udp_ip, udp_port), end="")
|
||||
comm = CommUDP(udp_ip, udp_port)
|
||||
elif args.pcie:
|
||||
from litex.soc.tools.remote import CommPCIe
|
||||
bar = ""
|
||||
if len(sys.argv) > 2:
|
||||
bar = sys.argv[2]
|
||||
if len(sys.argv) > 3:
|
||||
bar_size = int(sys.argv[3])
|
||||
print("[CommPCIe] bar: {} / ".format(bar), end="")
|
||||
comm = CommPCIe(bar)
|
||||
pcie_bar = args.pcie_bar
|
||||
if args.pcie_bar is None:
|
||||
print("Need to speficy --pcie-bar, exiting.")
|
||||
exit()
|
||||
print("[CommPCIe] bar: {} / ".format(args.pcie_bar), end="")
|
||||
comm = CommPCIe(args.pcie_bar)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
parser.print_help()
|
||||
exit()
|
||||
|
||||
server = RemoteServer(comm)
|
||||
server = RemoteServer(comm, args.bind_ip, int(args.bind_port))
|
||||
server.open()
|
||||
server.start(4)
|
||||
try:
|
||||
|
|
|
@ -215,14 +215,20 @@ def main():
|
|||
|
||||
sim_config = SimConfig(default_clk="sys_clk")
|
||||
sim_config.add_module("serial2console", "serial")
|
||||
|
||||
cpu_endianness = "big"
|
||||
if "cpu_type" in soc_kwargs:
|
||||
if soc_kwargs["cpu_type"] in ["picorv32", "vexriscv"]:
|
||||
cpu_endianness = "little"
|
||||
|
||||
if args.rom_init:
|
||||
soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init)
|
||||
soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init, cpu_endianness)
|
||||
if not args.with_sdram:
|
||||
soc_kwargs["integrated_main_ram_size"] = 0x10000
|
||||
soc_kwargs["integrated_main_ram_size"] = 0x10000000 # 256 MB
|
||||
if args.ram_init is not None:
|
||||
soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init)
|
||||
soc_kwargs["integrated_main_ram_size"] = max(len(soc_kwargs["integrated_main_ram_init"]), 0x10000)
|
||||
soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init, cpu_endianness)
|
||||
else:
|
||||
assert args.ram_init is None
|
||||
soc_kwargs["integrated_main_ram_size"] = 0x0
|
||||
if args.with_ethernet:
|
||||
sim_config.add_module("ethernet", "eth", args={"interface": "tap0", "ip": "192.168.1.100"})
|
||||
|
@ -235,6 +241,8 @@ def main():
|
|||
with_etherbone=args.with_etherbone,
|
||||
with_analyzer=args.with_analyzer,
|
||||
**soc_kwargs)
|
||||
if args.ram_init is not None:
|
||||
soc.add_constant("ROM_BOOT_ADDRESS", 0x40000000)
|
||||
builder_kwargs["csr_csv"] = "csr.csv"
|
||||
builder = Builder(soc, **builder_kwargs)
|
||||
vns = builder.build(run=False, threads=args.threads, sim_config=sim_config, trace=args.trace)
|
||||
|
|
|
@ -15,6 +15,7 @@ repos = [
|
|||
("liteusb", ("http://github.com/enjoy-digital/", False, True)),
|
||||
("litedram", ("http://github.com/enjoy-digital/", False, True)),
|
||||
("litepcie", ("http://github.com/enjoy-digital/", False, True)),
|
||||
("litesata", ("http://github.com/enjoy-digital/", False, True)),
|
||||
("litesdcard", ("http://github.com/enjoy-digital/", False, True)),
|
||||
("liteiclink", ("http://github.com/enjoy-digital/", False, True)),
|
||||
("litevideo", ("http://github.com/enjoy-digital/", False, True)),
|
||||
|
|
Loading…
Reference in a new issue