1
0
Fork 0

Compare commits

...

65 Commits

Author SHA1 Message Date
Florian Agbuya 1ee382564e add pyfastservo package and initialize at boot 2024-04-24 18:03:17 +08:00
Florian Agbuya 7c6320f66d configure loading of bitstream at boot time 2024-04-24 18:03:17 +08:00
Florian Agbuya 3d98549fd1 rename board specific packages 2024-04-23 14:19:19 +08:00
Florian Agbuya 0ff299aa55 increase qemu image size 2024-04-04 13:43:19 +08:00
Florian Agbuya c2d38540c0 integrate linien-server to not-os 2024-04-04 13:06:01 +08:00
Florian Agbuya d9a2d60b50 configure arm linux toolchain 2024-03-26 17:53:25 +08:00
Florian Agbuya 26dd210eb6 rebase from 251f65f 2024-03-26 17:51:46 +08:00
Florian Agbuya 251f65f217 cross-compilation transferred to crossSystem 2024-03-26 17:50:40 +08:00
Florian Agbuya 0d3f87c5bc use nix gnu toolchain format for baremetal apps 2024-03-25 15:14:15 +08:00
Florian Agbuya 208d56adb2 fix linien-server red pitaya dependencies 2024-03-20 13:40:09 +08:00
Florian Agbuya 628582a981 add spidev on device tree 2024-03-15 11:46:51 +08:00
Florian Agbuya bc09e60a15 add fpga programming support 2024-03-14 13:03:09 +08:00
Florian Agbuya 88b3197c0c add provenance information 2024-03-08 14:35:59 +08:00
Florian Agbuya 0cda432bf9 add fast-servo python init scripts 2024-03-08 14:35:59 +08:00
Florian Agbuya 1244c84f67 fix typo 2024-03-06 17:53:13 +08:00
Florian Agbuya 3618a1f17d add linien-server package 2024-03-06 11:48:08 +08:00
Florian Agbuya 22992e2e82 update nixpkgs and use upstream qemu 2024-03-05 09:50:55 +08:00
Florian Agbuya d6ac3944fb linux: add fpga support 2024-03-04 17:40:33 +08:00
Florian Agbuya c61597ea4f fix qemu build errors 2024-03-01 18:09:53 +08:00
Florian Agbuya efe58d8106 move not-os patches to dedicated folder 2024-03-01 17:14:09 +08:00
Florian Agbuya 007ca18cab fix homeless-shelter error 2024-03-01 16:39:56 +08:00
Florian Agbuya 506bbcc0db add fast-servo linien gateware 2024-03-01 16:39:56 +08:00
Florian Agbuya e12b672cdc add __pycache__ 2024-03-01 16:39:56 +08:00
Florian Agbuya cd9590503c add fast-servo gateware support files 2024-03-01 16:39:56 +08:00
Florian Agbuya e4dcc0e84a configure shutdown instructions in runit stage 3 2024-02-22 09:58:29 +08:00
Florian Agbuya 1f3591a693 add nix substituters and update nix.conf 2024-02-20 14:02:51 +08:00
Florian Agbuya afa00efee3 clean up device tree package 2024-02-20 09:51:57 +08:00
Florian Agbuya 25ef8fa486 refactor build script for better board management 2024-02-20 09:51:57 +08:00
Florian Agbuya 073f1c9bbd device tree source from u-boot and cleanup 2024-02-20 09:51:44 +08:00
Florian Agbuya 388e7e7082 configure qemu with u-boot and cleanup 2024-02-20 09:51:00 +08:00
Florian Agbuya 22129bc04e fix fast-servo u-boot 2024-02-20 09:51:00 +08:00
Florian Agbuya 62b8b691fe configure device-tree support 2024-02-20 09:50:41 +08:00
Florian Agbuya 69a252e488 add fast-servo bootimage, sd-image and cleanup 2024-02-20 09:48:40 +08:00
Florian Agbuya ae31216084 add fast-servo fsbl support 2024-02-20 09:48:40 +08:00
Florian Agbuya e6f4512554 add device-tree builder 2024-02-20 09:48:40 +08:00
Florian Agbuya eb10e3ad4e configure fast-servo u-boot 2024-02-20 09:48:40 +08:00
Florian Agbuya d17356e750 add fast-servo device tree files 2024-02-20 09:48:40 +08:00
Florian Agbuya 72e91bfdb2 set NIX_PATH 2024-02-19 15:55:59 +08:00
Florian Agbuya a86db3cd33 add nano as default text editor 2024-02-15 17:29:11 +08:00
Florian Agbuya 0de5ddeb1e transfer definition of nameserver to avoid patch hunk error 2024-02-15 17:26:56 +08:00
Florian Agbuya 38638fa5fe fix modprobe and nix-path-registration error 2024-02-14 16:58:40 +08:00
Florian Agbuya b252e0a913 add ssl certificates 2024-01-22 11:30:40 +08:00
Florian Agbuya e94262db53 remove kernel module bloat 2024-01-17 17:56:38 +08:00
Florian Agbuya 2639192a92 replace nameserver 2024-01-17 10:33:29 +08:00
Florian Agbuya f6055cf908 fix login errors 2024-01-17 10:16:17 +08:00
Florian Agbuya 8f664049d6 zynq: remove strace and add wget 2024-01-16 14:33:22 +08:00
Florian Agbuya c74391e94e zynq: add first boot commands 2024-01-16 12:21:37 +08:00
Florian Agbuya bd4885c597 enable host key generation on first boot 2024-01-15 17:51:52 +08:00
Florian Agbuya dad71891b6 zynq: configure networking 2024-01-13 21:59:22 +08:00
Florian Agbuya 1f62e6a35e not-os: enable networking 2024-01-08 19:44:52 +08:00
Florian Agbuya 1aee5344a5 flake: add not-os disk image builder and qemu 2024-01-05 12:43:23 +08:00
Sebastien Bourdeauducq 543a8632c6 flake: add hydraJobs 2024-01-02 17:21:01 +08:00
Florian Agbuya f14b459624 flake: apply not-os patches 2024-01-02 17:09:10 +08:00
Florian Agbuya f172746e89 add not-os nixpkgs related patches 2024-01-02 17:06:42 +08:00
Florian Agbuya 0f97509b78 add not-os zynq related patches 2024-01-02 17:05:54 +08:00
Florian Agbuya 3f92b3f13b activationSripts: add previous var value (closes #6) 2024-01-02 14:05:45 +08:00
Florian Agbuya d12dee6198 flake: update flake inputs 2024-01-02 13:41:57 +08:00
Florian Agbuya 791e9abd7a update flake inputs 2023-12-21 15:50:38 +08:00
Florian Agbuya aff470615c update not-os patch 2023-12-21 14:06:24 +08:00
Florian Agbuya 52675eefd4 flake: configure u-boot to autoboot kernel
Signed-off-by: Florian Agbuya <fa@m-labs.ph>
2023-12-20 16:32:54 +08:00
Florian Agbuya 7ae798a809 flake: add various boot fixes
Signed-off-by: Florian Agbuya <fa@m-labs.ph>
2023-12-20 15:19:59 +08:00
Florian Agbuya 3b34e11cbf flake: use the uImage format for not-os 2023-12-13 17:16:10 +08:00
Florian Agbuya ed7d4386b9 update not-os patch hash 2023-12-13 09:55:04 +08:00
Sebastien Bourdeauducq a9a3c64aff fix not-os patch hash 2023-12-12 17:07:18 +08:00
Florian Agbuya 0f1acb3e10 flake: fix not-os
Signed-off-by: Florian Agbuya <fa@m-labs.ph>
2023-12-12 16:49:03 +08:00
39 changed files with 32084 additions and 217 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
__pycache__
result

706
fast-servo/fast-servo.dts Normal file
View File

@ -0,0 +1,706 @@
# 0 "system-top.dts"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "system-top.dts"
/dts-v1/;
# 1 "zynq-7000.dtsi" 1
# 15 "zynq-7000.dtsi"
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "xlnx,zynq-7000";
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu0: cpu@0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0>;
clocks = <&clkc 3>;
clock-latency = <1000>;
cpu0-supply = <&regulator_vccpint>;
operating-points = <
666667 1000000
333334 1000000
>;
};
cpu1: cpu@1 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <1>;
clocks = <&clkc 3>;
};
};
fpga_full: fpga-full {
compatible = "fpga-region";
fpga-mgr = <&devcfg>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
};
pmu@f8891000 {
compatible = "arm,cortex-a9-pmu";
interrupts = <0 5 4>, <0 6 4>;
interrupt-parent = <&intc>;
reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >;
};
regulator_vccpint: fixedregulator {
compatible = "regulator-fixed";
regulator-name = "VCCPINT";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
regulator-boot-on;
regulator-always-on;
};
replicator {
compatible = "arm,coresight-static-replicator";
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
out-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
replicator_out_port0: endpoint {
remote-endpoint = <&tpiu_in_port>;
};
};
port@1 {
reg = <1>;
replicator_out_port1: endpoint {
remote-endpoint = <&etb_in_port>;
};
};
};
in-ports {
port {
replicator_in_port0: endpoint {
remote-endpoint = <&funnel_out_port>;
};
};
};
};
amba: axi {
u-boot,dm-pre-reloc;
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
ranges;
adc: adc@f8007100 {
compatible = "xlnx,zynq-xadc-1.00.a";
reg = <0xf8007100 0x20>;
interrupts = <0 7 4>;
interrupt-parent = <&intc>;
clocks = <&clkc 12>;
};
can0: can@e0008000 {
compatible = "xlnx,zynq-can-1.0";
status = "disabled";
clocks = <&clkc 19>, <&clkc 36>;
clock-names = "can_clk", "pclk";
reg = <0xe0008000 0x1000>;
interrupts = <0 28 4>;
interrupt-parent = <&intc>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
can1: can@e0009000 {
compatible = "xlnx,zynq-can-1.0";
status = "disabled";
clocks = <&clkc 20>, <&clkc 37>;
clock-names = "can_clk", "pclk";
reg = <0xe0009000 0x1000>;
interrupts = <0 51 4>;
interrupt-parent = <&intc>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
gpio0: gpio@e000a000 {
compatible = "xlnx,zynq-gpio-1.0";
#gpio-cells = <2>;
clocks = <&clkc 42>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <0 20 4>;
reg = <0xe000a000 0x1000>;
};
i2c0: i2c@e0004000 {
compatible = "cdns,i2c-r1p10";
status = "disabled";
clocks = <&clkc 38>;
interrupt-parent = <&intc>;
interrupts = <0 25 4>;
reg = <0xe0004000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
};
i2c1: i2c@e0005000 {
compatible = "cdns,i2c-r1p10";
status = "disabled";
clocks = <&clkc 39>;
interrupt-parent = <&intc>;
interrupts = <0 48 4>;
reg = <0xe0005000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
};
intc: interrupt-controller@f8f01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
interrupt-controller;
reg = <0xF8F01000 0x1000>,
<0xF8F00100 0x100>;
};
L2: cache-controller@f8f02000 {
compatible = "arm,pl310-cache";
reg = <0xF8F02000 0x1000>;
interrupts = <0 2 4>;
arm,data-latency = <3 2 2>;
arm,tag-latency = <2 2 2>;
cache-unified;
cache-level = <2>;
};
mc: memory-controller@f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
ocm: sram@fffc0000 {
compatible = "mmio-sram";
reg = <0xfffc0000 0x10000>;
};
uart0: serial@e0000000 {
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
status = "disabled";
clocks = <&clkc 23>, <&clkc 40>;
clock-names = "uart_clk", "pclk";
reg = <0xE0000000 0x1000>;
interrupts = <0 27 4>;
};
uart1: serial@e0001000 {
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
status = "disabled";
clocks = <&clkc 24>, <&clkc 41>;
clock-names = "uart_clk", "pclk";
reg = <0xE0001000 0x1000>;
interrupts = <0 50 4>;
};
spi0: spi@e0006000 {
compatible = "xlnx,zynq-spi-r1p6";
reg = <0xe0006000 0x1000>;
status = "disabled";
interrupt-parent = <&intc>;
interrupts = <0 26 4>;
clocks = <&clkc 25>, <&clkc 34>;
clock-names = "ref_clk", "pclk";
#address-cells = <1>;
#size-cells = <0>;
};
spi1: spi@e0007000 {
compatible = "xlnx,zynq-spi-r1p6";
reg = <0xe0007000 0x1000>;
status = "disabled";
interrupt-parent = <&intc>;
interrupts = <0 49 4>;
clocks = <&clkc 26>, <&clkc 35>;
clock-names = "ref_clk", "pclk";
#address-cells = <1>;
#size-cells = <0>;
};
qspi: spi@e000d000 {
clock-names = "ref_clk", "pclk";
clocks = <&clkc 10>, <&clkc 43>;
compatible = "xlnx,zynq-qspi-1.0";
status = "disabled";
interrupt-parent = <&intc>;
interrupts = <0 19 4>;
reg = <0xe000d000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
};
gem0: ethernet@e000b000 {
compatible = "xlnx,zynq-gem", "cdns,zynq-gem", "cdns,gem";
reg = <0xe000b000 0x1000>;
status = "disabled";
interrupts = <0 22 4>;
clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>;
clock-names = "pclk", "hclk", "tx_clk";
#address-cells = <1>;
#size-cells = <0>;
};
gem1: ethernet@e000c000 {
compatible = "xlnx,zynq-gem", "cdns,zynq-gem", "cdns,gem";
reg = <0xe000c000 0x1000>;
status = "disabled";
interrupts = <0 45 4>;
clocks = <&clkc 31>, <&clkc 31>, <&clkc 14>;
clock-names = "pclk", "hclk", "tx_clk";
#address-cells = <1>;
#size-cells = <0>;
};
smcc: memory-controller@e000e000 {
compatible = "arm,pl353-smc-r2p1", "arm,primecell";
reg = <0xe000e000 0x0001000>;
status = "disabled";
clock-names = "memclk", "apb_pclk";
clocks = <&clkc 11>, <&clkc 44>;
ranges = <0x0 0x0 0xe1000000 0x1000000
0x1 0x0 0xe2000000 0x2000000
0x2 0x0 0xe4000000 0x2000000>;
#address-cells = <2>;
#size-cells = <1>;
interrupt-parent = <&intc>;
interrupts = <0 18 4>;
nfc0: nand-controller@0,0 {
compatible = "arm,pl353-nand-r2p1";
reg = <0 0 0x1000000>;
status = "disabled";
#address-cells = <0x1>;
#size-cells = <0x0>;
};
nor0: flash@1,0 {
status = "disabled";
compatible = "cfi-flash";
reg = <1 0 0x2000000>;
#address-cells = <1>;
#size-cells = <1>;
};
};
sdhci0: mmc@e0100000 {
compatible = "arasan,sdhci-8.9a";
status = "disabled";
clock-names = "clk_xin", "clk_ahb";
clocks = <&clkc 21>, <&clkc 32>;
interrupt-parent = <&intc>;
interrupts = <0 24 4>;
reg = <0xe0100000 0x1000>;
};
sdhci1: mmc@e0101000 {
compatible = "arasan,sdhci-8.9a";
status = "disabled";
clock-names = "clk_xin", "clk_ahb";
clocks = <&clkc 22>, <&clkc 33>;
interrupt-parent = <&intc>;
interrupts = <0 47 4>;
reg = <0xe0101000 0x1000>;
};
slcr: slcr@f8000000 {
u-boot,dm-pre-reloc;
#address-cells = <1>;
#size-cells = <1>;
compatible = "xlnx,zynq-slcr", "syscon", "simple-mfd";
reg = <0xF8000000 0x1000>;
ranges;
clkc: clkc@100 {
u-boot,dm-pre-reloc;
#clock-cells = <1>;
compatible = "xlnx,ps7-clkc";
fclk-enable = <0xf>;
clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x",
"cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x",
"dci", "lqspi", "smc", "pcap", "gem0", "gem1",
"fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1",
"sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1",
"dma", "usb0_aper", "usb1_aper", "gem0_aper",
"gem1_aper", "sdio0_aper", "sdio1_aper",
"spi0_aper", "spi1_aper", "can0_aper", "can1_aper",
"i2c0_aper", "i2c1_aper", "uart0_aper", "uart1_aper",
"gpio_aper", "lqspi_aper", "smc_aper", "swdt",
"dbg_trc", "dbg_apb";
reg = <0x100 0x100>;
};
rstc: rstc@200 {
compatible = "xlnx,zynq-reset";
reg = <0x200 0x48>;
#reset-cells = <1>;
syscon = <&slcr>;
};
pinctrl0: pinctrl@700 {
compatible = "xlnx,pinctrl-zynq";
reg = <0x700 0x200>;
syscon = <&slcr>;
};
};
dmac_s: dmac@f8003000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0xf8003000 0x1000>;
interrupt-parent = <&intc>;
interrupt-names = "abort", "dma0", "dma1", "dma2", "dma3",
"dma4", "dma5", "dma6", "dma7";
interrupts = <0 13 4>,
<0 14 4>, <0 15 4>,
<0 16 4>, <0 17 4>,
<0 40 4>, <0 41 4>,
<0 42 4>, <0 43 4>;
#dma-cells = <1>;
#dma-channels = <8>;
#dma-requests = <4>;
clocks = <&clkc 27>;
clock-names = "apb_pclk";
};
devcfg: devcfg@f8007000 {
compatible = "xlnx,zynq-devcfg-1.0";
interrupt-parent = <&intc>;
interrupts = <0 8 4>;
reg = <0xf8007000 0x100>;
clocks = <&clkc 12>, <&clkc 15>, <&clkc 16>, <&clkc 17>, <&clkc 18>;
clock-names = "ref_clk", "fclk0", "fclk1", "fclk2", "fclk3";
syscon = <&slcr>;
};
efuse: efuse@f800d000 {
compatible = "xlnx,zynq-efuse";
reg = <0xf800d000 0x20>;
};
global_timer: timer@f8f00200 {
compatible = "arm,cortex-a9-global-timer";
reg = <0xf8f00200 0x20>;
interrupts = <1 11 0x301>;
interrupt-parent = <&intc>;
clocks = <&clkc 4>;
};
ttc0: timer@f8001000 {
interrupt-parent = <&intc>;
interrupts = <0 10 4>, <0 11 4>, <0 12 4>;
compatible = "cdns,ttc";
clocks = <&clkc 6>;
reg = <0xF8001000 0x1000>;
};
ttc1: timer@f8002000 {
interrupt-parent = <&intc>;
interrupts = <0 37 4>, <0 38 4>, <0 39 4>;
compatible = "cdns,ttc";
clocks = <&clkc 6>;
reg = <0xF8002000 0x1000>;
};
scutimer: timer@f8f00600 {
interrupt-parent = <&intc>;
interrupts = <1 13 0x301>;
compatible = "arm,cortex-a9-twd-timer";
reg = <0xf8f00600 0x20>;
clocks = <&clkc 4>;
};
usb0: usb@e0002000 {
compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
status = "disabled";
clocks = <&clkc 28>;
interrupt-parent = <&intc>;
interrupts = <0 21 4>;
reg = <0xe0002000 0x1000>;
phy_type = "ulpi";
};
usb1: usb@e0003000 {
compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
status = "disabled";
clocks = <&clkc 29>;
interrupt-parent = <&intc>;
interrupts = <0 44 4>;
reg = <0xe0003000 0x1000>;
phy_type = "ulpi";
};
watchdog0: watchdog@f8005000 {
clocks = <&clkc 45>;
compatible = "cdns,wdt-r1p2";
interrupt-parent = <&intc>;
interrupts = <0 9 1>;
reg = <0xf8005000 0x1000>;
timeout-sec = <10>;
};
etb@f8801000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0xf8801000 0x1000>;
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
in-ports {
port {
etb_in_port: endpoint {
remote-endpoint = <&replicator_out_port1>;
};
};
};
};
tpiu@f8803000 {
compatible = "arm,coresight-tpiu", "arm,primecell";
reg = <0xf8803000 0x1000>;
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
in-ports {
port {
tpiu_in_port: endpoint {
remote-endpoint = <&replicator_out_port0>;
};
};
};
};
funnel@f8804000 {
compatible = "arm,coresight-static-funnel", "arm,primecell";
reg = <0xf8804000 0x1000>;
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
out-ports {
port {
funnel_out_port: endpoint {
remote-endpoint =
<&replicator_in_port0>;
};
};
};
in-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
funnel0_in_port0: endpoint {
remote-endpoint = <&ptm0_out_port>;
};
};
port@1 {
reg = <1>;
funnel0_in_port1: endpoint {
remote-endpoint = <&ptm1_out_port>;
};
};
port@2 {
reg = <2>;
funnel0_in_port2: endpoint {
};
};
};
};
ptm@f889c000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0xf889c000 0x1000>;
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
cpu = <&cpu0>;
out-ports {
port {
ptm0_out_port: endpoint {
remote-endpoint = <&funnel0_in_port0>;
};
};
};
};
ptm@f889d000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0xf889d000 0x1000>;
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
cpu = <&cpu1>;
out-ports {
port {
ptm1_out_port: endpoint {
remote-endpoint = <&funnel0_in_port1>;
};
};
};
};
};
};
# 10 "system-top.dts" 2
# 1 "pcw.dtsi" 1
/ {
cpus {
cpu@0 {
operating-points = <500000 1000000 250000 1000000>;
};
};
};
&gem0 {
enet-reset = <&gpio0 50 0>;
phy-mode = "rgmii-id";
status = "okay";
xlnx,ptp-enet-clock = <0x4f790d8>;
};
&gpio0 {
emio-gpio-width = <64>;
gpio-mask-high = <0x0>;
gpio-mask-low = <0x5600>;
};
&i2c0 {
clock-frequency = <400000>;
status = "okay";
};
&i2c1 {
clock-frequency = <400000>;
status = "okay";
};
&intc {
num_cpus = <2>;
num_interrupts = <96>;
};
&qspi {
is-dual = <0>;
num-cs = <1>;
spi-rx-bus-width = <4>;
spi-tx-bus-width = <4>;
status = "okay";
};
&sdhci0 {
status = "okay";
xlnx,has-cd = <0x0>;
xlnx,has-power = <0x0>;
xlnx,has-wp = <0x0>;
};
&spi0 {
is-decoded-cs = <0>;
num-cs = <3>;
status = "okay";
};
&spi1 {
is-decoded-cs = <0>;
num-cs = <3>;
status = "okay";
};
&uart0 {
cts-override ;
device_type = "serial";
port-number = <0>;
status = "okay";
};
&usb0 {
phy_type = "ulpi";
status = "okay";
usb-reset = <&gpio0 51 0>;
};
&clkc {
fclk-enable = <0x0>;
ps-clk-frequency = <33333333>;
};
# 11 "system-top.dts" 2
# 1 "system-user.dtsi" 1
&spi0 {
is-decoded-cs = <1>;
num-cs = <4>;
spidev@1 {
compatible = "rohm,dh2228fv";
spi-max-frequency = <50000000>;
reg = <1>;
};
spidev@2 {
compatible = "rohm,dh2228fv";
spi-max-frequency = <50000000>;
reg = <2>;
};
spidev@3 {
compatible = "rohm,dh2228fv";
spi-max-frequency = <50000000>;
reg = <3>;
};
spidev@4 {
compatible = "rohm,dh2228fv";
spi-max-frequency = <50000000>;
reg = <4>;
};
};
&spi1 {
spidev@0 {
compatible = "rohm,dh2228fv";
spi-max-frequency = <50000000>;
reg = <0>;
};
};
# 12 "system-top.dts" 2
/ {
model = "Sinara Fast Servo board";
chosen {
bootargs = "earlycon";
stdout-path = "serial0:115200n8";
};
aliases {
ethernet0 = &gem0;
i2c0 = &i2c0;
i2c1 = &i2c1;
serial0 = &uart0;
mmc0 = &sdhci0;
spi0 = &qspi;
spi1 = &spi0;
spi2 = &spi1;
};
memory {
device_type = "memory";
reg = <0x0 0x40000000>;
};
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

241
fast-servo/fsbl.patch Normal file
View File

@ -0,0 +1,241 @@
diff --git a/lib/sw_apps/zynq_fsbl/misc/fast-servo/ps7_init.h b/lib/sw_apps/zynq_fsbl/misc/fast-servo/ps7_init.h
index 9572636306..2f3816271e 100644
--- a/lib/sw_apps/zynq_fsbl/misc/fast-servo/ps7_init.h
+++ b/lib/sw_apps/zynq_fsbl/misc/fast-servo/ps7_init.h
@@ -67,20 +67,20 @@ extern unsigned long * ps7_peripherals_init_data;
/* Freq of all peripherals */
-#define APU_FREQ 666666687
+#define APU_FREQ 500000000
#define DDR_FREQ 533333374
#define DCI_FREQ 10158730
#define QSPI_FREQ 200000000
#define SMC_FREQ 10000000
-#define ENET0_FREQ 25000000
+#define ENET0_FREQ 125000000
#define ENET1_FREQ 10000000
#define USB0_FREQ 60000000
#define USB1_FREQ 60000000
-#define SDIO_FREQ 50000000
-#define UART_FREQ 50000000
-#define SPI_FREQ 10000000
-#define I2C_FREQ 111111115
-#define WDT_FREQ 111111115
+#define SDIO_FREQ 100000000
+#define UART_FREQ 100000000
+#define SPI_FREQ 166666672
+#define I2C_FREQ 83333336
+#define WDT_FREQ 83333336
#define TTC_FREQ 50000000
#define CAN_FREQ 10000000
#define PCAP_FREQ 200000000
diff --git a/lib/sw_apps/zynq_fsbl/misc/fast-servo/ps7_init_gpl.h b/lib/sw_apps/zynq_fsbl/misc/fast-servo/ps7_init_gpl.h
index 8962bed427..df2f16adec 100644
--- a/lib/sw_apps/zynq_fsbl/misc/fast-servo/ps7_init_gpl.h
+++ b/lib/sw_apps/zynq_fsbl/misc/fast-servo/ps7_init_gpl.h
@@ -81,20 +81,20 @@ extern unsigned long * ps7_peripherals_init_data;
/* Freq of all peripherals */
-#define APU_FREQ 666666687
+#define APU_FREQ 500000000
#define DDR_FREQ 533333374
#define DCI_FREQ 10158730
#define QSPI_FREQ 200000000
#define SMC_FREQ 10000000
-#define ENET0_FREQ 25000000
+#define ENET0_FREQ 125000000
#define ENET1_FREQ 10000000
#define USB0_FREQ 60000000
#define USB1_FREQ 60000000
-#define SDIO_FREQ 50000000
-#define UART_FREQ 50000000
-#define SPI_FREQ 10000000
-#define I2C_FREQ 111111115
-#define WDT_FREQ 111111115
+#define SDIO_FREQ 100000000
+#define UART_FREQ 100000000
+#define SPI_FREQ 166666672
+#define I2C_FREQ 83333336
+#define WDT_FREQ 83333336
#define TTC_FREQ 50000000
#define CAN_FREQ 10000000
#define PCAP_FREQ 200000000
diff --git a/lib/sw_apps/zynq_fsbl/misc/fast-servo/xparameters.h b/lib/sw_apps/zynq_fsbl/misc/fast-servo/xparameters.h
index 997a982ca1..5461fbb477 100644
--- a/lib/sw_apps/zynq_fsbl/misc/fast-servo/xparameters.h
+++ b/lib/sw_apps/zynq_fsbl/misc/fast-servo/xparameters.h
@@ -9,21 +9,26 @@
#define XPAR_CPU_ID 0U
/* Definitions for peripheral PS7_CORTEXA9_0 */
-#define XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687
+#define XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ 500000000
/******************************************************************/
/* Canonical definitions for peripheral PS7_CORTEXA9_0 */
-#define XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ 666666687
+#define XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ 500000000
/******************************************************************/
+
+/* Definitions for interface M_AXI_GP0 */
+#define XPAR_M_AXI_GP0_BASEADDR 0x40000000
+#define XPAR_M_AXI_GP0_HIGHADDR 0x40001FFF
+
#include "xparameters_ps.h"
-#define STDIN_BASEADDRESS 0xE0001000
-#define STDOUT_BASEADDRESS 0xE0001000
+#define STDIN_BASEADDRESS 0xE0000000
+#define STDOUT_BASEADDRESS 0xE0000000
/******************************************************************/
@@ -120,7 +125,7 @@
#define XPAR_PS7_ETHERNET_0_DEVICE_ID 0
#define XPAR_PS7_ETHERNET_0_BASEADDR 0xE000B000
#define XPAR_PS7_ETHERNET_0_HIGHADDR 0xE000BFFF
-#define XPAR_PS7_ETHERNET_0_ENET_CLK_FREQ_HZ 25000000
+#define XPAR_PS7_ETHERNET_0_ENET_CLK_FREQ_HZ 125000000
#define XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0 8
#define XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1 1
#define XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0 8
@@ -138,7 +143,7 @@
#define XPAR_XEMACPS_0_DEVICE_ID XPAR_PS7_ETHERNET_0_DEVICE_ID
#define XPAR_XEMACPS_0_BASEADDR 0xE000B000
#define XPAR_XEMACPS_0_HIGHADDR 0xE000BFFF
-#define XPAR_XEMACPS_0_ENET_CLK_FREQ_HZ 25000000
+#define XPAR_XEMACPS_0_ENET_CLK_FREQ_HZ 125000000
#define XPAR_XEMACPS_0_ENET_SLCR_1000Mbps_DIV0 8
#define XPAR_XEMACPS_0_ENET_SLCR_1000Mbps_DIV1 1
#define XPAR_XEMACPS_0_ENET_SLCR_100Mbps_DIV0 8
@@ -265,13 +270,13 @@
/******************************************************************/
/* Definitions for driver IICPS */
-#define XPAR_XIICPS_NUM_INSTANCES 1
+#define XPAR_XIICPS_NUM_INSTANCES 2
/* Definitions for peripheral PS7_I2C_0 */
#define XPAR_PS7_I2C_0_DEVICE_ID 0
#define XPAR_PS7_I2C_0_BASEADDR 0xE0004000
#define XPAR_PS7_I2C_0_HIGHADDR 0xE0004FFF
-#define XPAR_PS7_I2C_0_I2C_CLK_FREQ_HZ 111111115
+#define XPAR_PS7_I2C_0_I2C_CLK_FREQ_HZ 83333336
/******************************************************************/
@@ -280,7 +285,7 @@
#define XPAR_XIICPS_0_DEVICE_ID XPAR_PS7_I2C_0_DEVICE_ID
#define XPAR_XIICPS_0_BASEADDR 0xE0004000
#define XPAR_XIICPS_0_HIGHADDR 0xE0004FFF
-#define XPAR_XIICPS_0_I2C_CLK_FREQ_HZ 111111115
+#define XPAR_XIICPS_0_I2C_CLK_FREQ_HZ 83333336
/******************************************************************/
@@ -376,9 +381,9 @@
#define XPAR_PS7_SD_0_DEVICE_ID 0
#define XPAR_PS7_SD_0_BASEADDR 0xE0100000
#define XPAR_PS7_SD_0_HIGHADDR 0xE0100FFF
-#define XPAR_PS7_SD_0_SDIO_CLK_FREQ_HZ 50000000
-#define XPAR_PS7_SD_0_HAS_CD 1
-#define XPAR_PS7_SD_0_HAS_WP 1
+#define XPAR_PS7_SD_0_SDIO_CLK_FREQ_HZ 100000000
+#define XPAR_PS7_SD_0_HAS_CD 0
+#define XPAR_PS7_SD_0_HAS_WP 0
#define XPAR_PS7_SD_0_BUS_WIDTH 0
#define XPAR_PS7_SD_0_MIO_BANK 0
#define XPAR_PS7_SD_0_HAS_EMIO 0
@@ -398,9 +403,9 @@
#define XPAR_XSDPS_0_DEVICE_ID XPAR_PS7_SD_0_DEVICE_ID
#define XPAR_XSDPS_0_BASEADDR 0xE0100000
#define XPAR_XSDPS_0_HIGHADDR 0xE0100FFF
-#define XPAR_XSDPS_0_SDIO_CLK_FREQ_HZ 50000000
-#define XPAR_XSDPS_0_HAS_CD 1
-#define XPAR_XSDPS_0_HAS_WP 1
+#define XPAR_XSDPS_0_SDIO_CLK_FREQ_HZ 100000000
+#define XPAR_XSDPS_0_HAS_CD 0
+#define XPAR_XSDPS_0_HAS_WP 0
#define XPAR_XSDPS_0_BUS_WIDTH 0
#define XPAR_XSDPS_0_MIO_BANK 0
#define XPAR_XSDPS_0_HAS_EMIO 0
@@ -422,15 +427,15 @@
/* Definitions for peripheral PS7_TTC_0 */
#define XPAR_PS7_TTC_0_DEVICE_ID 0U
#define XPAR_PS7_TTC_0_BASEADDR 0XF8001000U
-#define XPAR_PS7_TTC_0_TTC_CLK_FREQ_HZ 111111115U
+#define XPAR_PS7_TTC_0_TTC_CLK_FREQ_HZ 83333336U
#define XPAR_PS7_TTC_0_TTC_CLK_CLKSRC 0U
#define XPAR_PS7_TTC_1_DEVICE_ID 1U
#define XPAR_PS7_TTC_1_BASEADDR 0XF8001004U
-#define XPAR_PS7_TTC_1_TTC_CLK_FREQ_HZ 111111115U
+#define XPAR_PS7_TTC_1_TTC_CLK_FREQ_HZ 83333336U
#define XPAR_PS7_TTC_1_TTC_CLK_CLKSRC 0U
#define XPAR_PS7_TTC_2_DEVICE_ID 2U
#define XPAR_PS7_TTC_2_BASEADDR 0XF8001008U
-#define XPAR_PS7_TTC_2_TTC_CLK_FREQ_HZ 111111115U
+#define XPAR_PS7_TTC_2_TTC_CLK_FREQ_HZ 83333336U
#define XPAR_PS7_TTC_2_TTC_CLK_CLKSRC 0U
@@ -439,17 +444,17 @@
/* Canonical definitions for peripheral PS7_TTC_0 */
#define XPAR_XTTCPS_0_DEVICE_ID XPAR_PS7_TTC_0_DEVICE_ID
#define XPAR_XTTCPS_0_BASEADDR 0xF8001000U
-#define XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ 111111115U
+#define XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ 83333336U
#define XPAR_XTTCPS_0_TTC_CLK_CLKSRC 0U
#define XPAR_XTTCPS_1_DEVICE_ID XPAR_PS7_TTC_1_DEVICE_ID
#define XPAR_XTTCPS_1_BASEADDR 0xF8001004U
-#define XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ 111111115U
+#define XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ 83333336U
#define XPAR_XTTCPS_1_TTC_CLK_CLKSRC 0U
#define XPAR_XTTCPS_2_DEVICE_ID XPAR_PS7_TTC_2_DEVICE_ID
#define XPAR_XTTCPS_2_BASEADDR 0xF8001008U
-#define XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ 111111115U
+#define XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ 83333336U
#define XPAR_XTTCPS_2_TTC_CLK_CLKSRC 0U
@@ -458,21 +463,21 @@
/* Definitions for driver UARTPS */
#define XPAR_XUARTPS_NUM_INSTANCES 1
-/* Definitions for peripheral PS7_UART_1 */
-#define XPAR_PS7_UART_1_DEVICE_ID 0
-#define XPAR_PS7_UART_1_BASEADDR 0xE0001000
-#define XPAR_PS7_UART_1_HIGHADDR 0xE0001FFF
-#define XPAR_PS7_UART_1_UART_CLK_FREQ_HZ 50000000
-#define XPAR_PS7_UART_1_HAS_MODEM 0
+/* Definitions for peripheral PS7_UART_0 */
+#define XPAR_PS7_UART_0_DEVICE_ID 0
+#define XPAR_PS7_UART_0_BASEADDR 0xE0000000
+#define XPAR_PS7_UART_0_HIGHADDR 0xE0000FFF
+#define XPAR_PS7_UART_0_UART_CLK_FREQ_HZ 100000000
+#define XPAR_PS7_UART_0_HAS_MODEM 0
/******************************************************************/
-/* Canonical definitions for peripheral PS7_UART_1 */
-#define XPAR_XUARTPS_0_DEVICE_ID XPAR_PS7_UART_1_DEVICE_ID
-#define XPAR_XUARTPS_0_BASEADDR 0xE0001000
-#define XPAR_XUARTPS_0_HIGHADDR 0xE0001FFF
-#define XPAR_XUARTPS_0_UART_CLK_FREQ_HZ 50000000
+/* Canonical definitions for peripheral PS7_UART_0 */
+#define XPAR_XUARTPS_0_DEVICE_ID XPAR_PS7_UART_0_DEVICE_ID
+#define XPAR_XUARTPS_0_BASEADDR 0xE0000000
+#define XPAR_XUARTPS_0_HIGHADDR 0xE0000FFF
+#define XPAR_XUARTPS_0_UART_CLK_FREQ_HZ 100000000
#define XPAR_XUARTPS_0_HAS_MODEM 0

View File

@ -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)
-
-
-

View File

@ -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

View File

@ -0,0 +1,5 @@
## Source Repository
Files in this directory were copied from [elhep/Fast-Servo-Firmware](https://github.com/elhep/Fast-Servo-Firmware/tree/master/fast_servo/gateware).
## Commit ID
The files were copied from commit ID [7fae40c](https://github.com/elhep/Fast-Servo-Firmware/commit/7fae40c0f872a91218be378f8289b98b1e366729).

View File

@ -0,0 +1,3 @@
import os
verilog_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "verilog")

View File

@ -0,0 +1,179 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
from migen import *
from migen.genlib.cdc import MultiReg
from misoc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage
class _CRG(Module):
def __init__(self, platform, dco_clk, dco_freq=200e6):
self.clock_domains.cd_dco = ClockDomain()
self.clock_domains.cd_dco2x = ClockDomain()
self.clock_domains.cd_dco2d = ClockDomain()
dco_clk_p, dco_clk_n = dco_clk
dco_clk_buf = Signal()
self.specials += Instance(
"IBUFGDS", i_I=dco_clk_p, i_IB=dco_clk_n, o_O=dco_clk_buf
)
# # #
clk_feedback = Signal()
clk_feedback_buf = Signal()
clk_dco = Signal()
clk_dco2x = Signal()
clk_dco2d = Signal()
self.locked = Signal()
platform.add_period_constraint(dco_clk_p, 1e9 / dco_freq)
self.specials += [
Instance(
"PLLE2_BASE",
p_BANDWIDTH="OPTIMIZED",
p_DIVCLK_DIVIDE=1,
p_CLKFBOUT_PHASE=0.0,
p_CLKFBOUT_MULT=4, # VCO @ 800 MHz
p_CLKIN1_PERIOD=(1e9 / dco_freq),
p_REF_JITTER1=0.01,
p_STARTUP_WAIT="FALSE",
i_CLKIN1=dco_clk_buf,
i_PWRDWN=0,
i_RST=ResetSignal("sys"),
i_CLKFBIN=clk_feedback_buf,
o_CLKFBOUT=clk_feedback,
p_CLKOUT0_DIVIDE=4,
p_CLKOUT0_PHASE=0.0,
p_CLKOUT0_DUTY_CYCLE=0.5,
o_CLKOUT0=clk_dco, # 200 MHz <- dco_clk
p_CLKOUT1_DIVIDE=2,
p_CLKOUT1_PHASE=0.0,
p_CLKOUT1_DUTY_CYCLE=0.5,
o_CLKOUT1=clk_dco2x, # 400 MHZ <- 2 * dco_clk = 2*200 MHz
p_CLKOUT2_DIVIDE=8,
p_CLKOUT2_PHASE=0.0,
p_CLKOUT2_DUTY_CYCLE=0.5,
o_CLKOUT2=clk_dco2d, # 100 MHz <- dco_clk / 2 = 200 MHz / 2
o_LOCKED=self.locked,
)
]
self.specials += Instance("BUFG", i_I=clk_feedback, o_O=clk_feedback_buf)
self.specials += Instance("BUFG", i_I=clk_dco, o_O=self.cd_dco.clk)
self.specials += Instance("BUFG", i_I=clk_dco2d, o_O=self.cd_dco2d.clk)
self.specials += Instance("BUFG", i_I=clk_dco2x, o_O=self.cd_dco2x.clk)
class ADC(Module, AutoCSR):
def __init__(self, platform, dco_freq=200e6):
adc_pads = platform.request("adc")
afe_pads = platform.request("adc_afe")
self.frame_csr = CSRStatus(4)
self.data_ch0 = CSRStatus(16)
self.data_ch1 = CSRStatus(16)
self.tap_delay = CSRStorage(5)
self.bitslip_csr = CSRStorage(1)
self.afe_ctrl = CSRStorage(4)
tap_delay_val = Signal(5)
bitslip = Signal()
bitslip_re_dco_2d = Signal()
ch1_gain_x10 = Signal()
ch2_gain_x10 = Signal()
ch1_shdn = Signal()
ch2_shdn = Signal()
self.data_out = [Signal(16, reset_less=True), Signal(16, reset_less=True)]
self.s_frame = Signal(4)
###
# DCO clock coming from LTC2195
# dco_clk = Record([("p", 1), ("n", 1)])
dco_clk =(adc_pads.dco_p, adc_pads.dco_n)
self.comb += [
# dco_clk.p.eq(adc_pads.dco_p),
# dco_clk.n.eq(adc_pads.dco_n),
tap_delay_val.eq(self.tap_delay.storage),
Cat(ch1_gain_x10, ch2_gain_x10, ch1_shdn, ch2_shdn).eq(
self.afe_ctrl.storage
),
]
self.submodules._crg = _CRG(platform, dco_clk, dco_freq)
self.specials += MultiReg(self.bitslip_csr.re, bitslip_re_dco_2d, "dco2d")
self.sync.dco2d += [
bitslip.eq(Mux(bitslip_re_dco_2d, self.bitslip_csr.storage, 0))
]
self.comb += [
self.frame_csr.status.eq(self.s_frame),
self.data_ch0.status.eq(self.data_out[0]),
self.data_ch1.status.eq(self.data_out[1]),
]
self.comb += [
afe_pads.ch1_gain.eq(ch1_gain_x10),
afe_pads.ch2_gain.eq(ch2_gain_x10),
afe_pads.nshdn_ch1.eq(~ch1_shdn),
afe_pads.nshdn_ch2.eq(~ch2_shdn),
]
dummy = Signal(8)
dummy_idelay_rdy = Signal()
self.specials += Instance(
"LTC2195",
i_rst_in=ResetSignal("sys"),
i_clk200=ClockSignal("idelay"),
i_DCO=ClockSignal("dco"),
i_DCO_2D=ClockSignal("dco2d"),
i_FR_in_p=adc_pads.frame_p,
i_FR_in_n=adc_pads.frame_n,
i_D0_in_p=adc_pads.data0_p,
i_D0_in_n=adc_pads.data0_n,
i_D1_in_p=adc_pads.data1_p,
i_D1_in_n=adc_pads.data1_n,
i_bitslip=bitslip,
i_delay_val=tap_delay_val,
o_ADC0_out=self.data_out[1], # LANES swapped on hardware
o_ADC1_out=self.data_out[0],
o_FR_out=self.s_frame,
o_o_data_from_pins=dummy,
o_idelay_rdy=dummy_idelay_rdy,
)
class AUX_ADC_CTRL(Module, AutoCSR):
def __init__(self, platform):
adc_aux_pads = platform.request("aux_adc")
self.adc_aux_ctrl = CSRStorage(5)
self.comb += [
adc_aux_pads.diff_n.eq(~self.adc_aux_ctrl.storage[0]),
adc_aux_pads.a.eq(self.adc_aux_ctrl.storage[1:4]),
adc_aux_pads.range.eq(self.adc_aux_ctrl.storage[4]),
]

View File

@ -0,0 +1,84 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
from migen import *
from misoc.interconnect.csr import AutoCSR, CSRStorage
from migen.genlib.io import DDROutput
class DAC(Module, AutoCSR):
def __init__(self, platform):
dac_pads = platform.request("dac")
dac_afe_pads = platform.request("dac_afe")
self.dac_ctrl = CSRStorage(3)
self.output_value_ch0 = CSRStorage(14)
self.output_value_ch1 = CSRStorage(14)
manual_override = Signal()
ch0_pd = Signal()
ch1_pd = Signal()
output_data_ch0 = Signal(14)
output_data_ch1 = Signal(14)
self.data_in = [Signal(14, reset_less=True), Signal(14, reset_less=True)]
platform.add_period_constraint(dac_pads.dclkio, 10.0)
self.comb += [
Cat(manual_override, ch0_pd, ch1_pd).eq(self.dac_ctrl.storage),
dac_pads.rst.eq(ResetSignal("sys")),
dac_afe_pads.ch1_pd_n.eq(~ch0_pd),
dac_afe_pads.ch2_pd_n.eq(~ch1_pd),
output_data_ch0.eq(
Mux(manual_override, self.output_value_ch0.storage, self.data_in[0])
),
output_data_ch1.eq(
Mux(manual_override, self.output_value_ch1.storage, self.data_in[1])
),
]
# data
for lane in range(14):
self.specials += DDROutput(
i1 = output_data_ch0[lane],
i2 = output_data_ch1[lane],
o = dac_pads.data[lane],
clk = ClockSignal("dco2d")
)
# clock forwarding
self.specials += DDROutput(
i1 = 0b0,
i2 = 0b1,
o = dac_pads.dclkio,
clk = ClockSignal("dco2d"),
)
class AUX_DAC_CTRL(Module, AutoCSR):
def __init__(self, platform):
dac_aux_pads = platform.request("aux_dac")
self.dac_aux_ctrl = CSRStorage(3)
self.comb += [
dac_aux_pads.nclr.eq(~self.dac_aux_ctrl.storage[0]),
dac_aux_pads.bin.eq(self.dac_aux_ctrl.storage[1]),
dac_aux_pads.nldac.eq(~self.dac_aux_ctrl.storage[2]),
]

View File

@ -0,0 +1,385 @@
# Copyright 2014-2015 Robert Jördens <jordens@gmail.com>
# Copyright 2018-2022 Benjamin Wiegand <benjamin.wiegand@physik.hu-berlin.de>
# Copyright 2021-2022 Bastian Leykauf <leykauf@physik.hu-berlin.de>
# Copyright 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
#
# This file is part of Fast Servo Software Package and is based on Linien.
#
# 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 functools import reduce
from operator import or_
from migen import (
DIR_M_TO_S,
DIR_S_TO_M,
Cat,
ClockSignal,
If,
Instance,
Module,
Record,
Replicate,
ResetSignal,
Signal,
)
from misoc.interconnect import csr_bus, wishbone
sys_layout = [
("rstn", 1, DIR_M_TO_S),
("clk", 1, DIR_M_TO_S),
("addr", 32, DIR_M_TO_S),
("wdata", 32, DIR_M_TO_S),
("sel", 4, DIR_M_TO_S),
("wen", 1, DIR_M_TO_S),
("ren", 1, DIR_M_TO_S),
("rdata", 32, DIR_S_TO_M),
("err", 1, DIR_S_TO_M),
("ack", 1, DIR_S_TO_M),
]
axi_layout = [
("arvalid", 1),
("awvalid", 1),
("bready", 1),
("rready", 1),
("wlast", 1),
("wvalid", 1),
("arid", 12),
("awid", 12),
("wid", 12),
("arburst", 2),
("arlock", 2),
("arsize", 3),
("awburst", 2),
("awlock", 2),
("awsize", 3),
("arprot", 3),
("awprot", 3),
("araddr", 32),
("awaddr", 32),
("wdata", 32),
("arcache", 4),
("arlen", 4),
("arqos", 4),
("awcache", 4),
("awlen", 4),
("awqos", 4),
("wstrb", 4),
("aclk", 1),
("arready", 1),
("awready", 1),
("bvalid", 1),
("rlast", 1),
("rvalid", 1),
("wready", 1),
("bid", 12),
("rid", 12),
("bresp", 2),
("rresp", 2),
("rdata", 32),
("arstn", 1),
]
class PitayaPS(Module):
def __init__(self, cpu):
self.fclk = Signal(4)
self.frstn = Signal(4)
###
self.submodules.axi = Axi2Sys()
axi = self.axi.axi
self.comb += [
axi.aclk.eq(self.fclk[0]),
axi.arstn.eq(self.frstn[0]),
]
self.specials += Instance(
"system_processing_system7_0_0",
io_MIO=cpu.mio,
io_PS_CLK=cpu.ps_clk,
io_PS_PORB=cpu.ps_porb,
io_PS_SRSTB=cpu.ps_srstb,
io_DDR_Addr=cpu.DDR_addr,
io_DDR_BankAddr=cpu.DDR_ba,
io_DDR_CAS_n=cpu.DDR_cas_n,
io_DDR_Clk_n=cpu.DDR_ck_n,
io_DDR_Clk=cpu.DDR_ck_p,
io_DDR_CKE=cpu.DDR_cke,
io_DDR_CS_n=cpu.DDR_cs_n,
io_DDR_DM=cpu.DDR_dm,
io_DDR_DQ=cpu.DDR_dq,
io_DDR_DQS_n=cpu.DDR_dqs_n,
io_DDR_DQS=cpu.DDR_dqs_p,
io_DDR_ODT=cpu.DDR_odt,
io_DDR_RAS_n=cpu.DDR_ras_n,
io_DDR_DRSTB=cpu.DDR_reset_n,
io_DDR_WEB=cpu.DDR_we_n,
io_DDR_VRN=cpu.ddr_vrn,
io_DDR_VRP=cpu.ddr_vrp,
o_FCLK_CLK0=self.fclk[0],
o_FCLK_CLK1=self.fclk[1],
o_FCLK_CLK2=self.fclk[2],
o_FCLK_CLK3=self.fclk[3],
o_FCLK_RESET0_N=self.frstn[0],
o_FCLK_RESET1_N=self.frstn[1],
o_FCLK_RESET2_N=self.frstn[2],
o_FCLK_RESET3_N=self.frstn[3],
i_M_AXI_GP0_ACLK=axi.aclk,
o_M_AXI_GP0_ARVALID=axi.arvalid,
o_M_AXI_GP0_AWVALID=axi.awvalid,
o_M_AXI_GP0_BREADY=axi.bready,
o_M_AXI_GP0_RREADY=axi.rready,
o_M_AXI_GP0_WLAST=axi.wlast,
o_M_AXI_GP0_WVALID=axi.wvalid,
o_M_AXI_GP0_ARID=axi.arid,
o_M_AXI_GP0_AWID=axi.awid,
o_M_AXI_GP0_WID=axi.wid,
o_M_AXI_GP0_ARBURST=axi.arburst,
o_M_AXI_GP0_ARLOCK=axi.arlock,
o_M_AXI_GP0_ARSIZE=axi.arsize,
o_M_AXI_GP0_AWBURST=axi.awburst,
o_M_AXI_GP0_AWLOCK=axi.awlock,
o_M_AXI_GP0_AWSIZE=axi.awsize,
o_M_AXI_GP0_ARPROT=axi.arprot,
o_M_AXI_GP0_AWPROT=axi.awprot,
o_M_AXI_GP0_ARADDR=axi.araddr,
o_M_AXI_GP0_AWADDR=axi.awaddr,
o_M_AXI_GP0_WDATA=axi.wdata,
o_M_AXI_GP0_ARCACHE=axi.arcache,
o_M_AXI_GP0_ARLEN=axi.arlen,
o_M_AXI_GP0_ARQOS=axi.arqos,
o_M_AXI_GP0_AWCACHE=axi.awcache,
o_M_AXI_GP0_AWLEN=axi.awlen,
o_M_AXI_GP0_AWQOS=axi.awqos,
o_M_AXI_GP0_WSTRB=axi.wstrb,
i_M_AXI_GP0_ARREADY=axi.arready,
i_M_AXI_GP0_AWREADY=axi.awready,
i_M_AXI_GP0_BVALID=axi.bvalid,
i_M_AXI_GP0_RLAST=axi.rlast,
i_M_AXI_GP0_RVALID=axi.rvalid,
i_M_AXI_GP0_WREADY=axi.wready,
i_M_AXI_GP0_BID=axi.bid,
i_M_AXI_GP0_RID=axi.rid,
i_M_AXI_GP0_BRESP=axi.bresp,
i_M_AXI_GP0_RRESP=axi.rresp,
i_M_AXI_GP0_RDATA=axi.rdata,
i_SPI0_SS_I=0,
# i_SPI0_SS_I=spi.ss_i,
# o_SPI0_SS_O=spi.ss_o,
# o_SPI0_SS_T=spi.ss_t,
# o_SPI0_SS1_O=spi.ss1_o,
# o_SPI0_SS2_O=spi.ss2_o,
i_SPI0_SCLK_I=0,
# i_SPI0_SCLK_I=spi.sclk_i,
# o_SPI0_SCLK_O=spi.sclk_o,
# o_SPI0_SCLK_T=spi.sclk_t,
i_SPI0_MOSI_I=0,
# i_SPI0_MOSI_I=spi.mosi_i,
# o_SPI0_MOSI_O=spi.mosi_o,
# o_SPI0_MOSI_T=spi.mosi_t,
i_SPI0_MISO_I=0,
# i_SPI0_MISO_I=spi.miso_i,
# o_SPI0_MISO_O=spi.miso_o,
# o_SPI0_MISO_T=spi.miso_t,
i_USB0_VBUS_PWRFAULT=0,
)
class Axi2Sys(Module):
def __init__(self):
self.sys = Record(sys_layout)
self.axi = Record(axi_layout)
###
self.comb += [self.sys.clk.eq(self.axi.aclk), self.sys.rstn.eq(self.axi.arstn)]
self.specials += Instance(
"axi_slave",
p_AXI_DW=32,
p_AXI_AW=32,
p_AXI_IW=12,
i_axi_clk_i=self.axi.aclk,
i_axi_rstn_i=self.axi.arstn,
i_axi_awid_i=self.axi.awid,
i_axi_awaddr_i=self.axi.awaddr,
i_axi_awlen_i=self.axi.awlen,
i_axi_awsize_i=self.axi.awsize,
i_axi_awburst_i=self.axi.awburst,
i_axi_awlock_i=self.axi.awlock,
i_axi_awcache_i=self.axi.awcache,
i_axi_awprot_i=self.axi.awprot,
i_axi_awvalid_i=self.axi.awvalid,
o_axi_awready_o=self.axi.awready,
i_axi_wid_i=self.axi.wid,
i_axi_wdata_i=self.axi.wdata,
i_axi_wstrb_i=self.axi.wstrb,
i_axi_wlast_i=self.axi.wlast,
i_axi_wvalid_i=self.axi.wvalid,
o_axi_wready_o=self.axi.wready,
o_axi_bid_o=self.axi.bid,
o_axi_bresp_o=self.axi.bresp,
o_axi_bvalid_o=self.axi.bvalid,
i_axi_bready_i=self.axi.bready,
i_axi_arid_i=self.axi.arid,
i_axi_araddr_i=self.axi.araddr,
i_axi_arlen_i=self.axi.arlen,
i_axi_arsize_i=self.axi.arsize,
i_axi_arburst_i=self.axi.arburst,
i_axi_arlock_i=self.axi.arlock,
i_axi_arcache_i=self.axi.arcache,
i_axi_arprot_i=self.axi.arprot,
i_axi_arvalid_i=self.axi.arvalid,
o_axi_arready_o=self.axi.arready,
o_axi_rid_o=self.axi.rid,
o_axi_rdata_o=self.axi.rdata,
o_axi_rresp_o=self.axi.rresp,
o_axi_rlast_o=self.axi.rlast,
o_axi_rvalid_o=self.axi.rvalid,
i_axi_rready_i=self.axi.rready,
o_sys_addr_o=self.sys.addr,
o_sys_wdata_o=self.sys.wdata,
o_sys_sel_o=self.sys.sel,
o_sys_wen_o=self.sys.wen,
o_sys_ren_o=self.sys.ren,
i_sys_rdata_i=self.sys.rdata,
i_sys_err_i=self.sys.err,
i_sys_ack_i=self.sys.ack,
)
class SysInterconnect(Module):
def __init__(self, master, *slaves):
cs = Signal(max=len(slaves)) if len(slaves) != 1 else Signal()
self.comb += cs.eq(master.addr[20:23])
rets = []
for i, s in enumerate(slaves):
sel = Signal()
self.comb += [
sel.eq(cs == i),
s.clk.eq(master.clk),
s.rstn.eq(master.rstn),
s.addr.eq(master.addr),
s.wdata.eq(master.wdata),
s.sel.eq(master.sel),
s.wen.eq(sel & master.wen),
s.ren.eq(sel & master.ren),
]
ret = Cat(s.err, s.ack, s.rdata)
rets.append(Replicate(sel, len(ret)) & ret)
self.comb += Cat(master.err, master.ack, master.rdata).eq(reduce(or_, rets))
class Sys2Wishbone(Module):
def __init__(self):
self.wishbone = wb = wishbone.Interface()
self.sys = sys = Record(sys_layout)
###
sys2 = Record(sys_layout)
self.specials += Instance(
"bus_clk_bridge",
i_sys_clk_i=sys.clk,
i_sys_rstn_i=sys.rstn,
i_sys_addr_i=sys.addr,
i_sys_wdata_i=sys.wdata,
i_sys_sel_i=sys.sel,
i_sys_wen_i=sys.wen,
i_sys_ren_i=sys.ren,
o_sys_rdata_o=sys.rdata,
o_sys_err_o=sys.err,
o_sys_ack_o=sys.ack,
i_clk_i=ClockSignal(),
i_rstn_i=~ResetSignal(),
o_addr_o=sys2.addr,
o_wen_o=sys2.wen,
o_ren_o=sys2.ren,
o_wdata_o=sys2.wdata,
i_rdata_i=sys2.rdata,
i_err_i=sys2.err,
i_ack_i=sys2.ack,
)
self.sync += [
If(
sys2.ren | sys2.wen,
wb.cyc.eq(1),
wb.adr.eq(sys2.addr[2:]),
wb.we.eq(sys2.wen),
wb.dat_w.eq(sys2.wdata),
).Elif(wb.ack, wb.cyc.eq(0))
]
self.comb += [
wb.stb.eq(wb.cyc),
sys2.rdata.eq(wb.dat_r),
sys2.ack.eq(wb.ack),
sys2.err.eq(wb.err),
]
class SysCDC(Module):
def __init__(self, cd_target="sys"):
self.source = Record(sys_layout)
self.target = Record(sys_layout)
self.specials += Instance(
"bus_clk_bridge",
i_sys_clk_i=self.source.clk,
i_sys_rstn_i=self.source.rstn,
i_sys_addr_i=self.source.addr,
i_sys_wdata_i=self.source.wdata,
i_sys_sel_i=self.source.sel,
i_sys_wen_i=self.source.wen,
i_sys_ren_i=self.source.ren,
o_sys_rdata_o=self.source.rdata,
o_sys_err_o=self.source.err,
o_sys_ack_o=self.source.ack,
i_clk_i=self.target.clk,
i_rstn_i=self.target.rstn,
o_addr_o=self.target.addr,
o_wdata_o=self.target.wdata,
o_wen_o=self.target.wen,
o_ren_o=self.target.ren,
i_rdata_i=self.target.rdata,
i_err_i=self.target.err,
i_ack_i=self.target.ack,
)
self.comb += [
self.target.clk.eq(ClockSignal(cd_target)),
self.target.rstn.eq(~ResetSignal(cd_target)),
]
class Sys2CSR(Module):
def __init__(self):
self.csr = csr_bus.Interface()
self.sys = Record(sys_layout)
###
stb = Signal()
self.sync += [
stb.eq(self.sys.wen | self.sys.ren),
self.csr.adr.eq(self.sys.addr[2:]),
self.csr.we.eq(self.sys.wen),
self.csr.dat_w.eq(self.sys.wdata),
self.sys.ack.eq(stb),
self.sys.rdata.eq(self.csr.dat_r),
]

View File

@ -0,0 +1,193 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
from migen import *
class PS7(Module):
def __init__(self, platform, ps7_name=None):
self.frstn = Signal()
self.ps7_tcl = []
self.platform = platform
self.ps7_name = "Zynq" if ps7_name is None else ps7_name
ps7_clk = platform.request("ps7_clk")
ps7_porb = platform.request("ps7_porb")
ps7_srstb = platform.request("ps7_srstb")
ps7_mio = platform.request("ps7_mio")
ps7_ddram = platform.request("ps7_ddram")
self.cpu_params = dict(
# Clk / Rst.
io_PS_CLK = ps7_clk,
io_PS_PORB = ps7_porb,
io_PS_SRSTB = ps7_srstb,
# MIO.
io_MIO = ps7_mio,
# DDRAM.
io_DDR_Addr = ps7_ddram.addr,
io_DDR_BankAddr = ps7_ddram.ba,
io_DDR_CAS_n = ps7_ddram.cas_n,
io_DDR_Clk_n = ps7_ddram.ck_n,
io_DDR_Clk = ps7_ddram.ck_p,
io_DDR_CKE = ps7_ddram.cke,
io_DDR_CS_n = ps7_ddram.cs_n,
io_DDR_DM = ps7_ddram.dm,
io_DDR_DQ = ps7_ddram.dq,
io_DDR_DQS_n = ps7_ddram.dqs_n,
io_DDR_DQS = ps7_ddram.dqs_p,
io_DDR_ODT = ps7_ddram.odt,
io_DDR_RAS_n = ps7_ddram.ras_n,
io_DDR_DRSTB = ps7_ddram.reset_n,
io_DDR_WEB = ps7_ddram.we_n,
io_DDR_VRN = ps7_ddram.vrn,
io_DDR_VRP = ps7_ddram.vrp,
# USB0.
# i_USB0_VBUS_PWRFAULT = 0,
# Fabric Clk / Rst.
# o_FCLK_CLK0 = ClockSignal("ps7"),
o_FCLK_RESET0_N = self.frstn
)
self.set_ps7(name=self.ps7_name,
config={
**self.platform.ps7_config
})
def add_ps7_config(self, config):
# Config must be provided as a config, value dict.
assert isinstance(config, dict)
# Add configs to PS7.
self.ps7_tcl.append("set_property -dict [list \\")
for config, value in config.items():
self.ps7_tcl.append("CONFIG.{} {} \\".format(config, '{{' + str(value) + '}}'))
self.ps7_tcl.append(f"] [get_ips {self.ps7_name}]")
def set_ps7(self, name=None, config=None, preset=None):
self.ps7_name = name
self.ps7_tcl.append(f"set ps7 [create_ip -vendor xilinx.com -name processing_system7 -module_name {self.ps7_name}]")
self.add_ps7_config(config)
def add_axi_gp_master(self, interface):
# assert type(interface) is Axi2Sys
axi_interface = interface
self.cpu_params.update({
# AXI GP clk.
f"i_M_AXI_GP0_ACLK" : axi_interface.aclk,
# AXI GP aw.
f"o_M_AXI_GP0_AWVALID" : axi_interface.awvalid,
f"i_M_AXI_GP0_AWREADY" : axi_interface.awready,
f"o_M_AXI_GP0_AWADDR" : axi_interface.awaddr,
f"o_M_AXI_GP0_AWBURST" : axi_interface.awburst,
f"o_M_AXI_GP0_AWLEN" : axi_interface.awlen,
f"o_M_AXI_GP0_AWSIZE" : axi_interface.awsize,
f"o_M_AXI_GP0_AWID" : axi_interface.awid,
f"o_M_AXI_GP0_AWLOCK" : axi_interface.awlock,
f"o_M_AXI_GP0_AWPROT" : axi_interface.awprot,
f"o_M_AXI_GP0_AWCACHE" : axi_interface.awcache,
f"o_M_AXI_GP0_AWQOS" : axi_interface.awqos,
# AXI GP w.
f"o_M_AXI_GP0_WVALID" : axi_interface.wvalid,
f"o_M_AXI_GP0_WLAST" : axi_interface.wlast,
f"i_M_AXI_GP0_WREADY" : axi_interface.wready,
f"o_M_AXI_GP0_WID" : axi_interface.wid,
f"o_M_AXI_GP0_WDATA" : axi_interface.wdata,
f"o_M_AXI_GP0_WSTRB" : axi_interface.wstrb,
# AXI GP b.
f"i_M_AXI_GP0_BVALID" : axi_interface.bvalid,
f"o_M_AXI_GP0_BREADY" : axi_interface.bready,
f"i_M_AXI_GP0_BID" : axi_interface.bid,
f"i_M_AXI_GP0_BRESP" : axi_interface.bresp,
# AXI GP ar.
f"o_M_AXI_GP0_ARVALID" : axi_interface.arvalid,
f"i_M_AXI_GP0_ARREADY" : axi_interface.arready,
f"o_M_AXI_GP0_ARADDR" : axi_interface.araddr,
f"o_M_AXI_GP0_ARBURST" : axi_interface.arburst,
f"o_M_AXI_GP0_ARLEN" : axi_interface.arlen,
f"o_M_AXI_GP0_ARID" : axi_interface.arid,
f"o_M_AXI_GP0_ARLOCK" : axi_interface.arlock,
f"o_M_AXI_GP0_ARSIZE" : axi_interface.arsize,
f"o_M_AXI_GP0_ARPROT" : axi_interface.arprot,
f"o_M_AXI_GP0_ARCACHE" : axi_interface.arcache,
f"o_M_AXI_GP0_ARQOS" : axi_interface.arqos,
# AXI GP r.
f"i_M_AXI_GP0_RVALID" : axi_interface.rvalid,
f"o_M_AXI_GP0_RREADY" : axi_interface.rready,
f"i_M_AXI_GP0_RLAST" : axi_interface.rlast,
f"i_M_AXI_GP0_RID" : axi_interface.rid,
f"i_M_AXI_GP0_RRESP" : axi_interface.rresp,
f"i_M_AXI_GP0_RDATA" : axi_interface.rdata,
})
def add_i2c_emio(self, platform, i2c_name, i2c_number):
ps7_i2c_pads = platform.request(i2c_name, i2c_number) #, loose=True)
if ps7_i2c_pads is not None:
o_i2c_scl = Signal()
i_i2c_scl = Signal()
t_i2c_scl = Signal()
o_i2c_sda = Signal()
i_i2c_sda = Signal()
t_i2c_sda = Signal()
self.specials += Instance("IOBUF",
i_T = t_i2c_sda,
i_I = o_i2c_sda,
io_IO = ps7_i2c_pads.sda,
o_O = i_i2c_sda,
)
self.specials += Instance("IOBUF",
i_T = t_i2c_scl,
i_I = o_i2c_scl,
io_IO = ps7_i2c_pads.scl,
o_O = i_i2c_scl,
)
self.cpu_params.update({
f"i_I2C{i2c_number}_SCL_I" : i_i2c_scl,
f"o_I2C{i2c_number}_SCL_T" : t_i2c_scl,
f"o_I2C{i2c_number}_SCL_O" : o_i2c_scl,
f"i_I2C{i2c_number}_SDA_I" : i_i2c_sda,
f"o_I2C{i2c_number}_SDA_T" : t_i2c_sda,
f"o_I2C{i2c_number}_SDA_O" : o_i2c_sda,
})
def do_finalize(self):
if len(self.ps7_tcl):
self.ps7_tcl += [
f"upgrade_ip [get_ips {self.ps7_name}]",
f"generate_target all [get_ips {self.ps7_name}]",
f"synth_ip [get_ips {self.ps7_name}]"
]
self.platform.toolchain.pre_synthesis_commands += self.ps7_tcl
self.specials += Instance(self.ps7_name, **self.cpu_params)

View File

@ -0,0 +1,141 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
from enum import Enum
from migen import *
class SpiInterface(Enum):
ADC = 0
DAC = 1
class SpiPhy(Module):
def __init__(self, spi_type, ps7_spi_pads):
assert isinstance(spi_type, SpiInterface)
self.ps_ss = Signal(3, reset_less=True)
self.ps_miso_o = Signal()
self.ps_miso_t = Signal()
self.ps_mosi_o = Signal()
self.ps_mosi_t = Signal()
self.ps_sclk_o = Signal()
self.ps_sclk_t = Signal()
self.ps_sclk_i = Signal()
self.ps_mosi_i = Signal()
self.ps_miso_i = Signal()
self.ps_ss_i = Signal()
self.ps_ss_t = Signal()
if spi_type.name == "ADC":
cs_translated = Signal(4, reset_less=True)
main_adc_miso = Signal(reset_less=True)
aux_adc_miso_a = Signal(reset_less=True)
aux_adc_miso_b = Signal(reset_less=True)
aux_dac_miso = Signal(reset_less=True)
miso_signals = [main_adc_miso, aux_adc_miso_a, aux_adc_miso_b, aux_dac_miso]
# MAIN ADC
self.specials += Instance("OBUFT", i_I=self.ps_sclk_o, i_T=self.ps_sclk_t, o_O=ps7_spi_pads.sclk)
self.specials += Instance("OBUFT", i_I=self.ps_mosi_o, i_T=self.ps_mosi_t, o_O=ps7_spi_pads.mosi)
self.specials += Instance("IBUF", i_I=ps7_spi_pads.miso, o_O=main_adc_miso)
# AUX ADC
self.specials += Instance("OBUFT", i_I=self.ps_sclk_o, i_T=self.ps_sclk_t, o_O=ps7_spi_pads.aux_adc_sclk)
self.specials += Instance("IBUF", i_I=ps7_spi_pads.aux_adc_miso_a, o_O=aux_adc_miso_a)
self.specials += Instance("IBUF", i_I=ps7_spi_pads.aux_adc_miso_b, o_O=aux_adc_miso_b)
# AUX DAC
self.specials += Instance("OBUFT", i_I=self.ps_sclk_o, i_T=self.ps_sclk_t, o_O=ps7_spi_pads.aux_dac_sclk)
self.specials += Instance("OBUFT", i_I=self.ps_mosi_o, i_T=self.ps_mosi_t, o_O=ps7_spi_pads.aux_dac_mosi)
self.specials += Instance("IBUF", i_I=ps7_spi_pads.aux_dac_miso, o_O=aux_dac_miso)
cases = {}
# for i in range(4):
# case_mask = ~(1 << i) & 0xF
# print(f"Case mask: 0b{case_mask:04b}")
# cases[i + 1] = [
# cs_translated.eq(case_mask),
# self.ps_miso_i.eq(miso_signals[i])
# ]
cases[0b001] = [
cs_translated.eq(0b1110),
self.ps_miso_i.eq(main_adc_miso),
]
cases[0b010] = [
cs_translated.eq(0b1101),
self.ps_miso_i.eq(aux_adc_miso_a),
]
cases[0b011] = [
cs_translated.eq(0b1011),
self.ps_miso_i.eq(aux_adc_miso_b),
]
cases[0b100] = [
cs_translated.eq(0b0111),
self.ps_miso_i.eq(aux_dac_miso),
]
cases["default"] = [
cs_translated.eq(0b1111),
self.ps_miso_i.eq(0b1),
]
self.comb += [
self.ps_ss_i.eq(1),
Case(self.ps_ss, cases),
ps7_spi_pads.cs.eq(cs_translated[0]),
# only one CS line physically available to AUX ADC
ps7_spi_pads.aux_adc_cs.eq(cs_translated[1] & cs_translated[2]),
ps7_spi_pads.aux_dac_miso.eq(cs_translated[3]),
]
else:
self.specials += Instance(
"spi2threewire",
o_ps_sclk_i = self.ps_sclk_i,
i_ps_sclk_o = self.ps_sclk_o,
i_ps_sclk_t = self.ps_sclk_t,
o_ps_mosi_i = self.ps_mosi_i,
i_ps_mosi_o = self.ps_mosi_o,
i_ps_mosi_t = self.ps_mosi_t,
o_ps_miso_i = self.ps_miso_i,
i_ps_miso_o = self.ps_miso_o,
i_ps_miso_t = self.ps_miso_t,
o_ps_ss_i = self.ps_ss_i,
i_ps_ss = self.ps_ss,
i_ps_ss_t = self.ps_ss_t,
o_o_ss = ps7_spi_pads.cs,
o_o_sclk = ps7_spi_pads.sclk,
io_sdio = ps7_spi_pads.sdio,
)

View File

@ -0,0 +1,336 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2022-2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
from migen.build.generic_platform import *
from migen.build.xilinx import XilinxPlatform
import os
from fast_servo.gateware import verilog_dir
# IOs ----------------------------------------------------------------------------------------------
_io = [
# Front panel LEDs
("fp_led", 0, Pins("G7"), IOStandard("LVCMOS25")),
("fp_led", 1, Pins("G8"), IOStandard("LVCMOS25")),
("fp_led", 2, Pins("G2"), IOStandard("LVCMOS25")),
("fp_led", 3, Pins("G3"), IOStandard("LVCMOS25")),
# LEDs
("user_led", 0, Pins("AB16"), IOStandard("LVCMOS33")),
("user_led", 1, Pins("AA14"), IOStandard("LVCMOS33")),
("user_led", 2, Pins("AA15"), IOStandard("LVCMOS33")),
# ETH LEDs
("eth_led", 0, Pins("V11"), IOStandard("LVCMOS33")),
("eth_led", 1, Pins("U13"), IOStandard("LVCMOS33")),
("from_eth_phy", 0, Pins("J3"), IOStandard("LVCMOS18")),
("from_eth_phy", 1, Pins("K8"), IOStandard("LVCMOS18")),
# CLK 100 MHz from oscillator
("clk100", 0, Pins("Y14"), IOStandard("LVCMOS33")),
# MGT clk from on-board Si5338A
("mgt_clk1", 0,
Subsignal("p", Pins("U5")),
Subsignal("n", Pins("V5")),
IOStandard("LVDS_25"),
),
# FCLK125 from on-board Si5338A
("fclk125", 0, Pins("K2"), IOStandard("LVCMOS18")),
# # ADC CLK
# ("fpga_clk", 0,
# Subsignal("p", Pins("C6")),
# Subsignal("n", Pins("C5")),
# IOStandard("LVDS_25"),
# ),
# DAC CLK
("fpga_clk", 1,
Subsignal("p", Pins("J7")),
Subsignal("n", Pins("J6")),
IOStandard("LVDS_25"),
),
# MAIN ADC LT2195
("adc", 0,
Subsignal("data0_p", Pins("F7 B7 E4 D1"), IOStandard("LVDS_25")),
Subsignal("data0_n", Pins("E7 B6 E3 C1"), IOStandard("LVDS_25")),
Subsignal("data1_p", Pins("A2 D5 F2 D7"), IOStandard("LVDS_25")),
Subsignal("data1_n", Pins("A1 C4 F1 D6"), IOStandard("LVDS_25")),
Subsignal("dco_p", Pins("B4"), IOStandard("LVDS_25")),
Subsignal("dco_n", Pins("B3"), IOStandard("LVDS_25")),
Subsignal("frame_p", Pins("B2"), IOStandard("LVDS_25")),
Subsignal("frame_n", Pins("B1"), IOStandard("LVDS_25"))
),
# ADC AFE
("adc_afe", 0,
Subsignal("ch1_gain", Pins("AA12"), IOStandard("LVCMOS33")),
Subsignal("ch2_gain", Pins("AB11"), IOStandard("LVCMOS33")),
Subsignal("nshdn_ch1", Pins("G4"), IOStandard("LVCMOS25")),
Subsignal("nshdn_ch2", Pins("F4"), IOStandard("LVCMOS25")),
),
# P5 R5 N1 N4 L2 P6 N3 R4 P1 L1 M3 M4 U2 T2
# MAIN DAC AD9117
("dac", 0,
Subsignal("data",
Pins("T2 U2 M4 M3 L1 P1 R4 N3 P6 L2 N4 N1 R5 P5"),
IOStandard("LVCMOS18")),
Subsignal("dclkio", Pins("U1"), IOStandard("LVCMOS18")),
Subsignal("rst", Pins("T1"), IOStandard("LVCMOS18")),
),
# DAC AFE
("dac_afe", 0,
Subsignal("ch1_pd_n", Pins("L5")),
Subsignal("ch2_pd_n", Pins("L4")),
IOStandard("LVCMOS18"),
),
# AUXILIARY ADC
("aux_adc", 0,
Subsignal("diff_n", Pins("W18")),
Subsignal("a", Pins("AB18 AB19 W17")),
Subsignal("range", Pins("U19")),
IOStandard("LVCMOS33")
),
# AUXILIARY DAC
("aux_dac", 0,
Subsignal("nclr", Pins("V19")),
Subsignal("bin", Pins("AA19")),
Subsignal("nldac", Pins("AB21")),
IOStandard("LVCMOS33")
),
# ADC SPI
("spi", 0,
Subsignal("sclk", Pins("J1"), IOStandard("LVCMOS18")),
Subsignal("mosi", Pins("J5"), IOStandard("LVCMOS18")),
Subsignal("miso", Pins("K5"), IOStandard("LVCMOS18")),
Subsignal("cs", Pins("J2"), IOStandard("LVCMOS18")),
Subsignal("aux_adc_sclk", Pins("AB22"), IOStandard("LVCMOS33")),
Subsignal("aux_adc_miso_a", Pins("Y18"), IOStandard("LVCMOS33")),
Subsignal("aux_adc_miso_b", Pins("AA16"), IOStandard("LVCMOS33")),
Subsignal("aux_adc_cs", Pins("Y19"), IOStandard("LVCMOS33")),
Subsignal("aux_dac_sclk", Pins("V18"), IOStandard("LVCMOS33")),
Subsignal("aux_dac_mosi", Pins("U17"), IOStandard("LVCMOS33")),
Subsignal("aux_dac_miso", Pins("U18"), IOStandard("LVCMOS33")),
Subsignal("aux_dac_cs", Pins("AA20"), IOStandard("LVCMOS33")),
),
# DAC SPI
("spi", 1,
Subsignal("sclk", Pins("K3"), IOStandard("LVCMOS18")),
Subsignal("sdio", Pins("R2"), IOStandard("LVCMOS18")),
Subsignal("cs", Pins("R3"), IOStandard("LVCMOS18")),
# Subsignal("sclk_aux", Pins("V18"), IOStandard("LVCMOS33")),
# Subsignal("mosi_aux", Pins("U17"), IOStandard("LVCMOS33")),
# Subsignal("miso_aux", Pins("U18"), IOStandard("LVCMOS33")),
# Subsignal("cs_aux", Pins("AA20"), IOStandard("LVCMOS33")),
),
#Pins("Y15 AB14 AB13 V13 V14 V15 U12 W13 W12 R17 W15 AB17 Y12 Y13 V16 W16 AA17 Y17"),
("gpio", 0,
Subsignal("n", Pins("Y15 AB14 AB13 V13 V14 V15 U12 W13"), IOStandard("LVCMOS33")),
Subsignal("p", Pins("W12 R17 W15 AB17 Y12 Y13 V16 W16"), IOStandard("LVCMOS33")),
),
# PS7
("ps7_clk", 0, Pins("_" * 1)),
("ps7_porb", 0, Pins("_" * 1)),
("ps7_srstb", 0, Pins("_" * 1)),
("ps7_mio", 0, Pins("_" * 54)),
("ps7_ddram", 0,
Subsignal("addr", Pins("_" * 15)),
Subsignal("ba", Pins("_" * 3)),
Subsignal("cas_n", Pins("_" * 1)),
Subsignal("ck_n", Pins("_" * 1)),
Subsignal("ck_p", Pins("_" * 1)),
Subsignal("cke", Pins("_" * 1)),
Subsignal("cs_n", Pins("_" * 1)),
Subsignal("dm", Pins("_" * 4)),
Subsignal("dq", Pins("_" * 32)),
Subsignal("dqs_n", Pins("_" * 4)),
Subsignal("dqs_p", Pins("_" * 4)),
Subsignal("odt", Pins("_" * 1)),
Subsignal("ras_n", Pins("_" * 1)),
Subsignal("reset_n", Pins("_" * 1)),
Subsignal("we_n", Pins("_" * 1)),
Subsignal("vrn", Pins("_" * 1)),
Subsignal("vrp", Pins("_" * 1)),
),
# I2C0 to Si5340 on Fast Servo
("ps7_i2c", 0,
Subsignal("sda", Pins("M2")),
Subsignal("scl", Pins("M1")),
IOStandard("LVCMOS18")
),
# Si540 nRST
("nrst", 0, Pins("M7"), IOStandard("LVCMOS18")),
]
_connector_eem = [
("eem", {
"d0_cc_n": "C3",
"d0_cc_p": "D3",
"d1_n": "A4",
"d1_p": "A5",
"d2_n": "F6",
"d2_p": "G6",
"d3_n": "A6",
"d3_p": "A7",
"d4_n": "E5",
"d4_p": "F5",
"d5_n": "H3",
"d5_p": "H4",
"d6_n": "B8",
"d6_p": "C8",
"d7_n": "D8",
"d7_p": "E8",
}),
]
_connector_gpio = [
("gpio", {
"qspi_io3": "Y15",
"qspi_io2": "AB14",
"qspi_io1": "AB13",
"qspi_io0": "V13",
"qspi_clk": "V14",
"qspi_ncs": "V15",
"hrtim_che1": "U12",
"hrtim_che2": "W13",
"hrtim_cha1": "W12",
"hrtim_cha2": "R17",
"lptim2_out": "W15",
"uart4_tx": "AB17",
"spi1_mosi": "Y12",
"spi1_miso": "Y13",
"spi1_nss": "V16",
"spi1_sck": "W16",
"i2c1_sda": "AA17",
"i2c1_scl": "Y17",
})
]
# PS7 config ---------------------------------------------------------------------------------------
ps7_config_board_preset = {
"PCW_PRESET_BANK0_VOLTAGE" : "LVCMOS 3.3V",
"PCW_PRESET_BANK1_VOLTAGE" : "LVCMOS 1.8V",
"PCW_CRYSTAL_PERIPHERAL_FREQMHZ" : "33.333333",
"PCW_QSPI_PERIPHERAL_ENABLE" : "1",
"PCW_QSPI_GRP_SINGLE_SS_ENABLE" : "1",
"PCW_SINGLE_QSPI_DATA_MODE" : "x4",
"PCW_QSPI_QSPI_IO" : "MIO 1 .. 6",
"PCW_QSPI_GRP_FBCLK_ENABLE" : "1",
# SD Card
"PCW_SD0_PERIPHERAL_ENABLE" : "1",
"PCW_SD0_SD0_IO" : "MIO 40 .. 45",
"PCW_MIO_40_PULLUP" : "disabled",
"PCW_MIO_41_PULLUP" : "disabled",
"PCW_MIO_42_PULLUP" : "disabled",
"PCW_MIO_43_PULLUP" : "disabled",
"PCW_MIO_44_PULLUP" : "disabled",
"PCW_MIO_45_PULLUP" : "disabled",
# UART
"PCW_UART0_PERIPHERAL_ENABLE" : "1",
"PCW_UART0_UART0_IO" : "MIO 10 .. 11",
# ETHERNET
"PCW_ACT_ENET0_PERIPHERAL_FREQMHZ" : "125",
"PCW_ENET0_PERIPHERAL_CLKSRC" : "ARM PLL",
"PCW_ENET0_PERIPHERAL_ENABLE" : "1",
"PCW_ENET0_ENET0_IO" : "MIO 16 .. 27",
"PCW_ENET0_GRP_MDIO_ENABLE" : "1",
"PCW_ENET0_GRP_MDIO_IO" : "MIO 52 .. 53",
"PCW_ENET_RESET_ENABLE" : "1",
"PCW_ENET0_RESET_ENABLE" : "1",
"PCW_ENET0_RESET_IO" : "MIO 50",
# USB
"PCW_USB0_PERIPHERAL_ENABLE" : "1",
"PCW_USB0_USB0_IO" : "MIO 28 .. 39",
"PCW_USB_RESET_ENABLE" : "1",
"PCW_USB0_RESET_ENABLE" : "1",
"PCW_USB0_RESET_IO" : "MIO 51",
"PCW_WDT_PERIPHERAL_ENABLE" : "1",
"PCW_TTC0_PERIPHERAL_ENABLE" : "1", # TTC0 required for Linux
# I2C
"PCW_I2C_RESET_ENABLE" : "0",
"PCW_I2C_RESET_POLARITY" : "Active Low",
# I2C0
"PCW_I2C0_I2C0_IO" : "EMIO",
"PCW_I2C0_PERIPHERAL_ENABLE" : "1",
"PCW_I2C0_GRP_INT_ENABLE" : "1",
"PCW_I2C0_GRP_INT_IO" : "EMIO",
# I2C1
"PCW_I2C1_PERIPHERAL_ENABLE" : "1",
"PCW_I2C1_I2C1_IO" : "MIO 48 .. 49",
"PCW_I2C1_I2C1_IO" : "MIO 12 .. 13",
"PCW_I2C1_PERIPHERAL_ENABLE" : "1",
"PCW_UIPARAM_DDR_MEMORY_TYPE" : "DDR 3 (Low Voltage)",
"PCW_UIPARAM_DDR_PARTNO" : "MT41J256M16 RE-125",
"PCW_GPIO_MIO_GPIO_ENABLE" : "1",
"PCW_FPGA0_PERIPHERAL_FREQMHZ" : "100",
"PCW_EN_CLK0_PORT" : "0", # dont use FCLK0
}
class Platform(XilinxPlatform):
default_clk_name = "clk100"
default_clk_period = 10.0
def __init__(self):
XilinxPlatform.__init__(self, "xc7z015-clg485-1", _io, _connector_gpio + _connector_eem, toolchain="vivado")
ps7_config = ps7_config_board_preset
self.ps7_config = ps7_config
verilog_sources = os.listdir(verilog_dir)
self.add_sources(verilog_dir, *verilog_sources)
def do_finalize(self, fragment):
try:
XilinxPlatform.do_finalize(self, fragment)
self.add_period_constraint(self.lookup_request(self.default_clk_name, loose=True), self.default_clk_period)
except ValueError:
pass
except ConstraintError:
pass

View File

@ -0,0 +1,290 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
import os
from migen import *
from misoc.interconnect import csr_bus
from misoc.interconnect.csr import AutoCSR, CSRStorage
from fast_servo.gateware.cores.adc import ADC, AUX_ADC_CTRL
from fast_servo.gateware.cores.dac import AUX_DAC_CTRL, DAC
from fast_servo.gateware.cores.pitaya_ps import Axi2Sys, Sys2CSR, SysCDC, SysInterconnect
from fast_servo.gateware.cores.ps7 import PS7
from fast_servo.gateware.cores.spi_phy import SpiInterface, SpiPhy
class CRG(Module):
def __init__(self, platform):
self.ps_rst = Signal()
self.locked = Signal()
self.clock_domains.cd_sys = ClockDomain()
self.clock_domains.cd_sys_double = ClockDomain()
self.clock_domains.cd_idelay = ClockDomain()
# # #
# Clk.
clk100 = platform.request("clk100")
platform.add_period_constraint(clk100, 10.0)
self.clkin = clk100
clk100_buf = Signal()
self.specials += Instance("IBUFG", i_I=clk100, o_O=clk100_buf)
clk_feedback = Signal()
clk_feedback_buf = Signal()
clk_sys = Signal()
clk_idelay = Signal()
self.specials += [
Instance(
"PLLE2_BASE",
p_BANDWIDTH="OPTIMIZED",
p_DIVCLK_DIVIDE=1,
p_CLKFBOUT_PHASE=0.0,
p_CLKFBOUT_MULT=10,
p_CLKIN1_PERIOD=10.0,
p_REF_JITTER1=0.01,
p_STARTUP_WAIT="FALSE",
i_CLKIN1=clk100_buf,
i_PWRDWN=0,
i_RST=self.ps_rst,
i_CLKFBIN=clk_feedback_buf,
o_CLKFBOUT=clk_feedback,
p_CLKOUT0_DIVIDE=10,
p_CLKOUT0_PHASE=0.0,
p_CLKOUT0_DUTY_CYCLE=0.5,
o_CLKOUT0=clk_sys, # 100 MHz <- sys_clk
p_CLKOUT1_DIVIDE=5,
p_CLKOUT1_PHASE=0.0,
p_CLKOUT1_DUTY_CYCLE=0.5,
o_CLKOUT1=clk_idelay, # 200 MHZ <- 2 * sys_clk = 2*100 MHz
o_LOCKED=self.locked,
)
]
self.specials += Instance("BUFG", i_I=clk_feedback, o_O=clk_feedback_buf)
self.specials += Instance("BUFG", i_I=clk_sys, o_O=self.cd_sys.clk)
self.specials += Instance("BUFG", i_I=clk_idelay, o_O=self.cd_idelay.clk)
self.specials += Instance("BUFG", i_I=clk_idelay, o_O=self.cd_sys_double.clk)
# Ignore sys_clk to pll clkin path created by SoC's rst.
platform.add_false_path_constraints(self.cd_sys.clk, self.clkin)
self.specials += Instance("FD", p_INIT=1, i_D=~self.locked, i_C=self.cd_sys.clk, o_Q=self.cd_sys.rst)
class BaseSoC(PS7, AutoCSR):
def __init__(self, platform, passthrouh=False):
PS7.__init__(self, platform)
# TODO:
# LINIEN SPECIFIC csr_map - in the future should be moved
# to csr_devices list
self.csr_map = {
"adc": 9,
"fp_led0": 10,
"fp_led1": 11,
"fp_led2": 12,
"fp_led3": 13,
"dac": 14,
"adc_aux_ctrl": 15,
"dac_aux_ctrl": 16,
}
self.soc_name = "FastServo"
self.interconnect_slaves = []
self.csr_devices = []
self.platform = platform
self.submodules.crg = CRG(platform)
# # # AXI to system bus bridge
self.submodules.axi2sys = Axi2Sys()
self.submodules.sys2csr = Sys2CSR()
self.submodules.syscdc = SysCDC()
self.add_axi_gp_master(self.axi2sys.axi)
self.comb += [
self.axi2sys.axi.aclk.eq(ClockSignal("sys")),
self.axi2sys.axi.arstn.eq(self.frstn),
self.syscdc.target.connect(self.sys2csr.sys),
]
# ETH LEDS
self.comb += [
platform.request("eth_led", 0).eq(platform.request("from_eth_phy", 0)),
platform.request("eth_led", 1).eq(platform.request("from_eth_phy", 1)),
]
# I2C0 to Si5340 on Fast Servo
self.add_i2c_emio(platform, "ps7_i2c", 0)
# SPI0 - interface to main ADC and auxiliary ADC
self.add_spi_interface(platform, SpiInterface.ADC)
# SPI1 - interface to main DAC and auxiliary DAC
self.add_spi_interface(platform, SpiInterface.DAC)
# self.add_main_adc(platform)
self.submodules.adc = ADC(platform)
self.csr_devices.append("adc")
# self.add_main_dac(platform)
self.submodules.dac = DAC(platform)
self.csr_devices.append("dac")
# DEBUG
if passthrouh:
DAC_DATA_WIDTH = 14
for ch in range(2):
saturate = Signal()
adc_signal = self.adc.data_out[ch]
self.comb += [
saturate.eq(adc_signal[-3:] != Replicate(adc_signal[-1], 3)),
self.dac.data_in[ch].eq(Mux(saturate,
Cat(Replicate(~adc_signal[-1], DAC_DATA_WIDTH-1), adc_signal[-1]),
adc_signal[:-2]))
]
si_5340_nrst = platform.request("nrst")
self.comb += si_5340_nrst.eq(1)
for i in range(4):
led_pin = platform.request("fp_led", i)
setattr(self.submodules, f"fp_led{i}", LED(led_pin))
self.csr_devices.append(f"fp_led{i}")
self.submodules.adc_aux_ctrl = AUX_ADC_CTRL(platform)
self.csr_devices.append("adc_aux_ctrl")
self.submodules.dac_aux_ctrl = AUX_DAC_CTRL(platform)
self.csr_devices.append("dac_aux_ctrl")
def add_spi_interface(self, platform, spi_type):
assert isinstance(spi_type, SpiInterface)
n = spi_type.value
ps7_spi_pads = platform.request("spi", spi_type.value)
spi_phy = SpiPhy(spi_type, ps7_spi_pads)
self.submodules += spi_phy
ps7_config_spi = {
f"PCW_SPI{n}_GRP_SS0_ENABLE" : "1",
f"PCW_SPI{n}_GRP_SS0_IO" : "EMIO",
f"PCW_SPI{n}_GRP_SS1_ENABLE" : "1",
f"PCW_SPI{n}_GRP_SS1_IO" : "EMIO",
f"PCW_SPI{n}_GRP_SS2_ENABLE" : "1",
f"PCW_SPI{n}_GRP_SS2_IO" : "EMIO",
f"PCW_SPI{n}_PERIPHERAL_ENABLE" : "1",
f"PCW_SPI{n}_SPI{n}_IO" : "EMIO",
f"PCW_SPI_PERIPHERAL_CLKSRC" : "IO PLL",
f"PCW_SPI_PERIPHERAL_DIVISOR0" : "10",
f"PCW_SPI_PERIPHERAL_FREQMHZ" : "166.666666",
}
self.add_ps7_config(ps7_config_spi)
self.cpu_params.update({
f"o_SPI{n}_MISO_O" : spi_phy.ps_miso_o,
f"o_SPI{n}_MISO_T" : spi_phy.ps_miso_t,
f"o_SPI{n}_MOSI_O" : spi_phy.ps_mosi_o,
f"o_SPI{n}_MOSI_T" : spi_phy.ps_mosi_t,
f"o_SPI{n}_SCLK_O" : spi_phy.ps_sclk_o,
f"o_SPI{n}_SCLK_T" : spi_phy.ps_sclk_t,
f"i_SPI{n}_SCLK_I" : spi_phy.ps_sclk_i,
f"i_SPI{n}_MOSI_I" : spi_phy.ps_mosi_i,
f"i_SPI{n}_MISO_I" : spi_phy.ps_miso_i,
f"i_SPI{n}_SS_I" : spi_phy.ps_ss_i,
f"o_SPI{n}_SS_O" : spi_phy.ps_ss[0],
f"o_SPI{n}_SS1_O" : spi_phy.ps_ss[1],
f"o_SPI{n}_SS2_O" : spi_phy.ps_ss[2],
f"o_SPI{n}_SS_T" : spi_phy.ps_ss_t,
})
def add_interconnect_slave(self, slave):
self.interconnect_slaves.append(slave)
def get_csr_dev_address(self, name, memory):
# TODO: switch to MiSoC-like address retriving from
# the list of CSR devices
if memory is not None:
name = name + "_" + memory.name_override
try:
return self.csr_map[name]
except KeyError:
return None
def soc_finalize(self):
# Overload this method to customize SystemInterconnect
# and csrbanks - especially useful in Linien
self.add_interconnect_slave(self.syscdc.source)
self.submodules.interconnect = SysInterconnect(
self.axi2sys.sys,
*self.interconnect_slaves
)
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()
)
def do_finalize(self):
self.soc_finalize()
PS7.do_finalize(self)
def build(self, *args, **kwargs):
self.platform.build(self, *args, **kwargs)
class LED(Module, AutoCSR):
def __init__(self, led):
self.led_out = CSRStorage(1)
self.comb += led.eq(self.led_out.storage)
if __name__ == "__main__":
import subprocess
from fast_servo.gateware.fast_servo_platform import Platform
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--debug", action="store_true", default=False, help="Hardwire ADC data to DAC")
args = parser.parse_args()
root_path = os.getcwd()
platform = Platform()
fast_servo = BaseSoC(platform, passthrouh=args.debug)
build_dir = "builds/fast_servo_gw_debug" if args.debug else"builds/fast_servo_gw"
build_name = "top"
fast_servo.build(build_dir=build_dir, build_name=build_name, run=True)
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)

View File

@ -0,0 +1,162 @@
///////////////////////////////////////////////////////////////////////////////
// LTC2195.v
//
// 8/03/21
// Jakub Matyas
//
// LTC2195 controller.
//
//
///////////////////////////////////////////////////////////////////////////////
// `include "timescale.v"
`timescale 1ns/1ps // this was in the SelectIO design
module LTC2195(
input rst_in,
input clk200,
input DCO,
input DCO_2D,
input FR_in_p,
input FR_in_n,
input [3:0] D0_in_p,
input [3:0] D0_in_n,
input [3:0] D1_in_p,
input [3:0] D1_in_n,
input bitslip,
input [4:0] delay_val,
output reg [15:0] ADC0_out,
output reg [15:0] ADC1_out,
output reg [3:0] FR_out,
output wire [8:0] o_data_from_pins,
output idelay_rdy
);
// ///////////////////////////////////////////////////////////////////////////////
// // LVDS inputs
localparam N_BITS = 4;
localparam N_LANES = 9; // for each channel 4 lanes + 1 lane for FRAME
wire [N_LANES-1:0] data_in_p, data_in_n, data_in_from_pins, data_in_from_pins_delay;
assign data_in_p = {FR_in_p, D1_in_p, D0_in_p};
assign data_in_n = {FR_in_n, D1_in_n, D0_in_n};
assign o_data_from_pins = data_in_from_pins_delay;
wire [N_LANES*4 -1:0] data_out;
wire [35:0 ]data_out_mod;
assign data_out_mod = {~data_out[35:24], data_out[23:20], ~data_out[19:16], data_out[15:0]};
always @(posedge DCO_2D) begin
ADC0_out <= {
data_out_mod[0], data_out_mod[4], data_out_mod[1], data_out_mod[5],
data_out_mod[2], data_out_mod[6], data_out_mod[3], data_out_mod[7],
data_out_mod[8], data_out_mod[12], data_out_mod[9], data_out_mod[13],
data_out_mod[10], data_out_mod[14], data_out_mod[11], data_out_mod[15]
};
ADC1_out <= {
data_out_mod[16 + 0], data_out_mod[16 + 4], data_out_mod[16 + 1], data_out_mod[16 + 5],
data_out_mod[16 + 2], data_out_mod[16 + 6], data_out_mod[16 + 3], data_out_mod[16 + 7],
data_out_mod[16 + 8], data_out_mod[16 + 12], data_out_mod[16 + 9], data_out_mod[16 + 13],
data_out_mod[16 + 10], data_out_mod[16 + 14], data_out_mod[16 + 11], data_out_mod[16 + 15]
};
FR_out <= {data_out_mod[32], data_out_mod[33], data_out_mod[34], data_out_mod[35]}; // value that arrived first is LSB, therefore reversing order
end
wire s_idelay_rdy;
IDELAYCTRL IDELAYCTRL_inst (
.RDY(s_idelay_rdy), // 1-bit output: Ready output
.REFCLK(clk200), // 1-bit input: Reference clock input
.RST(s_rst) // 1-bit input: Active high reset input
);
assign idelay_rdy = s_idelay_rdy;
reg s_rst;
reg [5:0] rst_cnt;
wire serdes_o;
always @(posedge DCO_2D) begin
if (rst_in) begin
s_rst <= 1'b1;
rst_cnt <= 'b0;
end else begin
if (rst_cnt == 22)
s_rst <= 'b0;
else
rst_cnt <= rst_cnt + 1;
end
end
genvar lane;
generate for (lane=0; lane<N_LANES; lane=lane+1) begin
IBUFDS #(
.DIFF_TERM("TRUE")
)
ibufds_inst (
.I(data_in_p[lane]),
.IB(data_in_n[lane]),
.O(data_in_from_pins[lane])
);
IDELAYE2 #(
.CINVCTRL_SEL("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE)
.DELAY_SRC("IDATAIN"), // Delay input (IDATAIN, DATAIN)
.HIGH_PERFORMANCE_MODE("TRUE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE")
.IDELAY_TYPE("VAR_LOAD"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
.IDELAY_VALUE(0), // Input delay tap setting (0-31)
.PIPE_SEL("FALSE"), // Select pipelined mode, FALSE, TRUE
.REFCLK_FREQUENCY(200.0), // IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0).
.SIGNAL_PATTERN("DATA") // DATA, CLOCK input signal
)
IDELAYE2_inst (
.C(clk200),
.CE('b0),
.CNTVALUEIN(delay_val),
.LD(1'b1),
.DATAOUT(data_in_from_pins_delay[lane]), // 1-bit output: Delayed data output
.IDATAIN(data_in_from_pins[lane]), // 1-bit input: Data input from the I/O
.LDPIPEEN (1'b0),
.REGRST (1'b0),
.CINVCTRL (1'b0)
);
ISERDESE2 #(
.DATA_RATE("DDR"),
.DATA_WIDTH(3'd4),
.INTERFACE_TYPE("NETWORKING"),
.IOBDELAY("BOTH"),
.SERDES_MODE("MASTER"),
.NUM_CE(2'd2)
)
iserdes_inst (
.CE1(1'd1),
.CE2(1'd1),
.DYNCLKDIVSEL('b0),
.DYNCLKSEL('b0),
.CLK(DCO),
.CLKB(!DCO),
.CLKDIV(DCO_2D),
// .D(data_in_from_pins[lane]),
.DDLY(data_in_from_pins_delay[lane]),
.RST(s_rst),
.BITSLIP(bitslip),
// DATA is MSB first and OUTA is LANE0, so in case of OUTA:
// Q1 = D9
// Q2 = D11
// Q3 = D13
// Q4 = D15
.Q1(data_out[lane*N_BITS + 3]),
.Q2(data_out[lane*N_BITS + 2]),
.Q3(data_out[lane*N_BITS + 1]),
.Q4(data_out[lane*N_BITS + 0])
);
end
endgenerate
endmodule

View File

@ -0,0 +1,265 @@
/**
* $Id: axi_slave.v 961 2014-01-21 11:40:39Z matej.oblak $
*
* @brief Red Pitaya symplified AXI slave.
*
* @Author Matej Oblak
*
* (c) Red Pitaya http://www.redpitaya.com
*
* This part of code is written in Verilog hardware description language (HDL).
* Please visit http://en.wikipedia.org/wiki/Verilog
* for more details on the language used herein.
*/
/**
* GENERAL DESCRIPTION:
*
* AXI slave used also for simple bus master.
*
*
* /------\
* WR ADDRESS ----> | WR |
* WR DATA ----> | | -----------
* WR RESPONSE <---- | CH | |
* \------/ /--------\
* | SIMPLE | ---> WR/RD ADDRRESS
* AXI | | ---> WR DATA
* | RP | <--- RD DATA
* | BUS | <--- ACKNOWLEDGE
* /------\ \--------/
* RD ADDRESS ----> | RD | |
* RD DATA <---- | CH | -----------
* \------/
*
*
* Because AXI bus is quite complex simplier bus was created.
*
* It combines write and read channel, where write has bigger priority. Command
* is then send forward to red pitaya bus. When wite or read acknowledge is
* received AXI response is created and new AXI is accepted.
*
* To prevent AXI lockups because no response is received, this slave creates its
* own after 32 cycles (ack_cnt).
*
*/
module axi_slave
#(
parameter AXI_DW = 64 , // data width (8,16,...,1024)
parameter AXI_AW = 32 , // address width
parameter AXI_IW = 8 , // ID width
parameter AXI_SW = AXI_DW >> 3 // strobe width - 1 bit for every data byte
)
(
// global signals
input axi_clk_i , //!< AXI global clock
input axi_rstn_i , //!< AXI global reset
// axi write address channel
input [ AXI_IW-1: 0] axi_awid_i , //!< AXI write address ID
input [ AXI_AW-1: 0] axi_awaddr_i , //!< AXI write address
input [ 4-1: 0] axi_awlen_i , //!< AXI write burst length
input [ 3-1: 0] axi_awsize_i , //!< AXI write burst size
input [ 2-1: 0] axi_awburst_i , //!< AXI write burst type
input [ 2-1: 0] axi_awlock_i , //!< AXI write lock type
input [ 4-1: 0] axi_awcache_i , //!< AXI write cache type
input [ 3-1: 0] axi_awprot_i , //!< AXI write protection type
input axi_awvalid_i , //!< AXI write address valid
output axi_awready_o , //!< AXI write ready
// axi write data channel
input [ AXI_IW-1: 0] axi_wid_i , //!< AXI write data ID
input [ AXI_DW-1: 0] axi_wdata_i , //!< AXI write data
input [ AXI_SW-1: 0] axi_wstrb_i , //!< AXI write strobes
input axi_wlast_i , //!< AXI write last
input axi_wvalid_i , //!< AXI write valid
output axi_wready_o , //!< AXI write ready
// axi write response channel
output [ AXI_IW-1: 0] axi_bid_o , //!< AXI write response ID
output reg [ 2-1: 0] axi_bresp_o , //!< AXI write response
output reg axi_bvalid_o , //!< AXI write response valid
input axi_bready_i , //!< AXI write response ready
// axi read address channel
input [ AXI_IW-1: 0] axi_arid_i , //!< AXI read address ID
input [ AXI_AW-1: 0] axi_araddr_i , //!< AXI read address
input [ 4-1: 0] axi_arlen_i , //!< AXI read burst length
input [ 3-1: 0] axi_arsize_i , //!< AXI read burst size
input [ 2-1: 0] axi_arburst_i , //!< AXI read burst type
input [ 2-1: 0] axi_arlock_i , //!< AXI read lock type
input [ 4-1: 0] axi_arcache_i , //!< AXI read cache type
input [ 3-1: 0] axi_arprot_i , //!< AXI read protection type
input axi_arvalid_i , //!< AXI read address valid
output axi_arready_o , //!< AXI read address ready
// axi read data channel
output [ AXI_IW-1: 0] axi_rid_o , //!< AXI read response ID
output reg [ AXI_DW-1: 0] axi_rdata_o , //!< AXI read data
output reg [ 2-1: 0] axi_rresp_o , //!< AXI read response
output reg axi_rlast_o , //!< AXI read last
output reg axi_rvalid_o , //!< AXI read response valid
input axi_rready_i , //!< AXI read response ready
// RP system read/write channel
output [ AXI_AW-1: 0] sys_addr_o , //!< system bus read/write address.
output [ AXI_DW-1: 0] sys_wdata_o , //!< system bus write data.
output reg [ AXI_SW-1: 0] sys_sel_o , //!< system bus write byte select.
output reg sys_wen_o , //!< system bus write enable.
output reg sys_ren_o , //!< system bus read enable.
input [ AXI_DW-1: 0] sys_rdata_i , //!< system bus read data.
input sys_err_i , //!< system bus error indicator.
input sys_ack_i //!< system bus acknowledge signal.
);
//---------------------------------------------------------------------------------
//
// AXI slave Module
wire ack ;
reg [ 6-1: 0] ack_cnt ;
reg rd_do ;
reg [ AXI_IW-1: 0] rd_arid ;
reg [ AXI_AW-1: 0] rd_araddr ;
reg rd_error ;
wire rd_errorw ;
reg wr_do ;
reg [ AXI_IW-1: 0] wr_awid ;
reg [ AXI_AW-1: 0] wr_awaddr ;
reg [ AXI_IW-1: 0] wr_wid ;
reg [ AXI_DW-1: 0] wr_wdata ;
reg wr_error ;
wire wr_errorw ;
assign wr_errorw = (axi_awlen_i != 4'h0) || (axi_awsize_i != 3'b010); // error if write burst and more/less than 4B transfer
assign rd_errorw = (axi_arlen_i != 4'h0) || (axi_arsize_i != 3'b010); // error if read burst and more/less than 4B transfer
always @(posedge axi_clk_i) begin
if (axi_rstn_i == 1'b0) begin
rd_do <= 1'b0 ;
rd_error <= 1'b0 ;
end
else begin
if (axi_arvalid_i && !rd_do && !axi_awvalid_i && !wr_do) // accept just one read request - write has priority
rd_do <= 1'b1 ;
else if (axi_rready_i && rd_do && ack)
rd_do <= 1'b0 ;
if (axi_arvalid_i && axi_arready_o) begin // latch ID and address
rd_arid <= axi_arid_i ;
rd_araddr <= axi_araddr_i ;
rd_error <= rd_errorw ;
end
end
end
always @(posedge axi_clk_i) begin
if (axi_rstn_i == 1'b0) begin
wr_do <= 1'b0 ;
wr_error <= 1'b0 ;
end
else begin
if (axi_awvalid_i && !wr_do && !rd_do) // accept just one write request - if idle
wr_do <= 1'b1 ;
else if (axi_bready_i && wr_do && ack)
wr_do <= 1'b0 ;
if (axi_awvalid_i && axi_awready_o) begin // latch ID and address
wr_awid <= axi_awid_i ;
wr_awaddr <= axi_awaddr_i ;
wr_error <= wr_errorw ;
end
if (axi_wvalid_i && wr_do) begin // latch ID and write data
wr_wid <= axi_wid_i ;
wr_wdata <= axi_wdata_i ;
end
end
end
assign axi_awready_o = !wr_do && !rd_do ;
assign axi_wready_o = (wr_do && axi_wvalid_i) || (wr_errorw && axi_wvalid_i) ;
assign axi_bid_o = wr_awid ;
//assign axi_bresp_o = {wr_error,1'b0} ; // 2'b10 SLVERR
//assign axi_bvalid_o = (sys_wen_o && axi_bready_i) || (wr_error && axi_bready_i) ;
assign axi_arready_o = !rd_do && !wr_do && !axi_awvalid_i ;
assign axi_rid_o = rd_arid ;
//assign axi_rdata_o = sys_rdata_i ;
always @(posedge axi_clk_i) begin
if (axi_rstn_i == 1'b0) begin
axi_bvalid_o <= 1'b0 ;
axi_bresp_o <= 2'h0 ;
axi_rlast_o <= 1'b0 ;
axi_rvalid_o <= 1'b0 ;
axi_rresp_o <= 2'h0 ;
end
else begin
axi_bvalid_o <= wr_do && ack ;
axi_bresp_o <= {(wr_error || ack_cnt[5]),1'b0} ; // 2'b10 SLVERR 2'b00 OK
axi_rlast_o <= rd_do && ack ;
axi_rvalid_o <= rd_do && ack ;
axi_rresp_o <= {(rd_error || ack_cnt[5]),1'b0} ; // 2'b10 SLVERR 2'b00 OK
axi_rdata_o <= sys_rdata_i ;
end
end
// acknowledge protection
always @(posedge axi_clk_i) begin
if (axi_rstn_i == 1'b0) begin
ack_cnt <= 6'h0 ;
end
else begin
if ((axi_arvalid_i && axi_arready_o) || (axi_awvalid_i && axi_awready_o)) // rd || wr request
ack_cnt <= 6'h1 ;
else if (ack)
ack_cnt <= 6'h0 ;
else if (|ack_cnt)
ack_cnt <= ack_cnt + 6'h1 ;
end
end
assign ack = sys_ack_i || ack_cnt[5] || (rd_do && rd_errorw) || (wr_do && wr_errorw); // bus acknowledge or timeout or error
//------------------------------------------
// Simple slave interface
always @(posedge axi_clk_i) begin
if (axi_rstn_i == 1'b0) begin
sys_wen_o <= 1'b0 ;
sys_ren_o <= 1'b0 ;
sys_sel_o <= {AXI_SW{1'b0}} ;
end
else begin
sys_wen_o <= wr_do && axi_wvalid_i && !wr_errorw ;
sys_ren_o <= axi_arvalid_i && axi_arready_o && !rd_errorw ;
sys_sel_o <= {AXI_SW{1'b1}} ;
end
end
assign sys_addr_o = rd_do ? rd_araddr : wr_awaddr ;
assign sys_wdata_o = wr_wdata ;
endmodule

View File

@ -0,0 +1,128 @@
/**
* $Id: bus_clk_bridge.v 961 2014-01-21 11:40:39Z matej.oblak $
*
* @brief Red Pitaya system bus clock crossing bridge.
*
* @Author Matej Oblak
*
* (c) Red Pitaya http://www.redpitaya.com
*
* This part of code is written in Verilog hardware description language (HDL).
* Please visit http://en.wikipedia.org/wiki/Verilog
* for more details on the language used herein.
*/
/**
* GENERAL DESCRIPTION:
*
* Clock domain bridge for system bus.
*
*
* /------\
* SYSTEM | | PROCESSING
* BUS <-----> | SYNC | <-----> BUS
* | |
* \------/
*
*
* System bus runs on one clock domain while processing runs on separate. To
* simplify transition of writing and reading data this bridge was created.
*
*/
module bus_clk_bridge
(
// system bus
input sys_clk_i , //!< bus clock
input sys_rstn_i , //!< bus reset - active low
input [ 32-1: 0] sys_addr_i , //!< bus address
input [ 32-1: 0] sys_wdata_i , //!< bus write data
input [ 4-1: 0] sys_sel_i , //!< bus write byte select
input sys_wen_i , //!< bus write enable
input sys_ren_i , //!< bus read enable
output [ 32-1: 0] sys_rdata_o , //!< bus read data
output sys_err_o , //!< bus error indicator
output sys_ack_o , //!< bus acknowledge signal
// Destination bus
input clk_i , //!< clock
input rstn_i , //!< reset - active low
output reg [ 32-1: 0] addr_o , //!< address
output reg [ 32-1: 0] wdata_o , //!< write data
output wen_o , //!< write enable
output ren_o , //!< read enable
input [ 32-1: 0] rdata_i , //!< read data
input err_i , //!< error indicator
input ack_i //!< acknowledge signal
);
//---------------------------------------------------------------------------------
// Synchronize signals between clock domains
reg sys_rd ;
reg sys_wr ;
reg sys_do ;
reg [ 2-1: 0] sys_sync ;
reg sys_done ;
reg dst_do ;
reg [ 2-1: 0] dst_sync ;
reg dst_done ;
always @(posedge sys_clk_i) begin
if (sys_rstn_i == 1'b0) begin
sys_rd <= 1'b0 ;
sys_wr <= 1'b0 ;
sys_do <= 1'b0 ;
sys_sync <= 2'h0 ;
sys_done <= 1'b0 ;
end
else begin
if ((sys_do == sys_done) && (sys_wen_i || sys_ren_i)) begin
addr_o <= sys_addr_i ;
wdata_o <= sys_wdata_i ;
sys_rd <= sys_ren_i ;
sys_wr <= sys_wen_i ;
sys_do <= !sys_do ;
end
sys_sync <= {sys_sync[0], dst_done};
sys_done <= sys_sync[1];
end
end
always @(posedge clk_i) begin
if (rstn_i == 1'b0) begin
dst_do <= 1'b0 ;
dst_sync <= 2'h0 ;
dst_done <= 1'b0 ;
end
else begin
dst_sync <= {dst_sync[0], sys_do};
dst_do <= dst_sync[1];
if (ack_i && (dst_do != dst_done))
dst_done <= dst_do;
end
end
assign ren_o = sys_rd && (dst_sync[1]^dst_do);
assign wen_o = sys_wr && (dst_sync[1]^dst_do);
assign sys_rdata_o = rdata_i ;
assign sys_err_o = err_i ;
assign sys_ack_o = sys_done ^ sys_sync[1] ;
endmodule

View File

@ -0,0 +1,111 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: WUT
// Engineer: Jakub Matyas
//
// Create Date: 03/02/2023 01:39:08 PM
// Design Name:
// Module Name: spi2threewire
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module spi2threewire (
output ps_sclk_i,
input ps_sclk_o,
input ps_sclk_t,
output ps_mosi_i,
input ps_mosi_o,
input ps_mosi_t,
output ps_miso_i,
input ps_miso_o,
input ps_miso_t,
output ps_ss_i,
input [2:0] ps_ss,
input ps_ss_t,
output o_ss,
output o_sclk,
inout sdio
);
assign ps_sclk_i = 1'b0;
assign ps_mosi_i = 1'b0;
assign ps_ss_i = 1'b1;
reg [3:0] bit_count = 'd0;
// rd_wr_n - whether it will be READ transaction or WRITE
// first bit of the command
reg rd_wr_n = 'd0;
reg sdio_buffer_direction = 'd0;
wire s_sclk;
wire s_csn;
wire s_sdio_buffer_direction;
assign s_sclk = ps_sclk_o;
assign s_csn = ps_ss[0];
assign o_ss = s_csn;
// 1 if there is a SPI tranmsission going on (CS_N is LOW)
// AND transmission is of READ type
// 0 otherwise
assign s_sdio_buffer_direction = sdio_buffer_direction & ~s_csn;
always @(posedge s_sclk or posedge s_csn) begin
if (s_csn == 1'b1) begin
// after the transmission, fill bit counter with ZEROS
// and zero transmission type (rd_wr_n)
bit_count <= 4'd0;
rd_wr_n <= 1'b0;
end else begin
// on every rising edge increment bit counter
// sample first bit to get the knowledge of the transmission type
bit_count <= (bit_count < 4'd15) ? bit_count + 1'b1 : bit_count;
if (bit_count == 4'b0)
rd_wr_n <= ps_mosi_o;
end
end
always @(negedge s_sclk or posedge s_csn) begin
if (s_csn == 1'b1)
sdio_buffer_direction <= 1'b0;
else begin
if (bit_count == 4'd8)
// after the 8th bit, on falling edge,
// set the SDIO buffer direction
// accordingly to the transmission type
sdio_buffer_direction <= rd_wr_n;
end
end
IOBUF IOBUF_inst (
.O(ps_miso_i),
.IO(sdio),
.I(ps_mosi_o),
.T(s_sdio_buffer_direction) // 3-state enable input, high=input (from ext), low=output
);
OBUFT sclk_buf (
.O(o_sclk),
.I(ps_sclk_o),
.T('b0)
);
endmodule

View File

@ -0,0 +1,5 @@
## Source Repository
Files in this directory were copied from [elhep/Fast-Servo-Firmware](https://github.com/elhep/Fast-Servo-Firmware/tree/master/fast_servo/pythonscripts).
## Commit ID
The files were copied from commit ID [7fae40c](https://github.com/elhep/Fast-Servo-Firmware/commit/7fae40c0f872a91218be378f8289b98b1e366729).

View File

View File

@ -0,0 +1,319 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
import mmap
import os
import spidev
from pyfastservo.common import (
ADC_AFE_CTRL_ADDR,
ADC_BITSLIP_ADDR,
ADC_CH0_HIGH_ADDR,
ADC_CH0_LOW_ADDR,
ADC_CH1_HIGH_ADDR,
ADC_CH1_LOW_ADDR,
ADC_DELAY_ADDR,
ADC_FRAME_ADDR,
AUX_ADC_ADDR,
MAP_MASK,
PAGESIZE,
)
# /dev/spidev1.0 <=> spidev<BUS>.<DEVICE>
MAIN_ADC_BUS = 1
MAIN_ADC_DEVICE = 1
AUX_ADC_BUS = 1
AUX_ADC_PORT_A = 2
AUX_ADC_PORT_B = 3
def main_adc_config(test_pattern):
high_word = (test_pattern & 0xFF00) >> 8
low_word = test_pattern & 0xFF
spi = spidev.SpiDev()
try:
spi.open(MAIN_ADC_BUS, MAIN_ADC_DEVICE)
spi.max_speed_hz = 50000
spi.mode = 0b00 # CPOL = 0 CPHA = 0
spi.cshigh = True
# spi.read0 = False
spi_buffer = [0x00, 0x80] # reset
rx_buffer = [0x00, 0x00]
spi.xfer2(spi_buffer)
# REGISTER A1
spi_buffer = [0x01, 0x20] # set to Two's complement Data Format
spi.xfer2(spi_buffer)
# read values back
spi_buffer = [0x81, 0x00]
rx_buffer = spi.xfer2(spi_buffer)
print(f"Spi readback register 0x01: 0x{rx_buffer[1]:02x}")
if rx_buffer[1] != 0x20:
print("Different value read than sent in reg 0x02")
# REGISTER A2
spi_buffer = [
0x02,
0x15,
] # set to LVDS output, set 4 data lanes and turn on test mode
spi.xfer2(spi_buffer)
# read values back
spi_buffer = [0x82, 0x00]
rx_buffer = spi.xfer2(spi_buffer)
print(f"Spi readback register 0x02: 0x{rx_buffer[1]:02x}")
if rx_buffer[1] != 0x15:
print("Different value read than sent in reg 0x02")
# REGISTER A3
# test pattern high word
spi_buffer = [0x03, high_word]
spi.xfer2(spi_buffer)
# read balues back
spi_buffer = [0x83, 0x00]
rx_buffer = spi.xfer2(spi_buffer)
print(f"Spi readback register 0x03: 0x{rx_buffer[1]:02x}")
if rx_buffer[1] != high_word:
print("Different value read than sent in reg 0x03")
# REGISTER A4
# test pattern low word
spi_buffer = [0x04, low_word]
spi.xfer2(spi_buffer)
# read balues back
spi_buffer = [0x84, 0x00]
rx_buffer = spi.xfer2(spi_buffer)
print(f"Spi readback register 0x04: 0x{rx_buffer[1]:02x}")
if rx_buffer[1] != low_word:
print("Different value read than sent in reg 0x04")
finally:
spi.close()
def main_adc_test_mode(enable):
spi = spidev.SpiDev()
try:
spi.open(MAIN_ADC_BUS, MAIN_ADC_DEVICE)
spi.max_speed_hz = 50000
spi.mode = 0b00 # CPOL = 0 CPHA = 0
spi.cshigh = True
# spi.read0 = True
reg_contents = (
0x15 if enable else 0x11
) # set to LVDS output, set 4 data lanes and turn on or off test mode
spi_buffer = [0x02, reg_contents]
spi.xfer2(spi_buffer)
# read values back
spi_buffer = [0x82, 0x00]
rx_buffer = spi.xfer2(spi_buffer)
print(f"Spi readback register 0x02: 0x{rx_buffer[1]:02x}")
if rx_buffer[1] != reg_contents:
print("Different value read than sent in reg 0x02")
finally:
spi.close()
def read_from_memory(address, n_bytes):
assert n_bytes <= 4
addr = address
try:
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
with mmap.mmap(
f,
PAGESIZE,
mmap.MAP_SHARED,
mmap.PROT_READ | mmap.PROT_WRITE,
offset=addr & ~MAP_MASK,
) as mem:
start_addr = addr & MAP_MASK
stop_addr = start_addr + 4
# print(f"addr: 0x{addr:x}\tstart_addr: 0x{start_addr}\tstop_addr: 0x{stop_addr}")
contents = mem[start_addr:stop_addr]
read_value = list(contents)[:n_bytes]
# print("Read value: ", read_value)
finally:
os.close(f)
return read_value
def write_to_memory(address, value):
value_bytes = value.to_bytes(4, "little")
addr = address
try:
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
with mmap.mmap(
f,
PAGESIZE,
mmap.MAP_SHARED,
mmap.PROT_READ | mmap.PROT_WRITE,
offset=addr & ~MAP_MASK,
) as mem:
start_addr = addr & MAP_MASK
stop_addr = start_addr + 4
# print(f"addr: 0x{addr:x}\tstart_addr: 0x{start_addr}\tstop_addr: 0x{stop_addr}")
mem[start_addr:stop_addr] = value_bytes
contents = mem[start_addr:stop_addr]
# print("Read value: ", list(contents), " written value: ", list(value_bytes))
finally:
os.close(f)
def word_align():
value = 0
edge_detected = False
transition = False
tap_delay = 0
for i in range(4):
current_frame = read_from_memory(ADC_FRAME_ADDR, 1)[0]
if current_frame != 0x0C:
print(
f"Performing bitslip (bitslip iteration: {i}). Reason: current_frame is 0x{current_frame:02x} instead of 0x0C"
)
write_to_memory(ADC_BITSLIP_ADDR, 1)
else:
print(f"No bitslip required; Currernt frame = 0x{current_frame:02x}")
break
current_frame = read_from_memory(ADC_FRAME_ADDR, 1)[0]
prev_frame = current_frame
for i in range(32):
write_to_memory(ADC_DELAY_ADDR, tap_delay)
if edge_detected == 1:
break
current_frame = read_from_memory(ADC_FRAME_ADDR, 1)[0]
print(f"Tap delay: {tap_delay}")
print(f"Current frame: 0x{current_frame:02x}")
if current_frame == prev_frame:
tap_delay += 1
elif not transition:
tap_delay += 1
transition = True
elif transition:
tap_delay = i // 2
edge_detected = True
prev_frame = current_frame
if not edge_detected:
tap_delay = 11 # empirically tested to work best
write_to_memory(ADC_DELAY_ADDR, tap_delay)
print(f"No edge detected; setting iDelay to: {tap_delay}")
if edge_detected:
write_to_memory(ADC_DELAY_ADDR, tap_delay + 2)
print(f"Edge detected; setting iDelay to (tap_delay + 2): {tap_delay} + 2")
adc_ch0 = read_from_memory(ADC_CH0_HIGH_ADDR, 4)
print(f"ADC_CH0: 0x{adc_ch0}")
adc_ch0 = (read_from_memory(ADC_CH0_HIGH_ADDR, 1)[0] << 8) | read_from_memory(
ADC_CH0_LOW_ADDR, 1
)[0]
adc_ch1 = (read_from_memory(ADC_CH1_HIGH_ADDR, 1)[0] << 8) | read_from_memory(
ADC_CH1_LOW_ADDR, 1
)[0]
print(f"Final ADC_CH0: 0x{adc_ch0:04x}")
print(f"Final ADC_CH1: 0x{adc_ch1:04x}")
def modify_bit(original_value, position, bit_value):
mask = 1 << position
return (original_value & ~mask) | (bit_value << position)
def adc_aux_config():
# MSB to LSB
# | RANGE | ADDR [2:0] | DIFF |
# DIFF = 0 => configure as single ended (it is negated in gateware)
# RANGE = 0 => configure as 0-2.5 Vref
to_write = 0b00000
write_to_memory(AUX_ADC_ADDR, to_write)
def adc_aux_read(port, type, pin):
# port:
# 1 - port A
# 2 - port B
# type:
# 0 - single-ended
# 1 - differential
# pin:
# 0b000 - VA1/VB1
# 0b001 - VA2/VB2
# 0b010 - VA3/VB3
# 0b011 - VA4/VB4
assert type in (0, 1)
assert port in (1, 2)
write_buffer = [0, 0]
read_buffer = [0, 0]
aux_config_reg = read_from_memory(AUX_ADC_ADDR, 1)[0]
aux_config = (aux_config_reg & 0b10001) | pin << 1
write_to_memory(AUX_ADC_ADDR, aux_config)
spi = spidev.SpiDev()
try:
spi.open(1, 3) # AUX ADC 1?
spi.max_speed_hz = 5000
spi.mode = 0b00
spi.cshigh = True
read_buffer = spi.xfer2(write_buffer)
mu_voltage = read_buffer[0] << 8 | read_buffer[1] >> 2
print(f"MU_voltage: 0x{mu_voltage:04X}")
print(f"Read_buffer[0]: 0x{read_buffer[0]:02X}")
print(f"Read_buffer[1]: 0x{read_buffer[1]:02X}")
return mu_voltage * 2.5 / 4096
finally:
spi.close()
def main():
main_adc_config(0x811F)
word_align()
main_adc_test_mode(False)
write_to_memory(ADC_AFE_CTRL_ADDR, 0b1100) # {-, -, ch2_X10, ch1_X10}
print(read_from_memory(ADC_AFE_CTRL_ADDR, 1)[0])
if __name__ == "__main__":
main()

View File

@ -0,0 +1,74 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
CSR_SIZE = 0x800
MAP_SIZE = 0x1000
MAP_MASK = 0xFFF
PAGESIZE = 0x1000
# LINIEN_OFFSET = 0x0
LINIEN_OFFSET = 0x300000
# ----------------------------------------------------------------
# FRONT PANEL LEDS REGISTER ADDRESSES
LED0_BASE_ADDR = 0x40005000 + LINIEN_OFFSET
LED1_BASE_ADDR = 0x40005800 + LINIEN_OFFSET
LED2_BASE_ADDR = 0x40006000 + LINIEN_OFFSET
LED3_BASE_ADDR = 0x40006800 + LINIEN_OFFSET
# ----------------------------------------------------------------
# DAC REGISTER ADDRESSES
ADC_BASE_ADDR = 0x40004800 + LINIEN_OFFSET
ADC_FRAME_OFFSET = 0x0
ADC_CH0_HIGH_OFFSET = 0x4
ADC_CH0_LOW_OFFSET = 0x8
ADC_CH1_HIGH_OFFSET = 0xC
ADC_CH1_LOW_OFFSET = 0x10
ADC_TAP_DELAY_OFFSET = 0x14
ADC_BITSLIP_OFFSET = 0x18
ADC_AFE_CTRL_OFFSET = 0x1C
ADC_FRAME_ADDR = ADC_BASE_ADDR + ADC_FRAME_OFFSET
ADC_CH0_HIGH_ADDR = ADC_BASE_ADDR + ADC_CH0_HIGH_OFFSET
ADC_CH0_LOW_ADDR = ADC_BASE_ADDR + ADC_CH0_LOW_OFFSET
ADC_CH1_HIGH_ADDR = ADC_BASE_ADDR + ADC_CH1_HIGH_OFFSET
ADC_CH1_LOW_ADDR = ADC_BASE_ADDR + ADC_CH1_LOW_OFFSET
ADC_DELAY_ADDR = ADC_BASE_ADDR + ADC_TAP_DELAY_OFFSET
ADC_BITSLIP_ADDR = ADC_BASE_ADDR + ADC_BITSLIP_OFFSET
ADC_AFE_CTRL_ADDR = ADC_BASE_ADDR + ADC_AFE_CTRL_OFFSET
AUX_ADC_ADDR = 0x40007800 + LINIEN_OFFSET
# ----------------------------------------------------------------
# DAC REGISTER ADDRESSES
DAC_BASE_ADDR = 0x40007000 + LINIEN_OFFSET
CTRL_OFFSET = 0x0
CH0_HIGH_WORD_OFFSET = 0x4
CH0_LOW_WORD_OFFSET = 0x8
CH1_HIGH_WORD_OFFSET = 0xC
CH1_LOW_WORD_OFFSET = 0x10
CTRL_ADDR = DAC_BASE_ADDR + CTRL_OFFSET
CH0_HIGH_WORD_ADDR = DAC_BASE_ADDR + CH0_HIGH_WORD_OFFSET
CH0_LOW_WORD_ADDR = DAC_BASE_ADDR + CH0_LOW_WORD_OFFSET
CH1_HIGH_WORD_ADDR = DAC_BASE_ADDR + CH1_HIGH_WORD_OFFSET
CH1_LOW_WORD_ADDR = DAC_BASE_ADDR + CH1_LOW_WORD_OFFSET

View File

@ -0,0 +1,182 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
import mmap
import os
import spidev
from pyfastservo.common import (
CH0_HIGH_WORD_ADDR,
CH0_LOW_WORD_ADDR,
CH1_HIGH_WORD_ADDR,
CH1_LOW_WORD_ADDR,
CTRL_ADDR,
MAP_MASK,
PAGESIZE,
)
# /dev/spidev2.0 <=> spidev<BUS>.<DEVICE>
MAIN_DAC_BUS = 2
MAIN_DAC_DEVICE = 0
DAC_VERSION = 0x0A
def main_dac_init():
spi = spidev.SpiDev()
try:
spi.open(MAIN_DAC_BUS, MAIN_DAC_DEVICE)
spi.max_speed_hz = 5000
spi.mode = 0b00 # CPOL = 0 CPHA = 0
spi.cshigh = True
spi_buffer = [0x00, 0x10] # software reset
spi.xfer2(spi_buffer)
spi_buffer = [0x00, 0x00] # release software reset
spi.xfer2(spi_buffer)
spi_buffer = [
0x80,
0x00,
] # for some reason it is needed to read the reset address for reset to actually reset
rx_buffer = spi.xfer2(spi_buffer)
spi_buffer = [0x9F, 0x00] # hardware version
rx_buffer = spi.xfer2(spi_buffer)
if rx_buffer[1] != DAC_VERSION:
print(f"Unrecognized device: 0x{rx_buffer[1]:02X}")
print("=== Contents of spi buffer after DAC VERSION read back: ===")
print(f"0x{rx_buffer[0]:02X}{rx_buffer[1]:02X}")
spi_buffer = [0x82, 00]
rx_buffer = spi.xfer2(spi_buffer)
print(f"0x{rx_buffer[0]:02X}{rx_buffer[1]:02X}")
# set to 2's complement and I to be first of pair on data input pads
spi_buffer = [0x02, 0xB4]
rx_buffer = spi.xfer2(spi_buffer)
spi_buffer = [0x82, 00]
rx_buffer = spi.xfer2(spi_buffer)
print(f"0x{rx_buffer[0]:02X}{rx_buffer[1]:02X}")
for i in range(10):
spi_buffer = [0x94, 0x00]
rx_buffer = spi.xfer2(spi_buffer)
print(f"0x{rx_buffer[0]:02X}{rx_buffer[1]:02X}")
finally:
spi.close()
def read_from_memory(address, n_bytes):
assert n_bytes <= 4
addr = address
try:
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
with mmap.mmap(
f,
PAGESIZE,
mmap.MAP_SHARED,
mmap.PROT_READ | mmap.PROT_WRITE,
offset=addr & ~MAP_MASK,
) as mem:
start_addr = addr & MAP_MASK
stop_addr = start_addr + 4
# print(f"addr: 0x{addr:x}\tstart_addr: 0x{start_addr}\tstop_addr: 0x{stop_addr}")
contents = mem[start_addr:stop_addr]
read_value = list(contents)[:n_bytes]
finally:
os.close(f)
return read_value
def write_to_memory(address, value):
value_bytes = value.to_bytes(4, "little")
addr = address
try:
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
with mmap.mmap(
f,
PAGESIZE,
mmap.MAP_SHARED,
mmap.PROT_READ | mmap.PROT_WRITE,
offset=addr & ~MAP_MASK,
) as mem:
start_addr = addr & MAP_MASK
stop_addr = start_addr + 4
mem[start_addr:stop_addr] = value_bytes
contents = mem[start_addr:stop_addr]
finally:
os.close(f)
def manual_override(enable=True):
reg_contents = read_from_memory(CTRL_ADDR, 1)[0]
print(f"REG contents: 0b{reg_contents:03b}")
to_write = reg_contents | 0b1 if enable else reg_contents & 0b110
write_to_memory(CTRL_ADDR, to_write)
def power_down(channel, power_down=True):
assert channel in (0, 1)
bitmask = 1 << (channel + 1) & 0b111
reg_contents = read_from_memory(CTRL_ADDR, 1)[0]
value = (1 if power_down else 0) << (channel + 1)
reg_contents &= ~bitmask
to_write = reg_contents | value
write_to_memory(CTRL_ADDR, to_write)
reg_contents = read_from_memory(CTRL_ADDR, 1)[0]
print(f"REG contents: 0b{reg_contents:03b}")
def write_sample(channel, sample):
assert channel in (0, 1)
if channel == 0:
addresses = [CH0_HIGH_WORD_ADDR, CH0_LOW_WORD_ADDR]
else:
addresses = [CH1_HIGH_WORD_ADDR, CH1_LOW_WORD_ADDR]
low_word_value = sample & 0xFF
high_word_value = (sample >> 8) & 0x3F
values = [high_word_value, low_word_value]
for addr, value in zip(addresses, values):
write_to_memory(addr, value)
def write_ramp():
signal = [i for i in range(16384)]
for value in signal:
write_sample(0, value)
def main():
main_dac_init()
power_down(0, False)
power_down(1, False)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,66 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
import mmap
import os
import time
from pyfastservo.common import (
LED0_BASE_ADDR,
LED1_BASE_ADDR,
LED2_BASE_ADDR,
LED3_BASE_ADDR,
MAP_MASK,
PAGESIZE,
)
ON = 1
OFF = 0
def main():
addrs = [LED0_BASE_ADDR, LED1_BASE_ADDR, LED2_BASE_ADDR, LED3_BASE_ADDR]
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
for addr in addrs:
with mmap.mmap(
f,
PAGESIZE,
mmap.MAP_SHARED,
mmap.PROT_READ | mmap.PROT_WRITE,
offset=addr & ~MAP_MASK,
) as mem:
for i in range(6):
start_addr = addr & MAP_MASK
stop_addr = start_addr + 4
print(
f"addr: 0x{addr:x}\tstart_addr: 0x{start_addr}\tstop_addr: 0x{stop_addr}"
)
mem[start_addr:stop_addr] = ON.to_bytes(4, "little")
contents = mem[start_addr:stop_addr]
time.sleep(0.5)
mem[start_addr:stop_addr] = OFF.to_bytes(4, "little")
contents = mem[start_addr:stop_addr]
time.sleep(0.5)
os.close(f)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,28 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
from pyfastservo import adc, si5340, dac
def main():
si5340.configure_si5340()
adc.main()
dac.main()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,118 @@
# This file is part of Fast Servo Software Package.
#
# Copyright (C) 2023 Jakub Matyas
# Warsaw University of Technology <jakubk.m@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
from smbus2 import SMBus
BUS_NO = 0
IC_ADDR = 0x74
PAGE_ADDR = 0x1
OUT0_MUX_SEL_ADDR = 0x15
OUT1_MUX_SEL_ADDR = 0x1A
OUT2_MUX_SEL_ADDR = 0x29
OUT3_MUX_SEL_ADDR = 0x2E
OUT2_AMPL_ADDR = 0x28
OUT3_PDN_ADDR = 0x2B
OUT3_FORMAT_ADDR = 0x2C
OUT3_AMPL_ADDR = 0x2D
N1_DIVIDER_UPDATE_ADDR = 0x17
data_to_write = 0
clk_out_addr = [
OUT0_MUX_SEL_ADDR,
OUT1_MUX_SEL_ADDR,
OUT2_MUX_SEL_ADDR,
OUT3_MUX_SEL_ADDR,
]
def configure_si5340():
with SMBus(BUS_NO) as bus:
bus.write_byte_data(IC_ADDR, PAGE_ADDR, 0x0) # setting page to page 0
# read device id
low_word = bus.read_byte_data(IC_ADDR, 0x2)
high_word = bus.read_byte_data(IC_ADDR, 0x3)
print(f"DEV ID: 0x{high_word:2x}{low_word:2x}")
data_to_write = 0x1
bus.write_byte_data(
IC_ADDR, PAGE_ADDR, data_to_write
) # change to page 1 for output settings
readback = bus.read_byte_data(IC_ADDR, PAGE_ADDR)
if data_to_write != readback:
raise ValueError(f"Failed to set page.")
for addr in clk_out_addr:
bus.write_byte_data(IC_ADDR, addr, 1) # set source to N1
bus.write_byte_data(IC_ADDR, OUT2_AMPL_ADDR, 13)
readback = bus.read_byte_data(IC_ADDR, OUT2_AMPL_ADDR)
# if data_to_write != readback:
# raise ValueError(f"Problematic read: {readback}.")
bus.write_byte_data(IC_ADDR, OUT2_AMPL_ADDR, 0x6B) # setting OUT2 to LVDS25
bus.write_byte_data(IC_ADDR, OUT3_FORMAT_ADDR, 0xCC) # SETTING out3 to LVCMOS 18
# bus.write_byte_data(IC_ADDR, 0x2E, 0x09) # SETTING out3 to LVCMOS 33
readback = bus.read_byte_data(IC_ADDR, OUT3_PDN_ADDR)
print(f"Si5340 OUTx_PDN CLK3: 0x{readback}")
readback = bus.read_byte_data(IC_ADDR, OUT3_FORMAT_ADDR)
print(f"Si5340 OUTx_FORMAT CLK3: 0x{readback}")
readback = bus.read_byte_data(IC_ADDR, OUT3_AMPL_ADDR)
print(f"Si5340 OUTx_AMPL CLK3: 0x{readback}")
readback = bus.read_byte_data(IC_ADDR, OUT3_MUX_SEL_ADDR)
print(f"Si5340 OUTx_CM CLK3: 0x{readback}")
bus.write_byte_data(
IC_ADDR, PAGE_ADDR, 0x3
) # setting page to 3 to change dividers values
n1_numerator = [0x0, 0x0, 0x0, 0x60, 0x22, 0x0]
n1_numerator_10M = [0x0, 0x0, 0x0, 0xC0, 0x57, 0x1]
n1_num_addr = [0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12]
n1_denom_addr = [0x13, 0x14, 0x15, 0x16]
for addr, value in zip(n1_num_addr, n1_numerator):
bus.write_byte_data(IC_ADDR, addr, value)
bus.write_byte_data(IC_ADDR, N1_DIVIDER_UPDATE_ADDR, 1)
for addr in n1_num_addr:
readback = bus.read_byte_data(IC_ADDR, addr)
print(f"Numerator buffer: 0x{readback:02x}")
for addr in n1_denom_addr:
readback = bus.read_byte_data(IC_ADDR, addr)
print(f"Denominator buffer: 0x{readback:02x}")
bus.write_byte_data(IC_ADDR, PAGE_ADDR, 0x0) # setting page to page 0
if __name__ == "__main__":
configure_si5340()

31
fast-servo/u-boot.patch Normal file
View File

@ -0,0 +1,31 @@
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 480269fa60..64b20e4200 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -339,6 +339,7 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \
zynq-cse-nor.dtb \
zynq-cse-qspi-single.dtb \
zynq-dlc20-rev1.0.dtb \
+ zynq-fast-servo.dtb \
zynq-microzed.dtb \
zynq-minized.dtb \
zynq-picozed.dtb \
diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig
index 474abc7f6b..6e6bbd4aab 100644
--- a/configs/xilinx_zynq_virt_defconfig
+++ b/configs/xilinx_zynq_virt_defconfig
@@ -80,6 +80,7 @@ CONFIG_CMD_MTDPARTS_SPREAD=y
CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES=y
CONFIG_CMD_UBI=y
CONFIG_OF_BOARD=y
+CONFIG_SYS_CONFIG_NAME="zynq-fast-servo"
CONFIG_OF_LIST="zynq-zc702 zynq-zc706 zynq-zc770-xm010 zynq-zc770-xm011 zynq-zc770-xm011-x16 zynq-zc770-xm012 zynq-zc770-xm013 zynq-cc108 zynq-microzed zynq-minized zynq-picozed zynq-zed zynq-zturn zynq-zturn-v5 zynq-zybo zynq-zybo-z7 zynq-dlc20-rev1.0"
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_FAT=y
diff --git a/include/configs/zynq-fast-servo.h b/include/configs/zynq-fast-servo.h
new file mode 100644
index 0000000000..0aa486a2b7
--- /dev/null
+++ b/include/configs/zynq-fast-servo.h
@@ -0,0 +1 @@
+#include <configs/zynq-common.h>

View File

@ -18,11 +18,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1700794826,
"narHash": "sha256-RyJTnTNKhO0yqRpDISk03I/4A67/dp96YRxc86YOPgU=",
"lastModified": 1709237383,
"narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5a09cb4b393d58f9ed0d9ca1555016a8543c2ac8",
"rev": "1536926ef5621b09bba54035ae2bb6d806d72ac8",
"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"
}
}
},

616
flake.nix
View File

@ -4,123 +4,201 @@
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
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"; };
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ crosspkgs-overlay ]; };
pkgs-armv7l = pkgs.pkgsCross.zynq-armv7l-linux;
fsbl-support = ./fast-servo/fsbl-support;
gnu-platform = "arm-none-eabi";
binutils-pkg = { zlib, extraConfigureFlags ? [] }: pkgs.stdenv.mkDerivation rec {
basename = "binutils";
version = "2.30";
name = "${basename}-${gnu-platform}-${version}";
src = pkgs.fetchurl {
url = "https://ftp.gnu.org/gnu/binutils/binutils-${version}.tar.bz2";
sha256 = "028cklfqaab24glva1ks2aqa1zxa6w6xmc8q34zs1sb7h22dxspg";
};
configureFlags = [
"--enable-deterministic-archives"
"--target=${gnu-platform}"
"--with-cpu=cortex-a9"
"--with-fpu=vfpv3"
"--with-float=hard"
"--with-mode=thumb"
] ++ extraConfigureFlags;
outputs = [ "out" "info" "man" ];
depsBuildBuild = [ pkgs.buildPackages.stdenv.cc ];
buildInputs = [ zlib ];
enableParallelBuilding = true;
meta = {
description = "Tools for manipulating binaries (linker, assembler, etc.)";
longDescription = ''
The GNU Binutils are a collection of binary tools. The main
ones are `ld' (the GNU linker) and `as' (the GNU assembler).
They also include the BFD (Binary File Descriptor) library,
`gprof', `nm', `strip', etc.
'';
homepage = http://www.gnu.org/software/binutils/;
license = pkgs.lib.licenses.gpl3Plus;
/* Give binutils a lower priority than gcc-wrapper to prevent a
collision due to the ld/as wrappers/symlinks in the latter. */
priority = "10";
};
};
gcc-pkg = { gmp, mpfr, libmpc, platform-binutils, extraConfigureFlags ? [] }: pkgs.stdenv.mkDerivation rec {
basename = "gcc";
version = "9.1.0";
name = "${basename}-${gnu-platform}-${version}";
src = pkgs.fetchurl {
url = "https://ftp.gnu.org/gnu/gcc/gcc-${version}/gcc-${version}.tar.xz";
sha256 = "1817nc2bqdc251k0lpc51cimna7v68xjrnvqzvc50q3ax4s6i9kr";
};
preConfigure = ''
mkdir build
cd build
'';
configureScript = "../configure";
configureFlags = [
"--target=${gnu-platform}"
"--with-arch=armv7-a"
"--with-tune=cortex-a9"
"--with-fpu=vfpv3"
"--with-float=hard"
"--disable-libssp"
"--enable-languages=c"
"--with-as=${platform-binutils}/bin/${gnu-platform}-as"
"--with-ld=${platform-binutils}/bin/${gnu-platform}-ld" ] ++ extraConfigureFlags;
outputs = [ "out" "info" "man" ];
hardeningDisable = [ "format" "pie" ];
propagatedBuildInputs = [ gmp mpfr libmpc platform-binutils ];
enableParallelBuilding = true;
dontFixup = true;
};
newlib-pkg = { platform-binutils, platform-gcc }: pkgs.stdenv.mkDerivation rec {
pname = "newlib";
version = "3.1.0";
src = pkgs.fetchurl {
url = "ftp://sourceware.org/pub/newlib/newlib-${version}.tar.gz";
sha256 = "0ahh3n079zjp7d9wynggwrnrs27440aac04340chf1p9476a2kzv";
};
nativeBuildInputs = [ platform-binutils platform-gcc ];
configureFlags = [
"--target=${gnu-platform}"
"--with-cpu=cortex-a9"
"--with-fpu=vfpv3"
"--with-float=hard"
"--with-mode=thumb"
"--enable-interwork"
"--disable-multilib"
"--disable-newlib-supplied-syscalls"
"--with-gnu-ld"
"--with-gnu-as"
"--disable-newlib-io-float"
"--disable-werror"
patched-not-os = pkgs.applyPatches {
name = "not-os-patched";
src = not-os;
patches = [
./not-os-patches/network.patch
./not-os-patches/pr-28.patch
./not-os-patches/pr-29.patch
./not-os-patches/pr-30.patch
./not-os-patches/pr-31.patch
./not-os-patches/pr-33.patch
];
dontFixup = true;
};
gnutoolchain = rec {
binutils-bootstrap = pkgs.callPackage binutils-pkg { };
gcc-bootstrap = pkgs.callPackage gcc-pkg {
platform-binutils = binutils-bootstrap;
extraConfigureFlags = [ "--disable-libgcc" ];
crossSystem = {
system = "armv7l-linux";
linux-kernel = {
name = "zynq";
baseConfig = "multi_v7_defconfig";
target = "uImage";
installTarget = "uImage";
autoModules = false;
DTB = true;
makeFlags = [ "LOADADDR=0x8000" ];
};
newlib = pkgs.callPackage newlib-pkg {
platform-binutils = binutils-bootstrap;
platform-gcc = gcc-bootstrap;
};
crosspkgs-overlay = (self: super: {
pkgsCross = super.pkgsCross // {
zynq-baremetal = import super.path {
system = "x86_64-linux";
crossSystem = {
config = "arm-none-eabihf";
libc = "newlib";
gcc.cpu = "cortex-a9";
gcc.fpu = "vfpv3";
};
};
zynq-armv7l-linux = import super.path {
system = "x86_64-linux";
inherit crossSystem;
};
};
binutils = pkgs.callPackage binutils-pkg {
extraConfigureFlags = [ "--with-lib-path=${newlib}/arm-none-eabi/lib" ];
};
gcc = pkgs.callPackage gcc-pkg {
platform-binutils = binutils;
extraConfigureFlags = [ "--enable-newlib" "--with-headers=${newlib}/arm-none-eabi/include" ];
});
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";
};
pyrp3 = pkgs-armv7l.python3Packages.buildPythonPackage rec {
pname = "pyrp3";
version = "1.2.0";
pyproject = true;
src = pkgs.fetchFromGitHub {
owner = "linien-org";
repo = "pyrp3";
rev = "v${version}";
hash = "sha256-43TTlpJ5SMAjQM71bNVvrWQyciRXM3zpuA/Dw41AEgU=";
};
nativeBuildInputs = with pkgs-armv7l.python3Packages; [ setuptools wheel setuptools-scm ];
propagatedBuildInputs = with pkgs-armv7l.python3Packages; [
myhdl
rpyc4
cached-property
numpy
];
};
linien-server = pkgs-armv7l.python3Packages.buildPythonPackage rec {
pname = "linien-server";
pyproject = true;
inherit (pkgs.python3Packages.linien-common) src version;
sourceRoot = "source/linien-server";
postPatch = ''
substituteInPlace linien_server/acquisition.py \
--replace " start_nginx()" "" \
--replace " stop_nginx()" "" \
--replace " flash_fpga()" ""
'';
nativeBuildInputs = [ pkgs-armv7l.python3Packages.setuptools ];
propagatedBuildInputs = with pkgs-armv7l.python3Packages; [
appdirs
certifi
click
cma
pylpsd
pyrp3
requests
linien-common
];
};
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.overrideAttrs(oa: {
# config.py tries to access $HOME, but we do not need it for building gateware
postPatch = ''
echo > linien_common/config.py
echo > linien_common/__init__.py
'';
doCheck = false;
}))
]))
vivado
];
buildPhase = ''
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
'';
};
pyfastservo = pkgs-armv7l.python3Packages.buildPythonPackage rec {
name = "pyfastservo";
src = ./fast-servo;
preBuild = ''
cat > setup.py << EOF
from setuptools import setup
setup(
name="pyfastservo",
packages=["pyfastservo"],
install_requires=["spidev", "smbus2"],
entry_points = {"console_scripts": ["fp_leds=pyfastservo.fp_leds:main"]},
)
EOF
'';
propagatedBuildInputs = with pkgs-armv7l.python3Packages; [
spidev
smbus2
];
};
mkbootimage = pkgs.stdenv.mkDerivation {
@ -146,85 +224,259 @@
hardeningDisable = [ "fortify" ];
};
fsbl = { board ? "zc706" }: pkgs.stdenv.mkDerivation {
name = "${board}-fsbl";
src = pkgs.fetchFromGitHub {
owner = "Xilinx";
repo = "embeddedsw";
rev = "65c849ed46c88c67457e1fc742744f96db968ff1";
sha256 = "1rvl06ha40dzd6s9aa4sylmksh4xb9dqaxq462lffv1fdk342pda";
};
patches = [ ./fsbl.patch ];
nativeBuildInputs = [
pkgs.gnumake
gnutoolchain.binutils
gnutoolchain.gcc
];
patchPhase = ''
patch -p1 -i ${./fsbl.patch}
patchShebangs lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh
echo 'SEARCH_DIR("${gnutoolchain.newlib}/arm-none-eabi/lib");' >> lib/sw_apps/zynq_fsbl/src/lscript.ld
'';
buildPhase = ''
cd lib/sw_apps/zynq_fsbl/src
make BOARD=${board} "CFLAGS=-DFSBL_DEBUG_INFO -g"
'';
installPhase = ''
mkdir $out
cp fsbl.elf $out
'';
doCheck = false;
dontFixup = true;
};
u-boot = { board ? "zc706" }: pkgs.pkgsCross.armv7l-hf-multiplatform.buildUBoot {
defconfig = "xilinx_zynq_virt_defconfig";
preConfigure = ''
export DEVICE_TREE=zynq-${board}
'';
extraMeta.platforms = ["armv7l-linux"];
filesToInstall = ["u-boot.elf"];
};
bootimage = { board ? "zc706" }: pkgs.runCommand "${board}-bootimage"
{
buildInputs = [ mkbootimage ];
}
''
bifdir=`mktemp -d`
cd $bifdir
ln -s ${fsbl { inherit board; }}/fsbl.elf fsbl.elf
ln -s ${u-boot { inherit board; }}/u-boot.elf u-boot.elf
cat > boot.bif << EOF
the_ROM_image:
{
[bootloader]fsbl.elf
u-boot.elf
}
EOF
mkdir $out $out/nix-support
mkbootimage boot.bif $out/boot.bin
echo file binary-dist $out/boot.bin >> $out/nix-support/hydra-build-products
'';
not-os-configured = (import "${not-os}" {
board-package-set = { board }: let
not-os-configured = (import patched-not-os {
inherit nixpkgs;
extraModules = [
"${not-os}/zynq_image.nix"
];
platform = system: (import nixpkgs { config = {}; }).platforms.armv7l-hf-multiplatform;
"${patched-not-os}/zynq_image.nix"
] ++ pkgs.lib.optionals (board == "fast-servo") [
({ config, pkgs, lib, ... }: {
environment.systemPackages = [
linien-server
(pkgs.python3.withPackages(ps: [ pyfastservo ]))
];
boot.postBootCommands = lib.mkAfter ''
# Program the FPGA
set +x
echo "Flashing bitstream..."
echo 0 > /sys/class/fpga_manager/fpga0/flags
mkdir -p /lib/firmware
cp ${fast-servo-gateware}/gateware.bin /lib/firmware/
echo gateware.bin > /sys/class/fpga_manager/fpga0/firmware
# Run device init scripts
echo "Initializing clock generator, ADC, and DAC..."
python3 -m pyfastservo.initialize
'';
})];
system = "x86_64-linux";
crossSystem.system = "armv7l-linux";
inherit crossSystem;
});
in {
not-os-build = not-os-configured.config.system.build;
fsbl = pkgs.stdenv.mkDerivation {
name = "${board}-fsbl";
src = pkgs.fetchFromGitHub {
owner = "Xilinx";
repo = "embeddedsw";
rev = "xilinx_v2022.2";
sha256 = "sha256-UDz9KK/Hw3qM1BAeKif30rE8Bi6C2uvuZlvyvtJCMfw=";
};
nativeBuildInputs = [
pkgs.pkgsCross.zynq-baremetal.buildPackages.binutils
pkgs.pkgsCross.zynq-baremetal.buildPackages.gcc
];
postUnpack = ''
mkdir -p $sourceRoot/lib/sw_apps/zynq_fsbl/misc/fast-servo
cp $sourceRoot/lib/sw_apps/zynq_fsbl/misc/zc706/* $sourceRoot/lib/sw_apps/zynq_fsbl/misc/fast-servo
cp ${fsbl-support}/* $sourceRoot/lib/sw_apps/zynq_fsbl/misc/fast-servo
'';
patches = [] ++ pkgs.lib.optional (board == "fast-servo") ./fast-servo/fsbl.patch;
postPatch = ''
patchShebangs lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh
for x in lib/sw_apps/zynq_fsbl/src/Makefile lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh lib/bsp/standalone/src/arm/cortexa9/gcc/Makefile; do
substituteInPlace $x \
--replace "arm-none-eabi-" "arm-none-eabihf-"
done
'';
buildPhase = ''
cd lib/sw_apps/zynq_fsbl/src
make BOARD=${board} "CFLAGS=-DFSBL_DEBUG_INFO -g"
'';
installPhase = ''
mkdir $out
cp fsbl.elf $out
'';
doCheck = false;
dontFixup = true;
};
u-boot = (pkgs-armv7l.buildUBoot {
name = "${board}-u-boot";
defconfig = "xilinx_zynq_virt_defconfig";
patches = [] ++ pkgs.lib.optional (board == "fast-servo") ./fast-servo/u-boot.patch;
preConfigure = ''
export DEVICE_TREE=zynq-${board}
'';
extraConfig = ''
CONFIG_SYS_PROMPT="${board}-boot> "
CONFIG_AUTOBOOT=y
CONFIG_BOOTCOMMAND="${builtins.replaceStrings [ "\n" ] [ "; " ] ''
setenv bootargs 'root=/dev/mmcblk0p2 console=ttyPS0,115200n8 systemConfig=${builtins.unsafeDiscardStringContext not-os-build.toplevel}'
fatload mmc 0 0x6400000 uImage
fatload mmc 0 0x8000000 ${board}.dtb
fatload mmc 0 0xA400000 uRamdisk.image.gz
bootm 0x6400000 0xA400000 0x8000000
''}"
CONFIG_BOOTDELAY=0
CONFIG_USE_BOOTCOMMAND=y
'';
extraMeta.platforms = [ "armv7l-linux" ];
filesToInstall = [ "u-boot.elf" ];
}).overrideAttrs (oldAttrs: {
postUnpack = ''
cp ${fast-servo/fast-servo.dts} $sourceRoot/arch/arm/dts/zynq-fast-servo.dts
'';
postInstall = ''
mkdir -p $out/dts
cp arch/arm/dts/zynq-fast-servo.dts $out/dts
cp arch/arm/dts/zynq-zc706.dts $out/dts
cp arch/arm/dts/zynq-7000.dtsi $out/dts
'';
});
bootimage = pkgs.runCommand "${board}-bootimage"
{
buildInputs = [ mkbootimage ];
}
''
bifdir=`mktemp -d`
cd $bifdir
ln -s ${fsbl}/fsbl.elf fsbl.elf
ln -s ${u-boot}/u-boot.elf u-boot.elf
cat > boot.bif << EOF
the_ROM_image:
{
[bootloader]fsbl.elf
u-boot.elf
}
EOF
mkdir $out $out/nix-support
mkbootimage boot.bif $out/boot.bin
echo file binary-dist $out/boot.bin >> $out/nix-support/hydra-build-products
'';
dtb = pkgs.runCommand "${board}-dtb"
{
buildInputs = [ pkgs.gcc pkgs.dtc ];
}
''
mkdir -p $out
cp ${u-boot}/dts/zynq-${board}.dts .
if [ ${board} == "zc706" ]; then
mv zynq-${board}.dts zynq-${board}-top.dts
cp ${u-boot}/dts/zynq-7000.dtsi .
gcc -E -nostdinc -undef -D__DTS__ -x assembler-with-cpp -o zynq-${board}.dts zynq-${board}-top.dts
fi
dtc -I dts -O dtb -o ${board}.dtb zynq-${board}.dts
cp ${board}.dtb $out
'';
sd-image = let
rootfsImage = pkgs.callPackage (pkgs.path + "/nixos/lib/make-ext4-fs.nix") {
storePaths = [ not-os-build.toplevel ];
volumeLabel = "ROOT";
};
# Current firmware (kernel, bootimage, etc..) takes ~18MB
firmwareSize = 30;
firmwarePartitionOffset = 8;
in pkgs.stdenv.mkDerivation {
name = "${board}-sd-image";
nativeBuildInputs = with pkgs; [ dosfstools mtools libfaketime util-linux parted ];
buildCommand = ''
mkdir -p $out/nix-support $out/sd-image
export img=$out/sd-image/sd-image.img
echo "${pkgs.stdenv.buildPlatform.system}" > $out/nix-support/system
echo "file sd-image $img" >> $out/nix-support/hydra-build-products
gap=${toString firmwarePartitionOffset}
rootSizeBlocks=$(du -B 512 --apparent-size ${rootfsImage} | awk '{ print $1 }')
firmwareSizeBlocks=$((${toString firmwareSize} * 1024 * 1024 / 512))
imageSize=$((rootSizeBlocks * 512 + firmwareSizeBlocks * 512 + gap * 1024 * 1024))
truncate -s $imageSize $img
fat32Start="$((gap))MB"
fat32End="$((gap + ${toString firmwareSize}))MB"
parted $img mklabel msdos
parted $img mkpart primary fat32 $fat32Start $fat32End
parted $img mkpart primary ext4 $fat32End 100%
parted $img set 1 boot on
eval $(partx $img -o START,SECTORS --nr 2 --pairs)
dd conv=notrunc if=${rootfsImage} of=$img seek=$START count=$SECTORS
eval $(partx $img -o START,SECTORS --nr 1 --pairs)
truncate -s $((SECTORS * 512)) firmware_part.img
faketime "1970-01-01 00:00:00" mkfs.vfat -n BOOT firmware_part.img
mkdir firmware
cp ${bootimage}/boot.bin firmware/
cp ${dtb}/${board}.dtb firmware/
cp ${not-os-build.kernel}/uImage firmware/
cp ${not-os-build.uRamdisk}/initrd firmware/uRamdisk.image.gz
(cd firmware; mcopy -psvm -i ../firmware_part.img ./* ::)
dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS
'';
};
not-os-qemu = let
qemuScript = ''
#!/bin/bash
export PATH=${pkgs.qemu}/bin:$PATH
IMGDIR=$(mktemp -d /tmp/not-os-qemu-XXXXXX)
BASE=$(realpath $(dirname $0))
qemu-img convert -O qcow2 -f raw -o preallocation=metadata $BASE/sd-image.img $IMGDIR/sd-sparse.qcow2
qemu-img create -F qcow2 -f qcow2 -b $IMGDIR/sd-sparse.qcow2 $IMGDIR/sd-overlay.qcow2 2G
# Some command arguments are based from samples in Xilinx QEMU User Documentation
# See: https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/821854273/Running+Bare+Metal+Applications+on+QEMU
qemu-system-arm \
-M xilinx-zynq-a9 \
-m 1024 \
$([ ${board} = "zc706" ] && echo "-serial /dev/null") -serial stdio \
-display none \
-kernel $BASE/u-boot.elf \
-sd $IMGDIR/sd-overlay.qcow2
rm -rf $IMGDIR
'';
in pkgs.runCommand "${board}-qemu" {
inherit qemuScript;
passAsFile = [ "qemuScript" ];
preferLocalBuild = true;
}
''
mkdir $out
cd $out
cp -s ${u-boot}/u-boot.elf .
cp -s ${sd-image}/sd-image/sd-image.img .
cp $qemuScriptPath qemu-script
chmod +x qemu-script
patchShebangs qemu-script
'';
in {
"${board}-fsbl" = fsbl;
"${board}-u-boot" = u-boot;
"${board}-bootimage" = bootimage;
"${board}-dtb" = dtb;
"${board}-sd-image" = sd-image;
"${board}-qemu" = not-os-qemu;
};
in rec {
packages.x86_64-linux = {
inherit mkbootimage;
inherit migen misoc vivado;
};
packages.armv7l-linux = {
zc706-u-boot = u-boot { board = "zc706"; };
zc706-fsbl = fsbl { board = "zc706"; };
zc706-bootimage = bootimage { board = "zc706"; };
zc706-not-os = not-os-configured.config.system.build.zynq_image;
};
inherit fast-servo-gateware linien-server;
} //
(board-package-set { board = "zc706"; }) //
(board-package-set { board = "fast-servo"; });
hydraJobs = packages.x86_64-linux // packages.armv7l-linux;
};
nixConfig = {
allow-import-from-derivation = true;
};
}

View File

@ -1,31 +0,0 @@
diff --git a/lib/sw_apps/zynq_fsbl/src/Makefile b/lib/sw_apps/zynq_fsbl/src/Makefile
index 0e3ccdf1c5..a5b02f386e 100644
--- a/lib/sw_apps/zynq_fsbl/src/Makefile
+++ b/lib/sw_apps/zynq_fsbl/src/Makefile
@@ -71,11 +71,14 @@ endif
all: $(EXEC)
$(EXEC): $(LIBS) $(OBJS) $(INCLUDES)
- cp $(BSP_DIR)/$(BOARD)/ps7_init.* .
$(LINKER) $(LD1FLAGS) -o $@ $(OBJS) $(LDFLAGS)
rm -rf $(OBJS)
-
-
+
+.PHONY: ps7_init
+
+ps7_init:
+ cp $(BSP_DIR)/$(BOARD)/ps7_init.* .
+
$(LIBS):
echo "Copying BSP files"
$(BSP_DIR)/copy_bsp.sh $(BOARD) $(CC)
@@ -86,7 +89,7 @@ $(LIBS):
make -C $(BSP_DIR) -k all "CC=armcc" "AR=armar" "C_FLAGS= -O2 -c" "EC_FLAGS=--debug --wchar32"; \
fi;
-%.o:%.c
+%.o:%.c ps7_init
$(CC) $(CC_FLAGS) $(CFLAGS) $(ECFLAGS) -c $< -o $@ $(INCLUDEPATH)
%.o:%.S

View File

@ -0,0 +1,57 @@
diff --git a/configuration.nix b/configuration.nix
index 010c487..e1e85ba 100644
--- a/configuration.nix
+++ b/configuration.nix
@@ -1,4 +1,4 @@
-{ pkgs, ... }:
+{ pkgs, lib, ... }:
{
imports = [ ./qemu.nix ];
@@ -7,10 +7,15 @@
environment.etc = {
"ssh/authorized_keys.d/root" = {
text = ''
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC34wZQFEOGkA5b0Z6maE3aKy/ix1MiK1D0Qmg4E9skAA57yKtWYzjA23r5OCF4Nhlj1CuYd6P1sEI/fMnxf+KkqqgW3ZoZ0+pQu4Bd8Ymi3OkkQX9kiq2coD3AFI6JytC6uBi6FaZQT5fG59DbXhxO5YpZlym8ps1obyCBX0hyKntD18RgHNaNM+jkQOhQ5OoxKsBEobxQOEdjIowl2QeEHb99n45sFr53NFqk3UCz0Y7ZMf1hSFQPuuEC/wExzBBJ1Wl7E1LlNA4p9O3qJUSadGZS4e5nSLqMnbQWv2icQS/7J8IwY0M8r1MsL8mdnlXHUofPlG1r4mtovQ2myzOx clever@nixos
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKITUnIETct0d1Ky7iEofM8BV/U9ViuAd72abm26ibhkVKYuLlIvNBtf7+fsyaHR3cc4kmiUz26co4LV2q10HLO7nua7Ry0QhtPvPnpudandB4LbV4ieW1cqcWcPpsM1GssUZhZthbkwLf7h2exojqVj8vqPm5RaBl1eULXaPTldCiSe5ZxNuVbm3qT8Lfc2E3ifKT6A7WqZN00f1+YSnaA9uy0VgVDReDqyujAZaKGUwSa2G8eqzN3guN7VcBZek2p1v1n0EwpFdBxzT3Ncqh5wIYPNn084q5lU13TAjw+tTO7Q059e4HFLaR24w8NT60BrO1dbGYLbjWNri1G3pz root@router
+ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCMALVC8RDTHec+PC8y1s3tcpUAODgq6DEzQdHDf/cyvDMfmCaPiMxfIdmkns5lMa03hymIfSmLUF0jFFDc7biRp7uf9AAXNsrTmplHii0l0McuOOZGlSdZM4eL817P7UwJqFMxJyFXDjkubhQiX6kp25Kfuj/zLnupRCaiDvE7ho/xay6Jrv0XLz935TPDwkc7W1asLIvsZLheB+sRz9SMOb9gtrvk5WXZl5JTOFOLu+JaRwQLHL/xdcHJTOod7tqHYfpoC5JHrEwKzbhTOwxZBQBfTQjQktKENQtBxXHTe71rUEWfEZQGg60/BC4BrRmh4qJjlJu3v4VIhC7SSHn1 root
+ ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBNdIiLvP2hmDUFyyE0oLOIXrjrMdWWpBV9/gPR5m4AiARx4JkufIDZzmptdYQ5FhJORJ4lluPqp7dAmahoSwg4lv9Di0iNQpHMJvNGZLHYKM1H1FWCCFIEDJ8bD4SVfrDg== root
+ ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF/YybP+fQ0J+bNqM5Vgx5vDmVqVWsgUdF1moUxghv7d73GZAFaM6IFBdrXTAa33AwnWwDPMrTgP1V6SXBkb3ciJo/lD1urJGbydbSI5Ksq9d59wvOeANvyWYrQw6+eqTQ== sb
+ ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBFkmOCQ3BQh3qUjLtfdqyeBsx8rkk/QYlzB0TMrnfn6waLN6yKfPC3WVFv4zN5kNKb/OayvqDa+zfkKe85e/oIPQQKflF7GrCHdssz33DCnW90cz532E6iqG1pjeZjID2A== flo
'';
mode = "0444";
};
+ "resolv.conf".text = lib.mkForce ''
+ nameserver 192.168.1.1
+ '';
};
}
diff --git a/runit.nix b/runit.nix
index d7b0bf3..67cff43 100644
--- a/runit.nix
+++ b/runit.nix
@@ -7,8 +7,8 @@ let
Port 22
PidFile /run/sshd.pid
Protocol 2
- PermitRootLogin yes
- PasswordAuthentication yes
+ PermitRootLogin prohibit-password
+ PasswordAuthentication no
AuthorizedKeysFile /etc/ssh/authorized_keys.d/%u
'';
compat = pkgs.runCommand "runit-compat" {} ''
@@ -31,10 +31,10 @@ in
"runit/1".source = pkgs.writeScript "1" ''
#!${pkgs.runtimeShell}
${lib.optionalString config.not-os.simpleStaticIp ''
- ip addr add 10.0.2.15 dev eth0
+ ip addr add 103.206.98.205 dev eth0
ip link set eth0 up
- ip route add 10.0.2.0/24 dev eth0
- ip route add default via 10.0.2.2 dev eth0
+ ip route add 103.206.98.200/29 dev eth0
+ ip route add default via 103.206.98.200 dev eth0
''}
mkdir /bin/
ln -s ${pkgs.runtimeShell} /bin/sh

294
not-os-patches/pr-28.patch Normal file
View File

@ -0,0 +1,294 @@
diff --git a/base.nix b/base.nix
index 7eaee32..3a2a0a9 100644
--- a/base.nix
+++ b/base.nix
@@ -27,6 +27,11 @@ with lib;
description = "enable rngd";
default = false;
};
+ not-os.sd = mkOption {
+ type = types.bool;
+ default = false;
+ description = "enable sd image support";
+ };
not-os.simpleStaticIp = mkOption {
type = types.bool;
default = false;
@@ -86,15 +91,25 @@ with lib;
"nix/nix.conf".source = pkgs.runCommand "nix.conf" {} ''
extraPaths=$(for i in $(cat ${pkgs.writeReferencesToFile pkgs.runtimeShell}); do if test -d $i; then echo $i; fi; done)
cat > $out << EOF
- build-use-sandbox = true
+ auto-optimise-store = true
build-users-group = nixbld
- build-sandbox-paths = /bin/sh=${pkgs.runtimeShell} $(echo $extraPaths)
- build-max-jobs = 1
- build-cores = 4
+ cores = 0
+ extra-sandbox-paths = /bin/sh=${pkgs.runtimeShell} $(echo $extraPaths)
+ max-jobs = auto
+ sandbox = true
+ substituters = https://cache.armv7l.xyz
+ trusted-public-keys = cache.armv7l.xyz-1:kBY/eGnBAYiqYfg0fy0inWhshUo+pGFM3Pj7kIkmlBk=
+ trusted-users = root
EOF
'';
+ "ssl/certs/ca-certificates.crt".source = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+ "ssl/certs/ca-bundle.crt".source = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
bashrc.text = "export PATH=/run/current-system/sw/bin";
- profile.text = "export PATH=/run/current-system/sw/bin";
+ profile.text = ''
+ export PATH=/run/current-system/sw/bin
+ export EDITOR=nano
+ export NIX_PATH="nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels"
+ '';
"resolv.conf".text = "nameserver 10.0.2.3";
passwd.text = ''
root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash
diff --git a/runit.nix b/runit.nix
index d7b0bf3..70353a1 100644
--- a/runit.nix
+++ b/runit.nix
@@ -65,7 +65,6 @@ in
'';
"service/nix/run".source = pkgs.writeScript "nix" ''
#!${pkgs.runtimeShell}
- nix-store --load-db < /nix/store/nix-path-registration
nix-daemon
'';
}
diff --git a/stage-1.nix b/stage-1.nix
index 331fecd..aa5148e 100644
--- a/stage-1.nix
+++ b/stage-1.nix
@@ -117,11 +117,6 @@ let
plymouth --show-splash
''}
-
- for x in ${lib.concatStringsSep " " config.boot.initrd.kernelModules}; do
- modprobe $x
- done
-
root=/dev/vda
realroot=tmpfs
for o in $(cat /proc/cmdline); do
@@ -164,7 +159,9 @@ let
mkdir -p /mnt/nix/store/
- ${if config.not-os.nix then ''
+ ${if config.not-os.sd && config.not-os.nix then ''
+ mount $root /mnt
+ '' else if config.not-os.nix then ''
# make the store writeable
mkdir -p /mnt/nix/.ro-store /mnt/nix/.overlay-store /mnt/nix/store
mount $root /mnt/nix/.ro-store -t squashfs
@@ -190,6 +187,11 @@ let
initialRamdisk = pkgs.makeInitrd {
contents = [ { object = bootStage1; symlink = "/init"; } ];
};
+ # Use for zynq_image
+ uRamdisk = pkgs.makeInitrd {
+ makeUInitrd = true;
+ contents = [ { object = bootStage1; symlink = "/init"; } ];
+ };
in
{
options = {
@@ -205,6 +207,7 @@ in
config = {
system.build.bootStage1 = bootStage1;
system.build.initialRamdisk = initialRamdisk;
+ system.build.uRamdisk = uRamdisk;
system.build.extraUtils = extraUtils;
boot.initrd.availableKernelModules = [ ];
boot.initrd.kernelModules = [ "tun" "loop" "squashfs" ] ++ (lib.optional config.not-os.nix "overlay");
diff --git a/stage-2-init.sh b/stage-2-init.sh
index 6cc08e2..0c854c4 100644
--- a/stage-2-init.sh
+++ b/stage-2-init.sh
@@ -19,4 +19,7 @@ mount -t tmpfs tmpfs /dev/shm
$systemConfig/activate
+# Run any user-specified commands.
+@runtimeShell@ @postBootCommands@
+
exec runit
diff --git a/stage-2.nix b/stage-2.nix
index c61f9d6..fbdf0fd 100644
--- a/stage-2.nix
+++ b/stage-2.nix
@@ -20,6 +20,19 @@ with lib;
example = "256m";
type = types.str;
};
+ postBootCommands = mkOption {
+ default = "";
+ example = "rm -f /var/log/messages";
+ type = types.lines;
+ description = lib.mdDoc ''
+ Shell commands to be executed just before runit is started.
+ '';
+ };
+ };
+ networking.hostName = mkOption {
+ default = "";
+ type = types.strMatching
+ "^$|^[[:alnum:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$";
};
};
config = {
@@ -28,6 +41,9 @@ with lib;
isExecutable = true;
path = config.system.path;
inherit (pkgs) runtimeShell;
+ postBootCommands = pkgs.writeText "local-cmds" ''
+ ${config.boot.postBootCommands}
+ '';
};
};
}
diff --git a/zynq_image.nix b/zynq_image.nix
index 3fa23ab..9d1621e 100644
--- a/zynq_image.nix
+++ b/zynq_image.nix
@@ -1,66 +1,89 @@
-{ config, pkgs, ... }:
+{ lib, config, pkgs, ... }:
+with lib;
let
- # dont use overlays for the qemu, it causes a lot of wasted time on recompiles
- x86pkgs = import pkgs.path { system = "x86_64-linux"; };
- customKernel = pkgs.linux.override {
+ customKernel = (pkgs.linux.override {
extraConfig = ''
OVERLAY_FS y
+ MEDIA_SUPPORT n
+ FB n
+ DRM n
+ SOUND n
+ SQUASHFS n
+ BACKLIGHT_CLASS_DEVICE n
+ FPGA y
+ FPGA_BRIDGE y
+ FPGA_REGION y
+ OF_FPGA_REGION y
+ FPGA_MGR_ZYNQ_FPGA y
+ OF_OVERLAY y
'';
- };
+ }).overrideAttrs (oa: {
+ postInstall = ''
+ if [ -e arch/arm/boot/uImage ]; then
+ cp arch/arm/boot/uImage $out
+ fi
+ ${oa.postInstall}
+ '';
+ });
customKernelPackages = pkgs.linuxPackagesFor customKernel;
in {
imports = [ ./arm32-cross-fixes.nix ];
boot.kernelPackages = customKernelPackages;
nixpkgs.system = "armv7l-linux";
- system.build.zynq_image = let
- cmdline = "root=/dev/mmcblk0 console=ttyPS0,115200n8 systemConfig=${builtins.unsafeDiscardStringContext config.system.build.toplevel}";
- qemuScript = ''
- #!/bin/bash -v
- export PATH=${x86pkgs.qemu}/bin:$PATH
- set -x
- base=$(dirname $0)
-
- cp $base/root.squashfs /tmp/
- chmod +w /tmp/root.squashfs
- truncate -s 64m /tmp/root.squashfs
-
- qemu-system-arm \
- -M xilinx-zynq-a9 \
- -serial /dev/null \
- -serial stdio \
- -display none \
- -dtb $base/zynq-zc702.dtb \
- -kernel $base/zImage \
- -initrd $base/initrd \
- -drive file=/tmp/root.squashfs,if=sd,format=raw \
- -append "${cmdline}"
- '';
- in pkgs.runCommand "zynq_image" {
- inherit qemuScript;
- passAsFile = [ "qemuScript" ];
+ networking.hostName = "zynq";
+ not-os.sd = true;
+ not-os.simpleStaticIp = true;
+ system.build.zynq_image = pkgs.runCommand "zynq_image" {
preferLocalBuild = true;
} ''
mkdir $out
cd $out
- cp -s ${config.system.build.squashfs} root.squashfs
- cp -s ${config.system.build.kernel}/*zImage .
- cp -s ${config.system.build.initialRamdisk}/initrd initrd
- cp -s ${config.system.build.kernel}/dtbs/zynq-zc702.dtb .
+ cp -s ${config.system.build.kernel}/uImage .
+ cp -s ${config.system.build.uRamdisk}/initrd uRamdisk.image.gz
+ cp -s ${config.system.build.kernel}/dtbs/zynq-zc706.dtb devicetree.dtb
ln -sv ${config.system.build.toplevel} toplevel
- cp $qemuScriptPath qemu-script
- chmod +x qemu-script
- patchShebangs qemu-script
- ls -ltrh
- '';
- system.build.rpi_image_tar = pkgs.runCommand "dist.tar" {} ''
- mkdir -p $out/nix-support
- tar -cvf $out/dist.tar ${config.system.build.rpi_image}
- echo "file binary-dist $out/dist.tar" >> $out/nix-support/hydra-build-products
'';
- environment.systemPackages = [ pkgs.strace ];
- environment.etc."service/getty/run".source = pkgs.writeShellScript "getty" ''
- agetty ttyPS0 115200
+ environment = {
+ systemPackages = with pkgs; [ inetutils wget nano ];
+ etc = {
+ "service/getty/run".source = pkgs.writeShellScript "getty" ''
+ hostname ${config.networking.hostName}
+ exec setsid agetty ttyPS0 115200
+ '';
+ "pam.d/other".text = ''
+ auth sufficient pam_permit.so
+ account required pam_permit.so
+ password required pam_permit.so
+ session optional pam_env.so
+ '';
+ "security/pam_env.conf".text = "";
+ };
+ };
+ boot.postBootCommands = lib.mkIf config.not-os.sd ''
+ # On the first boot do some maintenance tasks
+ if [ -f /nix-path-registration ]; then
+ set -euo pipefail
+ set -x
+ # Figure out device names for the boot device and root filesystem.
+ rootPart=$(${pkgs.utillinux}/bin/findmnt -n -o SOURCE /)
+ bootDevice=$(lsblk -npo PKNAME $rootPart)
+ partNum=$(lsblk -npo MAJ:MIN $rootPart | ${pkgs.gawk}/bin/awk -F: '{print $2}')
+
+ # Resize the root partition and the filesystem to fit the disk
+ echo ",+," | sfdisk -N$partNum --no-reread $bootDevice
+ ${pkgs.parted}/bin/partprobe
+ ${pkgs.e2fsprogs}/bin/resize2fs $rootPart
+
+ # Register the contents of the initial Nix store
+ nix-store --load-db < /nix-path-registration
+
+ # nixos-rebuild also requires a "system" profile and an /etc/NIXOS tag.
+ touch /etc/NIXOS
+ nix-env -p /nix/var/nix/profiles/system --set /run/current-system
+
+ # Prevents this from running on later boots.
+ rm -f /nix-path-registration
+ fi
'';
- environment.etc."pam.d/other".text = "";
}

View File

@ -0,0 +1,41 @@
diff --git a/base.nix b/base.nix
index 7eaee32..c1881cb 100644
--- a/base.nix
+++ b/base.nix
@@ -155,6 +155,23 @@ with lib;
# dummy to make setup-etc happy
'';
system.activationScripts.etc = stringAfter [ "users" "groups" ] config.system.build.etcActivationCommands;
+ # Re-apply deprecated var value due to systemd preference in recent nixpkgs
+ # See https://github.com/NixOS/nixpkgs/commit/59e37267556eb917146ca3110ab7c96905b9ffbd
+ system.activationScripts.var = lib.mkForce ''
+ # Various log/runtime directories.
+
+ mkdir -p /var/tmp
+ chmod 1777 /var/tmp
+
+ # Empty, immutable home directory of many system accounts.
+ mkdir -p /var/empty
+ # Make sure it's really empty
+ ${pkgs.e2fsprogs}/bin/chattr -f -i /var/empty || true
+ find /var/empty -mindepth 1 -delete
+ chmod 0555 /var/empty
+ chown root:root /var/empty
+ ${pkgs.e2fsprogs}/bin/chattr -f +i /var/empty || true
+ '';
# nix-build -A system.build.toplevel && du -h $(nix-store -qR result) --max=0 -BM|sort -n
system.build.toplevel = pkgs.runCommand "not-os" {
diff --git a/systemd-compat.nix b/systemd-compat.nix
index 11464c6..cb223b8 100644
--- a/systemd-compat.nix
+++ b/systemd-compat.nix
@@ -9,6 +9,8 @@ with lib;
};
systemd.user = mkOption {
};
+ systemd.tmpfiles = mkOption {
+ };
};
config = {
};

135
not-os-patches/pr-30.patch Normal file
View File

@ -0,0 +1,135 @@
diff --git a/base.nix b/base.nix
index 7eaee32..622cbf1 100644
--- a/base.nix
+++ b/base.nix
@@ -120,10 +120,6 @@ with lib;
root:x:0:
nixbld:x:30000:nixbld1,nixbld10,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9
'';
- "ssh/ssh_host_rsa_key.pub".source = ./ssh/ssh_host_rsa_key.pub;
- "ssh/ssh_host_rsa_key" = { mode = "0600"; source = ./ssh/ssh_host_rsa_key; };
- "ssh/ssh_host_ed25519_key.pub".source = ./ssh/ssh_host_ed25519_key.pub;
- "ssh/ssh_host_ed25519_key" = { mode = "0600"; source = ./ssh/ssh_host_ed25519_key; };
};
boot.kernelParams = [ "systemConfig=${config.system.build.toplevel}" ];
boot.kernelPackages = lib.mkDefault (if pkgs.system == "armv7l-linux" then pkgs.linuxPackages_rpi1 else pkgs.linuxPackages);
diff --git a/gen_keys b/gen_keys
deleted file mode 100755
index ee586a2..0000000
--- a/gen_keys
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-mkdir ssh
-ssh-keygen -t rsa -b 4096 -f ssh/ssh_host_rsa_key -N ""
-ssh-keygen -t ed25519 -f ssh/ssh_host_ed25519_key -N ""
diff --git a/runit.nix b/runit.nix
index d7b0bf3..6d602b6 100644
--- a/runit.nix
+++ b/runit.nix
@@ -2,7 +2,6 @@
let
sshd_config = pkgs.writeText "sshd_config" ''
- HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
Port 22
PidFile /run/sshd.pid
@@ -30,6 +29,13 @@ in
{
"runit/1".source = pkgs.writeScript "1" ''
#!${pkgs.runtimeShell}
+
+ ED25519_KEY="/etc/ssh/ssh_host_ed25519_key"
+
+ if [ ! -f $ED25519_KEY ]; then
+ ${pkgs.openssh}/bin/ssh-keygen -t ed25519 -f $ED25519_KEY -N ""
+ fi
+
${lib.optionalString config.not-os.simpleStaticIp ''
ip addr add 10.0.2.15 dev eth0
ip link set eth0 up
diff --git a/ssh/ssh_host_ed25519_key b/ssh/ssh_host_ed25519_key
deleted file mode 100644
index 62f3b04..0000000
--- a/ssh/ssh_host_ed25519_key
+++ /dev/null
@@ -1,7 +0,0 @@
------BEGIN OPENSSH PRIVATE KEY-----
-b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
-QyNTUxOQAAACCyu5b2+49W47G9KYQj+7xz1YuY3w3Iz1kb/eIgNWPF7wAAAJhmBZVCZgWV
-QgAAAAtzc2gtZWQyNTUxOQAAACCyu5b2+49W47G9KYQj+7xz1YuY3w3Iz1kb/eIgNWPF7w
-AAAEBALOVU4aPZln0n7z7AR5jOoVnT7OhWAJiROqTw9ecEILK7lvb7j1bjsb0phCP7vHPV
-i5jfDcjPWRv94iA1Y8XvAAAAEGNsZXZlckBhbWQtbml4b3MBAgMEBQ==
------END OPENSSH PRIVATE KEY-----
diff --git a/ssh/ssh_host_ed25519_key.pub b/ssh/ssh_host_ed25519_key.pub
deleted file mode 100644
index c636ae4..0000000
--- a/ssh/ssh_host_ed25519_key.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILK7lvb7j1bjsb0phCP7vHPVi5jfDcjPWRv94iA1Y8Xv clever@amd-nixos
diff --git a/ssh/ssh_host_rsa_key b/ssh/ssh_host_rsa_key
deleted file mode 100644
index d9c3b46..0000000
--- a/ssh/ssh_host_rsa_key
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKAIBAAKCAgEAxTB2amEQdRnxKKoTpm81Eydd0gSgiotd0Ujeg+eEkArLwlWv
-6gjoeNEzcNH8tZ0g3sjk1SVheZNxdHWCXqJnL/EIpoGn8VNW7pgRP1ZgW48wPjJ7
-dN8eve/28d2QCDYEkZNDTjHzDEHP/TxngjA6lli0KX6SfJbKUmqR/kdn8A5NpsjM
-BmjQ/UkMTAH/KG3HhSHRoljHFsyfKw917a3uO9ahLiEnFih36/V9anjljboEZAux
-XKNFUJFWkn+QPGLnPQtrP85ZUtSEFiwjOCcjCctps+miRJwZsNHE2erqelJbJb7v
-Cq+paoffxc27U7dhvLoz2f9XalW4Sj8mL45kyysrN4WBSDxi1znPjxD6PuNsabCe
-TBisHj2M09Zv7hZIoR53Jv6cjwZoML5MN6VA2yc/OAoYvDAJET/ZRPkl8tzzvMXo
-Y+bfyUitYA3FJjBInFm+mmVkHTqi/V7SwFKWGXRhAO2JU0cUXUrDyI7OKnNS4Vue
-h5O7UHGhtBvoFLDpkr9GJwNJNZXtNdK77eQXPDkv0k2qQcLZQLGRR4hBTIL9GAgE
-3nlCGs6bNw+OgaiWMqcLwoe8IBeq0WDrjRDEuyoIOREAQYZ0twYrhvT5rLXhz9IJ
-nUyn7P7uX4/i2tDWy3iPHJHNtFSD2lLA+xuXA6xoW1REfL3lCpIHZtpopP8CAwEA
-AQKCAgEAjbNYtPNRd0UQJq+pdUWe90enxP8sOsMRxQ4/ULxzZ2tKpzkaM+z42bFD
-7QQJPJ1QfKgSwRSeqlYJBq5W5BiCXFIybCzp+aJw6v3+DuzMS59nBJsUWpTnq4gg
-hgg4s53VxKL1j+CXDqzQgOMCYuyzfUz7EoJxU/SsKXOJvBemGjy9EmhjLQvvesQe
-gRRCPtQ8t2/pDGgNkVWz36a5kPYXJ4sBwntychrcqoR7/qIoG6Ob+iTo7HArpEz8
-0EO465wLHbPx+yUWzU4IKULIgFaneCdjqzTuNa2TTJxBgHOu0f4Sn9pIPv6imPpR
-FPzVa8BxDMUl87bpI3G8ACbHEw+ZX52wxC5/149ofu9jxBiGxODsmCGullIsGnEH
-F0PhA2kJzzb/MPcfZRGTvp0kbP9i3DM1yTa2vLSWT2hCi94zpRRiWMgN4azwvQeA
-o/KLlQ78hRu8wdJ5lwn5/iDpDr13TN5cHc7uhf/bVdwOcS9uSMAZvdIqazThQhgy
-G3AF5oIg/8MYz/pGwZg4aUmLTXB8O/Xgqtj5yUduMxR/vChZiKWHNt6EWT1VMHKs
-ktVBiLUZvp8kfWqSNVcLjt7tI2+Dwy2hNIPpRXZOu7cSf0A0YsZlcB/MLWBKKtMk
-mnYL1+rFTuR9TB6YkmDWwRqTHTEtyaXPADRX9j8Y0kF0Qd0JATECggEBAPp1+P5m
-wWMn2xOuBb+Znv036O+NOnQ+OPP04lFXwSHUsR6BMPJDaA2B3n+15vGCxzMLNQsl
-qn44WiUm2hv8BwO9DkFm/VpB9yj+30gnP6RXThPUsO6msN1XTa+F6GnnoJ8vRfnO
-9+iRU97Owwi8IGoHeVlsXRKhbi6cIJ0Y711b6uN97mBnOB+ig0F7L2lHrRRVYO3R
-SPpvZunsksZEoxdNGM4qTbhVjFve1gXWHNzzqDGzCqwnPWynVE8jEjM3jEp5GRKo
-jIEEN4k1SBI5Ovou07qogLgtsZnudxlJCDSgLITlJbCMwluZ+sjpxu6GIZrbNtYt
-yaCS+wwMvZYuWbcCggEBAMmM4kv2Na9Y272/oRIh5J14op4qMBWOqjXTdAX0WhrD
-ay/+s77t6Gq/oMgmulqQLLgZcGkrz7Z8DWfdNoSxZvQQcftr3CHrgRiZvyFzvhRN
-bnk3vTAT1Ay1nRFOmHsciOGVI8EijRVIunFJu2r4aIfQ6RUpBV16RwMk9CYjYcA1
-DAYc+IEDfH9SFmWAkO2/X9Gv7616fvAQsIjT+lSTkM6SPpvvwW7g/X3sM138ATJm
-8EcBbT7NvTmGbVSDYhzSyPc/DfZXnNhSMXPZrbwRJQNhUzL26TsOJUCzzD9yhwAC
-JTOON3VBqE3IRlKVlts5bghDcCxxFVK87U2pR6BvrvkCggEAWmTboc2qPEQ1MEwd
-bQJfvFpCarrY/v06Buo6CEuYu8IMzsqnxLgJRN67U/Jt0Hp3tHd2BHjqqLVj64az
-L2hti67fB0HJbJrkPlqGcX8g3ApadpPL68YjjS8mLZQxxo8/jFQ+eCN3m+tfjsmm
-4G8tb7cU1+5hRQkYQCA/MRO/yD0VcFeSAh8exWQc5TQ1b1TcJbuOySZApYoxZXnp
-mz9IcW905WulM0NE7h9ltSOKtUAHUzCgSHO9Gorlxc4NkoiYzIQaRX6pfyLrfEzL
-nzAilgryhaqtEkwDjl/fgjO2j2/DwY8GZErZFsBjH8In9wxX8pDtoK1T2O1TSA0N
-G7fMzwKCAQA1omgWDs76eor/U59pU9uijBe6Pz/MfMqOyFZ3vy67MIW1n/H1PRo8
-TgJbQPMWZod/9kUTt7TuutRWb2eyqALdsAKlBW7vF9yiz0ctf791Z6WeXFbcFGq5
-dxr1IBUzrcQ/Q5DgNHGW2GPFAfn93Vzzx4Q/PUtQNNnw3EScYY4BuBwbBFqc+nCG
-8TFEkZH/so2tH0SIxbBB8i8IOmDDYQGH9yLyHDs9ZmIOwGxq9kTbRMlsG9UWgWl5
-hWxSsSPKx8zy/rSYeXgjmLvQOH0jLuzKmXuqdEpcjMcdELupprCGMAv2TEI10eMX
-z9Pm5ife7sl5KXkQWodyHRSJNiL5br8BAoIBADu7tRChFC5oplnjQ2LYNbS58pv3
-+44RLBe6pZjiHTo9lSRmS+ymRrVoGyJWHEsS1eWjYZseuLjgQ0GuegF7fpeqqIST
-gXRaJ3OkjBWXtSNt48zsaWUMUO6qI8V7viMmxnzWskELaoHJTmOQSUXS9/L0/MFz
-1vhe6VN+xxlb0+x2if326RGJBIrDwInnTcMoIT0kPo1t9HWvs1pO29Qkg3Zellmg
-iEarmJVdr9WO26j72e1IYBauorVQHG9rqdv6YOdtvqKSqqh/Axm3G2HAXKJd7s9T
-FZYTE/OZsUWzEbRv73ZbzDFhva3BbHAHV71y4Uyllk85/PQ5qXISkf84gM4=
------END RSA PRIVATE KEY-----
diff --git a/ssh/ssh_host_rsa_key.pub b/ssh/ssh_host_rsa_key.pub
deleted file mode 100644
index 63dbd02..0000000
--- a/ssh/ssh_host_rsa_key.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFMHZqYRB1GfEoqhOmbzUTJ13SBKCKi13RSN6D54SQCsvCVa/qCOh40TNw0fy1nSDeyOTVJWF5k3F0dYJeomcv8QimgafxU1bumBE/VmBbjzA+Mnt03x697/bx3ZAINgSRk0NOMfMMQc/9PGeCMDqWWLQpfpJ8lspSapH+R2fwDk2myMwGaND9SQxMAf8obceFIdGiWMcWzJ8rD3Xtre471qEuIScWKHfr9X1qeOWNugRkC7Fco0VQkVaSf5A8Yuc9C2s/zllS1IQWLCM4JyMJy2mz6aJEnBmw0cTZ6up6Ulslvu8Kr6lqh9/FzbtTt2G8ujPZ/1dqVbhKPyYvjmTLKys3hYFIPGLXOc+PEPo+42xpsJ5MGKwePYzT1m/uFkihHncm/pyPBmgwvkw3pUDbJz84Chi8MAkRP9lE+SXy3PO8xehj5t/JSK1gDcUmMEicWb6aZWQdOqL9XtLAUpYZdGEA7YlTRxRdSsPIjs4qc1LhW56Hk7tQcaG0G+gUsOmSv0YnA0k1le010rvt5Bc8OS/STapBwtlAsZFHiEFMgv0YCATeeUIazps3D46BqJYypwvCh7wgF6rRYOuNEMS7Kgg5EQBBhnS3BiuG9PmsteHP0gmdTKfs/u5fj+La0NbLeI8ckc20VIPaUsD7G5cDrGhbVER8veUKkgdm2mik/w== clever@amd-nixos

View File

@ -0,0 +1,28 @@
diff --git a/runit.nix b/runit.nix
index d7b0bf3..64f99f2 100644
--- a/runit.nix
+++ b/runit.nix
@@ -57,6 +57,23 @@ in
'';
"runit/3".source = pkgs.writeScript "3" ''
#!${pkgs.runtimeShell}
+ echo Waiting for services to stop...
+ sv force-stop /etc/service/*
+ sv exit /etc/service/*
+
+ echo Sending TERM signal to processes...
+ pkill --inverse -s0,1 -TERM
+ sleep 1
+ echo Sending KILL signal to processes...
+ pkill --inverse -s0,1 -KILL
+
+ echo Unmounting filesystems, disabling swap...
+ swapoff -a
+ umount -r -a -t nosysfs,noproc,nodevtmpfs,notmpfs
+ echo Remounting rootfs read-only...
+ mount -o remount,ro /
+
+ sync
echo and down we go
'';
"service/sshd/run".source = pkgs.writeScript "sshd_run" ''

1092
not-os-patches/pr-33.patch Normal file

File diff suppressed because it is too large Load Diff