Skocz do zawartości

32-bitowy soft-processor RISC-V 3,5 raza szybszy od Intel 80386DX 16 MHz


Pomocna odpowiedź

Napisano (edytowany)

Cześć,

przez ostatnie 2 lata miałem tyle projektów w pracy (i takie tempo), że w ogóle nie chciało mi się zamieszczać żadnych projektów elektronicznych na forum. Teraz wracam i zacznę od tematu "z grubej rury". W tym dziale forum "Forbot.pl" było zamieszczone kilka projektów soft-procesorów, ale wszystko były to bardze proste procesory (zaimplementowane kilka instrukcji CPU) o małej wydajności i bez obsługi kompilatora języka C. Wiekszośc z nich nie miała zaimplementowanych żadnych bloków do komunikacji ze światem zewnętrznym (chociażby UART) czy obsługi pinów GPIO. Więszość zamieszczonych w sieci projektów soft-processorów miała bardzo małe pamięci programu np. 1 KB i pamięci RAM, oraz brak obsługi kompilatora języka C co wykluczało ich zastosowanie w praktycznych projektach elektronicznych. Istotne jest także to aby soft-processor nie zajmował za dużo zasobów układy FPGA, żeby można go zaimplementować na małych układach FPGA (cena FPGA jest tu istotna). Nakreśliłem tutaj przyczyny małej przydatności soft-processora do praktycznych projketów.

Opisywany tutaj projekt a właściwie kilka projektów jest  rozległy i będę opisywał go tutaj etapami. Docelowo postało tutaj kilka soft-CPU o róznych projektach do różnych zastosowań i są to właściwie SOC bo mają peryferia takie jak UART, GPIO i kontroler pada do starych konsoli NES. Aby sprawdzić wydajność powstałego SOC (z zaimplementowaną kartą graficzną VGA) przeportowałem całą wersję gry "Prince od Persia" (wersja DOS z początku lat 90'tych na komputer PC). SOC został zaimplementowany na płytce FPGA z ujkładem firmy Gowin, którą zaprojektowałem sam około trzech lat temu (dołąćzę takżę projekt płytki PCB dla tego zestawu).

Poniżej zamieszczam zdjęcie zestawu FPGA z zaimplementowaną całą grą "Prince of Persia" - gra ma 12 poziomów i około 324 osobnych komnat oraz wiele pułapek i przeciwników. Gra jest zaimplementowana w języku C (program ma około 1013 KB) właśnie na tym SOC.

GameONFPGA.thumb.jpg.90273c93816746b1d89592f33334f442.jpg

 

Game_VGA.thumb.jpg.ca24685d3c7ca25d7546d1bba0b356c6.jpg

Zacznę może od zestawu FPGA na układzie GW1N-LV9LQ144C6/I5 firmy "Gowin Semiconductors". Układ ten ma 8640 LUT i 6480 przerzutników poniżej podaję link do Mousera z tym układem: https://www.mouser.pl/en/ProductDetail/GOWIN-Semiconductor/GW1N-LV9LQ144C6-I5?qs=wnTfsH77Xs6N%2FyGezJZrJQ%3D%3D

Około 3 lat temu zaprojektowałem płytkę PCB z tym układem FPGA oraz układem FTDI do programowania FPGA bez drogiego programatora firmy Gowin oraz układami pamięci SPI Flash i SPI PSRAM i wyjściem VGA oraz wielu pinami FPGA wyprowadzonymi na złącza płytki. Poniżej zamieszczam schemat płytki z FPGA Gowin, oraz projekt PCB w "EasyEDA" wersja standard i pliki Gerber do zamówienia plytki u producenta PCB.

Schematic_Gowin_GW1N_LV9_LQ144_DevBoard_SecondEd_2026-10-14.pdf

Gerber_SCH_Gowin_GW1N_LV9_LQ144_DevBoard_SecondEd_2026-10-14.zipGowin_GW1N_LV9_LQ144_DevBoard_SecondEd_PCB_Gowin_GW-N_LV9_LQ144_DevBoard_33_Po_2026-10-14.zip

Gdy wiec postanowiłem zaimplemantować SOC RISC-V na układzie FPGA miałem do tego idealną platformę sprzętową.

Od jakiegoś czasu interesowałem się programowaniem układów FPGA i szczególnie implementacją soft-procesorów na tych układach. Skończyłem chyba 5 kursów na platformie Udemy.com dotyczących projektowania procesorów (lub SOC) zarówno o własnych architekturacjh jak i właśnie RISC-V. Kursy opisywały architekturę własnych procesorów (lub CPU zgodnych z RISC-V przewaznie ISA=riscv32i) ale wiekszość z mich nie korzystała z ogólnie dostepnego kompilatora dla CPU RISCV i często były niejasności w opisie implementacji i architektury CPU. Dopiero ostatnio trafiłem na kurs UDemy gdzie była opisana cała lista rozkazów RISC-V RV32I (32 bitowa operacje stałoprzecinkowe) oraz architektura i implematacja ze wszystkimi szczegółami tak, że nareszcie zrozumiałem wszytstkie szczególy (łącznie z dekoderem instrukcji i układem sterującym CPU). Poza tym był opisany skrypt loadera dla tego CPU, plik startowy i opis kompilacji programu za pomocą ogólno-dostepnego kompilatora RISC-V (RV32I, -march=rv32i). Oraz szczególy ABI, użycia stosu i sterty w programach C. Były też zaimplementowane bench-testy do symulacji wszystkich rozkazów CPU. Był to więc ideqalny kandydat na soft-cpu nad którym miałem całkowitą kontrolę i którego rozumiałem w najmniejszych szczegółach. Do CPU zostały także dodane peryferia jak UART oraz GPIO co właściwie stanowiło cały miniaturowy SOC.

Niestety ten SOC miał dużo wad - najważniejsze z nich:

  1. mała częstotliwość maksymalna SOC wynosząca dla mojego układu FPGA Gowin około 10Mhz (wynikało to z faktu długich ścieżek układów kombinacyjnych bo układ nie miał zaimplementowanego potoku)
  2. pamieć programu wynosiła 280 bajtów a pamięć RAM 90 bajtów (o wiele za mało do praktycznych zastosowań i były te pamięci zaimplementowane w LUT układy FPGA co niepotrzebnie zajmowało zasoby
  3. co prawda układ wspierał komilator RISC-V ale nie miał obsługi żadnej biblioteki języka C więć pisząc na niego program nie mieliśmy dostępu do wielu istotnych funkcjijęzyka C.
  4. układ nie miał w CPU zaimplementowanej architektury potokowej (pipeline) więc poszczególne fazy wykonywania instrukcji CPU nie mogły zostać zrównoleglone przez co wydajność układu była słaba
  5. SOC nie wykorzytywał szybkiej pamięci BRAM z ukadu FPGA dla implementacji pamięci programu oraz RAM
  6. SOC nie wykorzystywał zewnetrzehj pamięci SPI FLASH ani SPI PSRAM w celu dalszego zwiększenia pamięci programu i RAM poza pojemność wewnętrznej pamięci BRAM FPGA
  7. niektóre części CPU nie były zaimplementaowane najbardziej optymalni (było miejsce do optymalizacji)

Tutaj kod programu w języku C który zajmował 280 bajtów i był zaimplementowany w pamięci programu składająćej się z LUT FPGA:

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

#define reg_uart_clkdiv (*(volatile uint32_t*)0x03000004)
#define reg_uart_data (*(volatile uint32_t*)0x03000008)
#define reg_leds (*(volatile uint32_t*)0x04000000)

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

void print(const char *p)
{
    for (unsigned i = 0; i < 128 && p[i] != '\0'; i++)
        putchar(p[i]);
}

void main()
{
	reg_uart_clkdiv = 520;

	print("Booting..");
}

Program ten po prostu wyświetlał tekst Booting.. poprzez UART. Poniżej podaję link do tego kursu Udemy oraz projket SOC z kursy (bez żadnych modyfikacji)/

https://www.udemy.com/course/build-a-risc-v-cpu-in-vhdl-from-scratch/learn/lecture/54189129?start=285#overview

riscv32i_cpu.zip

Postanowiłem na bazie tego SOC z kursu mocno rozbudować projket tak aby mógł on mieć zastosowanie w praktycznych projketach elektronicznych. Na poczatek postanowiłem dodać do  CPU  standardowy 5-fazowy pipeline co powinno umożliwić częściowo równloległe wykonywanie kilku instrukcji procesora (fazy pobierania crozkazu, dekodowania, wykonani zapisu do pamięci i rejestrów). Dodanie potoku powinno dzieki wstawieniu dodatkowych rejestrów skrócić długie ścieżki kombinacyjne w wykonaniu instrukcji i zwięszyć Fmax CPU. Całościowo dodanie potoku powinno mocno zwiększyć wydajność obliczeniową CPU - co jak się okazało po wykonaniu tych zmian miało miejsce. Częstotliwość maksymalna Fmax. dla CPU wzrosła do ponad 20 Mhz z 10 Mhz iwydajność z potokiem wzrosła. Nie będę tu zamieszczał wszystkich projektów pośrednich z faz implementacji i testów na FPGA, tylko dołączę docelowe projekty. W tym samym czasie zamieniłem pamięć programu z implementacji w LUT na wewnętrzne pamięci BRAM FPGA (ten układ FPGA Gowina ma około 50KB BRAM) z czego 32KB przeznaczyłem na pamięć programu a resztę na RAM (także stos i stertę), plik loadera został odpowiednio zmodyfikowany. Potem postanowiłem dodać obsługę biblioteki standardowej języka C - wybór padł tutakj na PicoLi9bc poniewaz jej wersja binarna po kompilacji zaajmuje zaledwie 11 KB. Podaję link do Github projektu tej biblioteki:

https://github.com/picolibc/picolibc

Poniżej zamieszczam projekt (Gowin FPGA, Firmware) dla wersji SOC z zegarem 20MHz, pamięcią programu oraz RAM ze stosem i stertą w wewnętrzej pamięci BRAM układu FPGA, oraz wkomponowaną biblioteką PicoLibc. W firmware sa napisane w C testy wykonania funkcji z bibliteki standardowej  (wyniki dostepne przez UART). Maksymalna pamięć programu (razem z Picolibc która zajmuje 11KB) nie może przekroczyć 32 KB.

RISCV_SOC_PICOLIBC_HEAP4K_V1.zip

Jak ta wersja zadziałała postanowiłem dodać do SOC kontrolery i obsługę zewnętrznych kostek pamięći SPI Flash (4MB) oraz SPI PSRAM (8MB). Wersja ta miała 16KB cache dla pamieci programu i 4KB cache dla pamięci RAM. Potem dodałem obsługę karty graficznej VGA  z framebuferem (buforem całego ekranu w pamięci PSRAM) i buforami dóch linii obrazu w szybkiej pamięci BRAM układu FPGA. Potem zaczęła się aktualizacja i implementacja szybkich transferów z PSRAM i SPI Flash aby zapewnić szybkie odświeżanie obrazu VGA. Na koniec została dodana obsługa prostego kontrolera do konsoli NES z Aliexpress.

Poniżej zamieszczam kartę katalogową końcowej wersji SOC,

KARTA_KATALOGOWA_RISCV_SOC_GOWIN-1.pdf

oraz diagram architektury docelowej wersji.

ARCHITEKTURA_SOC_GOWIN.thumb.png.3ad8c729c6ffbc06eee048dac891ab4c.png

ARCHITEKTURA_SOC_GOWIN-1.pdf

 

 

 

 

 

 

Edytowano przez FlyingDutch
  • Lubię! 1

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...