การทดลองใช้งาน PicoRV32 Soft-Core CPU ในเบื้องต้น สำหรับบอร์ด Lattice iCE40 FPGA#

Keywords: Lattice iCE40 FPGA, Open Source Hardware, OSHW FPGA Boards, FOSS FPGA Design Tools, PicoRV32


PicoRV32#

บทความนี้นำเสนอการทดลองใช้งาน PicoRV32 ซึ่งเป็น 32-bit Soft-Core CPU ตามสถาปัตยกรรมของซีพียูที่มีชื่อว่า RISC-V (ออกเสียงว่า "RISC-FIVE") โดยนำมาใช้กับบอร์ด iCE-Sugar ที่มีชิป Lattice iCE40UP5K FPGA เป็นองค์ประกอบหลักของบอร์ด

RISC-V เป็นสถาปัตยกรรมของชุดคำสั่งแบบเปิดและฟรี (Free and Open ISA) มีต้นกำเนิดมาจากทีมวิจัยที่มหาวิทยาลัย University of California at Berkeley (USA) จากนั้นจึงมีการรวมตัวเป็นองค์กรเพื่อดำเนินการพัฒนาต่อและเผยแพร่ภายใต้ชื่อ RISC-V Foundation

PicoRV32 ถูกออกแบบโดย Clifford (Claire) Wolf โดยใช้ภาษา Verilog เริ่มต้นในปีค.ศ. 2015 เผยแพร่โค้ดภายใต้ลิขสิทธิ์ ISC License (คล้ายกับ MIT License) มีการนำมาใช้กับบอร์ด เช่น Lattice iCE40-HX8K และ icoBoard ตั้งแต่ปีค.ศ. 2016 และใช้กับซอฟต์แวร์ "Project IceStorm" ซึ่งเป็น Open Source เวอร์ชันล่าสุดคือ PicoRV32 v1.0 (Release Date: March 3, 2019)

PicoRV32 ใช้สถาปัตยกรรมของชุดคำสั่งของ RISC-V ที่เป็น 32-bit Integer ISA: RV32[IMC]

ชิปอย่างเช่น Espressif ESP32-S2 และ ESP32-S3 ก็มีการใช้งาน PicoRV32 core อยู่ภายใน ซึ่งเน้นการทำงานแบบประหยัดพลังงาน และทำหน้าที่เป็น ULP (Ultra-low-power) coprocessor ในขณะที่ซีพียูหลัก Xtensa LX7 Core จะประมวลผลได้เร็วกว่า แต่ก็ใช้พลังงานมากกว่า

RISC-V Extensions

  • I: Load-store achitecture
  • M: Integer multiplication and division.
  • C: Compressed instructions (16-bit instructions)

นอกจากนั้นแล้ว PicoRV32 Core ยังได้จำแนกออกเป็น 3 รูปแบบการใช้งาน คือ

  • picorv32: มีการใช้งานบัสขนาด 32 บิต อย่างง่าย เพื่อเชื่อมต่อระหว่างซีพียูกับวงจรอื่น
  • picorv32_axi: รองรับการใช้งาน AXI-4 Lite Bus Master
  • picorv32_wb: รองรับการใช้งาน WishBone Bus Master

รูป: บล็อกไดอะแกรมของตัวอย่างดีไซนที่มีการใช้งาน PicoSoC

รูป: บล็อกไดอะแกรมสำหรับ PicoRV32 - Lattice iCE40HX-8K (Source: 7th RISC-V Workshop, November 2017)

PicoSoC

  • PicoSoC เป็นตัวอย่างการสร้างวงจรดิจิทัลที่มีการใช้งาน PicoRV32 Core สำหรับนำไปทดลองใช้งานกับบอร์ด iCE40 FPGA
  • ไฟล์ picosoc.v เป็นโมดูล Verilog ที่ภายในมีการใช้งาน PicoRV32 Core จากไฟล์ picorv32.v
  • มีการใช้งานหน่วยความจำ On-chip SRAM สำหรับการทำงานของซีพียู ใช้ Block SRAM ของชิป FPGA โดยปรกติแล้ว ก็จะมีขนาดเล็กและจำกัด เช่น 1024 words (4KB)
    • ชิป iCE40 UltraPlus FPGA มีหน่วยความจำภายที่เรียกว่า Single-Port SRAM ขนาดความจุโดยรวม 4x 256KBits (128KB) หรือ 32,768 Words และจะถูกใช้ในการสร้าง *SRAM (ice40up5k_spram)
  • สามารถเข้าถึงหน่วยความจำภายนอก (Q)SPI Flash เช่น การรันโค้ดจากหน่วยความจำแฟลชภายนอกได้
  • ในชิปหน่วยความจำแฟลช ช่วงแรกที่มีขนาด 1MB จะใช้สำหรับการเก็บข้อมูลของไฟล์ "บิตสตรีม" สำหรับชิป FPGA
  • PicoSoC มีวงจรอื่นรวมอยู่ด้วย เช่น
    • SPI Flash Memory Controller (spimemio): สำหรับการอ่านข้อมูลและโปรแกรมจากหน่วยความจำแฟลชภายนอก
    • Simple UART (simpleuart.v): สำหรับการเชื่อมต่อแบบบิตอนุกรม (default baudrate: 115200)
  • ไฟล์ icebreaker.v เป็นโมดูล Verilog ที่มีการใช้ picosoc เพื่อนำไปใช้กับชิป iCE40UP5K ของบอร์ด iCE-Breaker และไฟล์ icebreaker_tb.v เป็นไฟล์ Verilog Testbench ซึ่งต้องใช้โปรแกรม Icarus Verilog ในการจำลองการทำงาน
  • ไฟล์ icebreaker.pcf เป็นไฟล์ที่ใช้กำหนดหมายเลขขาของชิป FPGA สำหรับสัญญาณ I/O ของวงจร
    • วงจรทำงานด้วยสัญญาณ Clock ที่มีความถี่ 12MHz โดยรับสัญญาณอินพุตที่ขา Pin 35
  • ซอร์สโค้ดภาษาซีสำหรับการเขียนโปรแกรมอยู่ในไฟล์ firmware.c และโค้ดสำหรับ Startup อยู่ในไฟล์ start.s

PicoRV32 / PicoSoC สามารถนำมาใช้กับชิป Lattice iCE40 ได้หลายรุ่น เช่น iCE40HX8K และ iCE40UP5K และมีบอร์ด FPGA ที่สามารถนำมาทดลองใช้ได้ เช่น

  • Lattice iCE40HX-8K Evaluation Board
  • iCEBreaker (iCE40UP5K) Board

ซอฟต์แวร์ที่จำเป็นต้องใช้#

การแปลงโค้ด Verilog HDL ของวงจร PicoRV32 / PicoSoC ให้ใช้งานได้กับชิป Lattice iCE40 FPGA จะต้องใช้โปรแกรมที่เป็น Open Source ซึ่งจะไม่ขอกล่าวถึงในบทความนี้ ดังนั้นแนะนำให้ผู้อ่านได้ศึกษาขั้นตอนการติดตั้งซอฟต์แวร์ดังกล่าว ได้จากบทความ : "การใช้งานซอฟต์แวร์ Open Source FPGA Design Tools สำหรับบอร์ด Lattice iCE40 FPGA" และได้ทำการติดตั้งให้พร้อมใช้งานสำหรับ Ubuntu

ในส่วนที่เกี่ยวข้องกับการคอมไพล์โค้ดสำหรับ RISC-V CPU จะต้องใช้ Cross-Compilation GNU Toolchain for RISC-V ซึ่งเป็นซอฟต์แวร์ Open Source แต่ผู้ใช้จะต้องมาทำขั้นตอนคอมไพล์เอง (Build from Source Code) https://github.com/riscv/riscv-gnu-toolchain

แต่เพื่อความสะดวก ผู้ใช้สามารถดาวน์โหลดไฟล์ Binary Executables ได้จาก SiFive's Github Repo

เวอร์ชันที่ได้ดาวน์โหลดมาทดลองสำหรับ Ubuntu 22.04 LTS คือ Release Version: December 2020 (2020.12.8) ประกอบด้วยโปรแกรมที่เกี่ยวข้องดังนี้

  • GCC 10.2
  • Binutils 2.35
  • Newlib 4.1
  • GDB 10.1
  • Spike-DASM 1.0.1
  • OpenOCD 0.10.0

ขั้นตอนการดาวน์โหลดไฟล์และติดตั้งในระบบ Ubuntu 22.04 LTS มีการทำคำสั่งดังนี้

# Download and extract the archive file for RISCV64 Toolchain.
$ RISCV_TOOLS=riscv64-unknown-elf-toolchain-10.2.0-2020.12.8; \
  TGZ_FILE=${RISCV_TOOLS}-x86_64-linux-ubuntu14.tar.gz; \
  URL=https://static.dev.sifive.com/; \
  URL+=dev-tools/freedom-tools/v2020.12/; \
  URL+=$TGZ_FILE; echo "Downloading $URL ..."; \
  wget $URL -c -O $TGZ_FILE && \
  tar xfz $TGZ_FILE && rm -f $TGZ_FILE

# Move the directory to /opt/
$ sudo mv ${RISCV_TOOLS}-* /opt/${RISCV_TOOLS}-x86_64
$ export PATH="$PATH":/opt/${RISCV_TOOLS}-x86_64/bin

# Show the version of the 'riscv64-unknown-elf-gcc' program.
$ riscv64-unknown-elf-gcc --version | head -n 1

ถ้าต้องการจำลองการทำงานของ PicoSoC จะต้องติดตั้งและใช้งานโปรแกรม Icarus Verilog ก่อน ซึ่งมีขั้นตอนสำหรับการติดตั้งและใช้งานใน Ubuntu ดังนี้

## Build and install Icarus Verilog.
$ cd ~/Tools/
$ git clone https://github.com/steveicarus/iverilog
$ cd iverilog && sh autoconf.sh && ./configure
$ make -j $(nproc)
$ sudo make install

# Check the version of the 'iverilog' tool.
$ iverilog -V | sed -n 1p
Icarus Verilog version 13.0 (devel)

 

ขั้นตอนการดาวน์โหลดและคอมไพล์มีดังนี้

# PicoRV32 - A Size-Optimized RISC-V CPU
$ cd ~/
$ git clone https://github.com/YosysHQ/picorv32
$ cd ./picorv32/picosoc

แก้ไขไฟล์ Makefile ในบรรทัดแรก เพื่อตั้งชื่อของคอมไพล์ที่จะใช้งานให้ถูกต้อง

CROSS=riscv64-unknown-elf-

จากนั้นให้ลองทำคำสั่ง make เพื่อการจำลองการทำงานของวงจร PicoSoC ดังนี้

# Simulate the PicoSoC for iCE-Breaker Board.
$ make icebsim

รูป: การจำลองการทำงานของวงจร PicoSoC โดยใช้ Icarus Verilog Simulator

รูป: การแสดงคลื่นสัญญาณของวงจร PicoSoC โดยใช้ข้อมูลจากไฟล์ testbench.vcd และเปิดไฟล์ด้วยโปรแกรม GTKWave Viewer

 

ถัดไปหากต้องการสร้างไฟล์ "บิตสตรีม" สำหรับชิป FPGA ของบอร์ดทดลอง ให้ลองทำคำสั่งต่อไปนี้

# Build the .bin files (firwmare and bitstream) for iCE-Breaker Board.
$ make icebreaker_fw.bin
$ make icebreaker.bin

ผลจากการสังเคราะห์วงจรเพื่อนำไปใช้กับชิป iCE40UP5K ระบุว่า มีการใช้ Logic Cells (LUT4) จำนวน 4209/ 5280 หรือ 79% ใช้ SPRAM ทั้งหมด วงจรสามารถทำงานด้วยความถี่ 12MHz หรือสูงกว่าได้ แต่ไม่เกินประมาณ 15MHz ซึ่งถือว่าค่อนข้างต่ำ

รูป: ตัวอย่างการทำคำสั่ง เพื่อสร้างไฟล์ .bin สำหรับบอร์ด iCE-Breaker

 


การใช้งานสำหรับบอร์ด iCE-Sugar#

บอร์ด FPGA ที่ได้เลือกมาทดลองใช้งานตามที่ได้กล่าวไปคือ iCE-Sugar ของ Muse Lab บอร์ดนี้มีความเหมือนและความแตกต่างจากบอร์ด iCE-Breaker ของ Bit-Squared ดังนี้

รูป: แผนผังของบอร์ด iCE-Breaker

  • สิ่งที่มีเหมือนกันทั้งสองบอร์ด
    • ใช้ชิป iCE40UP5K-SG48I เหมือนกัน
    • ใช้สัญญาณอินพุตสำหรับ Clock ความถี่ 12MHz ป้อนเข้าที่ขา Pin 35
    • มีขา I/O สำหรับ 3-pin RGB (active-low) เหมือนกันทั้งสองบอร์ด
    • มีหน่วยความจำแฟลชภายนอก SPI Flash เชื่อมต่อขาสัญญาณเหมือนกัน (แต่มีขนาดที่แตกต่างกัน และ iCE-Breaker v1.0e ใช้หน่วยความจำแบบ 16MB QSPI-DDR Flash)
  • ความแตกต่าง
    • บอร์ด iCE-Breaker มีไอซี FTDI FT2232H ทำหน้าที่เป็น USB-to-SPI / USB-to-Serial Bridge ทำหน้าที่เป็นตัวโปรแกรมข้อมูลลงหน่วยความจำแฟลช และเชื่อมต่อกับชิป FPGA สำหรับ Serial Interface และใช้คำสั่ง iceprog สำหรับการโปรแกรมชิป
    • บอร์ด iCE-Sugar ใช้ชิปไมโครคอนโทรลเลอร์ (STM32F103) ทำหน้าที่เป็นวงจรที่เรียกว่า iCE-Link สำหรับการโปรแกรมข้อมูลลงหน่วยความจำแฟลช และเชื่อมต่อกับชิป FPGA สำหรับ Serial Interface รองรับการโปรแกรมด้วยวิธีของ DAPLink (Drag & Drop Programming) หรือใช้คำสั่ง icesprog ของ Muse Lab สำหรับการโปรแกรมชิป
    • ขา UART RX/TX ของบอร์ดiCE-Breaker คือ Pin 6 / 9 แต่สำหรับ iCE-Sugar คือ Pin 4 / 6
    • ดูการใช้งานขา I/O ของบอร์ด iCE-Sugar ได้จากไฟล์ icesugar.pcf และเปรียบเทียบกับไฟล์ icebreaker.pcf เพื่อดูความแตกต่าง

ดังนั้น ในขั้นตอนถัดไป ให้แก้ไขไฟล์ icebreaker.pcf ในส่วนที่เป็นขา UART RX/TX ในตรงกับการใช้งานสำหรับบอร์ด iCE-Sugar

# UART for iCE-Sugar
set_io ser_rx      4
set_io ser_tx      6

จากนั้นให้ทำคำสั่งต่อไปนี้

# Create the bitstream and the firmware files.
$ make clean icebreaker_fw.bin icebreaker.bin

# Merge the two binary files into a single file (picorv32.bin).
$ truncate -s 1048576 icebreaker.bin; \
  cat icebreaker.bin icebreaker_fw.bin > picorv32.bin

เมื่อได้ไฟล์ picorv32.bin ก็ให้เชื่อมต่อบอร์ด iCE-Sugar กับคอมพิวเตอร์ของผู้ใช้แล้วจะมองเห็นไดรฟ์ชื่อ iCELink จากนั้นจึงนำไฟล์ picorv32.bin ไปใส่ลงในไดรฟ์ดังกล่าว และเปิดโปรแกรมที่ใช้รับข้อมูลจากพอร์ต Serial เพื่อดูข้อความที่ถูกส่งออกมาจากบอร์ด

รูป: ตัวอย่างข้อความเอาต์พุตจากบอร์ด iCE-Sugar ผ่านทาง USB-to-Serial Bridge

ถัดไปให้ลองใช้โค้ดตัวอย่างต่อไปนี้ ก่อนอื่นให้สำเนาไฟล์ firmware.c เก็บไว้ก่อน แล้วจึงแก้ไขไฟล์ตามตัวอย่างโค้ดต่อไปนี้

โค้ดตัวอย่างนี้จะทำให้ RGB LED สีแดงและสีเขียว ติดดับสลับกันไป และส่งข้อความแสดงสถานะของ LED มาทาง UART

#include <stdint.h>
#include <stdbool.h>

// UART
#define reg_uart_clk_rate (*(volatile uint32_t*)0x02000004)
#define reg_uart_data     (*(volatile uint32_t*)0x02000008)
// LEDs
#define reg_leds          (*(volatile uint32_t*)0x03000000)

// macro for software-defined delay (approx. x*100ms)
#define _delay(x) { for(volatile int j=0; j < 2320*(x); j++); }

void putchar(char c) {
  if (c == '\n') {
    putchar('\r');
  }
  reg_uart_data = c;
}

void print_str(const char *p) {
  while (*p) {
    putchar(*(p++));
  }
}

void main(void) {
  reg_uart_clk_rate = 104; // Set UART clock rate
  print_str("PicoRV32 / PicoSoC using iCE-Sugar...\n");
  while(1) {
    print_str("LED: Red\n");
    reg_leds = ~(1<<6);
    _delay(5);
    print_str("LED: Green\n");
    reg_leds = ~(1<<7);
    _delay(5);
  }
}

เมื่อแก้ไขโค้ดแล้ว ให้ทำคำสั่งต่อไปนี้ เพื่อสร้างไฟล์ picorv32.bin ใหม่อีกครั้งแล้วจึงนำไปทดลองใช้งาน

$ make icebreaker_fw.bin icebreaker.bin 
$ truncate -s 1048576 icebreaker.bin; \
  cat icebreaker.bin icebreaker_fw.bin > picorv32.bin

รูป: ตัวอย่างข้อความเอาต์พุต

 


ตัวอย่างการใช้คำสั่ง icesprog#

ตัวอย่างการใช้คำสั่ง icesprog ของ Muse Lab สำหรับการเขียนข้อมูลลงในหน่วยความจำแฟลช มีดังนี้

# Find / List the USB device by the VID/PID.
$ lsusb | grep "ID 1d50:602b"
Bus 001 Device 002: ID 1d50:602b OpenMoko, Inc. FPGALink

# Detect the iCE-Sugar board.
$ sudo icesprog -p
probe chip
board: [iCESugar]
flash: [w25q64] (8MB)
done

# Erase the on-board Flash memory.
$ sudo icesprog -e
erase chip
done

# Write the bitstream file (file size: 1MB max).
$ sudo icesprog <bitsream.bin>

# Write the firmware file (with 1MB address offset).
$ sudo icesprog -o 0x100000 <firmware.bin>

 


กล่าวสรุป#

บทความนี้ได้นำเสนอตัวอย่างและขั้นตอนการทดลองใช้งาน PicoRV32 SoftCore CPU สำหรับชิป FPGA ในเบื้องต้น โดยใช้บอร์ด iCE-Sugar iCE40UP5K และ ซอฟต์แวร์ประเภท Open Source ภายใต้ระบบปฏิบัติการ Ubuntu Linux เพื่อการคอมไพล์โค้ดต่าง ๆ ให้ได้ไฟล์บิตสตรีมและไฟล์เฟิร์มแวร์ แล้วทำไปทดลองใช้กับบอร์ด FPGA

 


This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Created: 2023-08-20 | Last Updated: 2023-08-20