FPGA ile çalışırken bazı durumlarda tasarımımızın içine işlemci gömmek isteyebiliriz. FPGA içine herhangi bir RTL tasarım gibi gömülebilen ve FPGA’nın lojik kaynaklarını kullanan işlemcilere “soft-core” denir. Soft-core işlemciler, genelde ihtiyaçlara göre özelleştirilebilir yapıda olurlar. FPGA ile yapılan tasarımlarda sıklıkla kullanıldıklarından birçok FPGA üreticisinin kendi soft-core işlemci IP’leri bulunmaktadır. AMD için Microblaze ve Altera için Nios işlemcilerini örnek olarak verebiliriz. Açık kaynak tarafına baktığımızda ise çeşitli mimarilerde çok sayıda işlemci projesinin olduğunu görüyoruz. Fakat bu projelerin büyük kısmı FPGA üreticilerinin sunduğu çevrebirim ve mikromimari özelleştirme kabiliyetlerinden yoksunlar. Litex projesi, barındırdığı çeşitli açık kaynaklı çevrebirim ve işlemci çekirdekleriyle özelleştirilebilir bir SoC oluşturmaya imkan sağlıyor.
Bu yazıda Tang Nano 9K FPGA için Litex ekosisteminden bir SoC üretip çalıştırmaya değineceğiz. Bunu RISC-V İşlemci Tasarımı - Bölüm 7: Açık Kaynaklı FPGA Akışı bölümünde de kullandığımız Yosys/Apicula araçlarıyla gerçekleştireceğiz.
Litex ile SoC Üretimi
Öncelikle, eğer kurulu değilse Litex ve OSS CAD Suite araçlarının kurulumlarını yapmalıyız.
Daha sonra içinde çalışmak için bir dizin oluşturuyoruz:
$ mkdir example_project
$ cd example_project
Seçtiğimiz FPGA kartı Litex tarafından desteklendiği için hazır bir betik kullanabileceğiz. Bu Python betiğini -h
argümanı ile çağırıp, kullanımını inceleyebiliriz.
$ python3 -m litex_boards.targets.sipeed_tang_nano_9k -h
Komutun çıktısı aşağıda verilmiştir.
Çıktıyı göstermek için tıklayın
usage: {'description': 'LiteX SoC on Tang Nano 9K.'} [-h] [--toolchain {gowin,apicula}] [--build] [--load]
[--log-filename LOG_FILENAME] [--log-level LOG_LEVEL] [--flash]
[--sys-clk-freq SYS_CLK_FREQ]
[--bios-flash-offset BIOS_FLASH_OFFSET] [--with-spi-sdcard]
[--with-video-terminal] [--prog-kit PROG_KIT]
[--output-dir OUTPUT_DIR] [--gateware-dir GATEWARE_DIR]
[--software-dir SOFTWARE_DIR] [--include-dir INCLUDE_DIR]
[--generated-dir GENERATED_DIR] [--build-backend BUILD_BACKEND]
[--no-compile] [--no-compile-software] [--no-compile-gateware]
[--soc-csv SOC_CSV] [--soc-json SOC_JSON] [--soc-svd SOC_SVD]
[--memory-x MEMORY_X] [--doc] [--bios-lto]
[--bios-format {integer,float,double}]
[--bios-console {full,no-history,no-autocomplete,lite,disable}]
[--bus-standard BUS_STANDARD] [--bus-data-width BUS_DATA_WIDTH]
[--bus-address-width BUS_ADDRESS_WIDTH] [--bus-timeout BUS_TIMEOUT]
[--bus-bursting] [--bus-interconnect BUS_INTERCONNECT]
[--cpu-type CPU_TYPE] [--cpu-variant CPU_VARIANT]
[--cpu-reset-address CPU_RESET_ADDRESS] [--cpu-cfu CPU_CFU]
[--no-ctrl] [--integrated-rom-size INTEGRATED_ROM_SIZE]
[--integrated-rom-init INTEGRATED_ROM_INIT]
[--integrated-sram-size INTEGRATED_SRAM_SIZE]
[--integrated-main-ram-size INTEGRATED_MAIN_RAM_SIZE]
[--csr-data-width CSR_DATA_WIDTH]
[--csr-address-width CSR_ADDRESS_WIDTH] [--csr-paging CSR_PAGING]
[--csr-ordering CSR_ORDERING] [--ident IDENT] [--no-ident-version]
[--no-uart] [--uart-name UART_NAME] [--uart-baudrate UART_BAUDRATE]
[--uart-fifo-depth UART_FIFO_DEPTH] [--with-uartbone]
[--with-jtagbone] [--jtagbone-chain JTAGBONE_CHAIN] [--no-timer]
[--timer-uptime] [--with-watchdog]
[--watchdog-width WATCHDOG_WIDTH]
[--watchdog-reset-delay WATCHDOG_RESET_DELAY] [--l2-size L2_SIZE]
options:
-h, --help
show this help message and exit
Target options:
--toolchain {gowin,apicula}
FPGA toolchain (gowin or apicula). (default: gowin)
--build
Build design. (default: False)
--load Load bitstream. (default: False)
--flash
Flash Bitstream. (default: False)
--sys-clk-freq SYS_CLK_FREQ
System clock frequency. (default: 27000000.0)
--bios-flash-offset BIOS_FLASH_OFFSET
BIOS offset in SPI Flash. (default: 0x0)
--with-spi-sdcard
Enable SPI-mode SDCard support. (default: False)
--with-video-terminal
Enable Video Terminal (HDMI). (default: False)
--prog-kit PROG_KIT
Programmer select from Gowin/openFPGALoader. (default: openfpgaloader)
Logging options:
--log-filename LOG_FILENAME
Logging filename. (default: None)
--log-level LOG_LEVEL
Logging level: debug, info (default), warning error or critical. (default: info)
Builder options:
--output-dir OUTPUT_DIR
Base Output directory. (default: None)
--gateware-dir GATEWARE_DIR
Output directory for Gateware files. (default: None)
--software-dir SOFTWARE_DIR
Output directory for Software files. (default: None)
--include-dir INCLUDE_DIR
Output directory for Header files. (default: None)
--generated-dir GENERATED_DIR
Output directory for Generated files. (default: None)
--build-backend BUILD_BACKEND
Select build backend: litex or edalize. (default: litex)
--no-compile
Disable Software and Gateware compilation. (default: False)
--no-compile-software
Disable Software compilation only. (default: False)
--no-compile-gateware
Disable Gateware compilation only. (default: False)
--soc-csv SOC_CSV, --csr-csv SOC_CSV
Write SoC mapping to the specified CSV file. (default: None)
--soc-json SOC_JSON, --csr-json SOC_JSON
Write SoC mapping to the specified JSON file. (default: None)
--soc-svd SOC_SVD, --csr-svd SOC_SVD
Write SoC mapping to the specified SVD file. (default: None)
--memory-x MEMORY_X
Write SoC Memory Regions to the specified Memory-X file. (default: None)
--doc Generate SoC Documentation. (default: False)
BIOS options:
--bios-lto
Enable BIOS LTO (Link Time Optimization) compilation. (default: False)
--bios-format {integer,float,double}
Select BIOS printf format. (default: integer)
--bios-console {full,no-history,no-autocomplete,lite,disable}
Select BIOS console config. (default: full)
SoC options:
--bus-standard BUS_STANDARD
Select bus standard: wishbone, axi-lite, axi. (default: wishbone)
--bus-data-width BUS_DATA_WIDTH
Bus data-width. (default: 32)
--bus-address-width BUS_ADDRESS_WIDTH
Bus address-width. (default: 32)
--bus-timeout BUS_TIMEOUT
Bus timeout in cycles. (default: 1000000)
--bus-bursting
Enable burst cycles on the bus if supported. (default: False)
--bus-interconnect BUS_INTERCONNECT
Select bus interconnect: shared (default) or crossbar. (default: shared)
--cpu-type CPU_TYPE
Select CPU: None, serv, vexiiriscv, cv32e40p, neorv32, cva6, mor1kx, cv32e41p, kianv, fazyrv, cva5, cortex_m1,
eos_s3, ibex, marocchino, gowin_emcu, openc906, minerva, firev, femtorv, vexriscv, cortex_m3, naxriscv,
zynqmp, rocket, zynq7000, microwatt, vexriscv_smp, lm32, gowin_ae350, blackparrot, picorv32. (default:
vexriscv)
--cpu-variant CPU_VARIANT
CPU variant. (default: None)
--cpu-reset-address CPU_RESET_ADDRESS
CPU reset address (Boot from Integrated ROM by default). (default: None)
--cpu-cfu CPU_CFU
Optional CPU CFU file/instance to add to the CPU. (default: None)
--no-ctrl
Disable Controller. (default: False)
--integrated-rom-size INTEGRATED_ROM_SIZE
Size/Enable the integrated (BIOS) ROM (Automatically resized to BIOS size when smaller). (default: 131072)
--integrated-rom-init INTEGRATED_ROM_INIT
Integrated ROM binary initialization file (override the BIOS when specified). (default: None)
--integrated-sram-size INTEGRATED_SRAM_SIZE
Size/Enable the integrated SRAM. (default: 8192)
--integrated-main-ram-size INTEGRATED_MAIN_RAM_SIZE
size/enable the integrated main RAM. (default: None)
--csr-data-width CSR_DATA_WIDTH
CSR bus data-width (8 or 32). (default: 32)
--csr-address-width CSR_ADDRESS_WIDTH
CSR bus address-width. (default: 14)
--csr-paging CSR_PAGING
CSR bus paging. (default: 2048)
--csr-ordering CSR_ORDERING
CSR registers ordering (big or little). (default: big)
--ident IDENT
SoC identifier. (default: None)
--no-ident-version
Disable date/time in SoC identifier. (default: False)
--no-uart
Disable UART. (default: False)
--uart-name UART_NAME
UART type/name. (default: serial)
--uart-baudrate UART_BAUDRATE
UART baudrate. (default: 115200)
--uart-fifo-depth UART_FIFO_DEPTH
UART FIFO depth. (default: 16)
--with-uartbone
Enable UARTbone. (default: False)
--with-jtagbone
Enable Jtagbone support. (default: False)
--jtagbone-chain JTAGBONE_CHAIN
Jtagbone chain index. (default: 1)
--no-timer
Disable Timer. (default: False)
--timer-uptime
Add an uptime capability to Timer. (default: False)
--with-watchdog
Enable Watchdog. (default: False)
--watchdog-width WATCHDOG_WIDTH
Watchdog width. (default: 32)
--watchdog-reset-delay WATCHDOG_RESET_DELAY
Watchdog width. (default: None)
--l2-size L2_SIZE
L2 cache size. (default: 8192)
Açık kaynaklı FPGA araçlarını kullanmak istediğimiz için --toolchain apicula
argümanını vermeliyiz. Sistemin derlenmesi için --build
ifadesini ekliyoruz:
$ python3 -m litex_boards.targets.sipeed_tang_nano_9k --toolchain apicula --build
İlk denememiz ne yazık ki hatayla sonuçlanıyor.😕
Çıktıyı incelediğimizde, hatanın sentez aşamasında ortaya çıktığını görüyoruz. Yosys bir sinyal için “Unconstrained IO” hatası veriyor.
Hata çıktısı:
5. Executing JSON backend.
Warnings: 2 unique messages, 2 total
End of script. Logfile hash: 2f6167a4b0, CPU: user 24.10s system 0.52s, MEM: 965.94 MB peak
Yosys 0.45+148 (git sha1 1bf908dea, clang++ 14.0.0-1ubuntu1.1 -fPIC -O3)
Time spent: 53% 1x abc9_exe (28 sec), 13% 1x autoname (7 sec), ...
Info: Using uarch 'gowin' for device 'GW1NR-LV9QN88PC6/I5'
Info: Reading constraints...
Info: Create constant nets...
Info: Modify LUTs...
Info: Pack IOBs...
ERROR: Unconstrained IO:O_psram_reset_n_OBUF_O_1
0 warnings, 1 error
Hatayı çözmek için, derleme komutu verildiğinde oluşturulan example_project/build/sipeed_tang_nano_9k
dizinine göz gezdiriyoruz. Burada gateware
ve software
adında iki dizin bulunuyor. Sentezlenecek Verilog kodları gateware
dizininde yer alıyor. Burada bulunan Yosys betiğinden, sentezlenen dosyaların VexRiscv.v
ve sipeed_tang_nano_9k.v
olduğunu öğreniyoruz.
sipeed_tang_nano_9k.ys:
verilog_defaults -push
verilog_defaults -add -defer
read_verilog /home/neko/litex/pythondata-cpu-vexriscv/pythondata_cpu_vexriscv/verilog/VexRiscv.v
read_verilog /home/neko/example_project/build/sipeed_tang_nano_9k/gateware/sipeed_tang_nano_9k.v
verilog_defaults -pop
attrmap -tocase keep -imap keep="true" keep=1 -imap keep="false" keep=0 -remove keep=0
synth_gowin -top sipeed_tang_nano_9k
write_json sipeed_tang_nano_9k.json
sipeed_tang_nano_9k.v
isimli dosya tasarımın üst modül kodu. Hataya sebep olan O_psram_reset_n
sinyalinin burada yer aldığını görüyoruz.
sipeed_tang_nano_9k.v:
// -----------------------------------------------------------------------------
// Auto-Generated by: __ _ __ _ __
// / / (_) /____ | |/_/
// / /__/ / __/ -_)> <
// /____/_/\__/\__/_/|_|
// Build your hardware, easily!
// https://github.com/enjoy-digital/litex
//
// Filename : sipeed_tang_nano_9k.v
// Device : GW1NR-LV9QN88PC6/I5
// LiteX sha1 : 64cf925b3
// Date : 2024-10-06 17:17:16
//------------------------------------------------------------------------------
`timescale 1ns / 1ps
//------------------------------------------------------------------------------
// Module
//------------------------------------------------------------------------------
module sipeed_tang_nano_9k (
inout wire [15:0] IO_psram_dq,
inout wire [1:0] IO_psram_rwds,
output reg [1:0] O_psram_ck,
output reg [1:0] O_psram_ck_n,
output reg [1:0] O_psram_cs_n,
output reg [1:0] O_psram_reset_n,
(* keep = "true" *)
input wire clk27,
input wire serial_rx,
output reg serial_tx,
output reg spiflash_clk,
output wire spiflash_cs_n,
input wire spiflash_miso,
output reg spiflash_mosi,
input wire user_btn0,
output wire user_led0,
output wire user_led1,
output wire user_led2,
output wire user_led3,
output wire user_led4,
output wire user_led5
);
...
Kısıt (constraint) dosyasına baktığımızda da psram sinyallerinin burada olmadığı görünüyor.
sipeed_tang_nano_9k.cst:
IO_LOC "clk27" 52;
IO_PORT "clk27" IO_TYPE=LVCMOS33;
IO_LOC "user_btn0" 3;
IO_PORT "user_btn0" IO_TYPE=LVCMOS18;
IO_LOC "serial_rx" 18;
IO_PORT "serial_rx" IO_TYPE=LVCMOS33;
IO_LOC "serial_tx" 17;
IO_PORT "serial_tx" IO_TYPE=LVCMOS33;
IO_LOC "spiflash_cs_n" 60;
IO_PORT "spiflash_cs_n" IO_TYPE=LVCMOS33;
IO_LOC "spiflash_clk" 59;
IO_PORT "spiflash_clk" IO_TYPE=LVCMOS33;
IO_LOC "spiflash_miso" 62;
IO_PORT "spiflash_miso" IO_TYPE=LVCMOS33;
IO_LOC "spiflash_mosi" 61;
IO_PORT "spiflash_mosi" IO_TYPE=LVCMOS33;
IO_LOC "user_led0" 10;
IO_PORT "user_led0" IO_TYPE=LVCMOS18;
IO_LOC "user_led1" 11;
IO_PORT "user_led1" IO_TYPE=LVCMOS18;
IO_LOC "user_led2" 13;
IO_PORT "user_led2" IO_TYPE=LVCMOS18;
IO_LOC "user_led3" 14;
IO_PORT "user_led3" IO_TYPE=LVCMOS18;
IO_LOC "user_led4" 15;
IO_PORT "user_led4" IO_TYPE=LVCMOS18;
IO_LOC "user_led5" 16;
IO_PORT "user_led5" IO_TYPE=LVCMOS18;
Şimdi bu hataya sebep olan sinyallerin neden ortaya çıktığını inceleyelim. Üzerinde çalıştığımız Python betiği litex-kurulum-dizini/litex-boards/litex_boards/targets/sipeed_tang_nano_9k.py
adresinde yer alıyor. Bu dosyaya baktığımızda söz konusu sinyallerin aşağıda verilen kod bloğunda eklendiğini gözlemliyoruz.
sipeed_tang_nano_9k.py:
...
# HyperRAM ---------------------------------------------------------------------------------
if not self.integrated_main_ram_size:
# TODO: Use second 32Mbit PSRAM chip.
dq = platform.request("IO_psram_dq")
rwds = platform.request("IO_psram_rwds")
reset_n = platform.request("O_psram_reset_n")
cs_n = platform.request("O_psram_cs_n")
ck = platform.request("O_psram_ck")
ck_n = platform.request("O_psram_ck_n")
class HyperRAMPads:
def __init__(self, n):
self.clk = Signal()
self.rst_n = reset_n[n]
self.dq = dq[8*n:8*(n+1)]
self.cs_n = cs_n[n]
self.rwds = rwds[n]
hyperram_pads = HyperRAMPads(0)
self.comb += ck[0].eq(hyperram_pads.clk)
self.comb += ck_n[0].eq(~hyperram_pads.clk)
# FIXME: Issue with upstream HyperRAM core, so use old one. Need to investigate.
if not os.path.exists("hyperbus.py"):
os.system("wget https://github.com/litex-hub/litex-boards/files/8831568/hyperbus.py.txt")
os.system("mv hyperbus.py.txt hyperbus.py")
from hyperbus import HyperRAM
self.hyperram = HyperRAM(hyperram_pads)
self.bus.add_slave("main_ram", slave=self.hyperram.bus, region=SoCRegion(origin=self.mem_map["main_ram"], size=4 * MEGABYTE, mode="rwx"))
...
Buradan söz konusu sinyallerin integrated_main_ram_size
argümanı verilmediğinde oluştuğu anlaşılıyor.
📌 Kodda güncel HyperRAM çekirdeğinde problemin olduğu not düşülmüş. Fakat önerilen sürümde de zaten hata alıyoruz. HyperRAM, belki yalnızca Gowin IDE araçlarıyla destekleniyor olabilir.
integrated_main_ram_size
argümanına bir değer vererek, derleme işlemini tekrar deniyoruz:
$ python3 -m litex_boards.targets.sipeed_tang_nano_9k --integrated-main-ram-size 8192 --toolchain apicula --build
Bu defa da aşağıdaki hatayı alıyoruz:
Info: Running custom HCLK placer...
Info: Placed 0 cells based on constraints.
Info: Creating initial analytic placement for 7649 cells, random placement wirelen = 287489.
Info: at initial placer iter 0, wirelen = 3598
Info: at initial placer iter 1, wirelen = 3727
Info: at initial placer iter 2, wirelen = 3677
Info: at initial placer iter 3, wirelen = 3936
Info: Running main analytical placer, max placement attempts per cell = 43319432.
Info: at iteration #1, type ALU: wirelen solved = 4247, spread = 20743, legal = 21380; time = 0.21s
Info: at iteration #1, type GSR: wirelen solved = 21380, spread = 21380, legal = 21387; time = 0.20s
Info: at iteration #1, type DFF: wirelen solved = 21236, spread = 56899, legal = 72407; time = 0.69s
ERROR: Failed to expand region (0, 0) |_> (46, 28) of 10513 LUT4s
0 warnings, 1 error
Yosys çıktısındaki tüketim tablosunu incelediğimizde LUT4 kaynağının bir miktar aşıldığı ve üretilen sistemin FPGA kartımıza sığmadığı anlaşılıyor:
...
Info: Device utilisation:
Info: VCC: 1/ 1 100%
Info: IOB: 14/ 274 5%
Info: LUT4: 10513/ 8640 121%
Info: OSER16: 0/ 80 0%
Info: IDES16: 0/ 80 0%
Info: IOLOGICI: 0/ 276 0%
Info: IOLOGICO: 0/ 276 0%
Info: MUX2_LUT5: 3363/ 4320 77%
Info: MUX2_LUT6: 1101/ 2160 50%
Info: MUX2_LUT7: 426/ 1080 39%
Info: MUX2_LUT8: 156/ 1080 14%
Info: ALU: 892/ 6480 13%
Info: GND: 1/ 1 100%
Info: DFF: 2125/ 6480 32%
Info: RAM16SDP4: 4/ 270 1%
Info: BSRAM: 18/ 26 69%
Info: ALU54D: 0/ 10 0%
Info: MULTADDALU18X18: 0/ 10 0%
Info: MULTALU18X18: 0/ 10 0%
Info: MULTALU36X18: 0/ 10 0%
Info: MULT36X36: 0/ 5 0%
Info: MULT18X18: 0/ 20 0%
Info: MULT9X9: 0/ 40 0%
Info: PADD18: 0/ 20 0%
Info: PADD9: 0/ 40 0%
Info: GSR: 1/ 1 100%
Info: OSC: 0/ 1 0%
Info: rPLL: 1/ 2 50%
Info: FLASH608K: 0/ 1 0%
Info: BUFG: 0/ 22 0%
Info: DQCE: 0/ 24 0%
Info: DCS: 0/ 8 0%
Info: CLKDIV: 0/ 8 0%
Info: CLKDIV2: 0/ 16 0%
...
--cpu-type
argümanı verilmediği takdirde varsayılan işlemci olarak Vexriscv seçiliyor. Vexriscv, görece yüksek performanslı bir işlemci. Bu noktada daha küçük alan kaplayan işlemcileri deneyebiliriz.
Ibex işlemcisini deniyoruz:
$ python3 -m litex_boards.targets.sipeed_tang_nano_9k --cpu-type ibex --integrated-main-ram-size 8192 --toolchain apicula --build
Bu sefer aşağıdaki hatayı alıyoruz:
2. Executing Verilog-2005 frontend: /home/neko/litex/pythondata-cpu-ibex/pythondata_cpu_ibex/system_verilog/vendor/lowrisc_ip/ip/prim/rtl/prim_alert_pkg.sv
Parsing SystemVerilog input from `/home/neko/litex/pythondata-cpu-ibex/pythondata_cpu_ibex/system_verilog/vendor/lowrisc_ip/ip/prim/rtl/prim_alert_pkg.sv' to AST representation.
/home/neko/litex/pythondata-cpu-ibex/pythondata_cpu_ibex/system_verilog/vendor/lowrisc_ip/ip/prim/rtl/prim_alert_pkg.sv:19: ERROR: syntax error, unexpected OP_CAST
Ibex çekirdeği SystemVerilog ile yazıldığı için ne yazık ki Yosys tarafından desteklenmiyor.
Tang Nano 9K FPGA için kullanacağımız işlemci hem küçük hem de Verilog ile yazılmış olmalı. Bu noktada Picorv32, Serv ve FemtoRV gibi çekirdekleri deneyebiliriz. Ben Picorv32’yi seçiyorum:
$ python3 -m litex_boards.targets.sipeed_tang_nano_9k --cpu-type picorv32 --integrated-main-ram-size 8192 --toolchain apicula --build
Nihayet bu sefer hata almıyoruz:
Info: Program finished normally.
Derleme ve sentez işlemi başarılı olduğuna göre artık Bitstream’i FPGA’ya yükleyebiliriz. Bunun için --load
argümanını kullanıyoruz. Kalıcı olarak yüklemek için --flash
opsiyonuyla Flash belleğe yazabiliriz.
$ python3 -m litex_boards.targets.sipeed_tang_nano_9k --cpu-type picorv32 --integrated-main-ram-size 8192 --toolchain apicula --build --load
Yükleme tamamlandıktan sonra ürettiğimiz sistemin Litex BIOS’a erişip erişmediğini kontrol edeceğiz. Bunun için Litex Terminal uygulamasını kullanabiliriz. Litex Terminal argüman olarak seri bağlantı yolunu alıyor. Opsiyonel olarak da Baudrate belirtiyoruz:
$ litex_term /dev/ttyUSB1 --speed 115200
Terminal açıldıktan sonra çıktıyı gözlemlemek için işlemciyi sıfırlamalıyız. Reset butonu, FPGA kartı üzerinde S2 olarak işaretlenmiş.
Litex BIOS çıktısı:
__ _ __ _ __
/ / (_) /____ | |/_/
/ /__/ / __/ -_)> <
/____/_/\__/\__/_/|_|
Build your hardware, easily!
(c) Copyright 2012-2024 Enjoy-Digital
(c) Copyright 2007-2015 M-Labs
BIOS built on Oct 6 2024 17:56:26
BIOS CRC passed (be4fa310)
LiteX git sha1: 64cf925b3
--=============== SoC ==================--
CPU: PicoRV32 @ 27MHz
BUS: wishbone 32-bit @ 4GiB
CSR: 32-bit data
ROM: 64.0KiB
SRAM: 8.0KiB
FLASH: 4.0MiB
MAIN-RAM: 8.0KiB
--========== Initialization ============--
Memtest at 0x40000000 (8.0KiB)...
Write: 0x40000000-0x40002000 8.0KiB
Read: 0x40000000-0x40002000 8.0KiB
Memtest OK
Memspeed at 0x40000000 (Sequential, 8.0KiB)...
Write speed: 724.0KiB/s
Read speed: 723.4KiB/s
Initializing w25q32 SPI Flash @0x00000000...
SPI Flash clk configured to 13 MHz
Memspeed at 0 (Sequential, 4.0KiB)...
Read speed: 281.9KiB/s
Memspeed at 0 (Random, 4.0KiB)...
Read speed: 58.3KiB/s
--============== Boot ==================--
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
Timeout
No boot medium found
--============= Console ================--
litex> help
LiteX BIOS, available commands:
leds - Set Leds value
flush_cpu_dcache - Flush CPU data cache
crc - Compute CRC32 of a part of the address space
ident - Identifier of the system
help - Print this help
serialboot - Boot from Serial (SFL)
reboot - Reboot
boot - Boot from Memory
mem_cmp - Compare memory content
mem_speed - Test memory speed
mem_test - Test memory access
mem_copy - Copy address space
mem_write - Write address space
mem_read - Read address space
mem_list - List available memory regions
litex>
Çıktıda görüldüğü gibi BIOS, öncelikle seri önyüklemeyi deniyor. Seri port üzerinden herhangi bir program göndermediğimizde, birkaç komut destekleyen bir konsol açılıyor.
Bu noktada BIOS’tan bir programı önyüklemeyi deneyebiliriz. Litex projesinde, oluşturduğumuz sistem için derleyebileceğimiz “bare metal demo app” isminde örnek bir program bulunuyor. Bu programı derlemek için litex_bare_metal_demo
komutunu giriyoruz. Bu komuta argüman olarak “build” dizinimizi göstermeliyiz.
$ litex_bare_metal_demo --build-path=/home/neko/example_project/build/sipeed_tang_nano_9k
Komut yürütüldüğünde çıktısı şu şekilde:
CC donut.o
CC helloc.o
CC crt0.o
CC main.o
CC demo.elf
chmod -x demo.elf
OBJCOPY demo.bin
chmod -x demo.bin
Örnek proje derlendi ve sisteme yüklenmeye hazır. İkilik dosyayı seri port üzerinden göndermek için aşağıdaki komutu giriyoruz.
$ litex_term /dev/ttyUSB1 --speed 115200 --kernel=demo.bin
Uçbirim açılıp, işlemciyi resetlediğimizde tekrar hata alıyoruz:
--============== Boot ==================--
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
[LITEX-TERM] Received firmware download request from the device.
[LITEX-TERM] Uploading demo.bin to 0x40000000 (8132 bytes)...
[LITEX-TERM] Upload calibration... (inter-frame: 10.00us, length: 64)
[LITEX-TERM] Got unexpected response from device 'b'E''
Araştırmalarım sonucunda hataya neyin sebep olduğu ve çözümü hakkında net bir bilgiye ulaşamadım ancak Litex Terminal’in --safe
opsiyonu dikkatimi çekti.
--safe Safe serial boot mode, disable upload speed optimizations.
Güvenli seri önyükleme modu ile tekrar deniyoruz:
$ litex_term /dev/ttyUSB1 --speed 115200 --kernel=demo.bin --safe
Bu komutla birlikte seri önyükleme işlemini başarıyla gerçekleştirebildik. Bu noktada önceki komutta aldığımız hatanın sebebini düşük çalışma frekansına bağlayabilmemiz mümkün.
__ _ __ _ __
/ / (_) /____ | |/_/
/ /__/ / __/ -_)> <
/____/_/\__/\__/_/|_|
Build your hardware, easily!
(c) Copyright 2012-2024 Enjoy-Digital
(c) Copyright 2007-2015 M-Labs
BIOS built on Oct 6 2024 20:03:48
BIOS CRC passed (91a777bd)
LiteX git sha1: 64cf925b3
--=============== SoC ==================--
CPU: PicoRV32 @ 27MHz
BUS: wishbone 32-bit @ 4GiB
CSR: 32-bit data
ROM: 64.0KiB
SRAM: 8.0KiB
FLASH: 4.0MiB
MAIN-RAM: 8.0KiB
--========== Initialization ============--
Memtest at 0x40000000 (8.0KiB)...
Write: 0x40000000-0x40002000 8.0KiB
Read: 0x40000000-0x40002000 8.0KiB
Memtest OK
Memspeed at 0x40000000 (Sequential, 8.0KiB)...
Write speed: 724.0KiB/s
Read speed: 723.4KiB/s
Initializing w25q32 SPI Flash @0x00000000...
SPI Flash clk configured to 13 MHz
Memspeed at 0 (Sequential, 4.0KiB)...
Read speed: 281.9KiB/s
Memspeed at 0 (Random, 4.0KiB)...
Read speed: 58.3KiB/s
--============== Boot ==================--
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
[LITEX-TERM] Received firmware download request from the device.
[LITEX-TERM] Uploading demo.bin to 0x40000000 (8132 bytes)...
[LITEX-TERM] Upload complete (2.5KB/s).
[LITEX-TERM] Booting the device.
[LITEX-TERM] Done.
Executing booted program at 0x40000000
--============= Liftoff! ===============--
LiteX minimal demo app built Oct 6 2024 18:29:45
Available commands:
help - Show this command
reboot - Reboot CPU
led - Led demo
donut - Spinning Donut demo
helloc - Hello C
litex-demo-app> donut
Donut demo...
@@@$$@$$$@@$
$$$$$###########$$$$$
#####**!!!!!!!!!!!**###$$#
####**!==!==========!!!**####
###*!!!!==;;:::::::;;=!!!!!**##*
****!!!!=::~--,,.,,-~~;;=!=!!*****
****!!==;;:-,.........,~:;==!!!****!
=***!!!!=;:~,...........-~:;=!!!!***!
!!**!!!=;;:-,.. ..,-:;==!!!**!!=
=!!*!!!==;:~,. ~;==!!!!**!!!=;
;!!!****!***!== ;!!!!******!!!=:
:=!!!*****#######***######******!!!=;
;=!!***####$$$$$$@$$$$$###*****!!=;:
:==!!***##$$$$@@@@@$$$###***!!!=;~
~;=!!**#####$$$$$$$###****!!==;-
,:;=!!!*!*#########!**!!!=;;~.
-~:;==!!!*******!!!==;;:~.
,-::;;=======;;;:~-,
..,,------,,.
Demo kodunda, “Hello World” uygulaması helloc
, kartın üzerindeki LED’lerle ışık gösterisi yapan led
ve uçbirimde ASCII karakterlerle hareket eden donut
programları bulunuyor.