Stephen Smith's Blog

Musings on Machine Learning…

RISC-V Emulation Revisited

leave a comment »

Introduction

Back in September, 2019, I posted an article presenting a RISC-V Assembly Language “Hello World” program which I ran using the TinyEMU system emulator. There hasn’t been any work on TinyEMU since then and the much more powerful QEMU emulator/virtualizer recently released their version 8. Ubuntu is now releasing install images compiled for RISC-V along with pre-installed images that are ready to run. It’s really cool that you can run/emulate a RISC-V version of Linux on an Intel/Amd version of either Windows or Linux.

Installing and Running RISC-V Linux Under Windows

Here are the instructions to install QEMU and get a RISC-V version of Linux up to the first login prompt.

  1. Install Qemu. Download the Windows install image here. Run the downloaded program saying Yes to the Windows security prompts.
  2. Add c:\Program Files\Qemu to your system PATH, assuming the default installation folder.
  3. Download the Ubuntu Server preinstalled image here.
  4. Use 7-Zip or any uncompression program that understands xz format to extract the .img file from what you downloaded.
  5. Rename the img file as ubunturv.img, or change the name in the commands that follow.
  6. Add some free space to the image with:
    qemu-img resize ubunturv.img +10G
    This gives you some room to install programs once you are running.
  7. To run the image, two additional files are required: fw_jump.elf and uboot.elf. These are easy to install on Linux, but a bit hard to find for Windows, so I placed them both here. These then act as the emulated board’s BIOS.
  8. Now we are ready to run QEMU with the rather long command:
    qemu-system-riscv64 ^
        -machine virt ^
        -cpu rv64 ^
        -m 2G ^
        -device virtio-blk-device,drive=hd ^
        -drive file=ubunturv.img,if=none,id=hd ^
        -device virtio-net-device,netdev=net ^
        -netdev user,id=net,hostfwd=tcp::2222-:22 ^
        -bios fw_jump.elf ^
        -kernel uboot.elf ^
        -append “root=LABEL=rootfs console=ttyS0” ^
        -nographic
    This should then boot Linux and eventually lead you to a login prompt.

Installing and Running RISC-V Linux Under Linux

Now let’s do the same thing for Linux.

  1. Install QEMU with:
    sudo apt install qemu-system-riscv64
    sudo apt install u-boot-qemu opensbi
  2. Extract the img file from the xz file with:
    unxz < downloaded_file_name.img.xz > ubunturv.img
  3. Expand the image, so there is some disk space to play around with:
    sudo qemu-img resize ubunturv.img +10G
  4. Now we are ready to run with the rather long qemu command:
    qemu-system-riscv64 \
        -machine virt \
        -cpu rv64 \
        -m 2G \
        -device virtio-blk-device,drive=hd \
        -drive file=ubunturv.img,if=none,id=hd \
        -device virtio-net-device,netdev=net \
        -netdev user,id=net,hostfwd=tcp::2222-:22 \
        -bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.elf \
        -kernel /usr/lib/u-boot/qemu-riscv64_smode/uboot.elf \
        -object rng-random,filename=/dev/urandom,id=rng \
        -device virtio-rng-device,rng=rng \
        -append “root=LABEL=rootfs console=ttyS0” \
        -nographic
    This should then boot Linux and eventually lead you to a login prompt.

Logging in and Playing with RISC-V Assembly Language

The initial user id/password is ubuntu/ubuntu. The first time you login, Linux will force you to change the password. The computer name is also ubuntu which you can change if you need. Once logged in we can add the GNU Compiler Collection with:

sudo apt update
sudo apt install build-essential

This will also install GDB and a few other GCC related tools.

We can now copy the HelloWorld.s program from my previous article and paste it into vi to save it to the new image. Then we can compile and run the program:

as  -o HelloWorld.o HelloWorld.s
ld -o HelloWorld HelloWorld.o
./HelloWorld

At this point we can use gdb to debug the program, use objdump to look at the generated executable or perform any of the usual Linux type development activities.

Summary

Emulation has come a long way. It is amazing the way QEMU can emulate so many processors and that it works quite efficiently. This is a good option for anyone that wants to learn about RISC-V processors without investing in a RISC-V board. In fact QEMU supports quite a few CPU types that you can use to learn about those processors, even IBM 390 series mainframes.

Written by smist08

April 28, 2023 at 11:38 am

Posted in RiscV

Tagged with , , , ,

Starfive Visionfive 2 RISC-V SBC Review

with 2 comments

Introduction

I’ve blogged a few times on RISC-V processors, but even though they show great promise, there has been a definite lack of hardware. Finally, a number of single board computers (SBCs) are appearing. I recently purchased and received a Starfive Visionfive 2, which is roughly equivalent to a Raspberry Pi 4. It comes with a RISC-V 64-bit quad core CPU running at 1.5GHz, a GPU and an M.2 connector for an SSD. I opted for 8 Gig of memory. The board has two physical internet ports, but no built-in Wifi. I opted for a USB Wifi model, which can be included during ordering. I was able to order this on Amazon to take advantage of free shipping and received it in about a week, shipped from China.

The RISC-V world isn’t nearly as polished as the ARM world as led by the Raspberry Pi, and technical knowledge is required to set up and get things running, including a good knowledge of Linux. In this blog article I’ll go through what is needed to get Linux up and running and highlight the various pitfalls along the way.

Unboxing and Setup

The board and Wifi plug came in the mail in a box. On the bottom of the box is a QR code which links to Starfive’s documentation page. The quickstart guide is fairly straight forward, but there are a couple of mistakes and a couple of things that aren’t at all clear. With all that being said, I was able to get Linux up and running reasonably easily, though I did need to reburn the SDCard once.

Fortunately the Visionfive board uses the same USB-C connector for power as a Raspberry Pi 4, so I was able to easily unplug my Raspberry Pi and plug the power connector, keyboard and mouse into the Visionfive. The Visionfive uses a full size HDMI plug for video, unlike the Pi’s micro-HDMI port, so I needed to dig a regular HDMI cable out of my box of cables, which was no problem.

The quick start guide contains a link to Starfive’s versions of Debian Linux for RISC-V. It looks like they produce a version every month or so. I took the latest which was dated March 31, 2023. I burned it to an SD card, inserted it into the Visionfive board and powered it up. A red light came on, but otherwise nothing happened. No indication that anything was booting, no power to the USB ports, no signal to the monitor.

Set Boot Device DIP Switches

Back to the quick start manual and it talked about setting a couple of dip switches to select the boot device. One would think these would come set for SD card boot, since that is what the quick start guide gives directions for. But no these were set to boot from a UART.

Then I had to scratch my head as to which of these four labels corresponds to booting from the SD card. The correct answer is eMMC which stands for embedded multimedia card, not that is explained anywhere. But with one dip switch changed, the card booted from the SD card and I had Debian Linux up and running.

Manually Resize the File System

Once booted and logged in, the only three GUI programs available are settings, help and terminal. With settings, I entered in my Wifi password and got connected to the Internet. Ok, so let’s install something. The first program I went to install, resulted immediately in a disk full error. WTF? The image is only a couple of gigs and I used a 32 gig SD card. Looking at the quick start guide again, it says the disk image isn’t resized automatically on first boot, you have to perform this operation by hand. There were instructions for this in an appendix on how to use df, fdisk and resize2fs to do this. The instructions were ok, but left out the fact you had to run fdisk and resize2fs using sudo. Any regular Linux user knows this, but this might trip up beginners. Never mind that everyone else, including all Raspberry products, do this automatically on first boot.

DON’T INSTALL OPERATING SYSTEM UPDATES

Alright, now I have lots of disk space, and Wifi, let’s apply any operating system updates before installing anything else. So I ran “sudo apt update” and then “sudo apt upgrade” and the only thing to upgrade were the Mesa video drivers. I did this and rebooted. Now the system worked terribly. The mouse kept jumping around and the screen wasn’t updating properly. Obviously a bad update, so I had to reburn the SD card and repeated the previous steps to get back to a working system with Wifi and free disk space.

Installing Software

Some things were easy to install, some not. The easy ones included GCC, GEdit and Thonny Which is what I needed for doing software development. These all installed easily using the Debian apt command line package manager.

Installing a browser was not easy. Chromium doesn’t seem to have a RISC-V build. Firefox doesn’t install using apt. So I installed the Gnome Epiphany browser, which since Gnome is the default desktop, I thought should work. However it doesn’t, the screen comes up blank. I tried installing the Konqueror browser, which I thought is fairly simple and should work. It installed fine, but I couldn’t type in anything in the URL bar. At least Konqueror also installed the Dolphin file manager, which did work and I find useful.

Then browsing the documentation for the Visionfive board on rvspace.org, I found instructions on how to install custom builds of Firefox and a number of other packages. Run the script they provide, installed all these packages, including Firefox, but sadly Firefox would not start. One of the other packages is LibreOffice which does seem to work fine. So now I’m running fairly well, but without a browser, so I’m accessing the Internet through command line tools only.

The release notes mention that Firefox doesn’t work with hardware acceleration, but I wasn’t able to see where to turn off hardware acceleration with a quick look through the settings. Hopefully this is solved when the next update to the Visionfive Debian image drops.

Update 2023/04/23:

Here are a few things I’ve learned since originally publishing this article:

  • The display appears a bit pink, this is a bug that can be corrected by running the script: /opt/disable_monitor_color.sh
  • The Lynx browser, a text based browser works and can be installed using “sudo apt install lynx”. Clumsy but very retro.
  • If you connect using ssh or putty then the host to use is starfive.local which is much easier than the documented way of using the IP address. This works for either WiFi or direct connect.

Summary

It’s exciting to be running a SBC with a RISC-V processor. There are still lots of glitches and the performance isn’t where it needs to be, but it is a legitimate RISC-V development platform where you can experiment with this new exciting open instruction set architecture (ISA). Hopefully, there is enough community support to develop out the Linux support. ARM is backed by a number of large companies that spend a lot of money hiring people to refine and improve their Linux support. Hopefully the RISC-V community can rise to the challenge and match what is happening in the ARM world. Afterall, ten years ago ARM was at a similar disadvantage to the Intel/AMD world and it managed to overcome that and surpass Intel/AMD in many ways.

Written by smist08

April 21, 2023 at 10:30 am

Posted in RiscV

Tagged with , , ,

Simulating RISC-V on a Raspberry Pi

with one comment

Introduction

Last time, we assembled a small RISC-V program to run on my FPGA RISC-V core running on a Digilent Basys3 development board. To do this we used RARS, which is a quite good Assembler, Debugger, Simulator for RISC-V; in this article I thought I’d point out some other tools available from the official RISC-V github page, including the full GNU C toolchain.

The intent of RISC-V is to be as open source as possible. The main page for the RISC-V Github site contains links to all the RISC-V specifications as well as quite a bit of software including simulators and test tools to test your RISC-V implementation. There is a sister github site for collaborative software such as the GNU RISC-V toolchain which includes a C/C++ compiler, macro assembler and various library and linking tools.

Generally these tools are oriented towards Linux and MacOS and some won’t work in Windows since they require a case sensitive file system. You need to build all these tools yourself, but building them on Ubuntu Linux is fairly straightforward and well documented on the Github sites. I was able to build all these tools on a Raspberry Pi, however it took a full day to do so, and it requires the 64-bit version of the Raspberry Pi OS.

Building the RISC-V Tools

I don’t yet own a real RISC-V processor and my FPGA experiments are nowhere near being able to run Linux. This means I need to compile my RISC-V programs on an Intel or ARM processor, then I can either run the program on a simulator or try it on my FPGA CPU. Building the cross compiler is interesting since it has to first build the compiler executables using the host Intel or ARM GNU compiler and when this is finished use the resulting compiler to compile the C runtime library, so that this is produced in proper RISC-V machine code.

Below I’ll give the commands I used to build and run all the tools on the Raspberry Pi using the 64-bit version of the Raspberry Pi OS. The instructions on the RISCV Github page document the procedures for an Intel version of Linux, but most things work on ARM unmodified.

Install the Prerequisites

These are the recommended packages to install first:

pi@raspberrypi:~ $ sudo apt-get install autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev libtinfo5 libncurses5 libncurses5-dev libncursesw5-dev device-tree-compiler git pkg-config

Build the GNU Toolchain

This is the long step where you need to let the make step run overnight.

pi@raspberrypi:~ $ git clone https://github.com/riscv/riscv-gnu-toolchain
pi@raspberrypi:~ $ cd riscv-gnu-toolchain
pi@raspberrypi:~ $ ./configure --prefix=/opt/riscv --enable-multilib --with-arch=rv32i
pi@raspberrypi:~ $ sudo make
pi@raspberrypi:~ $ cd ..

You now have the GNU GCC compiler and build tools. To use them add:

export PATH=$PATH:/opt/riscv/bin
export RISCV=/opt/risc

To the end of your .bashrc file and start a new terminal window so these settings take effect. You can now compile a C program. Here is hello.c being compiled:

pi@raspberrypi:~ $ cat  hello.c
#include  <stdio.h>
void main()
{
    printf("Hello Raspberry Pi World\n");
}
pi@raspberrypi:~ $ riscv32-unknown-elf-gcc hello.c -o hello
pi@raspberrypi:~ $ 

You can’t run this program quite yet since this program is compiled to RISCV machine code. The unwieldy names of the tools are so the RISC-V versions don’t conflict with the ARM tools and cause havoc.

Build the Spike Simulator

To run the program, we’ll build the Spike simulator which will interpret our RISCV machine code and execute it as if it is running on a real CPU. There is a second library, we’ll build which provides support for some basic operating system calls along with a boot loader to get our simulated CPU up and running. First we build the simulator:

pi@raspberrypi:~ $ git clone https://github.com/riscv/riscv-isa-sim
pi@raspberrypi:~ $ cd riscv-isa-sim
pi@raspberrypi:~/riscv-isa-sim $ mkdir build
pi@raspberrypi:~/riscv-isa-sim $ cd build
pi@raspberrypi:~/riscv-isa-sim/build $ ../configure --prefix=$RISCV --with-isa=rv32i
pi@raspberrypi:~/riscv-isa-sim/build $ make
pi@raspberrypi:~/riscv-isa-sim/build $ sudo make install
pi@raspberrypi:~/riscv-isa-sim/build $ cd ..
pi@raspberrypi:~/riscv-isa-sim $ cd ..

Now we build the component which simulates some Linux system calls and provides a boot loader.

pi@raspberrypi:~ $ git clone https://github.com/riscv/riscv-pk
pi@raspberrypi:~ $ cd riscv-pk/
pi@raspberrypi:~/riscv-pk $ mkdir  build
pi@raspberrypi:~/riscv-pk $ cd  build
pi@raspberrypi:~/riscv-pk/build $ ../configure --prefix=$RISCV --host=riscv32-unknown-elf
pi@raspberrypi:~/riscv-pk/build $ make
pi@raspberrypi:~/riscv-pk/build $ sudo make install

With this we have the simulator built and we can now run our program:

pi@raspberrypi:~ $ spike /opt/riscv/riscv32-unknown-elf/bin/pk hello
bbl loader
Hello Raspberry Pi World
pi@raspberrypi:~ $ 

The string “bbl loader” is from the Berkeley boot loader and then we get the string that our program printed out.

If you want to see the RISC-V Assembly Language generated by the GCC compiler, you can use the objdump utility to disassemble the hello executable program:

pi@raspberrypi:~ $ riscv32-unknown-elf-objdump -d hello >hello.txt

Then below is a snippet of the main routine that we wrote. You can also browse the startup code and C library code that is contained there as well.

0001018c <main>:
   1018c: ff010113          add sp,sp,-16
   10190: 00112623          sw ra,12(sp)
   10194: 00812423          sw s0,8(sp)
   10198: 01010413          add s0,sp,16
   1019c: 000137b7          lui a5,0x13
   101a0: 66478513          add a0,a5,1636 # 13664 <__modsi3+0x30>
   101a4: 260000ef          jal 10404 <puts>
   101a8: 00000013          nop
   101ac: 00c12083          lw ra,12(sp)
   101b0: 00812403          lw s0,8(sp)
   101b4: 01010113          add sp,sp,16
   101b8: 00008067          ret

Summary

It is pretty cool that you can simulate a RISC-V processor on a Raspberry Pi and do development targeting RISC-V systems. Even though the Raspberry Pi is such an inexpensive system, it is still powerful enough to allow cross platform simulation and development. If you are interested in RISC-V development, but aren’t ready to purchase RISC-V hardware yet, then this is a good way to get started.

Written by smist08

April 1, 2023 at 8:06 pm

Counting on my RISC-V FPGA CPU

with one comment

Introduction

Last time, I talked about getting a minimal RISC-V CPU up and running on my Basys FPGA development board. In this article, we’ll connect up the seven segment displays as memory mapped I/O and write a simple RISC-V Assembly Language program to count on the display.

Connecting the Seven Segment Display

To support the four seven segment displays, I took the code from the book “FPGA Programming for Beginners” by Frank Bruno, and connected it to the RISC-V CPU from the book “Digital Design and Computer Architecture: RISC-V Edition” by Sarah L. Harris and David Harris. This turned out to be quite easy. Just needed to add a case statement in soc.sv where if the address is 0x100 then it goes to the seven segment display routine. I chose the rather low address 0x100 since that fits in an immediate argument saving additional code.

  always @(negedge clk_25)
    begin
        if(MemWrite) begin
            case(DataAdr)
                16'h100: encoded = WriteData;
            endcase
            led[7:0] = WriteData[7:0];  
            led[15:8] = DataAdr[7:0];
        end
    end

To test this, I needed to write a RISC-V Assembly Language program, only using the instructions that my mini RISC-V CPU supports.

Writing RISC-V Assembly Language

I wrote the simple program:

# Simple program to count on the 7-segment display
      addi x2, x0, 0     #initialize counter to 0
      addi x3, x0, 0x100 # memory address of seven seg display
main: addi x2, x2, 1     # add 1 to counter
      sw x2, (x3)        # save to the display
      addi x4, x0, 0x7ff # delay loop counter
      addi x6, x0, 9     # ready to shift left 9 bits
      sll x4, x4, x6     # shift left 9 bits
      addi x5, x0, 1     # will subtract from x4
loop: sub x4, x4, x5     # decrement counter
      beq x4, x0, next   # loop done, proceed
      beq x4, x4, loop   # repeat loop
next: beq x2, x2, main   # jump back to loop forever

The first version of this didn’t have the delay loop, so was simpler. With this nice Assembly Language source code, I needed a way to assemble it. I googled and found RARS (Risc-V Assembler and Runtime Simulator). RARS compiled the program fine and I could copy the compiled programs to the instruction memory in the SoC source code.

When I first ran the program, it was way too fast and the seven segment display just showed all eights (all segments lit up). So I added a delay loop, but due to the limited instruction set, I could only loop 0x7ff times, this slowed it down so the high order LED counted. I needed a way to create bigger numbers, so I implemented the SLL (shift logical left) instruction, which was easy to add to the ALU. I could have loaded a larger number from memory or could have written an outer loop to have two nested loops, but chose this instead. With this all done it works fairly well.

Utilization

Below is the utilization report for the hardware resources being used. Notice that with this simple CPU implementation that we are using a small percentage of the available resources. Hence, we have a lot of headroom to keep developing this simple CPU/computer.

+----------------------------+------+-------+------------+-----------+-------+
|          Site Type         | Used | Fixed | Prohibited | Available | Util% |
+----------------------------+------+-------+------------+-----------+-------+
| Slice LUTs*                |  347 |     0 |          0 |     20800 |  1.67 |
|   LUT as Logic             |  299 |     0 |          0 |     20800 |  1.44 |
|   LUT as Memory            |   48 |     0 |          0 |      9600 |  0.50 |
|     LUT as Distributed RAM |   48 |     0 |            |           |       |
|     LUT as Shift Register  |    0 |     0 |            |           |       |
| Slice Registers            |   93 |     0 |          0 |     41600 |  0.22 |
|   Register as Flip Flop    |   93 |     0 |          0 |     41600 |  0.22 |
|   Register as Latch        |    0 |     0 |          0 |     41600 |  0.00 |
| F7 Muxes                   |    2 |     0 |          0 |     16300 |  0.01 |
| F8 Muxes                   |    1 |     0 |          0 |      8150 |  0.01 |
+----------------------------+------+-------+------------+-----------+-------+

Summary

Developing a CPU is a lot of work, but a lot of fun. It’s amazing that with a low cost FPGA development board you can design a CPU and start building a computer around it. This was a small increment in my RISC-V CPU, but nice to see that the tools are quite easy to work with to accomplish my goal.

Written by smist08

March 8, 2023 at 6:41 pm

RISC-V on a Basys 3 FPGA Development Board

with 2 comments

Introduction

I’ve been working on learning how to program/configure FPGAs. I got off to a rocky start due to US export regulations, but after that I’ve been making good progress. Two good books I found are:

  1. “Digital Design and Computer Architecture: RISC-V Edition” by Sarah L. Harris and David Harris.
  2. “FPGA Programming for Beginners” by Frank Bruno.

The Harris’s RISC-V book is an excellent source on how to create a RISC-V CPU core in a Hardware Definition Language (HDL) giving examples in both System Verilog and VHDL. The Bruno book is great for how to implement simple hardware projects on Digilent FPGA boards based on the Artix-7 FPGA architecture.

This blog post looks at taking a RISC-V core from the Harris’s book and implementing it on a Digilent Basys3 FPGA development board using the information from Bruno’s book.

Getting RISC-V Up and Running

The Harris’s book has a lot of information on designing a RISC-V CPU. This implementation executes one instruction per clock cycle and implements the RISC-V instructions: 

  • lw, sw – load/save a word from/to memory
  • add, sub, and, or, slt, addi, andi, ori, slti – arithmetic/logic ALU instructions
  • beq – conditional branch
  • jal – jump and link.

These are enough instructions to execute simple programs and really emphasizes the R in RISC (really reduced instruction set).

First, I took the source code from the Harris’s book and along with the testbench and input it into Vivado. There were a couple of typos in the text and some of the code was left as an exercise, however the online book resources contained the complete correct code. With this in hand I was able to run the testbench in the Vivado simulator and have it pass the single automated test.

I was pretty happy at this, I could execute RISC-V instructions and examine the circuit schematic produced.

I then went to run it on the Basys3 board. This didn’t compile, complaining there weren’t enough I/O ports on the board. The reason for this is that the RISC-V core takes as input both the instruction and data memories as input parameters. These were instantiated as part of the testbench, and any input parameters that aren’t created in the circuit are expected to be connected to external ports.

Creating a SoC

My next step was to create a System on a Chip (SoC) module that would instantiate some memory, instantiate the RISC-V core and provide connections to the Digilent board’s I/O ports.

First I added the instruction and data memory to the SoC module and when I got it to compile, I got an error that nothing was produced. This turned out to be because I didn’t have any outputs, the optimizer was able to remove every component resulting in an empty implementation. The easiest way past this was to connect a couple of things to the LEDs on the board, this way I could see the same results as the test in the testbench program, namely that the program ends with DataAdr == 100 and WriteData == 25.

This causes Vivado to actually generate some circuits, however it then complains it can’t find a layout that works at 100MHz. The solution is given in Bruno’s book to include a clock module from the IP section of Vivado. This clock module is free, easily downloaded and incorporated into your project. With this you can configure the clock to a slower speed to allow more to happen in one clock cycle. Configuring the clock to 50MHz allowed Vivado to produce a layout and then generate a bitstream that I could download to the Basys board. This then lit up the LEDs as expected. The source code for the SoC module is at the end of this article.

Where to Next

There is still a long way to go to create a general purpose computer. The Assembly Language program is hard coded into the circuitry of the FPGA. There is very little I/O with only using a switch for reset and then the LEDs to give a limited view of the address bus.

Further the Vivado optimizer can remove a lot of circuitry because not all 32-bits are used in this example and it can execute the program in the optimizer and hard code the result. To start to make this useful it would be nice to:

  1. Add memory mapped I/O for more devices on the Basys board. Such as outputting numbers to the four seven-segment displays.
  2. Add more instructions from the RISC-V instruction set.
  3. Provide a way to download the machine code Assembly Language to the processor as it’s running. I.e. hard code a boot loader rather than the actual program.
  4. Add support for a VGA monitor, as the Basys does have a VGA video port. Similarly figure out a way to connect a keyboard.

The Basys 3 has rather limited memory, since it only has its distributed memory spread over various LUTs. More expensive boards from Digilent include banks of RAM that could be used to hold more extensive programs. I suspect if I wanted to port a BASIC interpreter, I would need the next Digilent board up in the line. But I have a lot of work to do before getting to that point.

Summary

Creating a small CPU on an FPGA is certainly fun, but it shows the amount of work required to create a CPU and its ecosystem. This is a simple CPU with a few instructions, no pipeline and no caches. But at least it is 32-bit. Implementing some of the RISC-V instruction set, which means I can use the GCC Assembler running on a Raspberry Pi to create the machine code. It is a long way from having what is required to run the Linux Kernel. But for those interested in minimalistic computing this is another alternative to creating custom CPUs that is a bit easier than constructing one out of discrete TTL logic components.

`timescale 1ns/10ps
module soc(
    input wire                         clk,
    input wire                         reset,
    output logic [15:0]    led
);
    logic [31:0] WriteData, DataAdr;
    logic MemWrite;
    logic [31:0] PC, Instr, ReadData;
logic                               clk_50;
generate
   sys_pll u_sys_pll
    (
     .clk_in1  (clk),
     .clk_out1 (clk_50)
     );    
endgenerate     
// instantiate processor and memories
    riscvsingle rvsingle( clk_50, reset, PC, Instr, MemWrite,
        DataAdr, WriteData, ReadData);
    socimem imem(PC, Instr);
    socdmem dmem(clk_50, MemWrite, DataAdr, WriteData, ReadData);  
   always @(negedge clk)
    begin
        if(MemWrite) begin
            led[7:0] = WriteData[7:0];  
            led[15:8] = DataAdr[7:0];
        end
    end
endmodule
module socimem(input logic [31:0] a,
    output logic [31:0] rd);
    logic [31:0] RAM[63:0];
    initial
    begin
    RAM[0]  = 32'h00500113;
    RAM[1]  = 32'h00C00193;
    RAM[2]  = 32'hFF718393;
    RAM[3]  = 32'h0023E233;
    RAM[4]  = 32'h0041F2B3;
    RAM[5]  = 32'h004282B3
    RAM[6]  = 32'h02728863;
    RAM[7]  = 32'h0041A233;
    RAM[8]  = 32'h00020463;
    RAM[9]  = 32'h00000293;
    RAM[10]  = 32'h0023A233;
    RAM[11]  = 32'h005203B3;
    RAM[12]  = 32'h402383B3;
    RAM[13]  = 32'h0471AA23;
    RAM[14]  = 32'h06002103;
    RAM[15]  = 32'h005104B3;
    RAM[16]  = 32'h008001EF;
    RAM[17]  = 32'h00100113;
    RAM[18]  = 32'h00910133;
    RAM[19]  = 32'h0221A023;
    RAM[20]  = 32'h00210063;
    end
    assign rd = RAM[a[31:2]]; // word aligned
endmodule
module socdmem(input logic clk, we,
    input logic [31:0] a, wd,
    output logic [31:0] rd);
    logic [31:0] RAM[63:0];
    assign rd = RAM[a[31:2]]; // word aligned
    always_ff @(posedge clk)
        if (we) RAM[a[31:2]] <= wd;
endmodule

Written by smist08

February 17, 2023 at 10:56 am

Introduction to FPGAs

leave a comment »

Introduction

Field Programmable Gate Arrays (FPGAs) are a form of programmable hardware that has become inexpensive and accessible recently. I recently purchased a Digilent Basys 3 FPGA development board for $200 based on a Xilinx Artix-7 FPGA. Xilinx makes their development software available free for non-commercial use on these lower end chips. If you’ve ever been interested in how chips are designed and developed, then FPGAs are a great way to get started. You program FPGAs using the same hardware design software that is used to design custom integrated circuit chips (ASICs). In this post, we’ll start to look at what an FPGA is and how it works.

Logic Gates and Truth Tables

Anyone that has taken a basic logic course will have encountered truth tables for the basic logic operations. Below are the basic logic building blocks including their symbol and truth table.

You can then build complicated logic circuits out of these building blocks. If you want to build an I/C, then you use a design pattern of the transistors for each logic gate. For instance a possible AND gate made out of transistors and resistors is below.

To build a CPU, you need a few more elements than basic logic gates, namely memory and a way to synchronize everything to a clock, but this is a good starting point.

FPGAs

The basic idea behind an FPGA is to provide an array of circuit elements that can execute any truth table, or lookup table in FPGA parlance. You program the FPGA by downloading all the truth tables to it and then execute them. A Xilinx Artix-7 FPGA contains thousands of configurable logic blocks (CLBs), each of which can be configured to execute a single 6-input lookup table (LUT) or two 5-input LUTs.

When you start building arithmetic operations from basic logic elements, you need a carry output as well. The CLBs support carry out operations so you can implement circuits like full adders. Further some of the CLBs contain memory and shift registers that you can use.

Extras

As chip densities and transistor counts increase, FPGA can have quite a large number of CLBs on a single chip. Further other elements are added to optimize common operations. For instance performing multiplication using the tools described is possible, but quite slow. Most FPGAs now contain custom multipliers that can be configured in or even a DSP. Similarly most FPGAs have custom components for external interfaces such as USB or I2C

Programming

FPGAs are programmed using hardware description languages such as SystemVerilog or VHDL. Both of these compile to what is required for your development board. The cool thing is that this same HDL could be used to generate the layout/masking for a custom application specific I/C (ASIC). The Xilinix development environment is Vivado which supports writing and compiling your HDL along with creating testbenches and running simulations. It also has limited debug support for running on your development board. Here is the source code view:

Here is the generated circuit diagram:

Here we run a simulation and can study the timing diagram:

The thing to remember is that HDL describes hardware and even though it looks like a programming language, it only superficially behaves like a programming language.

Why FPGAs?

FPGAs typically run at 300MHz or so. This is well below the speed of typical ARM, Intel or AMD CPUs. The big advantage of FPGAs is getting something up and running quickly using an iterative development/debug cycle. If you are creating ASICs then you need to do the design, send them out for test manufacturing and then test what you get back, a slow and expensive process.

For instance, a lot of the first RISC-V CPUs on the market were implemented on FPGAs. This is why they usually have fewer CPU cores and run at around 300MHz. This brought them to market quickly to let people start writing RISC-V code, such as adding basic support for RISC-V in the GCC compiler and the Linux kernel.

Another advantage of FPGAs is that if there is a bug, you can reprogram them. FPGAs are commonly used in automobiles and this allows the manufacturers to change the hardware via software updates rather than executing a costly recall and having to replace ASICs or circuit boards.

The other thing to note when implementing in hardware, like with FPGAs, is that you have a much greater freedom to run things in parallel. In fact everything runs at once by default, and you have to do some work to synchronize or serialize operations. This allows you to develop highly parallel processes, like for GPUs or TPUs. This level of parallelism gives FPGA development a huge advantage over CPUs and traditional programming, for certain application areas.

Summary

If you are interested in how I/Cs or CPUs are designed and implemented then inexpensive FPGA boards from companies like Digilent are a great starting point. The cost of entry is minimal and even if the hardware is lower end by today’s standards, it still gives you a long runway for learning. A great diversion for DIY electronics hobbyists.

Written by smist08

February 4, 2023 at 2:57 pm

Tracking Aircraft with a Raspberry Pi

leave a comment »

Introduction

MagPi Magazine issue 126 came out and contained a tutorial, by Tony Roberts, on connecting a Raspberry Pi to an SDR radio to retrieve flight information from nearby aircraft. I’ve been meaning to set up a Raspberry Pi as a flight tracker, so no more excuses, time to do it. Most aircraft have a transponder that broadcasts information on who they are. Newer aircraft also transmit their GPS coordinates. Using a simple Software Defined Radio (SDR) connected to Raspberry Pi we can receive these signals and display a map of the local area containing any transmitting aircraft.

You don’t need to do this to display aircraft positions, FlightRadar24 gets all this information and allows people to display it. FlightRadar24 gets the flight data from thousands of volunteers that run radio receivers and report the information back to FlightRadar24. This is what we did. In return, FlightRadar24 lets you have a business account which gives you full access to everything without any ads.

Newer aircraft have an ADS-B transponder that transmits the aircraft identification along with its location and other useful information. Older planes have an MLAT transponder that only sends the aircraft identification. FlightRadar24 can calculate the location of a plane with an MLAT transponder, if it receives data from four stations which allow it to calculate the position using timing data from when the signal is received at the various stations.

What You Need

To do this you need a Raspberry Pi, which I have quite a few of, an SDR radio dongle and a VHF/UHF antenna. The software supports a number of SDR radios, but one based on a DVB-T chip is most common. In my case I have one from RTL-SDR.COM.Fortunately, I had all of these lying around, the only struggle was finding an extra power adapter for this Pi. The full instructions on setting this up are in the MagPi article, but basically it consists of downloading a Raspberry Pi disk image from FlightRadar24, burning it to an SD card and then configuring the operating system. You typically run it headless, but you can connect a monitor and login if you have trouble with this.

ADS-B and MLAT transmit on 978 or 1090 MHz which is in the UHF band. A regular VHF/UHF antenna should work fine to receive these. However, if your antenna is adjustable, this is the frequency you want to tune for. The transponders transmit short bursts of 150 to 250 Watts, so receiving them is fairly easy, so you don’t have to worry too much. Still the better the antenna, the further away you will receive flight data. Keep in mind that VHF/UHF radio only works via line of sight, so the curvature of the Earth places a limit on how far you can receive from.

Here is a picture of this Raspberry Pi 4 connected to the SDR connected to a simple rabbit ears antenna.

I’ve ordered a new power supply for this Raspberry Pi and when it arrives I’ll move the setup upstairs to my ham shack and attach the SDR to my main outside VHF antenna. This will be shared with my regular VHF radio, so to protect the SDR, it needs to be connected to something like this MFJ device to protect the SDR.

The regular VHF radio broadcasts at 50 Watts and if that hits the SDR, it will release the magic smoke.

Viewing Flights

The FlightRadar24 Raspberry Pi image includes a small web server that lets you view the flight data you are collecting in a web browser, as long as that computer is on the same network. It does a pretty good job of showing the flights within range of your antenna.

Then the next level is to access FlightRadar24’s main website.

This shows all the flights recorded from all the stations that report to FlightRadar24 along with information gathered from other sources. This shows a lot more flights and can give more detailed information on each flight. There are also mobile app versions that allow you to view these on your tablet or phone.

Summary

Sure you can get most of this information for free by just running the phone app and choosing the free plan. But, it’s neat to see how it all works and to help provide this information for everyone else to use.

Written by smist08

January 27, 2023 at 10:38 am

Battling US Export Controls

leave a comment »

Introduction

My electronics DIY hobby must be getting more advanced as I’ve started running into trouble with US export controls designed to keep advanced US technology from terrorist states and others the US doesn’t like. I was having another look at RISC-V processors and how they are progressing, as part of this there is a lot of information on how to design a RISC-V CPU. Modern chips are mostly designed using hardware description languages (HDL) such as SystemVerilog. I’m not going to design a custom chip and certainly can’t afford to get one manufactured; but, this led me to Field Programmable Gate Array (FPGA) chips that let you run your HDL scripts through hardware configuration. Many of the early RISC-V CPUs were only produced on FPGAs and these days there is a lot of interest in FPGAs producing things like retro-CPUs, AI accelerators, robotic controllers and custom GPUs. The cool thing is that the software behind all this is free for student and non-commercial use; but, there is a catch.

Siemens SystemVerilog

I recently read the excellent book: “Digital Design and Computer Architecture, RISC-V Edition” by Sarah Harris and David Harris. To do the labs and exercises in the book required using the ModelSim student edition, now owned by Siemens. I went to download this and received:

I didn’t pursue this and was just sad I couldn’t play with the labs in the simulator.

Xilinx Vivado

This got me interested in FPGA design and I am currently reading “FPGA Programming for Beginners” by Frank Bruno. This book recommended using a Digilent development board for Xilinx Artix-7 FPGAs. The boards are easily available to purchase, including on Amazon. However, after my previous experience I thought I better check out the software first and sure enough ran into US export regulations again.

Xilinx was purchased by AMD in 2020 for 35 billion. Xilinx is the largest manufacturer of FPGA chips and their software and tools are excellent. There is an automated way to get approval, but it requires you to have an email address from an approved company or educational institution. I have neither and wondered if I would be able to get through the bureaucracy of such a large company to get approval.

I pressed the button to send an email explaining why the automated approval wouldn’t work for me. I explained my situation and pressed send. I had pretty low expectations and started looking at open source alternatives for FPGA development. I was pleasantly surprised to receive an email in about an hour asking for some government ID. I emailed back a photo of my drivers license and was given download permission in another hour. I was then able to download the software and get up and running. I then ordered the development board for under $200 from Amazon and it arrived in under a week.

Why All This Hassle?

So why is the US restricting people from FPGAs? Why restrict the student development boards? Why not just restrict the higher end products? I think the assumption is that Iran, Russia or North Korea would be able to create FPGAs to accelerate the computations required in their drones and missiles. This could be true, however the various CPUs from Intel, AMD and ARM that you can buy off the shelf are pretty powerful. The restrictions seem the tightest on software, but then downloading software is a direct export to other countries. When I bought my Digilent FPGA development board, I ordered it from Amazon.ca and had it shipped to B.C. It was fulfilled and shipped from Montreal. I imagine that if my shipping address was in Iran, Russia or North Korea that the order would have been canceled.

I’m not too sure how effective this all is, as I imagine members of these countries can use VPNs to spoof outside locations and produce fairly convincing fake IDs to fool whoever is checking these things. For the physical hardware, I wonder how easy it is to ship it to a third country that doesn’t have strict export restrictions and then ship it from there. For instance shipping the hardware to China, where it is probably manufactured anyway, and then shipped to, say Russia or North Korea.

Placing roadblocks and not providing any support probably slows down development, but doesn’t stop it. There are also a number of open source projects looking to open source the entire FPGA tool chain. Once these mature, I don’t think export restrictions will work on the software, at least in this space.

Summary

I feel the US export restrictions are doing more to limit students learning about advanced technology than they are keeping advanced technology away from rogue states. If the US doesn’t do more to promote technology education, they are going to keep slipping from their position as a technology leader in the world. After all, the technology innovations for the future are going to come from countries with the best educated students. The US runs the risk of putting too many roadblocks in the way of learners and hence restricting future technological advances.

Written by smist08

January 15, 2023 at 9:51 am

Looking Back and Looking Ahead

leave a comment »

Introduction

I made a number of technology predictions for 2022 here. Let’s look at how I did and make a fresh set of predictions for 2023. With the pandemic continuing, global supply chains still in turmoil and the war in Ukraine dragging on, there are a lot of unknowns going forwards. I’m optimistic 2023 will be a good year.

Looking Back on 2022

Let’s look at last year’s predictions and how we did:

  • The CPU Wars Rage On: This was an easy one and we saw new generations of chips from ARM, Intel and AMD. Apple introduced their M2 CPU, newer process technologies came online producing higher transistor counts in smaller areas. This will continue as the competition is intense and the amount of money being invested is huge.
  • New Generations of Graphics Cards: This did happen, both nVidia and AMD introduced their next generation of graphics cards. However, I feel the new generation disappointed, not offering the huge performance boosts promised. Further, even though demand is way down, supply is still tight and prices are way too high.
  • Ransomware & Hacking: Again an easy one. There were many high profile victims last year. Twitter being a bad one, showing why it isn’t a good idea to fire your security team.
  • Self-Driving Cars: This one was wrong. I feel after last year that self-driving cars seem even further away. There were a number of notable failures and crashes in this area. Still I think the problems are solvable and it’s only a matter of time.
  • Raspberry Pi 5: This didn’t happen and Eben Upton has stated that it won’t appear in 2023 either, due to supply chain problems.

Looking Ahead to 2023

Besides the continuations from 2022, here are a few new predictions.

New AI Applications Blossom

There is a huge amount of interest in ChatGPT. I asked ChatGPT to write this article but received:

I guess my job is safe, until ChatGPT starts browsing the Internet.

Apple released a service that uses AI to produce audio books for writers. Many are predicting the end of the job of narrator.

Through 2023, we’ll see many more AI applications released that will move us closer and closer to true general AI. I’m pretty sure we won’t reach general AI in 2023, but our computer hardware is approaching the complexity of the brain.

The Renaissance in DIY Electronics

Designing circuit boards, creating industry automation and designing computer chips used to be exceedingly expensive. Now we have:

Continuing Supply Chain Problems

Some supply problems have eased and demand for electronics has slackened noticeably. However, more stringent US export regulations are putting bureaucratic brakes on the shipment of electronics. For instance, to get the software for a $200 FPGA board that is available on Amazon, I had to send in all sorts of ID and emails to prove I wasn’t Russian or Iranian. As the US locks down exports to China, China is locking down exports back, causing more supply chain problems.

RISC-V Competes with the Raspberry Pi

The various companies behind the open source RISC-V processor family finally produce a CPU that is powerful enough to create a board equivalent to a Raspberry Pi. Currently there are quite a few low power RISC-V microcontrollers, but the availability of a development board equivalent to at least a Raspberry Pi has been sorely missing. They won’t be able to compete with higher end laptops and desktops yet, but at least getting a decent board that runs Linux will be a huge step in the right direction.

Electric Cars Become Mainstream

There is huge demand for electric cars, but the waiting lists to buy them are ridiculous. Finally, supply will start to catch up with demand as more mainstream car manufacturers such as Fiat-Chrysler bring their electric cars to market. There will need to be a matching proliferation of charging stations as already with the few electric cars on the road, there can often be long lineups. The technology in these vehicles is amazing and if they can reduce the charge time, the last obstacle to adoption will be removed.

Summary

In spite of all the supply chain problems and inflationary price pressure, 2022 was a good year for technology. We are seeing prices moderating and supply in some areas being restored, but 2023 will still be a bumpy year. I am excited about the prospects for new advances in AI, electric cars and RISC-V processors. I’m hopeful that I’ll have lots to write about this year.

Written by smist08

January 6, 2023 at 1:44 pm

KiCad on the Raspberry Pi

with one comment

Introduction

The Raspberry Pi has heralded in a renaissance in DIY electronics. The GPIO ports open up a world for custom electronics projects of everything from home control systems to fully autonomous robots. Most projects involve connecting a number of discrete components together on a breadboard and then connecting a few leads over to the Raspberry Pi’s GPIO ports. KiCad lets you take these projects to the next level allowing you to design and manufacture custom printed circuit boards to replace the breadboard with something more permanent. KiCad is an open source design tool that lets you nicely layout your electronic circuits, produce schematics and then take these and produce a PCB. Commercial PCB software is expensive and KiCad, now at version 6, has progressed to compete with the best of these.

In this article, we’ll look at using KiCad to design the circuit for the simple flashing LED hardware that we’ve used in so many previous blog articles.

Designing the Schematic

Creating a schematic is fairly simple in the Eeschema tool. The only gotcha was that the first time you run it, some operations are so slow you don’t know what’s going on. For instance, I was stuck on how to add my first symbol, but that’s because it was building the symbol library and on a Raspberry Pi, this takes a while. Once I was past this, everything went quite smoothly and I was impressed as to how easy this CAD program is to use. The general procedure to building a schematic is to:

  1. Add all the symbols to the schematic.
  2. Arrange the symbols to make wiring them simple, possibly rotating them.
  3. Add the wires to connect everything.
  4. Add documentation, such as proper labels and comments.

I added a Raspberry Pi GPIO header to the diagram to document how to wire up the flashing LEDs to a Raspberry Pi. In the properties for this symbol, I marked it as not going on the PCB board and not to be added to the bill of materials. I added terminals by each lead that goes to the Raspberry Pi, so if I create a PCB board then wires can be soldered to these and connected to the Pi’s GPIO pins. If I was only producing documentation, I could have left these terminals out.

If you are going to generate a PCB board then you need to ensure that each component has a footprint associated with it, which gives the precise measurements for the size and placement of pads on the board that is created.

Producing the PCB

Once you have the schematic, if you want a PCB, then there is a tool that generates the PCB from the schematic. This creates a board with all the components. You then need to:

  1. Arrange the components how you want them (just a matter of moving them).
  2. Provide the circuit paths. Usually following the wires from the schematic as a guide. You can place these on the front or back of the board, for my simple board, I placed them all on the back.
  3. View the finished board to ensure it is what you want. 

I found the creation of the PCB to be quite painless. Of course with more complicated wiring, it can be more of a challenge and might require multiple PCB layers.

Now you can generate the Gerber files and send them to a service to manufacture the board for you.

Below are 3D renderings of the top and bottom of the board.

Summary

Too bad I didn’t know about this tool when I wrote my three books on ARM Assembly Language Programming. I would have produced much better documentation on the hardware projects in the books. Oh well, either next book or future editions.

I’ve struggled with using CAD programs in the past, but this one I found quite easy to learn and use. It runs on Windows, MacOS and Linux including the Raspberry Pi. I have a nice large monitor connected to my Pi and found it worked quite well as a CAD workstation.

I was surprised with how easy it is to design PCB boards with KiCad and can see how this is a great contributor to the surge in DIY electronics.

Written by smist08

January 2, 2023 at 10:42 am

Posted in Electronics

Tagged with , , , ,