forked from M-Labs/nix-servo
add fast-servo linien gateware
This commit is contained in:
parent
65add988dc
commit
86bffe7280
|
@ -0,0 +1,38 @@
|
|||
# diff from elhep/Fast-Servo-Firmmware commit ID 7fae40c:
|
||||
# https://github.com/elhep/Fast-Servo-Firmware/commit/7fae40c0f872a91218be378f8289b98b1e366729
|
||||
# Fix for migen add_source deprecation and removed xilinx bootgen command
|
||||
# .bin file is being generated by bit2bin.py from Linien repository
|
||||
# https://github.com/linien-org/linien/blob/master/gateware/bit2bin.py
|
||||
|
||||
diff --git a/fast_servo/gateware/fast_servo_platform.py b/fast_servo/gateware/fast_servo_platform.py
|
||||
index 13b4aa3..89a8103 100644
|
||||
--- a/fast_servo/gateware/fast_servo_platform.py
|
||||
+++ b/fast_servo/gateware/fast_servo_platform.py
|
||||
@@ -324,7 +324,12 @@ class Platform(XilinxPlatform):
|
||||
self.ps7_config = ps7_config
|
||||
|
||||
verilog_sources = os.listdir(verilog_dir)
|
||||
- self.add_sources(verilog_dir, *verilog_sources)
|
||||
+ self.add_source_dir(verilog_dir)
|
||||
+
|
||||
+ def build(self, *args, **kwargs):
|
||||
+ build_dir = kwargs.get('build_dir', 'build')
|
||||
+ self.copy_sources(build_dir)
|
||||
+ super().build(*args, **kwargs)
|
||||
|
||||
def do_finalize(self, fragment):
|
||||
try:
|
||||
diff --git a/fast_servo/gateware/fast_servo_soc.py b/fast_servo/gateware/fast_servo_soc.py
|
||||
index 02128f5..abfc583 100644
|
||||
--- a/fast_servo/gateware/fast_servo_soc.py
|
||||
+++ b/fast_servo/gateware/fast_servo_soc.py
|
||||
@@ -282,9 +282,3 @@ if __name__ == "__main__":
|
||||
os.chdir(os.path.join(root_path, build_dir))
|
||||
with open(f"{build_name}.bif", "w") as f:
|
||||
f.write(f"all:\n{{\n\t{build_name}.bit\n}}")
|
||||
-
|
||||
- cmd = f"bootgen -image {build_name}.bif -arch zynq -process_bitstream bin -w on".split(" ")
|
||||
- subprocess.run(cmd)
|
||||
-
|
||||
-
|
||||
-
|
|
@ -0,0 +1,603 @@
|
|||
# diff between linen-org/linien commit ID 93f1f50:
|
||||
# https://github.com/linien-org/linien/commit/93f1f50ebd86fe3314cab5a549462d0fcbf6a658
|
||||
# and elhep/linien commit ID b73eea0:
|
||||
# https://github.com/elhep/linien/commit/b73eea07889dda8b55f0cf4c2afde96cf4c3efd1
|
||||
|
||||
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
|
||||
index b3f3683..98c6e51 100644
|
||||
--- a/.pre-commit-config.yaml
|
||||
+++ b/.pre-commit-config.yaml
|
||||
@@ -3,7 +3,7 @@ repos:
|
||||
rev: 23.11.0
|
||||
hooks:
|
||||
- id: black
|
||||
- exclude: ^(gateware/logic/|gateware/lowlevel/|gateware/linien_module.py|linien-server/linien_server/csrmap.py)
|
||||
+ exclude: ^(gateware/logic/|gateware/lowlevel/|gateware/linien_module.py|linien-server/linien_server/csrmap.py|gateware/targets)
|
||||
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.12.0
|
||||
diff --git a/gateware/build_fpga_image.sh b/gateware/build_fpga_image.sh
|
||||
index f822402..be7401c 100644
|
||||
--- a/gateware/build_fpga_image.sh
|
||||
+++ b/gateware/build_fpga_image.sh
|
||||
@@ -16,4 +16,9 @@ export PATH=$VIVADOPATH:$PATH
|
||||
|
||||
rm linien-server/linien_server/gateware.bin -f
|
||||
# run with -m option to avoid errors related to relative imports without breaking pytest
|
||||
-python3 -m gateware.fpga_image_helper
|
||||
\ No newline at end of file
|
||||
+
|
||||
+if [ -z "$1" ]; then
|
||||
+ python3 -m gateware.fpga_image_helper
|
||||
+else
|
||||
+ python3 -m gateware.fpga_image_helper -p $1
|
||||
+fi
|
||||
\ No newline at end of file
|
||||
diff --git a/gateware/fpga_image_helper.py b/gateware/fpga_image_helper.py
|
||||
index 6c34429..a0b12d0 100644
|
||||
--- a/gateware/fpga_image_helper.py
|
||||
+++ b/gateware/fpga_image_helper.py
|
||||
@@ -1,5 +1,6 @@
|
||||
# Copyright 2014-2015 Robert Jördens <jordens@gmail.com>
|
||||
# Copyright 2018-2022 Benjamin Wiegand <benjamin.wiegand@physik.hu-berlin.de>
|
||||
+# Copyright 2023 Jakub Matyas <jakubk.m@gmail.com>
|
||||
#
|
||||
# This file is part of Linien and based on redpid.
|
||||
#
|
||||
@@ -23,14 +24,16 @@ from pathlib import Path
|
||||
REPO_ROOT_DIR = Path(__file__).resolve().parents[1]
|
||||
|
||||
from .bit2bin import bit2bin
|
||||
-from .hw_platform import Platform
|
||||
-from .linien_module import RootModule
|
||||
|
||||
|
||||
def py_csrconstants(map, fil):
|
||||
fil.write("csr_constants = {\n")
|
||||
- for k, v in root.linien.csrbanks.constants:
|
||||
- fil.write(" '{}_{}': {},\n".format(k, v.name, v.value.value))
|
||||
+ for k, v in root.csrbanks.constants:
|
||||
+ if k == "linien":
|
||||
+ # compaitbility layer
|
||||
+ fil.write(" '{}': {},\n".format(v.name, v.value.value))
|
||||
+ else:
|
||||
+ fil.write(" '{}_{}': {},\n".format(k, v.name, v.value.value))
|
||||
fil.write("}\n\n")
|
||||
|
||||
|
||||
@@ -52,26 +55,49 @@ def get_csrmap(banks):
|
||||
def py_csrmap(it, fil):
|
||||
fil.write("csr = {\n")
|
||||
for reg in it:
|
||||
- fil.write(" '{}_{}': ({}, 0x{:03x}, {}, {}),\n".format(*reg))
|
||||
+ main_name = reg[0]
|
||||
+ secondary_name = reg[1]
|
||||
+ # compaitbility layer
|
||||
+ if main_name == "linien" or secondary_name.startswith(main_name):
|
||||
+ fil.write(" '{}': ({}, 0x{:03x}, {}, {}),\n".format(*reg[1:]))
|
||||
+ else:
|
||||
+ fil.write(" '{}_{}': ({}, 0x{:03x}, {}, {}),\n".format(*reg))
|
||||
fil.write("}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
- platform = Platform()
|
||||
- root = RootModule(platform)
|
||||
+ import argparse
|
||||
|
||||
+ parser = argparse.ArgumentParser()
|
||||
+ parser.add_argument("-p", "--platform", default=None)
|
||||
+ args = parser.parse_args()
|
||||
+ if args.platform is None or args.platform.lower() == "redpitaya":
|
||||
+ from gateware.hw_platform import Platform
|
||||
+ from gateware.targets.red_pitaya import PitayaSoC
|
||||
+
|
||||
+ platform = Platform()
|
||||
+ root = PitayaSoC(platform)
|
||||
+ elif args.platform.lower() == "fastservo":
|
||||
+ from fast_servo.gateware.fast_servo_platform import Platform
|
||||
+
|
||||
+ from gateware.targets.fast_servo import LinienFastServo
|
||||
+
|
||||
+ platform = Platform()
|
||||
+ root = LinienFastServo(platform)
|
||||
+ else:
|
||||
+ raise ValueError("Unknown platform")
|
||||
+
|
||||
+ platform.add_source_dir(REPO_ROOT_DIR / "gateware" / "verilog")
|
||||
+ build_dir = REPO_ROOT_DIR / "gateware" / "build"
|
||||
+ platform.build(root, build_name="top", build_dir=build_dir, run=True)
|
||||
with open(
|
||||
REPO_ROOT_DIR / "linien-server" / "linien_server" / "csrmap.py", "w"
|
||||
) as fil:
|
||||
- py_csrconstants(root.linien.csrbanks.constants, fil)
|
||||
- csr = get_csrmap(root.linien.csrbanks.banks)
|
||||
+ py_csrconstants(root.csrbanks.constants, fil)
|
||||
+ csr = get_csrmap([*root.csrbanks.banks, *root.linien.csrbanks.banks])
|
||||
py_csrmap(csr, fil)
|
||||
fil.write("states = {}\n".format(repr(root.linien.state_names)))
|
||||
fil.write("signals = {}\n".format(repr(root.linien.signal_names)))
|
||||
-
|
||||
- platform.add_source_dir(REPO_ROOT_DIR / "gateware" / "verilog")
|
||||
- build_dir = REPO_ROOT_DIR / "gateware" / "build"
|
||||
- platform.build(root, build_name="top", build_dir=build_dir)
|
||||
bit2bin(
|
||||
build_dir / "top.bit",
|
||||
REPO_ROOT_DIR / "linien-server" / "linien_server" / "gateware.bin",
|
||||
diff --git a/gateware/linien_module.py b/gateware/linien_module.py
|
||||
index 16ca186..6905ac0 100644
|
||||
--- a/gateware/linien_module.py
|
||||
+++ b/gateware/linien_module.py
|
||||
@@ -2,6 +2,7 @@
|
||||
# Copyright 2018-2022 Benjamin Wiegand <benjamin.wiegand@physik.hu-berlin.de>
|
||||
# Copyright 2021-2023 Bastian Leykauf <leykauf@physik.hu-berlin.de>
|
||||
# Copyright 2022 Christian Freier <christian.freier@nomadatomics.com>
|
||||
+# Copyright 2023 Jakub Matyas <jakubk.m@gmail.com>
|
||||
#
|
||||
# This file is part of Linien and based on redpid.
|
||||
#
|
||||
@@ -36,19 +37,13 @@ from misoc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage
|
||||
from .logic.autolock import FPGAAutolock
|
||||
from .logic.chains import FastChain, SlowChain, cross_connect
|
||||
from .logic.decimation import Decimate
|
||||
-from .logic.delta_sigma import DeltaSigma
|
||||
from .logic.iir import Iir
|
||||
from .logic.limit import LimitCSR
|
||||
from .logic.modulate import Modulate
|
||||
from .logic.pid import PID
|
||||
from .logic.sweep import SweepCSR
|
||||
-from .lowlevel.analog import PitayaAnalog
|
||||
-from .lowlevel.crg import CRG
|
||||
-from .lowlevel.dna import DNA
|
||||
-from .lowlevel.gpio import Gpio
|
||||
-from .lowlevel.pitaya_ps import PitayaPS, Sys2CSR, SysCDC, SysInterconnect
|
||||
+from .lowlevel.pitaya_ps import Sys2CSR
|
||||
from .lowlevel.scopegen import ScopeGen
|
||||
-from .lowlevel.xadc import XADC
|
||||
|
||||
|
||||
class LinienLogic(Module, AutoCSR):
|
||||
@@ -156,45 +151,24 @@ class LinienLogic(Module, AutoCSR):
|
||||
|
||||
|
||||
class LinienModule(Module, AutoCSR):
|
||||
- def __init__(self, platform):
|
||||
+ def __init__(self, soc):
|
||||
width = 14
|
||||
signal_width = 25
|
||||
coeff_width = 25
|
||||
chain_factor_bits = 8
|
||||
|
||||
self.init_submodules(
|
||||
- width, signal_width, coeff_width, chain_factor_bits, platform
|
||||
+ width, signal_width, coeff_width, chain_factor_bits, soc
|
||||
)
|
||||
- self.connect_everything(width, signal_width, coeff_width, chain_factor_bits)
|
||||
+ self.connect_everything(width, signal_width, coeff_width, chain_factor_bits, soc)
|
||||
|
||||
def init_submodules(
|
||||
- self, width, signal_width, coeff_width, chain_factor_bits, platform
|
||||
+ self, width, signal_width, coeff_width, chain_factor_bits, soc
|
||||
):
|
||||
- sys_double = ClockDomainsRenamer("sys_double")
|
||||
|
||||
self.submodules.logic = LinienLogic(
|
||||
coeff_width=coeff_width, chain_factor_width=chain_factor_bits
|
||||
)
|
||||
- self.submodules.analog = PitayaAnalog(
|
||||
- platform.request("adc"), platform.request("dac")
|
||||
- )
|
||||
- self.submodules.xadc = XADC(platform.request("xadc"))
|
||||
-
|
||||
- for i in range(4):
|
||||
- pwm = platform.request("pwm", i)
|
||||
- ds = sys_double(DeltaSigma(width=15))
|
||||
- self.comb += pwm.eq(ds.out)
|
||||
- setattr(self.submodules, f"ds{i}", ds)
|
||||
-
|
||||
- exp = platform.request("exp")
|
||||
- self.submodules.gpio_n = Gpio(exp.n)
|
||||
- self.submodules.gpio_p = Gpio(exp.p)
|
||||
-
|
||||
- leds = Cat(*(platform.request("user_led", i) for i in range(8)))
|
||||
- self.comb += leds.eq(self.gpio_n.o)
|
||||
-
|
||||
- self.submodules.dna = DNA(version=2)
|
||||
-
|
||||
self.submodules.fast_a = FastChain(
|
||||
width,
|
||||
signal_width,
|
||||
@@ -210,18 +184,22 @@ class LinienModule(Module, AutoCSR):
|
||||
offset_signal=self.logic.chain_b_offset_signed,
|
||||
)
|
||||
|
||||
+ # FIXME: does it do anything?!
|
||||
_ = ClockDomainsRenamer("sys_slow")
|
||||
sys_double = ClockDomainsRenamer("sys_double")
|
||||
max_decimation = 16
|
||||
self.submodules.decimate = sys_double(Decimate(max_decimation))
|
||||
self.clock_domains.cd_decimated_clock = ClockDomain()
|
||||
decimated_clock = ClockDomainsRenamer("decimated_clock")
|
||||
+ # TODO: No support for slow Analog Out on Fast Servo
|
||||
self.submodules.slow_chain = decimated_clock(SlowChain())
|
||||
-
|
||||
self.submodules.scopegen = ScopeGen(signal_width)
|
||||
|
||||
+ soc.add_interconnect_slave(self.scopegen.scope_sys)
|
||||
+ soc.add_interconnect_slave(self.scopegen.asg_sys)
|
||||
+
|
||||
self.state_names, self.signal_names = cross_connect(
|
||||
- self.gpio_n,
|
||||
+ soc.gpio_n,
|
||||
[
|
||||
("fast_a", self.fast_a),
|
||||
("fast_b", self.fast_b),
|
||||
@@ -233,10 +211,6 @@ class LinienModule(Module, AutoCSR):
|
||||
)
|
||||
|
||||
csr_map = {
|
||||
- "dna": 28,
|
||||
- "xadc": 29,
|
||||
- "gpio_n": 30,
|
||||
- "gpio_p": 31,
|
||||
"fast_a": 0,
|
||||
"fast_b": 1,
|
||||
"slow_chain": 2,
|
||||
@@ -251,19 +225,13 @@ class LinienModule(Module, AutoCSR):
|
||||
name if mem is None else name + "_" + mem.name_override
|
||||
],
|
||||
)
|
||||
- self.submodules.sys2csr = Sys2CSR()
|
||||
- self.submodules.csrcon = csr_bus.Interconnect(
|
||||
- self.sys2csr.csr, self.csrbanks.get_buses()
|
||||
- )
|
||||
- self.submodules.syscdc = SysCDC()
|
||||
- self.comb += self.syscdc.target.connect(self.sys2csr.sys)
|
||||
|
||||
- def connect_everything(self, width, signal_width, coeff_width, chain_factor_bits):
|
||||
+ def connect_everything(self, width, signal_width, coeff_width, chain_factor_bits, soc):
|
||||
s = signal_width - width
|
||||
|
||||
self.comb += [
|
||||
- self.fast_a.adc.eq(self.analog.adc_a),
|
||||
- self.fast_b.adc.eq(self.analog.adc_b),
|
||||
+ self.fast_a.adc.eq(soc.analog.adc_a),
|
||||
+ self.fast_b.adc.eq(soc.analog.adc_b),
|
||||
]
|
||||
|
||||
# now, we combine the output of the two paths, with a variable factor each.
|
||||
@@ -297,7 +265,7 @@ class LinienModule(Module, AutoCSR):
|
||||
self.comb += [
|
||||
If(
|
||||
self.logic.pid_only_mode.storage,
|
||||
- self.logic.pid.input.eq(self.analog.adc_a << s),
|
||||
+ self.logic.pid.input.eq(soc.analog.adc_a << s),
|
||||
).Else(
|
||||
self.logic.pid.input.eq(mixed_limited),
|
||||
),
|
||||
@@ -347,40 +315,42 @@ class LinienModule(Module, AutoCSR):
|
||||
# ANALOG OUTPUTS ---------------------------------------------------------------
|
||||
# ANALOG OUT 0 gets a special treatment because it may contain signal of slow
|
||||
# pid or sweep
|
||||
- analog_out = Signal((width + 3, True))
|
||||
- self.comb += [
|
||||
- analog_out.eq(
|
||||
- Mux(
|
||||
- self.logic.sweep_channel.storage == OutputChannel.ANALOG_OUT0,
|
||||
- self.logic.sweep.y,
|
||||
- 0,
|
||||
- )
|
||||
- + Mux(
|
||||
- self.logic.sweep_channel.storage == OutputChannel.ANALOG_OUT0,
|
||||
- self.logic.out_offset_signed,
|
||||
- 0,
|
||||
- )
|
||||
- + Mux(
|
||||
- self.logic.slow_control_channel.storage
|
||||
+
|
||||
+ if soc.soc_name == "RedPitaya":
|
||||
+ analog_out = Signal((width + 3, True))
|
||||
+ self.comb += [
|
||||
+ analog_out.eq(
|
||||
+ Mux(
|
||||
+ self.logic.sweep_channel.storage == OutputChannel.ANALOG_OUT0,
|
||||
+ self.logic.sweep.y,
|
||||
+ 0,
|
||||
+ )
|
||||
+ + Mux(
|
||||
+ self.logic.sweep_channel.storage == OutputChannel.ANALOG_OUT0,
|
||||
+ self.logic.out_offset_signed,
|
||||
+ 0,
|
||||
+ )
|
||||
+ + Mux(
|
||||
+ self.logic.slow_control_channel.storage
|
||||
== OutputChannel.ANALOG_OUT0,
|
||||
self.slow_chain.output,
|
||||
- 0,
|
||||
- )
|
||||
- ),
|
||||
- ]
|
||||
- # NOTE: not sure why limit is used
|
||||
- self.comb += self.slow_chain.limit.x.eq(analog_out)
|
||||
- # ds0 apparently has 16 bit, but only allowing positive values --> "15 bit"?
|
||||
- slow_out_shifted = Signal(15)
|
||||
- self.sync += slow_out_shifted.eq((self.slow_chain.limit.y << 1) + (1 << 14))
|
||||
- self.comb += self.ds0.data.eq(slow_out_shifted)
|
||||
-
|
||||
- # connect other analog outputs
|
||||
- self.comb += [
|
||||
- self.ds1.data.eq(self.logic.analog_out_1.storage),
|
||||
- self.ds2.data.eq(self.logic.analog_out_2.storage),
|
||||
- self.ds3.data.eq(self.logic.analog_out_3.storage),
|
||||
- ]
|
||||
+ 0,
|
||||
+ )
|
||||
+ ),
|
||||
+ ]
|
||||
+ # NOTE: not sure why limit is used
|
||||
+ self.comb += self.slow_chain.limit.x.eq(analog_out)
|
||||
+ # ds0 apparently has 16 bit, but only allowing positive values --> "15 bit"?
|
||||
+ slow_out_shifted = Signal(15)
|
||||
+ self.sync += slow_out_shifted.eq((self.slow_chain.limit.y << 1) + (1 << 14))
|
||||
+ self.comb += soc.ds0.data.eq(slow_out_shifted)
|
||||
+
|
||||
+ # connect other analog outputs
|
||||
+ self.comb += [
|
||||
+ soc.ds1.data.eq(self.logic.analog_out_1.storage),
|
||||
+ soc.ds2.data.eq(self.logic.analog_out_2.storage),
|
||||
+ soc.ds3.data.eq(self.logic.analog_out_3.storage),
|
||||
+ ]
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
@@ -395,7 +365,7 @@ class LinienModule(Module, AutoCSR):
|
||||
|
||||
self.comb += [
|
||||
self.logic.autolock.robust.at_start.eq(self.logic.sweep.sweep.trigger),
|
||||
- self.scopegen.gpio_trigger.eq(self.gpio_p.i[0]),
|
||||
+ self.scopegen.gpio_trigger.eq(soc.gpio_p.i[0]),
|
||||
self.scopegen.sweep_trigger.eq(self.logic.sweep.sweep.trigger),
|
||||
self.scopegen.automatically_rearm.eq(
|
||||
self.logic.autolock.request_lock.storage
|
||||
@@ -404,8 +374,8 @@ class LinienModule(Module, AutoCSR):
|
||||
self.scopegen.automatically_trigger.eq(
|
||||
self.logic.autolock.lock_running.status
|
||||
),
|
||||
- self.analog.dac_a.eq(self.logic.limit_fast1.y),
|
||||
- self.analog.dac_b.eq(self.logic.limit_fast2.y),
|
||||
+ soc.analog.dac_a.eq(self.logic.limit_fast1.y),
|
||||
+ soc.analog.dac_b.eq(self.logic.limit_fast2.y),
|
||||
]
|
||||
|
||||
# Having this in a comb statement caused errors. See PR #251.
|
||||
@@ -428,23 +398,4 @@ class DummyHK(Module, AutoCSR):
|
||||
self.submodules.csrcon = csr_bus.Interconnect(
|
||||
self.sys2csr.csr, self.csrbanks.get_buses()
|
||||
)
|
||||
- self.sys = self.sys2csr.sys
|
||||
-
|
||||
-
|
||||
-class RootModule(Module):
|
||||
- def __init__(self, platform):
|
||||
- self.submodules.ps = PitayaPS(platform.request("cpu"))
|
||||
- self.submodules.crg = CRG(
|
||||
- platform.request("clk125"), self.ps.fclk[0], ~self.ps.frstn[0]
|
||||
- )
|
||||
- self.submodules.linien = LinienModule(platform)
|
||||
-
|
||||
- self.submodules.hk = ClockDomainsRenamer("sys_ps")(DummyHK())
|
||||
-
|
||||
- self.submodules.ic = SysInterconnect(
|
||||
- self.ps.axi.sys,
|
||||
- self.hk.sys,
|
||||
- self.linien.scopegen.scope_sys,
|
||||
- self.linien.scopegen.asg_sys,
|
||||
- self.linien.syscdc.source,
|
||||
- )
|
||||
+ self.sys = self.sys2csr.sys
|
||||
\ No newline at end of file
|
||||
diff --git a/gateware/targets/__init__.py b/gateware/targets/__init__.py
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
diff --git a/gateware/targets/fast_servo.py b/gateware/targets/fast_servo.py
|
||||
new file mode 100644
|
||||
index 0000000..da5bf3b
|
||||
--- /dev/null
|
||||
+++ b/gateware/targets/fast_servo.py
|
||||
@@ -0,0 +1,85 @@
|
||||
+# Copyright 2023 Jakub Matyas <jakubk.m@gmail.com>
|
||||
+# Warsaw University of Technology
|
||||
+#
|
||||
+# This file is part of Linien and provides support for Linien on
|
||||
+# Fast Servo platform.
|
||||
+#
|
||||
+# Linien is free software: you can redistribute it and/or modify
|
||||
+# it under the terms of the GNU General Public License as published by
|
||||
+# the Free Software Foundation, either version 3 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# Linien is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with Linien. If not, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+from fast_servo.gateware.fast_servo_soc import BaseSoC
|
||||
+from migen import *
|
||||
+from misoc.interconnect import csr_bus
|
||||
+
|
||||
+from gateware.linien_module import DummyHK, LinienModule
|
||||
+from gateware.lowlevel.dna import DNA
|
||||
+from gateware.lowlevel.gpio import Gpio
|
||||
+from gateware.lowlevel.pitaya_ps import SysInterconnect
|
||||
+
|
||||
+
|
||||
+class FastServoAnalog(Module):
|
||||
+ def __init__(self, adc, dac):
|
||||
+ size = 14 # length of DAC
|
||||
+
|
||||
+ self.adc_a = Signal(size)
|
||||
+ self.adc_b = Signal(size)
|
||||
+ self.dac_a = Signal(size)
|
||||
+ self.dac_b = Signal(size)
|
||||
+
|
||||
+ self.comb += [
|
||||
+ self.adc_a.eq(adc.data_out[0][2:]),
|
||||
+ self.adc_b.eq(adc.data_out[1][2:]),
|
||||
+ ]
|
||||
+
|
||||
+ self.sync += [
|
||||
+ dac.data_in[0].eq(self.dac_a),
|
||||
+ dac.data_in[1].eq(self.dac_b),
|
||||
+ ]
|
||||
+
|
||||
+
|
||||
+class LinienFastServo(BaseSoC):
|
||||
+ def __init__(self, platform):
|
||||
+ super().__init__(platform)
|
||||
+
|
||||
+ self.submodules.dna = DNA(version=2)
|
||||
+
|
||||
+ self.submodules.analog = FastServoAnalog(self.adc, self.dac)
|
||||
+ gpios = platform.request("gpio")
|
||||
+ self.submodules.gpio_n = Gpio(gpios.n)
|
||||
+ # self.csr_devices.append("gpio_n")
|
||||
+ self.submodules.gpio_p = Gpio(gpios.p)
|
||||
+ # self.csr_devices.append("gpio_p")
|
||||
+ self.csr_map.update({
|
||||
+ "dna": 28,
|
||||
+ "gpio_n": 30,
|
||||
+ "gpio_p": 31,
|
||||
+ })
|
||||
+
|
||||
+ # ---------------------------------------------
|
||||
+ #
|
||||
+ # FIXME - passing self to LinienModule
|
||||
+ self.submodules.linien = LinienModule(self)
|
||||
+
|
||||
+ def soc_finalize(self):
|
||||
+ self.add_interconnect_slave(self.syscdc.source)
|
||||
+ self.submodules.csrbanks = csr_bus.CSRBankArray(self,
|
||||
+ self.get_csr_dev_address)
|
||||
+ self.submodules.csrcon = csr_bus.Interconnect(
|
||||
+ self.sys2csr.csr, [*self.csrbanks.get_buses(), *self.linien.csrbanks.get_buses()]
|
||||
+ )
|
||||
+ self.submodules.hk = DummyHK()
|
||||
+ self.submodules.interconnect = SysInterconnect(
|
||||
+ self.axi2sys.sys,
|
||||
+ self.hk.sys,
|
||||
+ *self.interconnect_slaves
|
||||
+ )
|
||||
\ No newline at end of file
|
||||
diff --git a/gateware/targets/red_pitaya.py b/gateware/targets/red_pitaya.py
|
||||
new file mode 100644
|
||||
index 0000000..c029e81
|
||||
--- /dev/null
|
||||
+++ b/gateware/targets/red_pitaya.py
|
||||
@@ -0,0 +1,103 @@
|
||||
+# Copyright 2014-2015 Robert Jördens <jordens@gmail.com>
|
||||
+# Copyright 2018-2022 Benjamin Wiegand <benjamin.wiegand@physik.hu-berlin.de>
|
||||
+# Copyright 2021-2023 Bastian Leykauf <leykauf@physik.hu-berlin.de>
|
||||
+# Copyright 2022 Christian Freier <christian.freier@nomadatomics.com>
|
||||
+# Copyright 2023 Jakub Matyas <jakubk.m@gmail.com>
|
||||
+#
|
||||
+# This file is part of Linien and based on redpid.
|
||||
+#
|
||||
+# Linien is free software: you can redistribute it and/or modify
|
||||
+# it under the terms of the GNU General Public License as published by
|
||||
+# the Free Software Foundation, either version 3 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# Linien is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with Linien. If not, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+from migen import *
|
||||
+from misoc.interconnect import csr_bus
|
||||
+from misoc.interconnect.csr import AutoCSR
|
||||
+
|
||||
+from gateware.linien_module import DummyHK, LinienModule
|
||||
+from gateware.logic.delta_sigma import DeltaSigma
|
||||
+from gateware.lowlevel.analog import PitayaAnalog
|
||||
+from gateware.lowlevel.crg import CRG
|
||||
+from gateware.lowlevel.dna import DNA
|
||||
+from gateware.lowlevel.gpio import Gpio
|
||||
+from gateware.lowlevel.pitaya_ps import PitayaPS, Sys2CSR, SysCDC, SysInterconnect
|
||||
+from gateware.lowlevel.xadc import XADC
|
||||
+
|
||||
+
|
||||
+class PitayaSoC(Module, AutoCSR):
|
||||
+ def __init__(self, platform):
|
||||
+ self.csr_map = {
|
||||
+ "gpio_n": 30,
|
||||
+ "gpio_p": 31,
|
||||
+ "dna": 28,
|
||||
+ "xadc": 29,
|
||||
+ }
|
||||
+ self.soc_name = "RedPitaya"
|
||||
+ self.interconnect_slaves = []
|
||||
+
|
||||
+ self.submodules.ps = PitayaPS(platform.request("cpu"))
|
||||
+ self.submodules.crg = CRG(
|
||||
+ platform.request("clk125"), self.ps.fclk[0], ~self.ps.frstn[0]
|
||||
+ )
|
||||
+ self.submodules.sys2csr = Sys2CSR()
|
||||
+ self.submodules.syscdc = SysCDC()
|
||||
+ self.comb += self.syscdc.target.connect(self.sys2csr.sys)
|
||||
+
|
||||
+ self.submodules.xadc = XADC(platform.request("xadc"))
|
||||
+ self.submodules.analog = PitayaAnalog(platform.request("adc"), platform.request("dac"))
|
||||
+
|
||||
+ for i in range(4):
|
||||
+ pwm = platform.request("pwm", i)
|
||||
+ ds = ClockDomainsRenamer("sys_double")(DeltaSigma(width=15))
|
||||
+ self.comb += pwm.eq(ds.out)
|
||||
+ setattr(self.submodules, f"ds{i}", ds)
|
||||
+
|
||||
+ exp = platform.request("exp")
|
||||
+ self.submodules.gpio_n = Gpio(exp.n)
|
||||
+ self.submodules.gpio_p = Gpio(exp.p)
|
||||
+
|
||||
+ leds = Cat(*(platform.request("user_led", i) for i in range(8)))
|
||||
+ self.comb += leds.eq(self.gpio_n.o)
|
||||
+
|
||||
+ self.submodules.dna = DNA(version=2)
|
||||
+
|
||||
+ # ---------------------------------------------
|
||||
+ #
|
||||
+ # FIXME - passing self to LinienModule
|
||||
+ self.submodules.linien = LinienModule(self)
|
||||
+ self.add_interconnect_slave(self.syscdc.source)
|
||||
+ self.run_finalize()
|
||||
+
|
||||
+
|
||||
+ def add_interconnect_slave(self, slave):
|
||||
+ self.interconnect_slaves.append(slave)
|
||||
+
|
||||
+ def get_csr_dev_address(self, name, memory):
|
||||
+ if memory is not None:
|
||||
+ name = name + "_" + memory.name_override
|
||||
+ try:
|
||||
+ return self.csr_map[name]
|
||||
+ except KeyError:
|
||||
+ return None
|
||||
+
|
||||
+ def run_finalize(self):
|
||||
+ self.submodules.csrbanks = csr_bus.CSRBankArray(self,
|
||||
+ self.get_csr_dev_address)
|
||||
+ self.submodules.csrcon = csr_bus.Interconnect(
|
||||
+ self.sys2csr.csr, [*self.csrbanks.get_buses(), *self.linien.csrbanks.get_buses()]
|
||||
+ )
|
||||
+ self.submodules.hk = DummyHK()
|
||||
+ self.submodules.interconnect = SysInterconnect(
|
||||
+ self.ps.axi.sys,
|
||||
+ self.hk.sys,
|
||||
+ *self.interconnect_slaves
|
||||
+ )
|
||||
\ No newline at end of file
|
44
flake.lock
44
flake.lock
|
@ -18,11 +18,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1703961334,
|
||||
"narHash": "sha256-M1mV/Cq+pgjk0rt6VxoyyD+O8cOUiai8t9Q6Yyq4noY=",
|
||||
"lastModified": 1706107048,
|
||||
"narHash": "sha256-SqcJ9KxQVY+eLojoqYuJhWa4+D9utUzEuFJzOcUS8iY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b0d36bd0a420ecee3bc916c91886caca87c894e9",
|
||||
"rev": "6fd7935607b68a96949b51ff08f12109e99ffd1f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -56,7 +56,43 @@
|
|||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"not-os": "not-os"
|
||||
"not-os": "not-os",
|
||||
"src-migen": "src-migen",
|
||||
"src-misoc": "src-misoc"
|
||||
}
|
||||
},
|
||||
"src-migen": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1702942348,
|
||||
"narHash": "sha256-gKIfHZxsv+jcgDFRW9mPqmwqbZXuRvXefkZcSFjOGHw=",
|
||||
"owner": "m-labs",
|
||||
"repo": "migen",
|
||||
"rev": "50934ad10a87ade47219b796535978b9bdf24023",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "m-labs",
|
||||
"repo": "migen",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"src-misoc": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1699352904,
|
||||
"narHash": "sha256-SglyTmXOPv8jJOjwAjJrj/WhAkItQfUbvKfUqrynwRg=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "a53859f2167c31ab5225b6c09f30cf05527b94f4",
|
||||
"revCount": 2452,
|
||||
"submodules": true,
|
||||
"type": "git",
|
||||
"url": "https://github.com/m-labs/misoc.git"
|
||||
},
|
||||
"original": {
|
||||
"submodules": true,
|
||||
"type": "git",
|
||||
"url": "https://github.com/m-labs/misoc.git"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
84
flake.nix
84
flake.nix
|
@ -5,7 +5,10 @@
|
|||
inputs.not-os.url = github:cleverca22/not-os;
|
||||
inputs.not-os.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
outputs = { self, nixpkgs, not-os }:
|
||||
inputs.src-migen = { url = github:m-labs/migen; flake = false; };
|
||||
inputs.src-misoc = { type = "git"; url = "https://github.com/m-labs/misoc.git"; submodules = true; flake = false; };
|
||||
|
||||
outputs = { self, nixpkgs, not-os, src-migen, src-misoc }:
|
||||
let
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
||||
not-os-cfg = not-os-configured.config.system;
|
||||
|
@ -22,6 +25,48 @@
|
|||
];
|
||||
};
|
||||
|
||||
migen = pkgs.python3Packages.buildPythonPackage rec {
|
||||
name = "migen";
|
||||
src = src-migen;
|
||||
format = "pyproject";
|
||||
nativeBuildInputs = [ pkgs.python3Packages.setuptools ];
|
||||
propagatedBuildInputs = [ pkgs.python3Packages.colorama ];
|
||||
};
|
||||
|
||||
misoc = pkgs.python3Packages.buildPythonPackage {
|
||||
name = "misoc";
|
||||
src = src-misoc;
|
||||
propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ];
|
||||
};
|
||||
|
||||
vivado = pkgs.buildFHSEnv {
|
||||
name = "vivado";
|
||||
targetPkgs = pkgs: with pkgs; let
|
||||
# Apply patch from https://github.com/nix-community/nix-environments/pull/54
|
||||
# to fix ncurses libtinfo.so's soname issue
|
||||
ncurses' = ncurses5.overrideAttrs (old: {
|
||||
configureFlags = old.configureFlags ++ [ "--with-termlib" ];
|
||||
postFixup = "";
|
||||
});
|
||||
in [
|
||||
libxcrypt-legacy
|
||||
(ncurses'.override { unicodeSupport = false; })
|
||||
zlib
|
||||
libuuid
|
||||
xorg.libSM
|
||||
xorg.libICE
|
||||
xorg.libXrender
|
||||
xorg.libX11
|
||||
xorg.libXext
|
||||
xorg.libXtst
|
||||
xorg.libXi
|
||||
freetype
|
||||
fontconfig
|
||||
];
|
||||
profile = "set -e; source /opt/Xilinx/Vivado/2022.2/settings64.sh";
|
||||
runScript = "vivado";
|
||||
};
|
||||
|
||||
not-os-configured = (import patched-not-os {
|
||||
inherit nixpkgs;
|
||||
extraModules = [
|
||||
|
@ -145,6 +190,34 @@
|
|||
};
|
||||
};
|
||||
|
||||
fast-servo-gateware = pkgs.stdenv.mkDerivation rec {
|
||||
name = "fast-servo-gateware";
|
||||
inherit (pkgs.python3Packages.linien-common) src;
|
||||
prePatch = ''
|
||||
mkdir -p fast_servo/gateware
|
||||
cp -r ${./fast-servo/linien-gateware}/. fast_servo/gateware
|
||||
'';
|
||||
patches = [
|
||||
fast-servo/linien-fast-servo-gateware.patch
|
||||
fast-servo/linien-fast-servo-server.patch
|
||||
];
|
||||
nativeBuildInputs = [
|
||||
(pkgs.python3.withPackages(ps: [ migen misoc ps.linien-common ]))
|
||||
vivado
|
||||
];
|
||||
buildPhase = ''
|
||||
export HOME=$(mktemp -d)
|
||||
python -m gateware.fpga_image_helper -p fastservo
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out $out/nix-support
|
||||
cp gateware/build/top.bit $out
|
||||
cp linien-server/linien_server/gateware.bin $out
|
||||
echo file binary-dist $out/top.bit >> $out/nix-support/hydra-build-products
|
||||
echo file binary-dist $out/gateware.bin >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
};
|
||||
|
||||
mkbootimage = pkgs.stdenv.mkDerivation {
|
||||
pname = "mkbootimage";
|
||||
version = "2.3dev";
|
||||
|
@ -384,10 +457,13 @@
|
|||
in rec {
|
||||
packages.x86_64-linux = {
|
||||
inherit mkbootimage;
|
||||
inherit migen misoc vivado;
|
||||
};
|
||||
packages.armv7l-linux =
|
||||
(board-package-set { board = "zc706"; }) //
|
||||
(board-package-set { board = "fast-servo"; });
|
||||
packages.armv7l-linux = {
|
||||
inherit fast-servo-gateware;
|
||||
} //
|
||||
(board-package-set { board = "zc706"; }) //
|
||||
(board-package-set { board = "fast-servo"; });
|
||||
|
||||
hydraJobs = packages.x86_64-linux // packages.armv7l-linux;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue