All robots require sensors, computing power, and actuators.
A readily available x86 PC provides a familiar Linux environment for development and deployment. However, PCs have a serious drawback: off-the-shelf motherboards lack low-latency and noise-tolerant connectivity to the outside world. USB seems like a workaround, but once the bus is busy, the latency can be baffling if you're connecting to a motor controller via USB.
Hidden inside the chassis is a solution called PCI Express. While you might not find PCI-e motor controllers or LiDARs easily, they are fast and have low latency. This is where ROPS comes in, acting as a bridge between PCI-e and buses like CAN and RS485, which you can find on motor controllers and sensors.
Since almost all mobile robots require IMU and GPS, ROPS makes these things much easier.
We will use the Xilinx Artix-7 XC7A35T as the core of the ROPS in a CSG325 package. The 35T is a mid-range Artix component, and the CSG325 package bundles all the essential GTP transceivers so that we can connect to the host via PCI-e.
The sensors we plan to use are the ST LSM9DS1 IMU, the ST LPS25HW barometer, and the uBlox NEO-M8T GPS.
There will be rear panel I/O for connecting third-party hardware, such as motor controllers and other sensors, but we haven't finalized any details yet. Currently, only a small number of FPGAs are used for I/O, so there's a lot of flexibility here. Additional I/O may also be present in the mezzanine within the main unit housing or on flexible cable connectors.
Verilog simulation tools
Tightening the write-compile-test loop is always helpful when working with any type of code, especially when you're just starting out. For SPI modules, the timing of the SPI output is paramount. For this, we need to simulate Verilog and check the output. Here are some tools I've used in the past.
editor
I use neovim, but it's not important. I highly recommend using syntax highlighting, powerful find and replace, and cross-platform compatibility so you can use it anytime, anywhere.
Bash Glue
This is where the magic happens: the script takes one argument as the file you're currently working with and waits for it to be saved. Once saved, the script compiles the file, simulates it, and updates the GTKWave output. I'm using Verilog here, but you can replace them with whatever's useful in your project after inotifywait. This could be a compiler, linter, etc. I save its output in the top left pane of my workspace so I can check for any errors that occur.
inotifywait
This is indeed the key to the script. When the file provided to the script as the first argument is closed, inotifywait exits if it is opened as writable. This way, if you capture a file or perform a difference, it won't do anything. It won't look inside the file to see if changes have been made; it only knows that the file is closed.
iVerilog
Icarus Verilog is a Verilog synthesis and simulation tool. iVerilog compiles the source code into a source code similar to an intermediate assembly, which is then executed by vvp, another part of the iVerilog toolset. This outputs a .lxt file that stores the waveforms of various connections and registers in Verilog.
In the script, the iRilog -o option names the output file; here we only use main. Then we call vvp on main and tell vvp to output the waveform to a .lxt file.
GTKWave
When simulating Verilog, you can use printf-like statements, or dump the state of each line and register it to a file. View the register dump. I'm using GTKWave. In my opinion, it's perfect software. When I want to examine the waveform, it does everything I need, nothing else.
In the script, we call gconftool-2 to update the waveform. I don't know why they chose a configuration tool for this, but it works.