604 lines
23 KiB
Diff
604 lines
23 KiB
Diff
|
# 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
|