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

 

 

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...