Architektura procesora

Projekt dotyczy zaprojektowania i implementacji autorskiego procesora w układzie FPGA, wykorzystując język opisu sprzętu Verilog. Celem projektu było stworzenie prostego procesora, zdolnego do wykonywania podstawowych instrukcji, takich jak MOV, JMP, ADD i inne operacje arytmetyczne oraz logiczne, z możliwością obsługi skoków warunkowych. Procesor został zaimplementowany w sposób modułowy, obejmujący rejestry, jednostkę sterującą, ALU, pamięć programu i danych, a także licznik rozkazów (PC). Dzięki tej implementacji możliwe jest zrozumienie i testowanie podstaw architektury CPU, przy jednoczesnej elastyczności w modyfikowaniu i rozszerzaniu funkcjonujących rozkazów oraz opracowywaniu nowych rozwiązań, takich jak przerwania czy potokowanie.

Projekt polega na zaprojektowaniu i zaimplementowaniu w układzie FPGA (z wykorzystaniem języka Verilog) własnej, uproszczonej architektury procesora z podstawowym zestawem instrukcji (m.in. MOV, ADD, JMP) oraz zewnętrznymi pamięciami programu i danych, co pozwala na uruchamianie niewielkich sekwencji rozkazów i obserwację działania typowych elementów CPU, takich jak liczniki rozkazów (PC), rejestry ogólnego przeznaczenia czy jednostka arytmetyczno-logiczna (ALU).

Poniższy schemat ilustruje podstawową architekturę autorskiego procesora zaimplementowanego w układzie FPGA z wykorzystaniem języka opisu sprzętu (np. Verilog). Procesor korzysta z 32‑bitowych słów rozkazów oraz 8‑bitowej szerokości danych, a główne komponenty układu to:


1. Pamięci programu i danych

  • Pamięć rozkazów ma organizację 256×32 bit, co oznacza, że może pomieścić maksymalnie 256 instrukcji, z których każda zajmuje 32 bity. Sygnał adresu tej pamięci (pc_addr) pochodzi z licznika rozkazów (rejestru pc), a wyjście pamięci (instr) jest następnie dekodowane.
  • Pamięć danych (256×8 bit) służy do przechowywania wartości tymczasowych, zmiennych i innych danych potrzebnych podczas wykonywania programu. Adres tej pamięci zwykle pochodzi z wyjścia ALU (alu_res), zaś dane mogą być do niej zapisywane lub odczytywane zależnie od typu instrukcji.

2. Rejestry i dekoder rozkazu

  • Rejestry ogólnego przeznaczenia: r0–r5, które mogą przechowywać dane i wyniki operacji.
  • Rejestr r6 jest w tym projekcie ustawiony na wartość 0 (co ułatwia np. porównywanie z zerem czy inicjalizację danych).
  • Rejestr r7 pełni funkcję licznika rozkazów (ang. Program Counter – PC). Z jego wyjścia korzysta pamięć rozkazów do pobierania kolejnej instrukcji.
  • Dekoder rozbija 32‑bitowe słowo instrukcji na poszczególne pola (m.in. pc_op, alu_op, rx_op, ry_op, rd_op, imm_op i ewentualne 8‑bitowe pole natychmiastowe imm[7:0]). Dzięki tym sygnałom poszczególne bloki CPU (ALU, multipleksery, rejestry) „wiedzą”, jak zareagować na konkretną instrukcję.

3. ALU (Jednostka Arytmetyczno-Logiczna)

ALU (Arithmetic Logic Unit) pobiera dwa operandy:

  1. Operand X – wybierany przez multiplekser rx_mux (np. zawartość jednego z rejestrów r0–r5 lub wartość 0 z r6).
  2. Operand Y – wybierany przez ry_mux (np. drugi rejestr albo wartość natychmiastową imm).

W zależności od rozkazu (alu_op), ALU może:

  • Wykonywać dodawanie (+),
  • Wykonywać operacje logiczne (np. AND),
  • Sprawdzać równość z zerem (==0) – co ułatwia implementację instrukcji porównania i skoków warunkowych.

Wynik z ALU (alu_res) może zostać zapisany do rejestru docelowego (np. przez rd_op), użyty jako adres do pamięci danych lub jako nowy adres PC w przypadku skoku.


4. Sterowanie skokami i aktualizacja PC

  • PC (r7) jest zwiększany o 1 po każdej wykonanej instrukcji, co oznacza sekwencyjne wykonywanie rozkazów.
  • Jeśli instrukcja przewiduje skok (warunek skoku ustawiony np. w wyniku operacji CMP), do rejestru PC może zostać załadowana inna wartość – np. wyjście ALU lub część natychmiastowa instrukcji.
  • Blok „warunek skoku” (cmp_res) decyduje, czy PC zostanie nadpisany nowym adresem, czy kontynuuje liczenie sekwencyjne.

5. Przykładowy przepływ wykonania instrukcji

  1. Pobranie instrukcji: PC (r7) wskazuje adres w pamięci rozkazów (256×32). Słowo 32‑bitowe trafia do dekodera.
  2. Dekodowanie: dekoder wyodrębnia pola określające typ rozkazu, docelowe rejestry, ewentualne pole natychmiastowe.
  3. Przygotowanie operandów: multipleksery rx_mux i ry_mux wybierają właściwe źródła danych (np. rejestry r0–r5, r6=0 lub wartość imm).
  4. Operacja w ALU: w zależności od alu_op wykonuje się dodawanie, AND czy porównanie.
  5. Zapis wyniku: wynik ALU może trafić do rejestru docelowego, pamięci danych lub zostać wykorzystany jako adres skoku.
  6. Aktualizacja PC: jeśli rozkaz to skok, a warunek jest spełniony, PC przyjmuje wartość z ALU; w przeciwnym razie PC jest inkrementowany (PC+1).

6. Zastosowania i rozwój

Tak zaprojektowany procesor może realizować podstawowe instrukcje, np. MOV, ADD, AND, CMP, JMP, JE, HLT itp. Nadaje się do nauki architektury CPU i implementacji w FPGA. Możliwe dalsze rozbudowy to m.in. dodanie kolejnych instrukcji, implementacja przerwań czy pipeline (potokowanie), a także rozbudowa pamięci i warstw cache.

Dzięki prostej, modułowej budowie oraz czytelnym rozdzieleniu pamięci rozkazów i danych, projekt jest łatwy w modyfikacji i może stanowić punkt wyjścia do zaawansowanych eksperymentów z własnymi mikroarchitekturami w układach programowalnych.

pl_PLPolish
Scroll to Top