A few years back in high school I worked on building the robot described in the 1979 book “How to Build Your Own Working Robot Pet” by Frank DaCosta. The robot was controlled by an 8085 (an 8-bit microprocessor), and required a ton of 74xx series logic chips to interface to the various control and sensor systems on the robot.
For my senior design project in college, I wanted to create a new robot where all of the control logic would be integrated onto a single chip, and so Pet on a Chip was born. This new robot improved upon the original by drastically reducing power consumption, size, weight, and improving maneuverability, and all of the control logic was implemented on an FPGA. This project built off of my TinySoC project I had worked on during the summer.
The robot’s FPGA contains the following modules:
- A custom 8-bit CPU with on-chip memory
- A simple text mode VGA graphics controller
- Twin closed loop motor speed controllers
- A servo controller
- An interface to a sonar module
- A UART
The most complex circuit on the FPGA is the CPU. It is a custom 8-bit RISC-like device, with a Harvard architecture utilizing a 16-bit wide instruction memory, and an 8-bit wide data memory, both of which take a 16-bit address. It is not fully pipelined but does fetch the next instruction while executing the current one. It can execute most instructions in a single cycle, however a few take two or three cycles to complete. While the design can be clocked up to 26 MHz, the current implementation utilizes a 16 MHz clock. The CPU has 16 general purpose 8-bit registers which can be used in pairs to form 16-bit pointers which are used by the various addressing modes of the instructions. Additionally it contains a 4-bit status register which holds the status of various flags. The CPU can also handle several interrupts generated by peripherals.
The GPU is a simple monochrome 80-column text-mode video controller, which generates a 640×480 VGA signal at 60 Hz. Through a control register, the programmer can select one of 7 colors for the text, and enable or disable an interrupt to the processor which fires at the end of each frame for animation purposes. To write text to the screen, the programmer writes to an ASCII buffer in the GPU. The GPU then scans through this buffer and looks up each character in a font ROM to determine which pixels to display.
The Motor Controller
The FPGA’s motor controller consists of a pair of closed loop speed controllers, one for each of the robot’s drive motors. Each controller monitors the pulses from the rotary encoder attached to the motor it drives. The number of pulses within a time interval are counted, and then this number is multiplied by a fixed point constant to calculate the RPM of the motor. This RPM value is then subtracted from the setpoint given by the programmer to generate an error signal. The error is then accumulated through an integrator, and fed to a PWM generator which drives the H-bridge controlling the motor’s speed. Additionally, the controllers have protection against integral windup, preventing erratic control if one of the wheels is forcibly bound and then released. While a PI controller is more conventional than a pure integral controller, it was found that this solution afforded adequate control, and so proportional control was not included to avoid the added complexity. Finally, the motor controller also enables the programmer to control the direction of the motors, as well as electrically brake them to stop quickly.
The Rangefinder Controller
The rangefinder controller consists of two submodules. The first submodule allows for the control of a hobby servomotor by generating a PWM signal. The programmer simply writes to a register to control the angle of the servomotor. The second submodule interfaces to an HC-SR04 sonar sensor which is mounted on the servomotor. It contains a state machine which interfaces with the sonar sensor allowing the programmer to simply write to a control register to initiate a distance measurement, and read from the register to get the result. When both these submodules are used together in a program, the robot can make a 180° scan of its environment from right to left.
The UART is a simple full duplex implementation with a dataframe consisting of 1 start-bit, 8 data-bits, and 1 stop-bit at a variable baud rate. The output of the UART is fed to an external FTDI chip which performs USB to serial conversion, allowing the robot to interface to a computer for easy debugging.
The Electronics Design
Since all of the control logic for the robot is implemented on the FPGA, the electronics design is fairly simple. The main components are as follows:
- 5V, 3.3V, and 1.2V low dropout linear voltage regulators
- iCE40HX8K FPGA
- FPGA configuration flash
- FTDI USB to serial converter
- FTDI configuration EEPROM
- H-bridge motor driver
There are also a variety of passives, indicator LEDs, buttons, connectors, crystal oscillators etc. Additionally, there is some amplification circuitry for a microphone input, however while constructed, this was not utilized by the project in the end. The design is broken up into two boards: the main board holding the FPGA and FTDI chips and support electronics, and the expansion board holding the H-bridge and microphone circuitry. Schematics for these can be seen in below. Additionally there is a switching 6 volt pre-regulator which steps down the voltage from a pack of 6 AA batteries before it supplies the main board.
As mentioned in the previous section, the electronics are divided between a main board and an expansion board. The main board is 4 layers, while the expansion board has only 2. The boards were manufactured by JLCPCB, but were populated and soldered by hand. For the main board, a steel solder stencil was used to evenly apply solder paste to the pads. Then the surface mount components were placed with tweezers, and then the board was reflowed with a hot air gun. Finally the through hole components were placed and soldered with an iron. The expansion board was much simpler, and only required assembly with an iron.
The software development for this project can be broken down into three main categories: the embedded code, the assembler, and the build scripts.
The embedded code consists of the assembly language programs which run on the soft-core CPU on the FPGA. Many programs have been developed for the pet, but the two most significant are the obstacle avoidance program and the shell. When running the obstacle avoidance program, the robot drives forwards while reading the sonar sensor. Whenever the distance ahead of the robot drops below a threshold, the robot stops and measures the distance to its right and left. The robot then turns in the direction that is the most clear and continues on its way.
The second major program is the shell, which gives the user access to an interactive command line running on the pet. Through the serial interface, the programmer can run commands like ”peek” and ”poke” to read and write to specific IO registers to test the hardware functionality. This program is very involved because it needs subroutines which read user data from a serial terminal while handling backspace characters and echoing the data back over the UART, all while protecting against buffer overflows. It also needs to be able to print and compare strings. Additionally, to implement the subroutines which convert binary numbers to strings, and vice versa, multiplication, division, and modulo subroutines are needed. This is difficult because the CPU does not have a hardware multiplier or divider.
Since the CPU is a custom design, and uses a custom instruction set, no assembler existed to translate the assembly code to the binary machine code. Since programming directly in machine code proved to be prohibitively slow and error prone, a two-pass assembler was developed in Python to perform the translation. This assembler included features such as symbolic labels and definitions, symbolic mathematical expression handling, and a variety of useful directives for setting the origin, and working with strings. The assembler also generates many useful error messages to help the programmer debug their code.
Creating the configuration bitstream for the FPGA is complex. First, the Verilog source is run through Yosys for synthesis along with a dummy hex image for initializing the block ram. Then nextpnr is run on the output to perform place and route. This produces an .asc file which contains all the configuration information for the FPGA’s LUTs as well as the dummy initialization data for the block ram. Then separately, the assembler translates the assembly source files to hex images. Then a program called icebram is run which searches the .asc file for the dummy initialization data for the block ram, and replaces it with the data from the hex images produced by the assembler. Finally, a program called icepack is run to create the configuration bitstream from the .asc file. While this process is complex, having synthesis and place and route be independent from the assembler is incredibly important. Since synthesis and place and route takes a significant amount of time to complete, it would be incredibly unwieldy to develop programs for the processor, if every time the assembly source had to be reassembled, synthesis and place and route also had to be redone. With this setup, synthesis and place and route only has to run once to produce the .asc file, and then every time the assembler is run, the .asc file is modified to reflect the new block ram configuration data for the processor. To further streamline the process, a makefile and two shell scripts were created so that the developer only has to run a few commands to assemble a new program and upload it to the board. A simplified diagram showing this process can be seen below.
Some of the most significant issues with the original robot pet involved its mechanical aspects such as its size, weight, steering radius, and sonar coverage. Since the original pet’s electronics took up significant space and power, the rest of the robot had to be quite large to accommodate the many components and the sizable lead acid battery need to power them. Since the electronics of the Pet on a Chip are significantly smaller and lower power, its body could be build much more compactly.
The body consists of three plates of 1/4th inch birch plywood, approximately 4” by 6”. These plates are stacked one on top of another separated by aluminum standoffs. Mounted on the front of the bottom plate is a free spinning castor ball which acts to stabilize the robot. Then between the bottom plate and the middle plate, two gear-head motors with wheels are mounted, one pointing to the left and the other to the right. Also sandwiched between the bottom plate and the middle plate is a battery compartment containing 6 AA batteries. Between the middle plate and the top plate is housed the switching 6V pre-regulator. Finally on the top plate is mounted the main control board, a power switch, and the servomotor. On top of the servomotor is mounted the sonar rangefinder so that the robot can scan its environment.
Pet on a Chip avoids obstacles more reliably than the original pet, it weighs almost 12 times less, and requires almost 13 times less power. Additionally it is significantly more maneuverable with a turning radius of zero, and has a sonar range of over 7 times the original.
Future work on the project will likely involve the development of a compiler for a higher level language. While the assembler makes it easy to translate assembly to machine code, assembly language is still a challenge to work with and so is currently one of the greatest impediments to further development. Additionally, an I2C bus controller ought to be implemented in Verilog so that a variety of more sophisticated sensors may be added to the project.
The Verilog, Python, Assembly, KiCad Files, and lots of documentation can be found on this project’s GitHub repo: https://github.com/ept221/pet-on-a-chip.