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": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1703961334,
|
"lastModified": 1706107048,
|
||||||
"narHash": "sha256-M1mV/Cq+pgjk0rt6VxoyyD+O8cOUiai8t9Q6Yyq4noY=",
|
"narHash": "sha256-SqcJ9KxQVY+eLojoqYuJhWa4+D9utUzEuFJzOcUS8iY=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "b0d36bd0a420ecee3bc916c91886caca87c894e9",
|
"rev": "6fd7935607b68a96949b51ff08f12109e99ffd1f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -56,7 +56,43 @@
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs",
|
"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.url = github:cleverca22/not-os;
|
||||||
inputs.not-os.inputs.nixpkgs.follows = "nixpkgs";
|
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
|
let
|
||||||
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
||||||
not-os-cfg = not-os-configured.config.system;
|
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 {
|
not-os-configured = (import patched-not-os {
|
||||||
inherit nixpkgs;
|
inherit nixpkgs;
|
||||||
extraModules = [
|
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 {
|
mkbootimage = pkgs.stdenv.mkDerivation {
|
||||||
pname = "mkbootimage";
|
pname = "mkbootimage";
|
||||||
version = "2.3dev";
|
version = "2.3dev";
|
||||||
|
@ -384,10 +457,13 @@
|
||||||
in rec {
|
in rec {
|
||||||
packages.x86_64-linux = {
|
packages.x86_64-linux = {
|
||||||
inherit mkbootimage;
|
inherit mkbootimage;
|
||||||
|
inherit migen misoc vivado;
|
||||||
};
|
};
|
||||||
packages.armv7l-linux =
|
packages.armv7l-linux = {
|
||||||
(board-package-set { board = "zc706"; }) //
|
inherit fast-servo-gateware;
|
||||||
(board-package-set { board = "fast-servo"; });
|
} //
|
||||||
|
(board-package-set { board = "zc706"; }) //
|
||||||
|
(board-package-set { board = "fast-servo"; });
|
||||||
|
|
||||||
hydraJobs = packages.x86_64-linux // packages.armv7l-linux;
|
hydraJobs = packages.x86_64-linux // packages.armv7l-linux;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue