Compare commits

...

8 Commits

14 changed files with 1390 additions and 44 deletions

View File

@ -27,8 +27,8 @@ PuzzleFW has the following features:
Further details about the firmware are in these documents:
- User manual, to be written
- Developer manual, including the build procedure, to be written
- [User manual](doc/user_manual.md)
- [Developer manual](doc/devel_manual.md), including build procedure
- [FPGA firmware description](doc/fpga_firmware.md)
## Supported boards

479
doc/devel_manual.md Normal file
View File

@ -0,0 +1,479 @@
---
gitea: none
include_toc: true
---
# Development manual
This document gives an overview of the internal structure of the PuzzleFW firmware package.
It also describes the process to build the FPGA firmware and the embedded software.
## FPGA design overview
The FPGA captures ADC samples and digital input signals.
ADC samples go into the analog acquisition chain.
The acquisition chain handles triggering and optional downsampling.
A configurable number of samples are collected following each trigger event.
Trigger events and collected samples are transferred to a buffer in DDR memory via the AXI slave interface of the Zynq processing system.
Digital signals go into a timetagger subsystem.
The timetagger detects edges on selected signals and assigns timestamps to such events.
Timestamped events are transferred to a buffer in DDR memory via the AXI slave interface.
All synchronous elements are clocked at 125 MHz, derived from the ADC sample clock.
![FPGA design schematic](fpga_design_schematic.png)
### Block design
A Vivado block design contains the Zynq processing system (ARM), AXI interconnect, and AXI-to-APB bridge.
This block design is instantiated in the top-level VHDL file.
![Block design](fpga_block_design.png)
### PS-to-PL interfaces
The following interfaces are used between the PS (ARM) and PL (FPGA):
- M\_AXI\_GP0 <br>
Used by embedded software to read and write registers in the FPGA via AXI and APB bus.
This interface is mapped to addresses 0x43000000 to 0x431fffff in the PS address map.
- S\_AXI\_HP0 <br>
Used by FPGA firmware to read and write to DDR memory.
- GPIO <br>
The PS controls a few specific digital signals in the FPGA via GPIO lines.
One of these lines is a global reset signal for the FPGA firmware.
- SPI0 <br>
Routed via EMIO through the FPGA to the SPI bus of the ADCs (only on 4-input boards).
- IRQ\_F2P <br>
Used by FPGA firmware to trigger interrupts in the PS.
- FCLK\_CLK0 <br>
Fixed 200 MHz clock generated by the PS.
On 4-input boards, the FPGA uses this clock as reference for IODELAY primitives.
On 2-input boards, this clock is not used.
### ADC input timing
The ADC transfers samples via a parallel source-synchronous interface.
A 125 MHz clock is sent along with the samples.
This is also the main clock source of the FPGA design.
On 2-input Red Pitaya boards, the ADC is hardwired to operate in _full rate CMOS mode_.
Each analog channel has 14 parallel data signals from ADC to FPGA.
These data signals transition on the falling clock edge, such that the FPGA can capture on the rising clock edge.
The FPGA buffers the 125 MHz ADC clock through a PLL.
Data signals are captured in the FPGA in IOB flip-flops, clocked on the rising edge of the buffered 125 MHz clock.
It turns out that a phase shift of 90 degrees in the PLL provides near-optimal timing for capturing the data signals.
This follows from synthesizer timing reports and has been confirmed experimentally by testing different PLL phase shift settings.
On 4-input Red Pitaya boards, only 7 parallel data signals per analog channel are connected from the ADCs to the FPGA.
The ADCs must be programmed (via SPI) to operate in _double data rate CMOS mode_.
In this mode, the ADC still outputs a 125 MHz clock, but data lines transition on both edges of the clock.
The data signals are routed through IDELAY components in the FPGA before being captured in IDDR registers.
The IDDR are clocked on the 125 MHz clock from the ADC that produces the samples (without PLL).
The IDELAY components use a fixed delay, tuned to 2.34 ns to optimize data capture timing.
Timing reports indicate that this provides sufficient margin.
This has been confirmed experimentally by phase-shifting the ADC output clock.
The main FPGA design runs on a 125 MHz clock, derived by a PLL from the ADC that samples channels 1 and 2.
Transferring samples from channels 3 and 4 to the main clock is slightly tricky because the two ADC clocks may be skewed with respect to each other.
A few mysterious timing constraints were added to deal with this.
## Embedded software overview
The purpose of the embedded software is to make the system remote accessible via the network.
The software collects data from the FPGA and transmits it via TCP.
Similarly, the software accepts remote control commands via TCP and executes these by accessing registers in the FPGA.
### Operating system
The embedded software runs within an embedded Linux system on the Red Pitaya.
The core operating system is based on [Buildroot](https://buildroot.org/), a framework that builds an embedded Linux system from scratch.
Buildroot automatically downloads and builds many additional open source packages that are needed to construct the embedded system.
Among these packages is a cross-compilation toolchain.
The kernel for the embedded system is built from the [Xilinx distribution of the Linux kernel](https://github.com/Xilinx/linux-xlnx).
It is necessary to use the Xilinx variant of Linux.
The vanilla Linux kernel can run on the Red Pitaya, but the Xilinx kernel provides important features that are missing from the vanilla kernel, such as programming the FPGA.
The shell and system utilities of the embedded system are based on Busybox.
Dropbear is installed as SSH server, but disabled by default.
The set of packages to be installed in the embedded system, along with their compile-time settings, are specified in the Buildroot configuration.
Further tweaking of the embedded system is done via a _filesystem overlay_: a set of files that are injected into the embedded root filesystem as a final step.
The overlay mechanism is used to install boot scripts and configuration files.
It is also used to install custom user space software.
### Boot flow
[U-Boot](https://source.denx.de/u-boot/u-boot) is used as boot loader and as _secondary program loader_ (SPL).
Building U-Boot requires a proper device tree for the board.
Building the U-Boot SPL image also requires the file `ps7_init_gpl.c`.
The contents of this file depend on the configuration of the Zynq programming system which is specified in the Vivado block design.
To generate this file, the FPGA design must be _exported_ from Vivado in the form of an XSA file.
The XSA file is actually a ZIP archive which contains `ps7_init_gpl.c` and the corresponding header file.
The U-Boot build script (`12_build_uboot.sh`) copies these files to the correct location in the U-Boot source tree.
The boot process of the Red Pitaya is as follows:
- The Zynq PS boots from ROM.
The ROM program reads `boot.bin` from the SD card and runs it.
- `boot.bin` is the U-Boot SPL image.
It initializes many subsystems in the Zynq PS, including the DDR memory controller.
It then reads `u-boot.img` from the SD card and runs it.
Note that we don't use a Xilinx FSBL at all.
Many Zynq tutorials explain how to build `boot.bin` using Xilinx tools.
That requires a non-free FSBL image which must be built in a Vitis project.
The PuzzleFW package avoids that whole mess by using U-Boot SPL instead.
- `u-boot.img` is the main U-Boot program image.
It reads and executes `boot.scr`, a script which describes the Linux boot process.
The script instructs U-Boot to read the Linux kernel `uImage`,
the device tree `devicetree.dtb` and the root filesystem image `rootfs.cpio.uboot`
from the SD card.
It then runs the Linux kernel.
- `uImage` is the Linux kernel image.
The kernel initializes drivers and subsystems.
The root filesystem is unpacked and mounted as a RAM filesystem.
The filesystem is writeable, but any changes remain in RAM and will be forgotten on the next reboot.
- A set of boot scripts are invoked to initialize the embedded system and start services.
Most of these scripts are prepared by Buildroot, but some scripts have been tweaked or specially created for PuzzleFW.
These scripts take care of the following:
- Read the MAC address from the EEPROM on the Red Pitaya board, and assign it to the Ethernet interface.
- Set a unique hostname `rp-XXXXXX` based on the MAC address.
- Obtain an IPv4 address via DHCP or a preconfigured static address.
This is controlled by a file in the configuration partition of the SD card.
- Start an SSH server, if enabled. By default, this is disabled.
- Read a BIT file from the SD card and program the FPGA.
Information in the EEPROM is used to determine which FPGA image must be used.
- Configure ADCs on the Red Pitaya board via SPI or GPIO.
- Load the Linux kernel driver to access the FPGA firmware.
- Run a user space program that accepts remote control commands via TCP.
### Linux kernel driver
A custom Linux kernel module is used to access the FPGA firmware.
This module is called `puzzlefw.ko`.
The driver is based on the Linux UIO framework.
The kernel module itself has minimal functionality.
Its only functions are:
- mapping the register address range of the FPGA to user space via mmap
- mapping the DMA buffer in DDR RAM to user space via mmap
- handling FPGA interrupts and notifying user space via UIO
All non-trivial interactions with the FPGA are done in user space.
This includes managing the data flow via DMA.
### User space software
The FPGA firmware is controlled by a user space program.
This program accepts remote control commands via TCP.
Commands are handled by reading and writing registers in the FPGA.
The program also collects data from the FPGA via DMA, and transmits these data through the network via TCP.
The program is written in C++.
It uses Boost Asio, an asynchronous I/O framework.
### Configuration partition
While the embedded software runs, the root filesystem is located in RAM.
The filesystem is writable, but any changes will be lost on the next boot.
In order to store persistent settings, the SD card has a separate configuration partition.
This is `/dev/mmcblk0p2`, formatted as Ext4.
The following files are stored there:
- `network.conf`: IP address configuraton (DHCP or static IP address)
- `calibration.conf`: analog calibration coefficients
- `start_ssh.conf`: enables or disables starting the SSH server
- SSH host key
The configuration partition is temporarily mounted read-only during boot, to read the configuration files.
Otherwise, the partition is only accessed when the configuration is modified.
In that case, the partition is temporarily mounted to write the updated files, then unmounted again.
As a result, writes to the SD card occur only when the user applies a change in the persistent configuration of the system.
This avoids unnecessary wear of the SD card.
## Build procedure
A Linux PC (x86-64) is required to build the system.
Development was done with Debian 12 (bookworm).
Other Linux distributions will probably also work.
The build process consists of two main steps.
These steps must be done in the following order:
1. Build the FPGA firmware for the Zynq PL.
2. Build the embedded software for the Zynq PS.
## Building FPGA firmware
Building the FPGA firmware requires Vivado release 2020.2.
Later releases will probably work, but may require adjustments.
There are two ways to build the firmware: as a Vivado project, or in Vivado non-project mode.
In most cases, non-project mode will be easier.
### Preparing the build environment
**Install Vivado** <br>
Download and install Vivado 2020.2.
The build scripts assume that Vivado is installed in `/opt/Xilinx/Vivado/2020.2`.
If a different location is used, it must be configured in the script environment file.
**Configure paths** <br>
If necessary, edit the file `redpitaya-puzzlefw/fpga/script_env` and make sure that `VIVADO_DIR` points to the directory where Vivado is installed.
**Install board files** <br>
When running Vivado in project mode, it requires board definition files
for the Red Pitaya.
These files are available from the original Red Pitaya FPGA repository.
Use the following steps to download and install these files.
- Go to directory `redpitaya-puzzlefw/fpga`
- Run `./01_get_redpitaya.sh`
- Copy the complete folder `redpitaya-puzzlefw/fpga/RedPitaya-FPGA/brd/redpitaya`
to `/opt/Xilinx/Vivado/2020.2/data/boards/board_files`
### Building FPGA firmware in non-project mode
There are two top-level designs, each targeting a specific Red Pitaya board type.
These designs are built in separate design runs:
- `puzzlefw_top` for the normal (2-input) Red Pitaya
- `puzzlefw_top_4ch` for the 4-input Red Pitaya
The following steps invoke Vivado in non-project mode to handle synthesis, implementation and bitfile generation of each top-level design.
- Go to directory `redpitaya-puzzlefw/fpga`
- Run `./11_build_bitfile.sh`
- Run `./12_build_bitfile_4ch.sh`
It is normal for the build process to display a large number of messages and warnings.
The build process produces the following output files:
- `puzzlefw_top.bit.bin` <br>
This file is required to program the FPGA.
- `redpitaya_puzzlefw.xsa` <br>
This file contains a description of the system configuration.
It is necessary to build U-boot.
- Similar files for the 4-input design.
The build process also creates various logs and report files in directory `vivado/output` (or `output_4ch`).
It is recommended to review the contents of `vivado/output/post_route_timing.rpt` to make sure that it does not report any timing violations and contains the line `All user specified timing constraints are met`.
### Building FPGA firmware in project mode
The repository contains a Vivado project file to build the design for the normal (2-input) Red Pitaya.
There is currently no project file for the 4-input board.
The following steps may be used to build the design in Vivado in project mode:
- Start Vivado, typically by running something like <br>
`source /opt/Xilinx/Vivado/2020.1/settings64.sh ; vivado`
- Open the project file `redpitaya-puzzlefw/fpga/vivado/redpitaya_puzzlefw.xpr`.
- In the *Flow Navigator* panel on the left, click on "Run Synthesis", then click "Ok".
It may appear that very little is happening, but synthesis should be running in the background.
The status is displayed in the *Design Runs* panel at the bottom of the screen.
- When synthesis completes successfully, choose "Run Implementation" and click "Ok".
- When implementation completes successfully, choose "Generate Bitstream" and click "Ok".
- When bitstream generation completes successfully, choose "View Reports".
- In the *Project Summary* panel, check that timing is ok (Number of Falling Endpoints should be 0).
- In the main menu bar, click *File*, *Export*, *Export Hardware*.
Select "Pre-synthesis".
Change XSA file name and export folder to write the XSA file to
`redpitaya-puzzlefw/fpga/redpitaya_puzzlefw.xsa`.
Then click "Finish".
The build process produces a BIT file `puzzlefw_top.bit` containing the FPGA design.
The Zynq software needs this file in a different format (`.bit.bin`) which can not be created by the Vivado IDE.
Use the following steps to convert the BIT file:
- Go to directory `redpitaya-puzzlefw/fpga`
- Run `./make_binfile.sh vivado/redpitaya_puzzlefw.runs/impl_1/puzzlefw_top.bit`
### Editing the block design
Most source files for the FPGA firmware can be edited with any text editor.
The VHDL source files are in directory `redpitaya-puzzlefw/fpga/rtl`.
Constraint files are in `redpitaya-puzzlefw/fpga/constraints`.
The only exception is the block design that links the Zynq processing system to the FPGA logic.
The block design is stored as `redpitaya-puzzlefw/fpga/vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/puzzlefw.bd`.
This file can only be edited through Vivado, as follows:
- Start Vivado as described above.
- Open the project file `redpitaya-puzzlefw/fpga/vivado/redpitaya_puzzlefw.xpr`.
- In the *Flow Navigator* panel on the left, click on "Open Block Design".
- Make changes as needed.
- In the main menu bar, click *File*, *Save Block Design*.
Both top-level designs (2-input and 4-input boards) use the same block design file.
This is a tricky situation because the block design file targets a specific FPGA part (e.g. `xc7z010clg400-1`), but the two boards have different FPGA parts.
When using the non-project build flow, we find that this just seems to work without issues.
During the build flow, Vivado quietly modifies the block design file to match the target part of the design run.
### Adding VHDL files to the project
When VHDL files are added to the project, both the Vivado project and the non-project build script must be updated.
To update the Vivado project:
- Open the project file `redpitaya-puzzlefw/fpga/vivado/redpitaya_puzzlefw.xpr`.
- In the *Flow Navigator* panel on the left, click "Add Sources".
- Add VHDL files directly from the directory `redpitaya-puzzlefw/fpga/rtl`.
Do not select "Copy sources into project".
- Vivado may get a confused because, by default, it does not support VHDL-2008.
To fix this, in the *Sources* panel, click "Libraries" below the hierachy tree.
Right-click each new VHDL file, choose "Set File Type" and change the file type to "VHDL 2008".
Vivado stores all project settings in the XPR file.
Changes to that file must be tracked in the Git repository.
To update the non-project build script:
- Open `redpitaya-puzzlefw/fpga/vivado/nonproject.tcl` in a text editor.
- Add `read_vhdl` statements to load the new VHDL files.
## Building embedded software
### Preparing the build environment
Install the following Debian packages (or equivalent packages on other Linux distributions):
<br>
`build-essential`,
`bc`,
`bzip2`,
`cpio`,
`dosfstools`,
`file`,
`git`,
`libncurses-dev`,
`mtools`,
`patch`,
`perl`,
`rsync`,
`unzip`,
`wget`.
### Downloading software
Use the following steps to download required software packages:
- Go to directory `redpitaya-puzzlefw/sw`
- Run `./01_get_buildroot.sh` to download [Buildroot](https://buildroot.org).
- Run `./02_get_uboot.sh` to download [U-Boot](https://source.denx.de/u-boot/u-boot).
- Run `./03_get_kernel.sh` to download the [Xilinx distribution of the Linux kernel](https://github.com/Xilinx/linux-xlnx).
### Building embedded software
Use the following steps to build the embedded software:
- Go to directory `redpitaya-puzzlefw/sw`
- Run `./11_build_buildroot.sh` to configure and build Buildroot.
<br>
One of the outcomes of this step is a cross-compilation toolchain for the ARM architecture.
Other build steps need this toolchain, therefore this must be the first step of the build flow.
- Run `./12_build_uboot.sh` to configure and build U-Boot.
<br>
This step requires the file `redpitaya-puzzlefw/fpga/redpitaya_puzzlefw.xsa` from the FPGA build flow.
- Run `./13_build_kernel.sh` to configure and build the Linux kernel.
- Run `./14_build_devicetree.sh` to build the device tree.
- Run `./15_build_driver.sh` to build the Linux kernel module that provides access to the FPGA firmware.
- Run `./16_build_userspace.sh` to build user space applications that will run on the Red Pitaya.
- Run `./21_rebuild_rootfs.sh` to re-build the embedded root filesystem, including the kernel driver and user space tools that were built during previous steps.
- Run `./22_prepare_sdcard.sh` to collect the files that must be installed on the SD card for the Red Pitaya.
- Run `./23_sdcard_image.sh` to build an image file which can be written to the SD card.
### Changing the Buildroot configuration
The Buildroot configuration for this project is stored in the folder `config`.
To change the configuration, start by applying the existing settings, then run the Buildroot configuration tool, then copy the new settings to the `config` folder.
Use the following steps:
- Copy `sw/config/buildroot_puzzlefw_defconfig` to `sw/buildroot-2023.02.08/.config`
- Go to `sw/buildroot-2023.02.8`
- Run `make olddefconfig`
- Run `make nconfig`
- Use the menu to change the configuration as needed.
- Run `make savedefconfig`
- Copy `sw/buildroot-2023.02.08/defconfig` to `sw/config/buildroot_puzzlefw_defconfig`
After changing the Buildroot configuration, rerun step `11_build_buildroot.sh`.
### Changing the U-Boot configuration
The U-Boot configuration for this project is stored in the folder `config`.
To change the configuration, start by applying the existing settings, then run the U-boot configuration tool, then copy the new settings to the `config` folder.
Use the following steps:
- Copy `sw/config/uboot_redpitaya_puzzlefw_defconfig` to `sw/u-boot/configs/redpitaya_puzzlefw_defconfig`
- Go to `sw/u-boot`
- Run `make redpitaya_puzzlefw_defconfig`
- Run `make nconfig`
- Use the menu to change the configuration as needed.
- Run `make savedefconfig`
- Copy `sw/u-boot/defconfig` to `sw/config/uboot_redpitaya_puzzlefw_defconfig`
After changing the Buildroot configuration, rerun step `12_build_uboot.sh`.
### Changing the Linux kernel configuration
The Linux kernel configuration for this project is stored in the folder `config`.
To change the configuration, start by applying the existing settings, then run the kernel configuration tool, then copy the new settings to the `config` folder.
Use the following steps:
- Copy `sw/config/linux_redpitaya_puzzlefw_defconfig` to `sw/linux-xlnx/.config`
- Go to `sw/linux-xlnx`
- Run `make ARCH=arm olddefconfig`
- Run `make ARCH=arm nconfig`
- Use the menu to change the configuration as needed.
- Run `make ARCH=arm savedefconfig`
- Copy `sw/linux-xlnx/defconfig` to `sw/config/linux_redpitaya_puzzlefw_defconfig`
After changing the Buildroot configuration, rerun step `13_build_kernel.sh`.
### Preparing the SD card
This section explains how to set up the SD card manually.
It is not normally necessary to do this.
An easier way to set up the SD card is by building an image file and writing it to the card.
The SD card contains two partitions:
- `/dev/mmcblk0p1` is a 256 MB partition with FAT filesystem
- `/dev/mmcblk0p2` is a 256 MB partition with an EXT4 filesystem
The FAT partition contains the following files:
| File | Description |
|----------------------------|-------------|
| `boot.bin` | first stage boot loader for the Zynq (built by U-Boot) |
| `u-boot.img` | main boot loader program (U-Boot) |
| `boot.scr` | boot script for U-Boot |
| `devicetree.dtb` | device tree for the Linux kernel |
| `uImage` | Linux kernel image |
| `rootfs.cpio.uboot` | root filesystem image |
| `puzzlefw_top.bit.bin` | FPGA firmware image for 2-input board |
| `puzzlefw_top_4ch.bit.bin` | FPGA firmware image for 4-input board |
The EXT4 partition can be left empty initially.
Configuration files will be written to this partition by the embedded system.
The following commands may be used to format the two partitions:
mkdosfs -F 16 /dev/mmcblk0p1
mke2fs -t ext4 -b 4096 /dev/mmcblk0p2

BIN
doc/fpga_block_design.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -0,0 +1,506 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="297mm"
height="210mm"
viewBox="0 0 297 210"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="fpga_design_overview.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="true"
inkscape:zoom="1.2938725"
inkscape:cx="71.490816"
inkscape:cy="177.37451"
inkscape:window-width="1514"
inkscape:window-height="1247"
inkscape:window-x="576"
inkscape:window-y="53"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
inkscape:lockguides="false">
<inkscape:grid
type="xygrid"
id="grid29"
originx="0"
originy="0" />
</sodipodi:namedview>
<defs
id="defs2">
<marker
style="overflow:visible"
id="marker29490"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Dot"
markerWidth="4"
markerHeight="4"
viewBox="0 0 5.4 5.4"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
id="path29488"
sodipodi:nodetypes="sssss" />
</marker>
<marker
style="overflow:visible"
id="marker29344"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Dot"
markerWidth="4"
markerHeight="4"
viewBox="0 0 5.4 5.4"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
id="path29342"
sodipodi:nodetypes="sssss" />
</marker>
<marker
style="overflow:visible"
id="marker29218"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Dot"
markerWidth="4"
markerHeight="4"
viewBox="0 0 5.4 5.4"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
id="path29216"
sodipodi:nodetypes="sssss" />
</marker>
<marker
style="overflow:visible"
id="marker9466"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Dot"
markerWidth="4"
markerHeight="4"
viewBox="0 0 5.4 5.4"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.45)"
style="fill:context-fill;fill-rule:evenodd;stroke:context-stroke;stroke-width:2"
d="M 5,0 C 5,2.76 2.76,5 0,5 -2.76,5 -5,2.76 -5,0 c 0,-2.76 2.3,-5 5,-5 2.76,0 5,2.24 5,5 z"
id="path9464"
sodipodi:nodetypes="sssss" />
</marker>
<marker
style="overflow:visible"
id="TriangleStart"
refX="0"
refY="0"
orient="auto-start-reverse"
inkscape:stockid="TriangleStart"
markerWidth="4.3239999"
markerHeight="4.9988437"
viewBox="0 0 5.3244081 6.1553851"
inkscape:isstock="true"
inkscape:collect="always"
preserveAspectRatio="xMidYMid">
<path
transform="scale(0.5)"
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path135" />
</marker>
<rect
x="50"
y="160"
width="110"
height="50"
id="rect8262" />
<rect
x="50"
y="160"
width="110"
height="50"
id="rect9048" />
<rect
x="50"
y="160"
width="110"
height="50"
id="rect10560" />
<rect
x="50"
y="160"
width="110"
height="50"
id="rect10566" />
<rect
x="50"
y="160"
width="105.41406"
height="67.484375"
id="rect10624" />
<rect
x="50"
y="160"
width="150.125"
height="27.484377"
id="rect12086" />
<rect
x="50"
y="160"
width="150.125"
height="27.484377"
id="rect12123" />
<rect
x="50"
y="160"
width="150.125"
height="27.484377"
id="rect12855" />
<rect
x="50"
y="160"
width="150.125"
height="27.484377"
id="rect14313" />
<rect
x="50"
y="160"
width="150.125"
height="27.484377"
id="rect14321" />
<rect
x="50"
y="160"
width="150.125"
height="27.484377"
id="rect16505" />
<rect
x="50"
y="160"
width="150.125"
height="27.484377"
id="rect17237" />
<rect
x="50"
y="160"
width="150.125"
height="27.484377"
id="rect20229" />
<rect
x="50"
y="160"
width="105.41406"
height="67.484375"
id="rect29672" />
<rect
x="50"
y="160"
width="80.114585"
height="23.184275"
id="rect29708" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:none;stroke:#000000;stroke-width:0.3;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none"
id="rect133"
width="190.6516"
height="84.732727"
x="26.458334"
y="7.9375" />
<rect
style="fill:#fff799;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect2424"
width="31.750004"
height="52.916664"
x="179.91667"
y="13.229167" />
<rect
style="fill:#b2ffb2;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect6690"
width="31.75"
height="10.583332"
x="31.75"
y="13.229167" />
<rect
style="fill:#ccdfff;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none"
id="rect6694"
width="42.068748"
height="15.874999"
x="74.270424"
y="13.594255" />
<rect
style="fill:#ffcdb2;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect6698"
width="42.333328"
height="10.583332"
x="127"
y="13.229167" />
<rect
style="fill:#cbdcff;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect9828"
width="42.068752"
height="15.875004"
x="74.083336"
y="50.270832" />
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,169.33334,-27.245888)"
id="text10622"
style="font-size:14.6667px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect10624);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="172.97659"
id="tspan32207"><tspan
style="fill:#000000;fill-opacity:1;stroke:none"
id="tspan32205">block design
</tspan></tspan><tspan
x="50"
y="191.30997"
id="tspan32211"><tspan
style="fill:#000000;fill-opacity:1;stroke:none"
id="tspan32209">(PS)</tspan></tspan></text>
<rect
style="fill:#ffcdb2;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect11354"
width="42.068748"
height="10.318751"
x="127"
y="34.395832" />
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,116.20478,-26.880356)"
id="text12084"
style="font-size:13.3333px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect12086);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="171.79685"
id="tspan32215"><tspan
style="font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono';fill:#000000;fill-opacity:1;stroke:none"
id="tspan32213">dma_write_channel</tspan></tspan></text>
<rect
style="fill:#ffcdb2;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect12117"
width="42.333328"
height="10.583332"
x="127"
y="55.5625" />
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,116.20478,15.452982)"
id="text12121"
style="font-size:13.3333px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect12123);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="171.79685"
id="tspan32219"><tspan
style="font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono';fill:#000000;fill-opacity:1;stroke:none"
id="tspan32217">dma_write_channel</tspan></tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,116.20479,-5.732634)"
id="text12853"
style="font-size:13.3333px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect12855);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="171.79685"
id="tspan32223"><tspan
style="font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono';fill:#000000;fill-opacity:1;stroke:none"
id="tspan32221">dma_axi_master</tspan></tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,21.166668,-26.933748)"
id="text14311"
style="font-size:13.3333px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect14313);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="171.79685"
id="tspan32227"><tspan
style="font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono';fill:#000000;fill-opacity:1;stroke:none"
id="tspan32225">adc_capture</tspan></tspan></text>
<rect
style="fill:#b2ffb2;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect14315"
width="31.75"
height="10.583332"
x="31.75"
y="50.270832" />
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,21.166666,10.10792)"
id="text14319"
style="font-size:13.3333px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect14321);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="171.79685"
id="tspan32231"><tspan
style="font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono';fill:#000000;fill-opacity:1;stroke:none"
id="tspan32229">deglitch</tspan></tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,63.499996,10.107924)"
id="text16503"
style="font-size:13.3333px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect16505);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="171.79685"
id="tspan32235"><tspan
style="font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono';fill:#000000;fill-opacity:1;stroke:none"
id="tspan32233">timetagger</tspan></tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,63.687086,-26.568659)"
id="text17235"
style="font-size:13.3333px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect17237);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="171.79685"
id="tspan32239"><tspan
style="font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono';fill:#000000;fill-opacity:1;stroke:none"
id="tspan32237">acquisition_chain</tspan></tspan></text>
<rect
style="fill:#ccffff;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect20223"
width="31.74999"
height="10.583332"
x="179.91667"
y="76.729164" />
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,168.70976,36.600693)"
id="text20227"
style="font-size:13.3333px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect20229);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="171.79685"
id="tspan32243"><tspan
style="font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono';fill:#000000;fill-opacity:1;stroke:none"
id="tspan32241">registers</tspan></tspan></text>
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
d="m 63.5,18.520833 7.9375,0"
id="path21149"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
d="m 63.5,55.5625 7.937501,0"
id="path22406"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
d="m 116.41667,18.520833 h 7.9375"
id="path22424"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
d="m 116.41667,60.854167 h 7.9375"
id="path22430"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
d="m 169.33333,39.6875 h 7.9375"
id="path22436"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
d="M 140.22917,55.5625 V 47.625"
id="path22442"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
d="M 140.22917,23.8125 V 31.75"
id="path22448"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
d="M 58.208333,50.270833 V 39.6875 H 79.375 l 0,-7.9375"
id="path22557"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart);marker-end:url(#TriangleStart)"
d="m 190.5,74.083333 0,-5.291666"
id="path24899"
sodipodi:nodetypes="cc" />
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker29218);stroke-dasharray:none"
d="M 31.75,52.916666 H 21.166666"
id="path25030" />
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker9466)"
d="M 31.75,54.239583 H 21.166666"
id="path26680" />
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker29344)"
d="M 31.750001,55.5625 H 21.166667"
id="path26650" />
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker29490)"
d="M 31.75,56.885417 H 21.166666"
id="path26658" />
<path
style="fill:#eabfff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-dasharray:none"
d="M 13.229167,18.520833 15.875,15.875 h 5.291666 v 5.291666 H 15.875 Z"
id="path27546" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-dasharray:none"
d="M 21.166666,17.197916 H 31.75"
id="path28300" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-dasharray:none"
d="M 21.166666,19.84375 H 31.75"
id="path28302" />
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,-0.20448484,-32.592506)"
id="text29670"
style="font-size:14.6667px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect29672);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="172.97659"
id="tspan32247"><tspan
style="fill:#000000;fill-opacity:1;stroke:none"
id="tspan32245">ADC</tspan></tspan></text>
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,-7.9374998,4.5041105)"
id="text29706"
style="font-size:14.6667px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect29708);display:inline;fill:none;fill-opacity:0.75;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><tspan
x="50"
y="172.97659"
id="tspan32251"><tspan
style="fill:#000000;fill-opacity:1;stroke:none"
id="tspan32249">digital I/O</tspan></tspan></text>
<rect
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect32120"
width="216.95833"
height="89.958336"
x="2.6458333"
y="5.2916665" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -40,6 +40,7 @@ By manipulating these GPIO signals, the Linux system can reset the FPGA firmware
| 0 | 54 | out (to FPGA) | Global firmware reset |
| 1 | 55 | in (from FPGA) | Reset status report |
| 2 | 56 | out (to FPGA) | ADC clock duty cycle stabilizer |
| 3 | 57 | out (to FPGA) | ADC sample derandomization |
### GPIO 0: Global firmware reset
@ -82,6 +83,19 @@ This GPIO signal is asynchronously routed through the FPGA to the ADC.
Changing the state of this signal may shift the phase of the ADC data clock.
It must therefore only be changed while the FPGA firmware is in reset.
### GPIO 3: ADC sample derandomization
GPIO 3 controls a sample derandomization function in the FPGA.
- GPIO 3 is an output from the PS to the FPGA.
- Driving this signal as `0` disables sample derandomization.
- Driving this signal as `1` enables sample derandomization.
This signal is only supported on Red Pitaya boards with 4 input channels.
On these boards, the ADC can optionally be configured to randomize its output
by XOR-ing the least significant bit into all other bits.
The derandomization function in the FPGA recovers the original sample values.
# SPI signals

View File

@ -1,4 +1,220 @@
# Remote access
---
gitea: none
include_toc: true
---
# PuzzleFW User Manual
PuzzleFW is an alternative, unofficial firmware package for the Red Pitaya.
It consists of FPGA firmware and embedded software.
The embedded software runs under Linux on the ARM processor in the Zynq.
The PuzzleFW firmware does not provide a built-in user interface.
It does not have a web interface, nor any other kind of graphical interface.
The only way to control the system is via the network, using a remote command protocol.
In typical cases, you would design custom PC software that connects to the Red Pitaya via the network to send commands and receive data.
Such software can then present the measured data on the PC in any way it wants, possibly via a custom graphical user interface.
## Analog input operation
The analog input subsystem captures ADC samples.
Depending on various configuration settings, the ADC samples are processed and ultimately transferred via the network.
### Analog input signals
A standard Red Pitaya STEMlab 125-14 has 2 analog input channels,
sampled by one dual-input ADC.
The analog inputs are labeled as channel 1 and channel 2.
A Red Pitaya STEMlab 125-14 4-input has 4 analog input channels,
sampled by a pair of dual-input ADCs.
The analog inputs are labeled as channel 1 to channel 4.
On a 4-input system, the firmware can operate either in 2-channel mode or
in 4-channel mode.
In 2-channel mode, only samples from channel 1 and channel 2 are processed.
### Sampling
All analog input channels are simultaneously sampled at a fixed
sample rate of 125 MSa/s.
Samples are unsigned 14-bit integers.
An input level of 0 Volt corresponds to the middle of the 14-bit range,
i.e. approximately 8192.
Since the Red Pitaya uses an inverting input circuit.
positive input voltages correspond to lower ADC codes,
and negative input voltages correspond to higher ADC codes.
### Downsampling (decimation)
The ADCs operate at a fixed sample rate of 125 MSa/s.
While the sample rate of the ADC can not be changed, the effective sample rate can be reduced by digital processing in the FPGA.
The effective sample rate after digital processing is equal to the ADC sample rate divided by the _sample rate divisor_ (also called _downsample factor_ or _decimation factor_).
The sample rate divisor is always an integer.
Setting the sample rate divisor to 1 results in an effective sample rate equal to the ADC sample rate, i.e. 125 MSa/s.
Setting a higher sample rate divisor reduces the effective sample rate to `125000000 / divisor` samples per second.
The maximum supported sample rate divisor is 2<sup>18</sup>, corresponding to
an effective sample rate of approximately 477 samples/s.
Rather than configuring the sample rate divisor, the system also supports configuring an effective sample rate in samples per second.
In this case, the requested sample rate is converted to the corresponding sample rate divisor and rounded to the nearest integer.
The system supports two modes of sample rate reduction: decimation and averaging.
In decimation mode with sample rate divisor _N_, only the first sample out of every group of _N_ samples is processed, and the remaining _N_ - 1 samples are discarded.
Decimation causes high frequency signals (above the Nyquist frequency) to alias into the downsampled data.
In averaging mode, the system calculates the sum of each group of _N_ samples.
Averaging mode has the advantage that it suppresses aliasing and noise.
For this reason, averaging mode is the default setting.
Averaging mode is implemented by summing sample values.
This causes an effective gain factor that depends on the sample rate divisor:
if _N_ samples are summed, the result is equal to _N_ times the average
sample value.
If the sample rate divisor is greater than 1024, the result may not fit
in a 24-bit word.
To fix this, the summed values are divided by a suitable power of 2. <br>
If _N_ &le; 1024, the effective downsample gain is equal to _N_. <br>
If _N_ &gt; 1024, the effective downsample gain is equal to _N_ / 2<sup>_k_</sup>, where _k_ = ceil(log<sub>2</sub>(_N_ / 1024)).
### Triggering
When a trigger occurs, the system collects a record consisting of a
configurable number of (downsampled) samples.
Samples are collected for all active channels.
The number of samples collected per trigger must be between 1 and 65536.
Collected samples are transferred via the network.
There are 3 ways to trigger the system:
- By sending an explicit trigger command.
- Via an external digital input signal.
A record is collected for each trigger pulse in the digital signal.
- Continuous triggering in auto-trigger mode.
There are 4 digital input signals that can be used for external triggering.
These signals are connected via pins `DIO0_P` to `DIO3_P` on the Red Pitaya.
Settings are available to select one of these signals, and
to trigger on either rising or falling edges of the selected signal.
An optional trigger delay can be specified.
The delay specifies the number of 8 ns cycles to wait after detecting
the trigger event and before recording the first ADC sample.
The external trigger event is subject to a jitter of 1 sample (8 ns).
New trigger events are ignored while the system is still processing a previous trigger.
When auto-trigger mode is active, the system triggers continuously.
A new trigger occurs as soon as acquisition for the previous trigger has ended, after a dead time controlled by the trigger delay setting.
In this mode, the sample rate divisor must be at least 2 (or at least 4 in 4-channel mode).
If the trigger delay is zero, sampling continues accross triggers at a fixed pace controlled by the sample rate divisor.
This makes it possible to set up continuous streaming sampling.
### Performance limits
Sample rates are limited in a number of ways:
- For acquisition runs up to about 16000 samples, the sample rate
is limited by internal data paths in the FPGA.
In this case, the sample rate divisor must be at least 1,
or at least 2 when operating in 4-channel mode.
- However, in auto-trigger mode, even for short acquisition runs,
the sample rate divisor must be at least 2,
or at least 4 when operating in 4-channel mode.
- For longer acquisition runs, the sample rate is limited by the
network transfer rate.
In this case, the maximum sample rate is approximately 5 MSa/s,
or 2.5 MSa/s when operating in 4-channel mode.
If the configured sample rate is too high, the system will either
refuse the sample rate setting, or sample data will be lost
when internal data buffers fill up.
When using external triggering, the maximum trigger rate depends
on the time it takes to complete data collection for a trigger.
The system is ready to accept a new trigger as soon as data collection
for the previous trigger ends.
At high sample rates, the maximum trigger rate is eventually also limited
by the data transfer rate via the network.
### Calibration
The analog inputs of the Red Pitaya support two different input ranges:
&plusmn; 1 V and &plusmn; 20 V.
The range is selected through jumpers on the board.
Software commands can not change the actual input range.
The firmware does provide commands to specify which input range is used by each channel.
The firmware also keeps track of calibration coefficients for each channel
and input range.
Two calibration coefficients, _offset_ and _gain_, establish a linear relation
between ADC codes and input voltage.
The conversion formula is as follows:
adc_code = offset + gain * input_voltage
Input ranges and calibration coefficients can be saved to the SD card of
the Red Pitaya to be preserved across power cycles.
## Timetagger operation
The timetagger subsystem detects changes on digital input signals
and assigns timestamps to such events.
The stream of timetagged events is transferred via the network.
The timestamp resolution is the same as the ADC sample rate, 125 MHz.
Timestamps are expressed in units of 8 ns cycles.
### Digital input signals
The timetagger has 4 digital input channels.
These signals are connected via pins `DIO0_P` to `DIO3_P` on the Red Pitaya.
Each input channel produces two types of events: rising edge events and falling edge events.
Each event type of each channel can be separately enabled or disabled for timetagging.
## Firmware installation
- Use a micro SD card, at least 1 GB.
- Get the PuzzleFW firmware image `puzzlefw_sdcard.img`
- Put the SD card in a Linux PC.
- Find out the device name of the SD card `/dev/sdX` where `X` is replaced by another letter.
Be **very careful** to get the device name right.
Other storage devices in the PC have similar names.
Writing the image will destroy all other data on the target device.
If you accidentally write the image to the main drive of your PC, you will have a very bad day.
- Make sure that the SD card is not mounted by some automatic device management subsystem in your PC.
- Run the following command as root: <br>
`dd if=puzzlefw_sdcard.img of=/dev/sdX bs=1M`
<br>
This command may take a few minutes to complete.
- Run `sync` and `eject /dev/sdX` before removing the SD card from the PC.
The SD card image can also be written on a PC with a different operating system than Linux.
The steps to do this are described in the official Red Pitaya documentation.
## Console access
The USB console port on the Red Pitaya can be used to login on
the Linux system running on the board.
This is mostly useful for debugging.
To access the console, use a terminal program such as `minicom`
to open the USB serial port of the Red Pitaya.
Set the baud rate to 115200 bps, character format to `8N1`.
Press Enter to get a login prompt on the console.
Use login `root` with password `root`.
## Network access
Remote access to the acquisition system is supported via TCP connections.
Three TCP server ports are used:
@ -7,44 +223,59 @@ Three TCP server ports are used:
- port 5002 is used to transfer timetagger data;
- port 5025 is used for commands.
### Default IP address settings
## Analog sample data stream
By default, the system attempts to obtain an IPv4 address via DHCP.
If the DHCP request fails, the system chooses a link-local address in
the range 169.254.x.x.
A client may connect to TCP port 5001 to receive analog sample data.
At most one client can be connected to this port at any time.
As an alternative to DHCP, a static IPv4 address can be configured via remote control commands.
The system has a unique host name `rp-xxxxxx.local`,
where the x characters are replaced by the last 6 digits of
the MAC address.
This is the same host name as used by the official Red Pitaya software.
### SSH access
It is possible to run an SSH server on the Red Pitaya.
This can be used to remotely log in on the Linux system.
To login via SSH, use username `root` with password `root`.
For security reasons, the SSH server is disabled by default.
An SSH server with an easy-to-guess password should never be connected to an untrusted network.
If you want to use the SSH server, you have to enable it explicitly.
To enable the SSH server, login on the USB console as described above.
Then run the following command: `puzzle-sshcfg enable` .
Finally, run `reboot` to reboot the Red Pitaya.
From this point onward, the SSH server will be started automatically during boot.
## Data stream protocol
Clients may connect to TCP port 5001 to receive analog sample data,
and to TCP port 5002 to receive timetagger data.
At most one client can be connected to each of these ports at any time.
If a new client connects while another connection is still active,
the server closes the old connection and uses the new connection instead.
Data flows through the TCP connection in one direction: from the server
to the client.
Data flows through these TCP connections in one direction:
from the server to the client.
The client must not send anything back to the server.
Analog sample data are transferred as a sequence of 64-bit binary messages.
Each message is sent as a group of 8 bytes with the least significant byte first.
The message stream corresponds to the output data format of the
analog acquisition chain as described in the FPGA firmware documentation.
Data are transferred as a sequence of 64-bit binary messages.
Each message is sent as 8 bytes with the least significant byte first.a
The message streams correspond to the output data format of the
analog acquisition chain and the timetagger as described in the
[FPGA firmware documentation](fpga_firmware.md#).
## Timetagger event stream
## Remote control protocol
A client may connect to TCP port 5002 to receive timetagger data.
At most one client can be connected to this port at any time.
If a new client connects while another connection is still active,
the server closes the old connection and uses the new connection instead.
Data flows through the TCP connection in one direction: from the server
to the client.
The client must not send anything back to the server.
Timetagger data are transferred as a sequence of 64-bit binary messages.
Each message is sent as a group of 8 bytes with the least significant byte first.
The message stream corresponds to the output data format of the timetagger
as described in the FPGA firmware documentation.
## Command protocol
A client may connect to TCP port 5025 to send commands.
Clients may connect to TCP port 5025 to send commands.
Multiple clients may be simultaneously connected to this port.
In that case, it is the responsibility of the clients to make sure
that they do not interfere with each other.
@ -232,7 +463,7 @@ Response: floating point number indicating the gain calibration for the active i
Command: `AIN:CAL:SAVE`
This command saves the active calibration settings to the SD card, to be used as power-on defaults.
The following settings are saved: for each analog input channel, its input range, offset calibration for low and high range, and gain calibration for low and high range.
The following settings are saved for each analog input channel: its input range, offset calibration for low and high range, and gain calibration for low and high range.
### `AIN:CHn:SAMPLE[:RAW]?`
@ -289,8 +520,8 @@ Response: decimal integer representing the downsample factor.
**Note:** Commands `AIN:SRATE` and `AIN:SRATE:DIVISOR` are different methods to control the same internal setting.
**Note:** When auto-trigger mode is selected, the downsample factor must be at least 2.
When 4 channels are active, the downsample factor must be at least 2, or 4 if auto-trigger mode is selected.
**Note:** When auto-trigger mode is selected, the downsample factor must be at least 2, or 4 if 4 channels are active.
In other trigger modes, the downsample factor must be at least 1, or 2 if 4 channels are active.
### `AIN:SRATE:MODE`

2
fpga/.gitignore vendored
View File

@ -1,6 +1,8 @@
RedPitaya-FPGA
puzzlefw_top.bit.bin
puzzlefw_top_4ch.bit.bin
redpitaya_puzzlefw.xsa
redpitaya_puzzlefw_4ch.xsa
vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/ip
vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/ipshared
vivado/redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/puzzlefw.bda

View File

@ -96,7 +96,7 @@ package puzzlefw_pkg is
-- Firmware info word.
constant fw_api_version: natural := 1;
constant fw_version_major: natural := 0;
constant fw_version_minor: natural := 16;
constant fw_version_minor: natural := 17;
constant fw_info_word: std_logic_vector(31 downto 0) :=
x"4a"
& std_logic_vector(to_unsigned(fw_api_version, 8))

View File

@ -153,6 +153,7 @@ architecture arch of puzzlefw_top_4ch is
-- Registers.
signal s_reg_control: registers_control;
signal s_reg_status: registers_status;
signal r_derandomize: std_logic;
-- DMA write channel control.
signal s_dma_write_cmd_addr: dma_address_array(0 to 1);
@ -174,6 +175,7 @@ architecture arch of puzzlefw_top_4ch is
signal s_tt_dma_data: dma_data_type;
signal s_timestamp: std_logic_vector(timestamp_bits - 1 downto 0);
signal s_adc_data_raw: adc_data_array(0 to 3);
signal s_adc_data: adc_data_array(0 to 3);
signal s_adc_sample: adc_data_array(0 to 3);
signal s_dig_in: std_logic_vector(3 downto 0);
@ -547,6 +549,15 @@ begin
s_reg_status.timestamp <= s_timestamp;
-- Register ADC derandomization switch.
-- GPIO(3) = '1' to enable ADC derandomizer, '0' to disable.
process (clk_adc) is
begin
if rising_edge(clk_adc) then
r_derandomize <= s_gpio_out(3);
end if;
end process;
-- Capture ADC data.
-- ADC A handles channels 0 and 1.
-- ADC B handles channels 2 and 3.
@ -559,7 +570,13 @@ begin
clk_intermediate => clk_adc_capture(0),
clk_handoff => clk_adc,
in_data => adc_dat_i(i),
out_data => s_adc_data(i) );
out_data => s_adc_data_raw(i) );
-- Optionally derandomize ADC samples.
s_adc_data(i)(0) <= s_adc_data_raw(i)(0);
gen_derandom: for k in 1 to 13 generate
s_adc_data(i)(k) <= s_adc_data_raw(i)(k) xor (s_adc_data_raw(i)(0) and r_derandomize);
end generate;
end generate;
-- Optionally generate simulated ADC samples.

View File

@ -0,0 +1,91 @@
#
# TCL script to build PuzzleFW firmware image
# for Red Pitaya 4-inputimage in non-project mode.
#
# Usage:
# vivado -mode batch -source nonproject_4ch.tcl
#
# Specify FPGA type.
# This is used by "synth_design".
set_part xc7z020clg400-1
## Specify path to RedPitaya board definition.
## Unclear whether this is required.
#set_param board.repoPaths [list "RedPitaya-FPGA/brd"]
# Specify HDL language.
# This determines the language of the HDL wrapper for the block design.
set_property target_language VHDL [current_project]
# Load VHDL files.
read_vhdl -vhdl2008 ../rtl/puzzlefw_pkg.vhd
read_vhdl -vhdl2008 ../rtl/acquisition_chain.vhd
read_vhdl -vhdl2008 ../rtl/acquisition_manager.vhd
read_vhdl -vhdl2008 ../rtl/acquisition_stream.vhd
read_vhdl -vhdl2008 ../rtl/adc_capture_ddr.vhd
read_vhdl -vhdl2008 ../rtl/adc_range_monitor.vhd
read_vhdl -vhdl2008 ../rtl/adc_sample_stream.vhd
read_vhdl -vhdl2008 ../rtl/deglitch.vhd
read_vhdl -vhdl2008 ../rtl/dma_axi_master.vhd
read_vhdl -vhdl2008 ../rtl/dma_write_channel.vhd
read_vhdl -vhdl2008 ../rtl/registers.vhd
read_vhdl -vhdl2008 ../rtl/sample_decimation.vhd
read_vhdl -vhdl2008 ../rtl/shift_engine.vhd
read_vhdl -vhdl2008 ../rtl/ffpair.vhd
read_vhdl -vhdl2008 ../rtl/simple_fifo.vhd
read_vhdl -vhdl2008 ../rtl/timestamp_gen.vhd
read_vhdl -vhdl2008 ../rtl/timetagger.vhd
read_vhdl -vhdl2008 ../rtl/trigger_detector.vhd
read_vhdl -vhdl2008 ../rtl/puzzlefw_top_4ch.vhd
# Load Zynq block design.
#
# Note: The attribute "synth_flow_mode" in the block design file
# MUST be set to "None". The default value is "Hierarchical", but that
# causes problems with synthesis of the IP cores used in the block design.
#
# Note: The attribute "gen_directory" in the block design file
# determines the location of output produced by "generate_target".
# It must be set to a relative path within the project directory.
#
read_bd redpitaya_puzzlefw.srcs/sources_1/bd/puzzlefw/puzzlefw.bd
set_property synth_checkpoint_mode none [get_files puzzlefw.bd]
generate_target all [get_files puzzlefw.bd]
# Load generated HDL wrapper for block design.
read_vhdl redpitaya_puzzlefw.gen/sources_1/bd/puzzlefw/hdl/puzzlefw_wrapper.vhd
# Load constraints.
read_xdc ../constraints/red_pitaya_4ch.xdc
# Run synthesis and implementation.
set outdir output_4ch
file mkdir $outdir
synth_design -top puzzlefw_top_4ch
report_utilization -file $outdir/post_synth_utilization.rpt
opt_design
place_design
report_io -file $outdir/post_place_io.rpt
phys_opt_design
route_design
write_checkpoint -force $outdir/post_route.dcp
report_drc -file $outdir/post_route_drc.rpt
report_utilization -file $outdir/post_route_utilization.rpt
report_timing_summary -file $outdir/post_route_timing.rpt
report_power -file $outdir/post_route_power.rpt
report_datasheet -file $outdir/post_route_datasheet.rpt
# Write .bit file.
write_bitstream -force $outdir/puzzlefw_top_4ch.bit
# Export XSA file.
# This MUST be done via a checkpoint file.
open_checkpoint $outdir/post_route.dcp
write_hw_platform -fixed -force -file $outdir/redpitaya_puzzlefw_4ch.xsa

View File

@ -44,8 +44,8 @@ start() {
exit 1
fi
# Drive internal GPIO line 0 low to reset FPGA.
# Note: EMIO GPIO line n is gpio (n + 54) in Linux.
# Drive internal GPIO(0) low to reset FPGA.
# Note: EMIO GPIO(n) is gpio (n + 54) in Linux.
gpioset 0 54=0
# Program FPGA.
@ -57,14 +57,20 @@ start() {
sleep 5
if [ "$eeprom_hw_rev" = "STEM_125-14_v1.0" ]; then
# Drive internal GPIO line 2 high to enable ADC duty cycle stabilizer.
# Drive internal GPIO(2) high to enable ADC duty cycle stabilizer.
gpioset 0 56=1
elif [ "$eeprom_hw_rev" = "STEM_125-14_Z7020_4IN_v1.3" ]; then
# Program ADCs for DDR data mode and enable duty cycle stabilizer.
/opt/puzzlefw/bin/puzzle-adccfg init --force --dcs
# Enable ADC output randomization.
/opt/puzzlefw/bin/puzzle-adccfg format --rand
# Drive internal GPIO(3) high to enable sample derandomization in FPGA.
gpioset 0 57=1
fi
# Drive internal GPIO line 0 high to release FPGA reset.
# Drive internal GPIO(0) high to release FPGA reset.
gpioset 0 54=1
sleep 1
}

View File

@ -1118,7 +1118,7 @@ private:
min_divisor *= 2;
}
if (ch4) {
min_divisor += 2;
min_divisor *= 2;
}
return min_divisor;
}

View File

@ -1,2 +1,2 @@
#define PUZZLEFW_SW_MAJOR 0
#define PUZZLEFW_SW_MINOR 4
#define PUZZLEFW_SW_MINOR 5