forked from M-Labs/artiq-zynq
Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
ac29cd30e5 | |||
35250b3f56 | |||
2ed2ffe417 | |||
18e05c91e1 | |||
e3d3cb2311 | |||
f543501012 | |||
111ac0c716 | |||
8128dc0b56 | |||
cbcda286dc | |||
dcb6129b0e | |||
f5933092c9 | |||
f25e261bdd | |||
44c2c0fe4d | |||
4c2c23fcdd | |||
480a80cab7 | |||
2ba4d8935d | |||
8c8a5d53b9 | |||
852123b42a | |||
f1fd55dee5 | |||
21d98711c1 | |||
0ae2138034 | |||
ce9d38827b | |||
1b474d2dd4 | |||
4f1689f254 | |||
506c741238 | |||
8815f76114 | |||
ef18fa4c6d | |||
faf9714e10 | |||
c90cb7adad | |||
8d4e42be32 | |||
dcd3cbc488 | |||
fcb38fae6c | |||
bfd8343876 | |||
4039431533 | |||
3f9bd06468 |
45
default.nix
45
default.nix
@ -8,23 +8,25 @@ let
|
|||||||
vivado = import <artiq-fast/vivado.nix> { inherit pkgs; };
|
vivado = import <artiq-fast/vivado.nix> { inherit pkgs; };
|
||||||
# FSBL configuration supplied by Vivado 2020.1 for these boards:
|
# FSBL configuration supplied by Vivado 2020.1 for these boards:
|
||||||
fsblTargets = ["zc702" "zc706" "zed"];
|
fsblTargets = ["zc702" "zc706" "zed"];
|
||||||
build = { target, variant }: let
|
sat_variants = ["satellite" "acpki_satellite" "nist_clock_satellite" "nist_qc2_satellite"];
|
||||||
|
build = { target, variant, json ? null }: let
|
||||||
szl = (import zynq-rs)."${target}-szl";
|
szl = (import zynq-rs)."${target}-szl";
|
||||||
fsbl = import "${zynq-rs}/nix/fsbl.nix" {
|
fsbl = import "${zynq-rs}/nix/fsbl.nix" {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
board = target;
|
board = target;
|
||||||
};
|
};
|
||||||
|
fwtype = if builtins.elem variant sat_variants then "satman" else "runtime";
|
||||||
|
|
||||||
firmware = rustPlatform.buildRustPackage rec {
|
firmware = rustPlatform.buildRustPackage rec {
|
||||||
# note: due to fetchCargoTarball, cargoSha256 depends on package name
|
# note: due to fetchCargoTarball, cargoSha256 depends on package name
|
||||||
name = "firmware";
|
name = "firmware";
|
||||||
|
|
||||||
src = ./src;
|
src = ./src;
|
||||||
cargoSha256 = "1g1nb8jz1na1v60hq3zrpgrwnw9qz7xrnnr2lkiyhsp72bg52ssl";
|
cargoSha256 = "0p9d2j7qp00wpxm48phl5rq26simzry6w0m673lyhrlbzqdz4frb";
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
pkgs.gnumake
|
pkgs.gnumake
|
||||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc artiq ])))
|
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ ps.jsonschema migen migen-axi misoc artiq ])))
|
||||||
cargo-xbuild
|
cargo-xbuild
|
||||||
pkgs.llvmPackages_9.llvm
|
pkgs.llvmPackages_9.llvm
|
||||||
pkgs.llvmPackages_9.clang-unwrapped
|
pkgs.llvmPackages_9.clang-unwrapped
|
||||||
@ -33,15 +35,15 @@ let
|
|||||||
export XARGO_RUST_SRC="${rustPlatform.rust.rustc}/lib/rustlib/src/rust/library"
|
export XARGO_RUST_SRC="${rustPlatform.rust.rustc}/lib/rustlib/src/rust/library"
|
||||||
export CLANG_EXTRA_INCLUDE_DIR="${pkgs.llvmPackages_9.clang-unwrapped.lib}/lib/clang/9.0.1/include"
|
export CLANG_EXTRA_INCLUDE_DIR="${pkgs.llvmPackages_9.clang-unwrapped.lib}/lib/clang/9.0.1/include"
|
||||||
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
||||||
make TARGET=${target} VARIANT=${variant}
|
make TARGET=${target} GWARGS="${if json == null then "-V ${variant}" else json}" ${fwtype}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out $out/nix-support
|
mkdir -p $out $out/nix-support
|
||||||
cp ../build/runtime.bin $out/runtime.bin
|
cp ../build/${fwtype}.bin $out/${fwtype}.bin
|
||||||
cp ../build/firmware/armv7-none-eabihf/release/runtime $out/runtime.elf
|
cp ../build/firmware/armv7-none-eabihf/release/${fwtype} $out/${fwtype}.elf
|
||||||
echo file binary-dist $out/runtime.bin >> $out/nix-support/hydra-build-products
|
echo file binary-dist $out/${fwtype}.bin >> $out/nix-support/hydra-build-products
|
||||||
echo file binary-dist $out/runtime.elf >> $out/nix-support/hydra-build-products
|
echo file binary-dist $out/${fwtype}.elf >> $out/nix-support/hydra-build-products
|
||||||
'';
|
'';
|
||||||
|
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
@ -50,12 +52,12 @@ let
|
|||||||
gateware = pkgs.runCommand "${target}-${variant}-gateware"
|
gateware = pkgs.runCommand "${target}-${variant}-gateware"
|
||||||
{
|
{
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc artiq ])))
|
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ ps.jsonschema migen migen-axi misoc artiq ])))
|
||||||
vivado
|
vivado
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
''
|
''
|
||||||
python ${./src/gateware}/${target}.py -g build -V ${variant}
|
python ${./src/gateware}/${target}.py -g build ${if json == null then "-V ${variant}" else json}
|
||||||
mkdir -p $out $out/nix-support
|
mkdir -p $out $out/nix-support
|
||||||
cp build/top.bit $out
|
cp build/top.bit $out
|
||||||
echo file binary-dist $out/top.bit >> $out/nix-support/hydra-build-products
|
echo file binary-dist $out/top.bit >> $out/nix-support/hydra-build-products
|
||||||
@ -66,7 +68,7 @@ let
|
|||||||
''
|
''
|
||||||
mkdir $out
|
mkdir $out
|
||||||
ln -s ${szl}/szl.elf $out
|
ln -s ${szl}/szl.elf $out
|
||||||
ln -s ${firmware}/runtime.bin $out
|
ln -s ${firmware}/${fwtype}.bin $out
|
||||||
ln -s ${gateware}/top.bit $out
|
ln -s ${gateware}/top.bit $out
|
||||||
'';
|
'';
|
||||||
sd = pkgs.runCommand "${target}-${variant}-sd"
|
sd = pkgs.runCommand "${target}-${variant}-sd"
|
||||||
@ -132,16 +134,25 @@ let
|
|||||||
in
|
in
|
||||||
(
|
(
|
||||||
(build { target = "zc706"; variant = "simple"; }) //
|
(build { target = "zc706"; variant = "simple"; }) //
|
||||||
|
(build { target = "zc706"; variant = "master"; }) //
|
||||||
|
(build { target = "zc706"; variant = "satellite"; }) //
|
||||||
(build { target = "zc706"; variant = "nist_clock"; }) //
|
(build { target = "zc706"; variant = "nist_clock"; }) //
|
||||||
|
(build { target = "zc706"; variant = "nist_clock_master"; }) //
|
||||||
|
(build { target = "zc706"; variant = "nist_clock_satellite"; }) //
|
||||||
(build { target = "zc706"; variant = "nist_qc2"; }) //
|
(build { target = "zc706"; variant = "nist_qc2"; }) //
|
||||||
|
(build { target = "zc706"; variant = "nist_qc2_master"; }) //
|
||||||
|
(build { target = "zc706"; variant = "nist_qc2_satellite"; }) //
|
||||||
(build { target = "zc706"; variant = "acpki_simple"; }) //
|
(build { target = "zc706"; variant = "acpki_simple"; }) //
|
||||||
|
(build { target = "zc706"; variant = "acpki_master"; }) //
|
||||||
|
(build { target = "zc706"; variant = "acpki_satellite"; }) //
|
||||||
(build { target = "zc706"; variant = "acpki_nist_clock"; }) //
|
(build { target = "zc706"; variant = "acpki_nist_clock"; }) //
|
||||||
|
(build { target = "zc706"; variant = "acpki_nist_clock_master"; }) //
|
||||||
|
(build { target = "zc706"; variant = "acpki_nist_clock_satellite"; }) //
|
||||||
(build { target = "zc706"; variant = "acpki_nist_qc2"; }) //
|
(build { target = "zc706"; variant = "acpki_nist_qc2"; }) //
|
||||||
(build { target = "coraz7"; variant = "10"; }) //
|
(build { target = "zc706"; variant = "acpki_nist_qc2_master"; }) //
|
||||||
(build { target = "coraz7"; variant = "07s"; }) //
|
(build { target = "zc706"; variant = "acpki_nist_qc2_satellite"; }) //
|
||||||
(build { target = "coraz7"; variant = "acpki_10"; }) //
|
(build { target = "kasli_soc"; variant = "demo"; json = ./demo.json; }) //
|
||||||
(build { target = "coraz7"; variant = "acpki_07s"; }) //
|
(build { target = "kasli_soc"; variant = "master"; json = ./kasli-soc-master.json; }) //
|
||||||
(build { target = "redpitaya"; variant = "simple"; }) //
|
(build { target = "kasli_soc"; variant = "satellite"; json = ./kasli-soc-satellite.json; }) //
|
||||||
(build { target = "redpitaya"; variant = "acpki_simple"; }) //
|
|
||||||
{ inherit zynq-rs; }
|
{ inherit zynq-rs; }
|
||||||
)
|
)
|
||||||
|
60
demo.json
Normal file
60
demo.json
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"target": "kasli_soc",
|
||||||
|
"variant": "demo",
|
||||||
|
"hw_rev": "v1.0",
|
||||||
|
"base": "standalone",
|
||||||
|
"peripherals": [
|
||||||
|
{
|
||||||
|
"type": "grabber",
|
||||||
|
"ports": [0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [1],
|
||||||
|
"bank_direction_low": "input",
|
||||||
|
"bank_direction_high": "output"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [2],
|
||||||
|
"bank_direction_low": "output",
|
||||||
|
"bank_direction_high": "output"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "urukul",
|
||||||
|
"dds": "ad9910",
|
||||||
|
"ports": [3, 4],
|
||||||
|
"clk_sel": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "zotino",
|
||||||
|
"ports": [5]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "sampler",
|
||||||
|
"ports": [6, 7]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mirny",
|
||||||
|
"ports": [8],
|
||||||
|
"clk_sel": 1,
|
||||||
|
"refclk": 125e6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fastino",
|
||||||
|
"ports": [9]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [10],
|
||||||
|
"bank_direction_low": "input",
|
||||||
|
"bank_direction_high": "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [11],
|
||||||
|
"bank_direction_low": "output",
|
||||||
|
"bank_direction_high": "input"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
60
kasli-soc-master.json
Normal file
60
kasli-soc-master.json
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"target": "kasli_soc",
|
||||||
|
"variant": "master",
|
||||||
|
"hw_rev": "v1.0",
|
||||||
|
"base": "master",
|
||||||
|
"peripherals": [
|
||||||
|
{
|
||||||
|
"type": "grabber",
|
||||||
|
"ports": [0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [1],
|
||||||
|
"bank_direction_low": "input",
|
||||||
|
"bank_direction_high": "output"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [2],
|
||||||
|
"bank_direction_low": "output",
|
||||||
|
"bank_direction_high": "output"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "urukul",
|
||||||
|
"dds": "ad9910",
|
||||||
|
"ports": [3, 4],
|
||||||
|
"clk_sel": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "zotino",
|
||||||
|
"ports": [5]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "sampler",
|
||||||
|
"ports": [6, 7]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mirny",
|
||||||
|
"ports": [8],
|
||||||
|
"clk_sel": 1,
|
||||||
|
"refclk": 125e6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fastino",
|
||||||
|
"ports": [9]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [10],
|
||||||
|
"bank_direction_low": "input",
|
||||||
|
"bank_direction_high": "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [11],
|
||||||
|
"bank_direction_low": "output",
|
||||||
|
"bank_direction_high": "input"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
60
kasli-soc-satellite.json
Normal file
60
kasli-soc-satellite.json
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"target": "kasli_soc",
|
||||||
|
"variant": "satellite",
|
||||||
|
"hw_rev": "v1.0",
|
||||||
|
"base": "satellite",
|
||||||
|
"peripherals": [
|
||||||
|
{
|
||||||
|
"type": "grabber",
|
||||||
|
"ports": [0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [1],
|
||||||
|
"bank_direction_low": "input",
|
||||||
|
"bank_direction_high": "output"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [2],
|
||||||
|
"bank_direction_low": "output",
|
||||||
|
"bank_direction_high": "output"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "urukul",
|
||||||
|
"dds": "ad9910",
|
||||||
|
"ports": [3, 4],
|
||||||
|
"clk_sel": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "zotino",
|
||||||
|
"ports": [5]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "sampler",
|
||||||
|
"ports": [6, 7]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mirny",
|
||||||
|
"ports": [8],
|
||||||
|
"clk_sel": 1,
|
||||||
|
"refclk": 125e6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fastino",
|
||||||
|
"ports": [9]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [10],
|
||||||
|
"bank_direction_low": "input",
|
||||||
|
"bank_direction_high": "input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dio",
|
||||||
|
"ports": [11],
|
||||||
|
"bank_direction_low": "output",
|
||||||
|
"bank_direction_high": "input"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
local_run.sh
23
local_run.sh
@ -13,9 +13,10 @@ fi
|
|||||||
|
|
||||||
impure=0
|
impure=0
|
||||||
load_bitstream=1
|
load_bitstream=1
|
||||||
board_host="192.168.1.52"
|
board_type="kasli_soc"
|
||||||
|
fw_type="runtime"
|
||||||
|
|
||||||
while getopts "ilb:" opt; do
|
while getopts "ilb:t:f:" opt; do
|
||||||
case "$opt" in
|
case "$opt" in
|
||||||
\?) exit 1
|
\?) exit 1
|
||||||
;;
|
;;
|
||||||
@ -25,24 +26,36 @@ while getopts "ilb:" opt; do
|
|||||||
;;
|
;;
|
||||||
b) board_host=$OPTARG
|
b) board_host=$OPTARG
|
||||||
;;
|
;;
|
||||||
|
t) board_type=$OPTARG
|
||||||
|
;;
|
||||||
|
f) fw_type=$OPTARG
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ -z "$board_host" ]; then
|
||||||
|
case $board_type in
|
||||||
|
kasli_soc) board_host="192.168.1.56";;
|
||||||
|
zc706) board_host="192.168.1.52";;
|
||||||
|
*) echo "Unknown board type"; exit 1;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
load_bitstream_cmd=""
|
load_bitstream_cmd=""
|
||||||
|
|
||||||
build_dir=`pwd`/build
|
build_dir=`pwd`/build
|
||||||
result_dir=`pwd`/result
|
result_dir=`pwd`/result
|
||||||
cd $OPENOCD_ZYNQ
|
cd $OPENOCD_ZYNQ
|
||||||
openocd -f zc706.cfg -c "load_image $SZL; resume 0; exit"
|
openocd -f $board_type.cfg -c "load_image $SZL/szl-$board_type.elf; resume 0; exit"
|
||||||
sleep 5
|
sleep 5
|
||||||
if [ $impure -eq 1 ]; then
|
if [ $impure -eq 1 ]; then
|
||||||
if [ $load_bitstream -eq 1 ]; then
|
if [ $load_bitstream -eq 1 ]; then
|
||||||
load_bitstream_cmd="-g $build_dir/gateware/top.bit"
|
load_bitstream_cmd="-g $build_dir/gateware/top.bit"
|
||||||
fi
|
fi
|
||||||
artiq_netboot $load_bitstream_cmd -f $build_dir/runtime.bin -b $board_host
|
artiq_netboot $load_bitstream_cmd -f $build_dir/$fwtype.bin -b $board_host
|
||||||
else
|
else
|
||||||
if [ $load_bitstream -eq 1 ]; then
|
if [ $load_bitstream -eq 1 ]; then
|
||||||
load_bitstream_cmd="-g $result_dir/top.bit"
|
load_bitstream_cmd="-g $result_dir/top.bit"
|
||||||
fi
|
fi
|
||||||
artiq_netboot $load_bitstream_cmd -f $result_dir/runtime.bin -b $board_host
|
artiq_netboot $load_bitstream_cmd -f $result_dir/$fwtype.bin -b $board_host
|
||||||
fi
|
fi
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Only ZC706 supported for now.
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [ -z "$OPENOCD_ZYNQ" ]; then
|
if [ -z "$OPENOCD_ZYNQ" ]; then
|
||||||
@ -18,8 +20,9 @@ impure_dir="build"
|
|||||||
sshopts=""
|
sshopts=""
|
||||||
load_bitstream=1
|
load_bitstream=1
|
||||||
board_host="192.168.1.52"
|
board_host="192.168.1.52"
|
||||||
|
fw_type="runtime"
|
||||||
|
|
||||||
while getopts "h:id:o:l" opt; do
|
while getopts "h:id:o:lt:" opt; do
|
||||||
case "$opt" in
|
case "$opt" in
|
||||||
\?) exit 1
|
\?) exit 1
|
||||||
;;
|
;;
|
||||||
@ -36,6 +39,8 @@ while getopts "h:id:o:l" opt; do
|
|||||||
;;
|
;;
|
||||||
b) board_host=$OPTARG
|
b) board_host=$OPTARG
|
||||||
;;
|
;;
|
||||||
|
t) fw_type=$OPTARG
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -46,17 +51,17 @@ echo "Creating $target_folder..."
|
|||||||
ssh $sshopts $target_host "mkdir -p $target_folder"
|
ssh $sshopts $target_host "mkdir -p $target_folder"
|
||||||
echo "Copying files..."
|
echo "Copying files..."
|
||||||
rsync -e "ssh $sshopts" -Lc $OPENOCD_ZYNQ/* $target_host:$target_folder
|
rsync -e "ssh $sshopts" -Lc $OPENOCD_ZYNQ/* $target_host:$target_folder
|
||||||
rsync -e "ssh $sshopts" -Lc $SZL $target_host:$target_folder
|
rsync -e "ssh $sshopts" -Lc $SZL/szl-zc706.elf $target_host:$target_folder/szl.elf
|
||||||
if [ $impure -eq 1 ]; then
|
if [ $impure -eq 1 ]; then
|
||||||
if [ $load_bitstream -eq 1 ]; then
|
if [ $load_bitstream -eq 1 ]; then
|
||||||
load_bitstream_cmd="-g build/gateware/top.bit"
|
load_bitstream_cmd="-g build/gateware/top.bit"
|
||||||
fi
|
fi
|
||||||
firmware="build/runtime.bin"
|
firmware="build/$fw_type.bin"
|
||||||
else
|
else
|
||||||
if [ $load_bitstream -eq 1 ]; then
|
if [ $load_bitstream -eq 1 ]; then
|
||||||
load_bitstream_cmd="-g $pure_dir/top.bit"
|
load_bitstream_cmd="-g $pure_dir/top.bit"
|
||||||
fi
|
fi
|
||||||
firmware="$pure_dir/runtime.bin"
|
firmware="$pure_dir/$fw_type.bin"
|
||||||
fi
|
fi
|
||||||
echo "Programming board..."
|
echo "Programming board..."
|
||||||
ssh $sshopts $target_host "cd $target_folder; openocd -f zc706.cfg -c'load_image szl.elf; resume 0; exit'"
|
ssh $sshopts $target_host "cd $target_folder; openocd -f zc706.cfg -c'load_image szl.elf; resume 0; exit'"
|
||||||
|
@ -6,7 +6,6 @@ let
|
|||||||
artiq-fast = <artiq-fast>;
|
artiq-fast = <artiq-fast>;
|
||||||
artiqpkgs = import "${artiq-fast}/default.nix" { inherit pkgs; };
|
artiqpkgs = import "${artiq-fast}/default.nix" { inherit pkgs; };
|
||||||
vivado = import "${artiq-fast}/vivado.nix" { inherit pkgs; };
|
vivado = import "${artiq-fast}/vivado.nix" { inherit pkgs; };
|
||||||
zc706-szl = (import zynq-rs).zc706-szl;
|
|
||||||
in
|
in
|
||||||
pkgs.stdenv.mkDerivation {
|
pkgs.stdenv.mkDerivation {
|
||||||
name = "artiq-zynq-env";
|
name = "artiq-zynq-env";
|
||||||
@ -22,7 +21,7 @@ in
|
|||||||
pkgs.openocd
|
pkgs.openocd
|
||||||
pkgs.openssh pkgs.rsync
|
pkgs.openssh pkgs.rsync
|
||||||
|
|
||||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc artiq artiq-netboot ])))
|
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc artiq artiq-netboot ps.jsonschema ps.pyftdi ])))
|
||||||
vivado
|
vivado
|
||||||
artiqpkgs.binutils-arm
|
artiqpkgs.binutils-arm
|
||||||
|
|
||||||
@ -32,5 +31,5 @@ in
|
|||||||
XARGO_RUST_SRC = "${rustPlatform.rust.rustc}/lib/rustlib/src/rust/library";
|
XARGO_RUST_SRC = "${rustPlatform.rust.rustc}/lib/rustlib/src/rust/library";
|
||||||
CLANG_EXTRA_INCLUDE_DIR = "${pkgs.llvmPackages_9.clang-unwrapped.lib}/lib/clang/9.0.1/include";
|
CLANG_EXTRA_INCLUDE_DIR = "${pkgs.llvmPackages_9.clang-unwrapped.lib}/lib/clang/9.0.1/include";
|
||||||
OPENOCD_ZYNQ = "${zynq-rs}/openocd";
|
OPENOCD_ZYNQ = "${zynq-rs}/openocd";
|
||||||
SZL = "${zc706-szl}/szl.elf";
|
SZL = "${(import zynq-rs).szl}";
|
||||||
}
|
}
|
||||||
|
16
src/Cargo.lock
generated
16
src/Cargo.lock
generated
@ -94,9 +94,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-hal"
|
name = "embedded-hal"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "db184d3fa27bc7a2344250394c0264144dfe0bc81a4401801dcb964b8dd172ad"
|
checksum = "e36cfb62ff156596c892272f3015ef952fe1525e85261fa3a7f327bd6b384ab9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nb 0.1.3",
|
"nb 0.1.3",
|
||||||
"void",
|
"void",
|
||||||
@ -195,7 +195,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "libasync"
|
name = "libasync"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embedded-hal",
|
"embedded-hal",
|
||||||
"libcortex_a9",
|
"libcortex_a9",
|
||||||
@ -207,7 +207,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "libboard_zynq"
|
name = "libboard_zynq"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field",
|
"bit_field",
|
||||||
"embedded-hal",
|
"embedded-hal",
|
||||||
@ -232,7 +232,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "libconfig"
|
name = "libconfig"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core_io",
|
"core_io",
|
||||||
"fatfs",
|
"fatfs",
|
||||||
@ -243,7 +243,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "libcortex_a9"
|
name = "libcortex_a9"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field",
|
"bit_field",
|
||||||
"libregister",
|
"libregister",
|
||||||
@ -259,7 +259,7 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "libregister"
|
name = "libregister"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field",
|
"bit_field",
|
||||||
"vcell",
|
"vcell",
|
||||||
@ -269,7 +269,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "libsupport_zynq"
|
name = "libsupport_zynq"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
|
@ -3,8 +3,10 @@ members = [
|
|||||||
"libc",
|
"libc",
|
||||||
"libdyld",
|
"libdyld",
|
||||||
"libdwarf",
|
"libdwarf",
|
||||||
|
"libio",
|
||||||
"libunwind",
|
"libunwind",
|
||||||
"runtime",
|
"runtime",
|
||||||
|
"satman"
|
||||||
]
|
]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
20
src/Makefile
20
src/Makefile
@ -1,16 +1,18 @@
|
|||||||
TARGET := zc706
|
TARGET := zc706
|
||||||
VARIANT := simple
|
GWARGS := -V simple
|
||||||
|
|
||||||
all: ../build/firmware/armv7-none-eabihf/release/runtime ../build/runtime.bin
|
all: runtime
|
||||||
|
|
||||||
|
runtime: ../build/runtime.bin
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
|
|
||||||
../build/pl.rs ../build/rustc-cfg: gateware/*
|
../build/pl.rs ../build/rustc-cfg: gateware/*
|
||||||
mkdir -p ../build
|
mkdir -p ../build
|
||||||
python gateware/$(TARGET).py -r ../build/pl.rs -c ../build/rustc-cfg -V $(VARIANT)
|
python gateware/$(TARGET).py -r ../build/pl.rs -c ../build/rustc-cfg -m ../build/mem.rs $(GWARGS)
|
||||||
|
|
||||||
../build/firmware/armv7-none-eabihf/release/runtime: ../build/pl.rs ../build/rustc-cfg $(shell find . -print)
|
../build/firmware/armv7-none-eabihf/release/runtime: ../build/pl.rs ../build/rustc-cfg
|
||||||
cd runtime && \
|
cd runtime && \
|
||||||
XBUILD_SYSROOT_PATH=`pwd`/../../build/sysroot \
|
XBUILD_SYSROOT_PATH=`pwd`/../../build/sysroot \
|
||||||
cargo xbuild --release \
|
cargo xbuild --release \
|
||||||
@ -19,3 +21,13 @@ all: ../build/firmware/armv7-none-eabihf/release/runtime ../build/runtime.bin
|
|||||||
|
|
||||||
../build/runtime.bin: ../build/firmware/armv7-none-eabihf/release/runtime
|
../build/runtime.bin: ../build/firmware/armv7-none-eabihf/release/runtime
|
||||||
llvm-objcopy -O binary ../build/firmware/armv7-none-eabihf/release/runtime ../build/runtime.bin
|
llvm-objcopy -O binary ../build/firmware/armv7-none-eabihf/release/runtime ../build/runtime.bin
|
||||||
|
|
||||||
|
satmanout: ../build/pl.rs ../build/rustc-cfg
|
||||||
|
cd satman && \
|
||||||
|
XBUILD_SYSROOT_PATH=`pwd`/../../build/sysroot \
|
||||||
|
cargo xbuild --release \
|
||||||
|
--target-dir ../../build/firmware \
|
||||||
|
--no-default-features --features=target_$(TARGET)
|
||||||
|
|
||||||
|
satman: satmanout
|
||||||
|
llvm-objcopy -O binary ../build/firmware/armv7-none-eabihf/release/satman ../build/satman.bin
|
@ -8,12 +8,13 @@ from migen.build.generic_platform import *
|
|||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.genlib.cdc import MultiReg
|
from migen.genlib.cdc import MultiReg
|
||||||
from migen_axi.integration.soc_core import SoCCore
|
from migen_axi.integration.soc_core import SoCCore
|
||||||
from migen_axi.platforms import coraz7
|
from migen_axi.platforms import kasli_soc
|
||||||
from misoc.interconnect.csr import *
|
from misoc.interconnect.csr import *
|
||||||
from misoc.integration import cpu_interface
|
from misoc.integration import cpu_interface
|
||||||
|
|
||||||
from artiq.gateware import rtio
|
from artiq.coredevice import jsondesc
|
||||||
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2
|
from artiq.gateware import rtio, eem_7series
|
||||||
|
from artiq.gateware.rtio.phy import ttl_simple
|
||||||
|
|
||||||
import dma
|
import dma
|
||||||
import analyzer
|
import analyzer
|
||||||
@ -21,55 +22,81 @@ import acpki
|
|||||||
|
|
||||||
|
|
||||||
class RTIOCRG(Module, AutoCSR):
|
class RTIOCRG(Module, AutoCSR):
|
||||||
def __init__(self, platform, rtio_internal_clk):
|
def __init__(self, platform):
|
||||||
self.clock_sel = CSRStorage()
|
|
||||||
self.pll_reset = CSRStorage(reset=1)
|
self.pll_reset = CSRStorage(reset=1)
|
||||||
self.pll_locked = CSRStatus()
|
self.pll_locked = CSRStatus()
|
||||||
self.clock_domains.cd_rtio = ClockDomain()
|
self.clock_domains.cd_rtio = ClockDomain()
|
||||||
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
|
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
|
||||||
|
|
||||||
rtio_external_clk = Signal()
|
clk_synth = platform.request("cdr_clk_clean_fabric")
|
||||||
# user_sma_clock = platform.request("user_sma_clock")
|
clk_synth_se = Signal()
|
||||||
# platform.add_period_constraint(user_sma_clock.p, 8.0)
|
platform.add_period_constraint(clk_synth.p, 8.0)
|
||||||
# self.specials += Instance("IBUFDS",
|
self.specials += [
|
||||||
# i_I=user_sma_clock.p, i_IB=user_sma_clock.n,
|
Instance("IBUFGDS",
|
||||||
# o_O=rtio_external_clk)
|
p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="FALSE",
|
||||||
|
i_I=clk_synth.p, i_IB=clk_synth.n, o_O=clk_synth_se),
|
||||||
|
]
|
||||||
|
|
||||||
pll_locked = Signal()
|
pll_locked = Signal()
|
||||||
rtio_clk = Signal()
|
rtio_clk = Signal()
|
||||||
rtiox4_clk = Signal()
|
rtiox4_clk = Signal()
|
||||||
|
fb_clk = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("PLLE2_ADV",
|
Instance("PLLE2_ADV",
|
||||||
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
||||||
|
p_BANDWIDTH="HIGH",
|
||||||
p_REF_JITTER1=0.01,
|
p_REF_JITTER1=0.001,
|
||||||
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
||||||
i_CLKIN1=rtio_internal_clk, i_CLKIN2=rtio_external_clk,
|
i_CLKIN2=clk_synth_se,
|
||||||
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
||||||
i_CLKINSEL=~self.clock_sel.storage,
|
i_CLKINSEL=0,
|
||||||
|
|
||||||
# VCO @ 1GHz when using 125MHz input
|
# VCO @ 1.5GHz when using 125MHz input
|
||||||
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
|
p_CLKFBOUT_MULT=12, p_DIVCLK_DIVIDE=1,
|
||||||
i_CLKFBIN=self.cd_rtio.clk,
|
i_CLKFBIN=fb_clk,
|
||||||
i_RST=self.pll_reset.storage,
|
i_RST=self.pll_reset.storage,
|
||||||
|
|
||||||
o_CLKFBOUT=rtio_clk,
|
o_CLKFBOUT=fb_clk,
|
||||||
|
|
||||||
p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
|
p_CLKOUT0_DIVIDE=3, p_CLKOUT0_PHASE=0.0,
|
||||||
o_CLKOUT0=rtiox4_clk),
|
o_CLKOUT0=rtiox4_clk,
|
||||||
|
|
||||||
|
p_CLKOUT1_DIVIDE=12, p_CLKOUT1_PHASE=0.0,
|
||||||
|
o_CLKOUT1=rtio_clk),
|
||||||
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
||||||
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
||||||
|
|
||||||
AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
|
AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
|
||||||
MultiReg(pll_locked, self.pll_locked.status)
|
MultiReg(pll_locked, self.pll_locked.status)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class CoraZ7(SoCCore):
|
eem_iostandard_dict = {
|
||||||
def __init__(self, device_variant="10", acpki=False):
|
0: "LVDS_25",
|
||||||
|
1: "LVDS_25",
|
||||||
|
2: "LVDS",
|
||||||
|
3: "LVDS",
|
||||||
|
4: "LVDS",
|
||||||
|
5: "LVDS",
|
||||||
|
6: "LVDS",
|
||||||
|
7: "LVDS",
|
||||||
|
8: "LVDS_25",
|
||||||
|
9: "LVDS_25",
|
||||||
|
10: "LVDS",
|
||||||
|
11: "LVDS",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def eem_iostandard(eem):
|
||||||
|
return IOStandard(eem_iostandard_dict[eem])
|
||||||
|
|
||||||
|
|
||||||
|
class GenericStandalone(SoCCore):
|
||||||
|
def __init__(self, description, acpki=False):
|
||||||
self.acpki = acpki
|
self.acpki = acpki
|
||||||
self.rustc_cfg = dict()
|
self.rustc_cfg = dict()
|
||||||
|
|
||||||
platform = coraz7.Platform(device_variant=device_variant)
|
platform = kasli_soc.Platform()
|
||||||
platform.toolchain.bitstream_commands.extend([
|
platform.toolchain.bitstream_commands.extend([
|
||||||
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
||||||
])
|
])
|
||||||
@ -81,16 +108,33 @@ class CoraZ7(SoCCore):
|
|||||||
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
||||||
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
||||||
|
|
||||||
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
self.rustc_cfg["HAS_SI5324"] = None
|
||||||
|
self.rustc_cfg["SI5324_SOFT_RESET"] = None
|
||||||
|
|
||||||
|
self.crg = self.ps7 # HACK for eem_7series to find the clock
|
||||||
|
self.submodules.rtio_crg = RTIOCRG(self.platform)
|
||||||
self.csr_devices.append("rtio_crg")
|
self.csr_devices.append("rtio_crg")
|
||||||
self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
|
self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
|
||||||
self.platform.add_false_path_constraints(
|
self.platform.add_false_path_constraints(
|
||||||
self.ps7.cd_sys.clk,
|
self.ps7.cd_sys.clk,
|
||||||
self.rtio_crg.cd_rtio.clk)
|
self.rtio_crg.cd_rtio.clk)
|
||||||
|
|
||||||
def add_rtio(self, rtio_channels):
|
self.rtio_channels = []
|
||||||
|
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
|
||||||
|
if has_grabber:
|
||||||
|
self.grabber_csr_group = []
|
||||||
|
eem_7series.add_peripherals(self, description["peripherals"], iostandard=eem_iostandard)
|
||||||
|
for i in (0, 1):
|
||||||
|
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
||||||
|
user_led = self.platform.request("user_led", i)
|
||||||
|
phy = ttl_simple.Output(user_led)
|
||||||
|
self.submodules += phy
|
||||||
|
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||||
|
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
||||||
|
self.rtio_channels.append(rtio.LogChannel())
|
||||||
|
|
||||||
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||||
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels)
|
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, self.rtio_channels)
|
||||||
self.csr_devices.append("rtio_core")
|
self.csr_devices.append("rtio_core")
|
||||||
|
|
||||||
if self.acpki:
|
if self.acpki:
|
||||||
@ -113,30 +157,29 @@ class CoraZ7(SoCCore):
|
|||||||
[self.rtio_core.cri])
|
[self.rtio_core.cri])
|
||||||
self.csr_devices.append("cri_con")
|
self.csr_devices.append("cri_con")
|
||||||
|
|
||||||
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
self.submodules.rtio_moninj = rtio.MonInj(self.rtio_channels)
|
||||||
self.csr_devices.append("rtio_moninj")
|
self.csr_devices.append("rtio_moninj")
|
||||||
|
|
||||||
self.submodules.rtio_analyzer = analyzer.Analyzer(self.rtio_tsc, self.rtio_core.cri,
|
self.submodules.rtio_analyzer = analyzer.Analyzer(self.rtio_tsc, self.rtio_core.cri,
|
||||||
self.ps7.s_axi_hp1)
|
self.ps7.s_axi_hp1)
|
||||||
self.csr_devices.append("rtio_analyzer")
|
self.csr_devices.append("rtio_analyzer")
|
||||||
|
|
||||||
|
if has_grabber:
|
||||||
|
self.rustc_cfg["has_grabber"] = None
|
||||||
|
self.add_csr_group("grabber", self.grabber_csr_group)
|
||||||
|
for grabber in self.grabber_csr_group:
|
||||||
|
self.platform.add_false_path_constraints(
|
||||||
|
self.rtio_crg.cd_rtio.clk, getattr(self, grabber).deserializer.cd_cl.clk)
|
||||||
|
|
||||||
class Simple(CoraZ7):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
CoraZ7.__init__(self, **kwargs)
|
|
||||||
|
|
||||||
platform = self.platform
|
class GenericMaster(SoCCore):
|
||||||
|
def __init__(self, description, **kwargs):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
rtio_channels = []
|
|
||||||
for i in range(2):
|
|
||||||
phy = ttl_simple.Output(platform.request("user_led", i))
|
|
||||||
self.submodules += phy
|
|
||||||
rtio_channels.append(rtio.Channel.from_phy(phy))
|
|
||||||
|
|
||||||
self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels)
|
class GenericSatellite(SoCCore):
|
||||||
rtio_channels.append(rtio.LogChannel())
|
def __init__(self, description, **kwargs):
|
||||||
|
raise NotImplementedError
|
||||||
self.add_rtio(rtio_channels)
|
|
||||||
|
|
||||||
|
|
||||||
def write_csr_file(soc, filename):
|
def write_csr_file(soc, filename):
|
||||||
@ -156,27 +199,33 @@ def write_rustc_cfg_file(soc, filename):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="ARTIQ port to the Cora Z7 Zynq development kit")
|
description="ARTIQ device binary builder for generic Kasli-SoC systems")
|
||||||
parser.add_argument("-r", default=None,
|
parser.add_argument("-r", default=None,
|
||||||
help="build Rust interface into the specified file")
|
help="build Rust interface into the specified file")
|
||||||
parser.add_argument("-c", default=None,
|
parser.add_argument("-c", default=None,
|
||||||
help="build Rust compiler configuration into the specified file")
|
help="build Rust compiler configuration into the specified file")
|
||||||
parser.add_argument("-g", default=None,
|
parser.add_argument("-g", default=None,
|
||||||
help="build gateware into the specified directory")
|
help="build gateware into the specified directory")
|
||||||
parser.add_argument("-V", "--variant", default="10",
|
parser.add_argument("--acpki", default=False, action="store_true",
|
||||||
help="variant: "
|
help="enable ACPKI")
|
||||||
"[acpki_]10/07s "
|
parser.add_argument("description", metavar="DESCRIPTION",
|
||||||
"(default: %(default)s)")
|
help="JSON system description file")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
description = jsondesc.load(args.description)
|
||||||
|
|
||||||
variant = args.variant.lower()
|
if description["target"] != "kasli_soc":
|
||||||
acpki = variant.startswith("acpki_")
|
raise ValueError("Description is for a different target")
|
||||||
if acpki:
|
|
||||||
variant = variant[6:]
|
if description["base"] == "standalone":
|
||||||
try:
|
cls = GenericStandalone
|
||||||
soc = Simple(device_variant=variant, acpki=acpki)
|
elif description["base"] == "master":
|
||||||
except KeyError:
|
cls = GenericMaster
|
||||||
raise SystemExit("Invalid variant (-V/--variant)")
|
elif description["base"] == "satellite":
|
||||||
|
cls = GenericSatellite
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid base")
|
||||||
|
|
||||||
|
soc = cls(description, acpki=args.acpki)
|
||||||
soc.finalize()
|
soc.finalize()
|
||||||
|
|
||||||
if args.r is not None:
|
if args.r is not None:
|
@ -1,191 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
from operator import itemgetter
|
|
||||||
|
|
||||||
from migen import *
|
|
||||||
from migen.build.generic_platform import *
|
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
||||||
from migen.genlib.cdc import MultiReg
|
|
||||||
from migen_axi.integration.soc_core import SoCCore
|
|
||||||
from migen_axi.platforms import redpitaya
|
|
||||||
from misoc.interconnect.csr import *
|
|
||||||
from misoc.integration import cpu_interface
|
|
||||||
|
|
||||||
from artiq.gateware import rtio
|
|
||||||
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2
|
|
||||||
|
|
||||||
import dma
|
|
||||||
import analyzer
|
|
||||||
import acpki
|
|
||||||
|
|
||||||
|
|
||||||
class RTIOCRG(Module, AutoCSR):
|
|
||||||
def __init__(self, platform, rtio_internal_clk):
|
|
||||||
self.clock_sel = CSRStorage()
|
|
||||||
self.pll_reset = CSRStorage(reset=1)
|
|
||||||
self.pll_locked = CSRStatus()
|
|
||||||
self.clock_domains.cd_rtio = ClockDomain()
|
|
||||||
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
|
|
||||||
|
|
||||||
rtio_external_clk = Signal()
|
|
||||||
# user_sma_clock = platform.request("user_sma_clock")
|
|
||||||
# platform.add_period_constraint(user_sma_clock.p, 8.0)
|
|
||||||
# self.specials += Instance("IBUFDS",
|
|
||||||
# i_I=user_sma_clock.p, i_IB=user_sma_clock.n,
|
|
||||||
# o_O=rtio_external_clk)
|
|
||||||
|
|
||||||
pll_locked = Signal()
|
|
||||||
rtio_clk = Signal()
|
|
||||||
rtiox4_clk = Signal()
|
|
||||||
self.specials += [
|
|
||||||
Instance("PLLE2_ADV",
|
|
||||||
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
|
||||||
|
|
||||||
p_REF_JITTER1=0.01,
|
|
||||||
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
|
||||||
i_CLKIN1=rtio_internal_clk, i_CLKIN2=rtio_external_clk,
|
|
||||||
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
|
||||||
i_CLKINSEL=~self.clock_sel.storage,
|
|
||||||
|
|
||||||
# VCO @ 1GHz when using 125MHz input
|
|
||||||
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
|
|
||||||
i_CLKFBIN=self.cd_rtio.clk,
|
|
||||||
i_RST=self.pll_reset.storage,
|
|
||||||
|
|
||||||
o_CLKFBOUT=rtio_clk,
|
|
||||||
|
|
||||||
p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
|
|
||||||
o_CLKOUT0=rtiox4_clk),
|
|
||||||
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
|
||||||
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
|
||||||
AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
|
|
||||||
MultiReg(pll_locked, self.pll_locked.status)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class Redpitaya(SoCCore):
|
|
||||||
def __init__(self, acpki=False):
|
|
||||||
self.acpki = acpki
|
|
||||||
self.rustc_cfg = dict()
|
|
||||||
|
|
||||||
platform = redpitaya.Platform()
|
|
||||||
platform.toolchain.bitstream_commands.extend([
|
|
||||||
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
|
||||||
])
|
|
||||||
ident = self.__class__.__name__
|
|
||||||
if self.acpki:
|
|
||||||
ident = "acpki_" + ident
|
|
||||||
SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident)
|
|
||||||
|
|
||||||
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
|
||||||
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
|
||||||
|
|
||||||
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
|
||||||
self.csr_devices.append("rtio_crg")
|
|
||||||
self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
|
|
||||||
self.platform.add_false_path_constraints(
|
|
||||||
self.ps7.cd_sys.clk,
|
|
||||||
self.rtio_crg.cd_rtio.clk)
|
|
||||||
|
|
||||||
def add_rtio(self, rtio_channels):
|
|
||||||
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
|
||||||
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels)
|
|
||||||
self.csr_devices.append("rtio_core")
|
|
||||||
|
|
||||||
if self.acpki:
|
|
||||||
self.rustc_cfg["ki_impl"] = "acp"
|
|
||||||
self.submodules.rtio = acpki.KernelInitiator(self.rtio_tsc,
|
|
||||||
bus=self.ps7.s_axi_acp,
|
|
||||||
user=self.ps7.s_axi_acp_user,
|
|
||||||
evento=self.ps7.event.o)
|
|
||||||
self.csr_devices.append("rtio")
|
|
||||||
else:
|
|
||||||
self.rustc_cfg["ki_impl"] = "csr"
|
|
||||||
self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc, now64=True)
|
|
||||||
self.csr_devices.append("rtio")
|
|
||||||
|
|
||||||
self.submodules.rtio_dma = dma.DMA(self.ps7.s_axi_hp0)
|
|
||||||
self.csr_devices.append("rtio_dma")
|
|
||||||
|
|
||||||
self.submodules.cri_con = rtio.CRIInterconnectShared(
|
|
||||||
[self.rtio.cri, self.rtio_dma.cri],
|
|
||||||
[self.rtio_core.cri])
|
|
||||||
self.csr_devices.append("cri_con")
|
|
||||||
|
|
||||||
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
|
||||||
self.csr_devices.append("rtio_moninj")
|
|
||||||
|
|
||||||
self.submodules.rtio_analyzer = analyzer.Analyzer(self.rtio_tsc, self.rtio_core.cri,
|
|
||||||
self.ps7.s_axi_hp1)
|
|
||||||
self.csr_devices.append("rtio_analyzer")
|
|
||||||
|
|
||||||
|
|
||||||
class Simple(Redpitaya):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
Redpitaya.__init__(self, **kwargs)
|
|
||||||
|
|
||||||
platform = self.platform
|
|
||||||
|
|
||||||
rtio_channels = []
|
|
||||||
for i in range(2):
|
|
||||||
phy = ttl_simple.Output(platform.request("user_led", i))
|
|
||||||
self.submodules += phy
|
|
||||||
rtio_channels.append(rtio.Channel.from_phy(phy))
|
|
||||||
|
|
||||||
self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels)
|
|
||||||
rtio_channels.append(rtio.LogChannel())
|
|
||||||
|
|
||||||
self.add_rtio(rtio_channels)
|
|
||||||
|
|
||||||
|
|
||||||
VARIANTS = {cls.__name__.lower(): cls for cls in [Simple]}
|
|
||||||
|
|
||||||
|
|
||||||
def write_csr_file(soc, filename):
|
|
||||||
with open(filename, "w") as f:
|
|
||||||
f.write(cpu_interface.get_csr_rust(
|
|
||||||
soc.get_csr_regions(), soc.get_csr_groups(), soc.get_constants()))
|
|
||||||
|
|
||||||
|
|
||||||
def write_rustc_cfg_file(soc, filename):
|
|
||||||
with open(filename, "w") as f:
|
|
||||||
for k, v in sorted(soc.rustc_cfg.items(), key=itemgetter(0)):
|
|
||||||
if v is None:
|
|
||||||
f.write("{}\n".format(k))
|
|
||||||
else:
|
|
||||||
f.write("{}=\"{}\"\n".format(k, v))
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="ARTIQ port to the Redpitaya Zynq development kit")
|
|
||||||
parser.add_argument("-r", default=None,
|
|
||||||
help="build Rust interface into the specified file")
|
|
||||||
parser.add_argument("-c", default=None,
|
|
||||||
help="build Rust compiler configuration into the specified file")
|
|
||||||
parser.add_argument("-g", default=None,
|
|
||||||
help="build gateware into the specified directory")
|
|
||||||
parser.add_argument("-V", "--variant", default="10",
|
|
||||||
help="variant: "
|
|
||||||
"[acpki_]simple "
|
|
||||||
"(default: %(default)s)")
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
variant = args.variant.lower()
|
|
||||||
acpki = variant.startswith("acpki_")
|
|
||||||
if acpki:
|
|
||||||
variant = variant[6:]
|
|
||||||
soc = Simple(acpki=acpki)
|
|
||||||
soc.finalize()
|
|
||||||
|
|
||||||
if args.r is not None:
|
|
||||||
write_csr_file(soc, args.r)
|
|
||||||
if args.c is not None:
|
|
||||||
write_rustc_cfg_file(soc, args.c)
|
|
||||||
if args.g is not None:
|
|
||||||
soc.build(build_dir=args.g)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -83,6 +83,7 @@ class ZC706(SoCCore):
|
|||||||
|
|
||||||
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
||||||
self.csr_devices.append("rtio_crg")
|
self.csr_devices.append("rtio_crg")
|
||||||
|
self.rustc_cfg["has_rtio_crg_clock_sel"] = None
|
||||||
self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
|
self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
|
||||||
self.platform.add_false_path_constraints(
|
self.platform.add_false_path_constraints(
|
||||||
self.ps7.cd_sys.clk,
|
self.ps7.cd_sys.clk,
|
||||||
|
@ -7,8 +7,6 @@ edition = "2018"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
|
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
|
||||||
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7", "libconfig/target_coraz7"]
|
|
||||||
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya", "libconfig/target_redpitaya"]
|
|
||||||
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc", "libconfig/target_kasli_soc"]
|
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc", "libconfig/target_kasli_soc"]
|
||||||
default = ["target_zc706"]
|
default = ["target_zc706"]
|
||||||
|
|
||||||
|
@ -94,13 +94,13 @@ async fn read_request(stream: &TcpStream, allow_close: bool) -> Result<Option<Re
|
|||||||
Ok(true) => {}
|
Ok(true) => {}
|
||||||
Ok(false) =>
|
Ok(false) =>
|
||||||
return Err(Error::UnexpectedPattern),
|
return Err(Error::UnexpectedPattern),
|
||||||
Err(smoltcp::Error::Illegal) => {
|
Err(smoltcp::Error::Finished) => {
|
||||||
if allow_close {
|
if allow_close {
|
||||||
info!("peer closed connection");
|
info!("peer closed connection");
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
} else {
|
} else {
|
||||||
error!("peer unexpectedly closed connection");
|
error!("peer unexpectedly closed connection");
|
||||||
return Err(smoltcp::Error::Illegal)?;
|
return Err(smoltcp::Error::Finished)?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) =>
|
Err(e) =>
|
||||||
@ -313,7 +313,9 @@ async fn load_kernel(buffer: &Vec<u8>, control: &Rc<RefCell<kernel::Control>>, s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_connection(stream: &TcpStream, control: Rc<RefCell<kernel::Control>>) -> Result<()> {
|
async fn handle_connection(stream: &mut TcpStream, control: Rc<RefCell<kernel::Control>>) -> Result<()> {
|
||||||
|
stream.set_ack_delay(None);
|
||||||
|
|
||||||
if !expect(stream, b"ARTIQ coredev\n").await? {
|
if !expect(stream, b"ARTIQ coredev\n").await? {
|
||||||
return Err(Error::UnexpectedPattern);
|
return Err(Error::UnexpectedPattern);
|
||||||
}
|
}
|
||||||
@ -407,7 +409,7 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
|
|||||||
let connection = Rc::new(Semaphore::new(1, 1));
|
let connection = Rc::new(Semaphore::new(1, 1));
|
||||||
let terminate = Rc::new(Semaphore::new(0, 1));
|
let terminate = Rc::new(Semaphore::new(0, 1));
|
||||||
loop {
|
loop {
|
||||||
let stream = TcpStream::accept(1381, 0x10_000, 0x10_000).await.unwrap();
|
let mut stream = TcpStream::accept(1381, 0x10_000, 0x10_000).await.unwrap();
|
||||||
|
|
||||||
if connection.try_wait().is_none() {
|
if connection.try_wait().is_none() {
|
||||||
// there is an existing connection
|
// there is an existing connection
|
||||||
@ -425,7 +427,7 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
|
|||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
select_biased! {
|
select_biased! {
|
||||||
_ = (async {
|
_ = (async {
|
||||||
let _ = handle_connection(&stream, control.clone())
|
let _ = handle_connection(&mut stream, control.clone())
|
||||||
.await
|
.await
|
||||||
.map_err(|e| warn!("connection terminated: {}", e));
|
.map_err(|e| warn!("connection terminated: {}", e));
|
||||||
if let Some(buffer) = &*idle_kernel {
|
if let Some(buffer) = &*idle_kernel {
|
||||||
|
@ -1,100 +1,67 @@
|
|||||||
#[cfg(feature = "target_zc706")]
|
use libboard_zynq;
|
||||||
mod i2c {
|
use crate::artiq_raise;
|
||||||
use libboard_zynq;
|
|
||||||
use crate::artiq_raise;
|
|
||||||
|
|
||||||
static mut I2C_BUS: Option<libboard_zynq::i2c::I2c> = None;
|
pub static mut I2C_BUS: Option<libboard_zynq::i2c::I2c> = None;
|
||||||
|
|
||||||
pub extern fn start(busno: i32) {
|
pub extern fn start(busno: i32) {
|
||||||
if busno > 0 {
|
if busno > 0 {
|
||||||
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
if (&mut I2C_BUS).as_mut().unwrap().start().is_err() {
|
|
||||||
artiq_raise!("I2CError", "I2C start failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
unsafe {
|
||||||
pub extern fn restart(busno: i32) {
|
if (&mut I2C_BUS).as_mut().unwrap().start().is_err() {
|
||||||
if busno > 0 {
|
artiq_raise!("I2CError", "I2C start failed");
|
||||||
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
|
||||||
}
|
}
|
||||||
unsafe {
|
|
||||||
if (&mut I2C_BUS).as_mut().unwrap().restart().is_err() {
|
|
||||||
artiq_raise!("I2CError", "I2C restart failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern fn stop(busno: i32) {
|
|
||||||
if busno > 0 {
|
|
||||||
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
if (&mut I2C_BUS).as_mut().unwrap().stop().is_err() {
|
|
||||||
artiq_raise!("I2CError", "I2C stop failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern fn write(busno: i32, data: i32) -> bool {
|
|
||||||
if busno > 0 {
|
|
||||||
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
match (&mut I2C_BUS).as_mut().unwrap().write(data as u8) {
|
|
||||||
Ok(r) => r,
|
|
||||||
Err(_) => artiq_raise!("I2CError", "I2C write failed"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern fn read(busno: i32, ack: bool) -> i32 {
|
|
||||||
if busno > 0 {
|
|
||||||
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
match (&mut I2C_BUS).as_mut().unwrap().read(ack) {
|
|
||||||
Ok(r) => r as i32,
|
|
||||||
Err(_) => artiq_raise!("I2CError", "I2C read failed"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init() {
|
|
||||||
let mut i2c = libboard_zynq::i2c::I2c::i2c0();
|
|
||||||
i2c.init().expect("I2C bus initialization failed");
|
|
||||||
unsafe { I2C_BUS = Some(i2c) };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "target_zc706"))]
|
pub extern fn restart(busno: i32) {
|
||||||
mod i2c {
|
if busno > 0 {
|
||||||
use crate::artiq_raise;
|
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
||||||
|
|
||||||
pub extern fn start(_busno: i32) {
|
|
||||||
artiq_raise!("I2CError", "No I2C bus");
|
|
||||||
}
|
}
|
||||||
|
unsafe {
|
||||||
pub extern fn restart(_busno: i32) {
|
if (&mut I2C_BUS).as_mut().unwrap().restart().is_err() {
|
||||||
artiq_raise!("I2CError", "No I2C bus");
|
artiq_raise!("I2CError", "I2C restart failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern fn stop(_busno: i32) {
|
|
||||||
artiq_raise!("I2CError", "No I2C bus");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern fn write(_busno: i32, _data: i32) -> bool {
|
|
||||||
artiq_raise!("I2CError", "No I2C bus");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern fn read(_busno: i32, _ack: bool) -> i32 {
|
|
||||||
artiq_raise!("I2CError", "No I2C bus");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init() {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use i2c::*;
|
pub extern fn stop(busno: i32) {
|
||||||
|
if busno > 0 {
|
||||||
|
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
if (&mut I2C_BUS).as_mut().unwrap().stop().is_err() {
|
||||||
|
artiq_raise!("I2CError", "I2C stop failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn write(busno: i32, data: i32) -> bool {
|
||||||
|
if busno > 0 {
|
||||||
|
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
match (&mut I2C_BUS).as_mut().unwrap().write(data as u8) {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(_) => artiq_raise!("I2CError", "I2C write failed"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern fn read(busno: i32, ack: bool) -> i32 {
|
||||||
|
if busno > 0 {
|
||||||
|
artiq_raise!("I2CError", "I2C bus could not be accessed");
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
match (&mut I2C_BUS).as_mut().unwrap().read(ack) {
|
||||||
|
Ok(r) => r as i32,
|
||||||
|
Err(_) => artiq_raise!("I2CError", "I2C read failed"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
let mut i2c = libboard_zynq::i2c::I2c::i2c0();
|
||||||
|
i2c.init().expect("I2C bus initialization failed");
|
||||||
|
unsafe { I2C_BUS = Some(i2c) };
|
||||||
|
}
|
||||||
|
@ -45,6 +45,8 @@ mod mgmt;
|
|||||||
mod analyzer;
|
mod analyzer;
|
||||||
mod irq;
|
mod irq;
|
||||||
mod i2c;
|
mod i2c;
|
||||||
|
#[cfg(has_si5324)]
|
||||||
|
mod si5324;
|
||||||
|
|
||||||
fn init_gateware() {
|
fn init_gateware() {
|
||||||
// Set up PS->PL clocks
|
// Set up PS->PL clocks
|
||||||
@ -108,6 +110,7 @@ fn init_rtio(timer: &mut GlobalTimer, cfg: &Config) {
|
|||||||
loop {
|
loop {
|
||||||
unsafe {
|
unsafe {
|
||||||
pl::csr::rtio_crg::pll_reset_write(1);
|
pl::csr::rtio_crg::pll_reset_write(1);
|
||||||
|
#[cfg(has_rtio_crg_clock_sel)]
|
||||||
pl::csr::rtio_crg::clock_sel_write(clock_sel);
|
pl::csr::rtio_crg::clock_sel_write(clock_sel);
|
||||||
pl::csr::rtio_crg::pll_reset_write(0);
|
pl::csr::rtio_crg::pll_reset_write(0);
|
||||||
}
|
}
|
||||||
@ -159,6 +162,20 @@ async fn report_async_rtio_errors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_si5324)]
|
||||||
|
// 125MHz output, from crystal, 7 Hz
|
||||||
|
const SI5324_SETTINGS: si5324::FrequencySettings
|
||||||
|
= si5324::FrequencySettings {
|
||||||
|
n1_hs : 10,
|
||||||
|
nc1_ls : 4,
|
||||||
|
n2_hs : 10,
|
||||||
|
n2_ls : 19972,
|
||||||
|
n31 : 4565,
|
||||||
|
n32 : 4565,
|
||||||
|
bwsel : 4,
|
||||||
|
crystal_ref: true
|
||||||
|
};
|
||||||
|
|
||||||
static mut LOG_BUFFER: [u8; 1<<17] = [0; 1<<17];
|
static mut LOG_BUFFER: [u8; 1<<17] = [0; 1<<17];
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -182,6 +199,9 @@ pub fn main_core0() {
|
|||||||
info!("detected gateware: {}", identifier_read(&mut [0; 64]));
|
info!("detected gateware: {}", identifier_read(&mut [0; 64]));
|
||||||
|
|
||||||
i2c::init();
|
i2c::init();
|
||||||
|
#[cfg(has_si5324)]
|
||||||
|
si5324::setup(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() },
|
||||||
|
&SI5324_SETTINGS, si5324::Input::Ckin2, timer).expect("cannot initialize Si5324");
|
||||||
|
|
||||||
let cfg = match Config::new() {
|
let cfg = match Config::new() {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
|
@ -121,7 +121,7 @@ async fn handle_connection(
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
let msg = read_i8(stream).await;
|
let msg = read_i8(stream).await;
|
||||||
if let Err(smoltcp::Error::Illegal) = msg {
|
if let Err(smoltcp::Error::Finished) = msg {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let msg: Request = FromPrimitive::from_i8(msg?).ok_or(Error::UnrecognizedPacket)?;
|
let msg: Request = FromPrimitive::from_i8(msg?).ok_or(Error::UnrecognizedPacket)?;
|
||||||
|
@ -184,7 +184,7 @@ pub fn start(timer: GlobalTimer) {
|
|||||||
info!("received connection");
|
info!("received connection");
|
||||||
let result = handle_connection(&stream, timer).await;
|
let result = handle_connection(&stream, timer).await;
|
||||||
match result {
|
match result {
|
||||||
Err(Error::NetworkError(smoltcp::Error::Illegal)) => info!("peer closed connection"),
|
Err(Error::NetworkError(smoltcp::Error::Finished)) => info!("peer closed connection"),
|
||||||
Err(error) => warn!("connection terminated: {}", error),
|
Err(error) => warn!("connection terminated: {}", error),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
273
src/runtime/src/si5324.rs
Normal file
273
src/runtime/src/si5324.rs
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
use core::result;
|
||||||
|
use log::info;
|
||||||
|
use libboard_zynq::{i2c::I2c, timer::GlobalTimer, time::Milliseconds};
|
||||||
|
use embedded_hal::blocking::delay::DelayUs;
|
||||||
|
#[cfg(not(si5324_soft_reset))]
|
||||||
|
use pl::csr;
|
||||||
|
|
||||||
|
type Result<T> = result::Result<T, &'static str>;
|
||||||
|
|
||||||
|
const ADDRESS: u8 = 0x68;
|
||||||
|
|
||||||
|
#[cfg(not(si5324_soft_reset))]
|
||||||
|
fn hard_reset(timer: GlobalTimer) {
|
||||||
|
unsafe { csr::si5324_rst_n::out_write(0); }
|
||||||
|
timer.delay_us(1_000);
|
||||||
|
unsafe { csr::si5324_rst_n::out_write(1); }
|
||||||
|
timer.delay_us(10_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: the logical parameters DO NOT MAP to physical values written
|
||||||
|
// into registers. They have to be mapped; see the datasheet.
|
||||||
|
// DSPLLsim reports the logical parameters in the design summary, not
|
||||||
|
// the physical register values.
|
||||||
|
pub struct FrequencySettings {
|
||||||
|
pub n1_hs: u8,
|
||||||
|
pub nc1_ls: u32,
|
||||||
|
pub n2_hs: u8,
|
||||||
|
pub n2_ls: u32,
|
||||||
|
pub n31: u32,
|
||||||
|
pub n32: u32,
|
||||||
|
pub bwsel: u8,
|
||||||
|
pub crystal_ref: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Input {
|
||||||
|
Ckin1,
|
||||||
|
Ckin2,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_frequency_settings(settings: &FrequencySettings) -> Result<FrequencySettings> {
|
||||||
|
if settings.nc1_ls != 0 && (settings.nc1_ls % 2) == 1 {
|
||||||
|
return Err("NC1_LS must be 0 or even")
|
||||||
|
}
|
||||||
|
if settings.nc1_ls > (1 << 20) {
|
||||||
|
return Err("NC1_LS is too high")
|
||||||
|
}
|
||||||
|
if (settings.n2_ls % 2) == 1 {
|
||||||
|
return Err("N2_LS must be even")
|
||||||
|
}
|
||||||
|
if settings.n2_ls > (1 << 20) {
|
||||||
|
return Err("N2_LS is too high")
|
||||||
|
}
|
||||||
|
if settings.n31 > (1 << 19) {
|
||||||
|
return Err("N31 is too high")
|
||||||
|
}
|
||||||
|
if settings.n32 > (1 << 19) {
|
||||||
|
return Err("N32 is too high")
|
||||||
|
}
|
||||||
|
let r = FrequencySettings {
|
||||||
|
n1_hs: match settings.n1_hs {
|
||||||
|
4 => 0b000,
|
||||||
|
5 => 0b001,
|
||||||
|
6 => 0b010,
|
||||||
|
7 => 0b011,
|
||||||
|
8 => 0b100,
|
||||||
|
9 => 0b101,
|
||||||
|
10 => 0b110,
|
||||||
|
11 => 0b111,
|
||||||
|
_ => return Err("N1_HS has an invalid value")
|
||||||
|
},
|
||||||
|
nc1_ls: settings.nc1_ls - 1,
|
||||||
|
n2_hs: match settings.n2_hs {
|
||||||
|
4 => 0b000,
|
||||||
|
5 => 0b001,
|
||||||
|
6 => 0b010,
|
||||||
|
7 => 0b011,
|
||||||
|
8 => 0b100,
|
||||||
|
9 => 0b101,
|
||||||
|
10 => 0b110,
|
||||||
|
11 => 0b111,
|
||||||
|
_ => return Err("N2_HS has an invalid value")
|
||||||
|
},
|
||||||
|
n2_ls: settings.n2_ls - 1,
|
||||||
|
n31: settings.n31 - 1,
|
||||||
|
n32: settings.n32 - 1,
|
||||||
|
bwsel: settings.bwsel,
|
||||||
|
crystal_ref: settings.crystal_ref
|
||||||
|
};
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
|
||||||
|
i2c.start().unwrap();
|
||||||
|
if !i2c.write(ADDRESS << 1).unwrap() {
|
||||||
|
return Err("Si5324 failed to ack write address")
|
||||||
|
}
|
||||||
|
if !i2c.write(reg).unwrap() {
|
||||||
|
return Err("Si5324 failed to ack register")
|
||||||
|
}
|
||||||
|
if !i2c.write(val).unwrap() {
|
||||||
|
return Err("Si5324 failed to ack value")
|
||||||
|
}
|
||||||
|
i2c.stop().unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_no_ack_value(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
|
||||||
|
i2c.start().unwrap();
|
||||||
|
if !i2c.write(ADDRESS << 1).unwrap() {
|
||||||
|
return Err("Si5324 failed to ack write address")
|
||||||
|
}
|
||||||
|
if !i2c.write(reg).unwrap() {
|
||||||
|
return Err("Si5324 failed to ack register")
|
||||||
|
}
|
||||||
|
i2c.write(val).unwrap();
|
||||||
|
i2c.stop().unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(i2c: &mut I2c, reg: u8) -> Result<u8> {
|
||||||
|
i2c.start().unwrap();
|
||||||
|
if !i2c.write(ADDRESS << 1).unwrap() {
|
||||||
|
return Err("Si5324 failed to ack write address")
|
||||||
|
}
|
||||||
|
if !i2c.write(reg).unwrap() {
|
||||||
|
return Err("Si5324 failed to ack register")
|
||||||
|
}
|
||||||
|
i2c.restart().unwrap();
|
||||||
|
if !i2c.write((ADDRESS << 1) | 1).unwrap() {
|
||||||
|
return Err("Si5324 failed to ack read address")
|
||||||
|
}
|
||||||
|
let val = i2c.read(false).unwrap();
|
||||||
|
i2c.stop().unwrap();
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rmw<F>(i2c: &mut I2c, reg: u8, f: F) -> Result<()> where
|
||||||
|
F: Fn(u8) -> u8 {
|
||||||
|
let value = read(i2c, reg)?;
|
||||||
|
write(i2c, reg, f(value))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ident(i2c: &mut I2c) -> Result<u16> {
|
||||||
|
Ok(((read(i2c, 134)? as u16) << 8) | (read(i2c, 135)? as u16))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(si5324_soft_reset)]
|
||||||
|
fn soft_reset(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> {
|
||||||
|
write_no_ack_value(i2c, 136, read(i2c, 136)? | 0x80)?;
|
||||||
|
timer.delay_us(10_000);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_xtal(i2c: &mut I2c) -> Result<bool> {
|
||||||
|
Ok((read(i2c, 129)? & 0x01) == 0) // LOSX_INT=0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_ckin(i2c: &mut I2c, input: Input) -> Result<bool> {
|
||||||
|
match input {
|
||||||
|
Input::Ckin1 => Ok((read(i2c, 129)? & 0x02) == 0), // LOS1_INT=0
|
||||||
|
Input::Ckin2 => Ok((read(i2c, 129)? & 0x04) == 0), // LOS2_INT=0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn locked(i2c: &mut I2c) -> Result<bool> {
|
||||||
|
Ok((read(i2c, 130)? & 0x01) == 0) // LOL_INT=0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn monitor_lock(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> {
|
||||||
|
info!("waiting for Si5324 lock...");
|
||||||
|
let timeout = timer.get_time() + Milliseconds(20_000);
|
||||||
|
while !locked(i2c)? {
|
||||||
|
// Yes, lock can be really slow.
|
||||||
|
if timer.get_time() > timeout {
|
||||||
|
return Err("Si5324 lock timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!(" ...locked");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> {
|
||||||
|
#[cfg(not(si5324_soft_reset))]
|
||||||
|
hard_reset(timer);
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
{
|
||||||
|
i2c.pca9548_select(0x70, 0)?;
|
||||||
|
i2c.pca9548_select(0x71, 1 << 3)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ident(i2c)? != 0x0182 {
|
||||||
|
return Err("Si5324 does not have expected product number");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(si5324_soft_reset)]
|
||||||
|
soft_reset(i2c, timer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bypass(i2c: &mut I2c, input: Input, timer: GlobalTimer) -> Result<()> {
|
||||||
|
let cksel_reg = match input {
|
||||||
|
Input::Ckin1 => 0b00,
|
||||||
|
Input::Ckin2 => 0b01,
|
||||||
|
};
|
||||||
|
init(i2c, timer)?;
|
||||||
|
rmw(i2c, 21, |v| v & 0xfe)?; // CKSEL_PIN=0
|
||||||
|
rmw(i2c, 3, |v| (v & 0x3f) | (cksel_reg << 6))?; // CKSEL_REG
|
||||||
|
rmw(i2c, 4, |v| (v & 0x3f) | (0b00 << 6))?; // AUTOSEL_REG=b00
|
||||||
|
rmw(i2c, 6, |v| (v & 0xc0) | 0b111111)?; // SFOUT2_REG=b111 SFOUT1_REG=b111
|
||||||
|
rmw(i2c, 0, |v| (v & 0xfd) | 0x02)?; // BYPASS_REG=1
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup(i2c: &mut I2c, settings: &FrequencySettings, input: Input, timer: GlobalTimer) -> Result<()> {
|
||||||
|
let s = map_frequency_settings(settings)?;
|
||||||
|
let cksel_reg = match input {
|
||||||
|
Input::Ckin1 => 0b00,
|
||||||
|
Input::Ckin2 => 0b01,
|
||||||
|
};
|
||||||
|
|
||||||
|
init(i2c, timer)?;
|
||||||
|
if settings.crystal_ref {
|
||||||
|
rmw(i2c, 0, |v| v | 0x40)?; // FREE_RUN=1
|
||||||
|
}
|
||||||
|
rmw(i2c, 2, |v| (v & 0x0f) | (s.bwsel << 4))?;
|
||||||
|
rmw(i2c, 21, |v| v & 0xfe)?; // CKSEL_PIN=0
|
||||||
|
rmw(i2c, 3, |v| (v & 0x2f) | (cksel_reg << 6) | 0x10)?; // CKSEL_REG, SQ_ICAL=1
|
||||||
|
rmw(i2c, 4, |v| (v & 0x3f) | (0b00 << 6))?; // AUTOSEL_REG=b00
|
||||||
|
rmw(i2c, 6, |v| (v & 0xc0) | 0b111111)?; // SFOUT2_REG=b111 SFOUT1_REG=b111
|
||||||
|
write(i2c, 25, (s.n1_hs << 5 ) as u8)?;
|
||||||
|
write(i2c, 31, (s.nc1_ls >> 16) as u8)?;
|
||||||
|
write(i2c, 32, (s.nc1_ls >> 8 ) as u8)?;
|
||||||
|
write(i2c, 33, (s.nc1_ls) as u8)?;
|
||||||
|
write(i2c, 34, (s.nc1_ls >> 16) as u8)?; // write to NC2_LS as well
|
||||||
|
write(i2c, 35, (s.nc1_ls >> 8 ) as u8)?;
|
||||||
|
write(i2c, 36, (s.nc1_ls) as u8)?;
|
||||||
|
write(i2c, 40, (s.n2_hs << 5 ) as u8 | (s.n2_ls >> 16) as u8)?;
|
||||||
|
write(i2c, 41, (s.n2_ls >> 8 ) as u8)?;
|
||||||
|
write(i2c, 42, (s.n2_ls) as u8)?;
|
||||||
|
write(i2c, 43, (s.n31 >> 16) as u8)?;
|
||||||
|
write(i2c, 44, (s.n31 >> 8) as u8)?;
|
||||||
|
write(i2c, 45, (s.n31) as u8)?;
|
||||||
|
write(i2c, 46, (s.n32 >> 16) as u8)?;
|
||||||
|
write(i2c, 47, (s.n32 >> 8) as u8)?;
|
||||||
|
write(i2c, 48, (s.n32) as u8)?;
|
||||||
|
rmw(i2c, 137, |v| v | 0x01)?; // FASTLOCK=1
|
||||||
|
rmw(i2c, 136, |v| v | 0x40)?; // ICAL=1
|
||||||
|
|
||||||
|
if !has_xtal(i2c)? {
|
||||||
|
return Err("Si5324 misses XA/XB signal");
|
||||||
|
}
|
||||||
|
if !has_ckin(i2c, input)? {
|
||||||
|
return Err("Si5324 misses clock input signal");
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor_lock(i2c, timer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn select_input(i2c: &mut I2c, input: Input, timer: GlobalTimer) -> Result<()> {
|
||||||
|
let cksel_reg = match input {
|
||||||
|
Input::Ckin1 => 0b00,
|
||||||
|
Input::Ckin2 => 0b01,
|
||||||
|
};
|
||||||
|
rmw(i2c, 3, |v| (v & 0x3f) | (cksel_reg << 6))?;
|
||||||
|
if !has_ckin(i2c, input)? {
|
||||||
|
return Err("Si5324 misses clock input signal");
|
||||||
|
}
|
||||||
|
monitor_lock(i2c, timer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -3,6 +3,6 @@ let
|
|||||||
in
|
in
|
||||||
pkgs.fetchgit {
|
pkgs.fetchgit {
|
||||||
url = "https://git.m-labs.hk/M-Labs/zynq-rs.git";
|
url = "https://git.m-labs.hk/M-Labs/zynq-rs.git";
|
||||||
rev = "2c161720fa12f8b7abecaf60f77b062b08ac9bc1";
|
rev = "57d8d8fbc7087863305721bcb8fdbdd13d65bd65";
|
||||||
sha256 = "0zpazkicqzps86r7lgqf09y9ary94mjvxw6gc41z9kjjyxar5fhr";
|
sha256 = "0gnbaxgingrxrxi2sjd592r1630ld4ckrz4r8ajx8zp7q3bb43jj";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user