PiBla
PiBla ist eine in VHDL geschriebene 8-Bit CPU. Die Grundarchitektur und der Befehlsatz entspricht dem des PicoBlaze Controllers für Xilinx-PLDs.
Überblick
Eine Beschreibung des Vorbildes - der Picoblaze - findet sich in der Wikipedia: [1], die Orginalbeschreibung von Xilinx dort: [2]. Der PiBla entstand auf dem Wunsch einen eigenen Controller zur Lernen und Forschen zu Schreiben, ohne selbst einen Assembler schreiben zu müssen oder völlig von Null (Architekturentwurf) anzufangen. Der Orginale Xilinx-Core kommt zwar auch als VHDL daher, allerdings beschreibt dies einen Netzliste aus Primitiven und eignet sich nicht wirklich um eigene Modifikation auszuforschen.
Der Pibla besteht aus dem eigentlichen Controller-Core und einem Block-Ram in der Befehlscode hinterlegt ist. Das eigentliche Programm wird in Assembler geschrieben, übersetzt und in ein Initialisierungsfile für den BlockRam umgewandelt.
Zielhardware
Der core wurde für den Spartan3 entwickelt und läuft auf dem Spartan3 Evalboard von Xilinx. Er ist ca 20% größer als der orginale picoblaze, da aber noch nicht völlig entwanzt, ist er auch noch nicht optimiert. Maximale Taktfrequenz lag so um 60 MHz. Probeweise wurde der core auch für Altera cyclone ii übersetzt. Der Ramblock für den Programmspeicher muss extra generiert (MegaFunction) werden und es werden FF statt RamBlöcke für das RegisterFile, Subroutine-Stack und ScratchPad-Ram FlopFlops implementiert. Der Core ist also ohne weitere Handarbeiten deutlicher größer im Vergleich zum Spartan 3 (mit distributed Ram).
Unterschiede
Zum PicoBlaze gibt es folgende Unterschiede:
- jeder Befehl wird in einem Takt abgearbeitet
- der VHDL-Code ist eine Verhaltensbeschreibung (keine Netzliste wie der Picoblaze)
Architekturdetails
Registerfile
Alle 16 Register sind durch einen 16x8bit DualPort RAM realisiert. Die beiden Source-register werden durch die beiden 4 bit Vectoren freg_aSx und freg_aSy addressiert, das Zielregister durch freg_ai. Der Dualport RAM ist als Feld von 16 Elementen integer beschreiben, die integer sind auf den Wertebereich 0 bis 255 eingeschränkt.
Call/Return addressstack
Der Speicher für die 10 bit breiten Rücksprungaddressen ist als Feld von 30 Elementen beschrieben und als "Last In" - "First Out" Memory realisiert. Bei jedem Abspeichern (save_pc = true) wird der Addresspointer des Stacks um eins erhöht, sonst beim Rücksprung (restore_pc = true) dekrementiert.. Ist beim Speichern die adresse 30 erreicht wird der pointer auf die erste Adresse ("1") gesetzt -overflow, ist beim Rücksprung dagegen die unterste Adresse aktive wird der pointer auf die höchste Adresse gesetzt -underflow.
Programm counter PC
Die Adresse mit dem nächsten Befehlscode kann sein:
- die aktuelle addresse im PC um eins inkrementiert: nx_address,
- die Adresse 0x3FF bei Interrupt-requests
- die bits 9 bis 0 des aktuellen OpCodes (Sprung-adresse): instruction(9 downto 0)
- der letzte Eintrag im call/Return-Stack addr4stack
addr4stack <= stack(stack_addr);
nx_address <= (others => '0') when count_q = "1111111111" else
count_q + 1;
ld_address <= "1111111111" when (interrupt = '1') and (interrupt_del_q = '0') and int_ena_q else
instruction(9 downto 0) when (load_pc or save_pc) else
addr4stack;
--mux: Instructionpointer (PC) is loaded with a) jump address or instruction stack (subprogramm) b) next address (incremented)
count <= unsigned(ld_address) when load_pc or restore_pc else
nx_address;
process(clk)
begin
if rising_edge(clk) then
count_q <= count;
end if;
end process;
Arithmetik/Logikeinheit - ALU
Status
2010-Dez-10: Alle Befehle sind implementiert, allerdings sind einige (Logic-Befehle, SUB) noch nicht komplett überprüft.
Sourcedepot
Auch auf diesem Server: [3] für SVN-Clients oder [4] Webbrowser (HTML).