Skip to content

Instantly share code, notes, and snippets.

@gigaherz
Created October 14, 2013 19:28
Show Gist options
  • Save gigaherz/6980749 to your computer and use it in GitHub Desktop.
Save gigaherz/6980749 to your computer and use it in GitHub Desktop.
An implementation of a simple 4-instruction CPU, in VHDL
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.constants.all;
use work.ctypes.all;
entity ALU is port (
clk : in std_logic;
iFn : in aluModes;
aOpr : in std_logic_vector(wordLength-1 downto 0);
bOpr : in std_logic_vector(wordLength-1 downto 0);
zf : out std_logic;
result : out std_logic_vector(wordLength-1 downto 0) );
end ALU;
architecture ALUArch of ALU is
signal tresult: std_logic_vector(wordLength-1 downto 0);
begin
process(iFn, aOpr, bOpr)
begin
case iFn is
when mAdd => tresult <= (aOpr + bOpr);
when mNor => tresult <= (not (aOpr or bOpr));
when mCmp => tresult <= (aOpr xor bOpr);
when mRot => tresult <= bOpr(0) & bOpr(wordLength-1 downto 1);
end case;
if (unsigned(tresult) = 0) then
zf <= '1';
else
zf <= '0';
end if;
result <= tresult;
end process;
end ALUArch;
package constants is
constant wordLength: integer := 16; -- Tamany de paraula
constant addrLength: integer := 7; -- Tamany d'adreça
end package constants;
package ctypes is
type aluModes is (mAdd,mNor,mCmp,mRot);
end package ctypes;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.constants.all;
use work.ctypes.all;
entity MS1 is port (
clk, reset: in STD_LOGIC;
IBus: in std_logic_vector(wordLength-1 downto 0);
OBus: out std_logic_vector(wordLength-1 downto 0));
end MS1;
architecture MS1Arch of MS1 is
component ram is port (
reset, r_w: in STD_LOGIC;
aBus: in STD_LOGIC_VECTOR(addrLength-1 downto 0); -- bus d'adreçes
iBus: inout STD_LOGIC_VECTOR(wordLength-1 downto 0); -- bus de dades d'entrada
oBus: inout STD_LOGIC_VECTOR(wordLength-1 downto 0)); -- bus de dades de sortida
end component;
component ALU is port (
clk : in std_logic;
iFn : in aluModes;
aOpr : in std_logic_vector(wordLength-1 downto 0);
bOpr : in std_logic_vector(wordLength-1 downto 0);
zf : out std_logic;
result : out std_logic_vector(wordLength-1 downto 0) );
end component;
component UP is port (
clk : in std_logic;
reset : in std_logic;
ramRW : in std_logic;
pcInc : in std_logic;
addrSel : in std_logic_vector(1 downto 0);
mToIR : in std_logic;
mToA : in std_logic;
mToB : in std_logic;
updZF : in std_logic;
aluMode : in aluModes;
mToOut : in std_logic;
m_in : in std_logic;
co1 : out std_logic_vector(1 downto 0);
co2 : out std_logic_vector(1 downto 0);
zfOut : out std_logic;
zfAlu : in std_logic;
aBus : out std_logic_vector(wordLength-1 downto 0); -- sortida del registre A cap a la ALU
bBus : out std_logic_vector(wordLength-1 downto 0); -- sortida del registre A cap a la ALU
mrBus : in std_logic_vector(wordLength-1 downto 0); -- sortida de dades de la UP cap a la RAM
iBus : in std_logic_vector(wordLength-1 downto 0); -- entrada de dades del port d'E/S
oBus : out std_logic_vector(wordLength-1 downto 0); -- sortida de dades del port d'E/S
addrBus : out std_logic_vector(addrLength-1 downto 0)
);
end component;
component UC is port (
clk : in std_logic;
reset : in std_logic;
ramRW : out std_logic;
pcInc : out std_logic;
addrSel : out std_logic_vector(1 downto 0);
mToIR : out std_logic;
mToA : out std_logic;
mToB : out std_logic;
updZF : out std_logic;
aluMode : out aluModes;
mToOut : out std_logic;
m_in : out std_logic;
co1 : in std_logic_vector(1 downto 0);
co2 : in std_logic_vector(1 downto 0);
zfOut : in std_logic;
aluZF : in std_logic);
end component;
signal ramRW: std_logic;
signal pcInc: std_logic;
signal addrSel: std_logic_vector(1 downto 0);
signal mToIR: std_logic;
signal mToA: std_logic;
signal mToB: std_logic;
signal updZF: std_logic;
signal aluMode: aluModes;
signal mToOut: std_logic;
signal m_in: std_logic;
signal co1: std_logic_vector(1 downto 0);
signal co2: std_logic_vector(1 downto 0);
signal zfOut: std_logic;
signal aluZF: std_logic;
signal addrBus: std_logic_vector(addrLength-1 downto 0);
signal ramOBus: std_logic_vector(wordLength-1 downto 0);
signal ramIBus: std_logic_vector(wordLength-1 downto 0);
signal aluABus: std_logic_vector(wordLength-1 downto 0);
signal aluBBus: std_logic_vector(wordLength-1 downto 0);
signal IBuf: std_logic_vector(wordLength-1 downto 0);
signal OBuf: std_logic_vector(wordLength-1 downto 0);
begin
cpuALU: ALU port map (clk,aluMode,aluABus,aluBBus,zfOut,ramIBus);
cpuRAM: RAM port map (clk,reset,addrBus,ramIBus,ramOBus);
cpuUC: UC port map (clk,reset,ramRW,pcInc,addrSel,mToIR,mToA,mToB,updZF,aluMode,mToOut,m_in,co1,co2,zfOut,aluZF);
cpuUP: UP port map (clk,reset,ramRW,pcInc,addrSel,mToIR,mToA,mToB,updZF,aluMode,mToOut,m_in,co1,co2,zfOut,aluZF,
aluABus,aluBBus,ramOBus,IBuf,OBuf,addrBus);
process(clk) is
begin
IBuf <= IBus;
end process;
OBus <= OBuf;
end;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.constants.all;
entity ram is port (
reset, r_w: in STD_LOGIC;
aBus: in STD_LOGIC_VECTOR(addrLength-1 downto 0); -- bus d'adreçes
iBus: inout STD_LOGIC_VECTOR(wordLength-1 downto 0); -- bus de dades d'entrada
oBus: inout STD_LOGIC_VECTOR(wordLength-1 downto 0)); -- bus de dades de sortida
end ram;
architecture ramArch of ram is
constant memSize: integer := 2**addrLength;
type ram_typ is array(0 to memSize-1) of STD_LOGIC_VECTOR(wordLength-1 downto 0);
signal ram: ram_typ;
begin
process(reset, r_w, aBus, iBus) begin
if reset = '1' then
-- resetejar la ram amb un programa d'exemple
ram(000) <= x"E07F";
ram(001) <= x"E07E";
ram(002) <= x"3FFD";
ram(003) <= x"3E7E";
ram(004) <= x"C007";
ram(005) <= x"8000";
ram(006) <= x"C002";
ram(007) <= x"F07D";
ram(008) <= x"8000";
ram(009) <= x"C009";
ram(010) <= x"0000";
ram(011) <= x"0000";
ram(012) <= x"0000";
ram(013) <= x"0000";
ram(014) <= x"0000";
ram(015) <= x"0000";
ram(016) <= x"0000";
ram(017) <= x"0000";
ram(018) <= x"0000";
ram(019) <= x"0000";
ram(020) <= x"0000";
ram(021) <= x"0000";
ram(022) <= x"0000";
ram(023) <= x"0000";
ram(024) <= x"0000";
ram(025) <= x"0000";
ram(026) <= x"0000";
ram(027) <= x"0000";
ram(028) <= x"0000";
ram(029) <= x"0000";
ram(030) <= x"0000";
ram(031) <= x"0000";
ram(032) <= x"0000";
ram(033) <= x"0000";
ram(034) <= x"0000";
ram(035) <= x"0000";
ram(036) <= x"0000";
ram(037) <= x"0000";
ram(038) <= x"0000";
ram(039) <= x"0000";
ram(040) <= x"0000";
ram(041) <= x"0000";
ram(042) <= x"0000";
ram(043) <= x"0000";
ram(044) <= x"0000";
ram(045) <= x"0000";
ram(046) <= x"0000";
ram(047) <= x"0000";
ram(048) <= x"0000";
ram(049) <= x"0000";
ram(050) <= x"0000";
ram(051) <= x"0000";
ram(052) <= x"0000";
ram(053) <= x"0000";
ram(054) <= x"0000";
ram(055) <= x"0000";
ram(056) <= x"0000";
ram(057) <= x"0000";
ram(058) <= x"0000";
ram(059) <= x"0000";
ram(060) <= x"0000";
ram(061) <= x"0000";
ram(062) <= x"0000";
ram(063) <= x"0000";
ram(064) <= x"0000";
ram(065) <= x"0000";
ram(066) <= x"0000";
ram(067) <= x"0000";
ram(068) <= x"0000";
ram(069) <= x"0000";
ram(070) <= x"0000";
ram(071) <= x"0000";
ram(072) <= x"0000";
ram(073) <= x"0000";
ram(074) <= x"0000";
ram(075) <= x"0000";
ram(076) <= x"0000";
ram(077) <= x"0000";
ram(078) <= x"0000";
ram(079) <= x"0000";
ram(080) <= x"0000";
ram(081) <= x"0000";
ram(082) <= x"0000";
ram(083) <= x"0000";
ram(084) <= x"0000";
ram(085) <= x"0000";
ram(086) <= x"0000";
ram(087) <= x"0000";
ram(088) <= x"0000";
ram(089) <= x"0000";
ram(090) <= x"0000";
ram(091) <= x"0000";
ram(092) <= x"0000";
ram(093) <= x"0000";
ram(094) <= x"0000";
ram(095) <= x"0000";
ram(096) <= x"0000";
ram(097) <= x"0000";
ram(098) <= x"0000";
ram(099) <= x"0000";
ram(100) <= x"0000";
ram(101) <= x"0000";
ram(102) <= x"0000";
ram(103) <= x"0000";
ram(104) <= x"0000";
ram(105) <= x"0000";
ram(106) <= x"0000";
ram(107) <= x"0000";
ram(108) <= x"0000";
ram(109) <= x"0000";
ram(110) <= x"0000";
ram(111) <= x"0000";
ram(112) <= x"0000";
ram(113) <= x"0000";
ram(114) <= x"0000";
ram(115) <= x"0000";
ram(116) <= x"0000";
ram(117) <= x"0000";
ram(118) <= x"0000";
ram(119) <= x"0000";
ram(120) <= x"0000";
ram(121) <= x"0000";
ram(122) <= x"0000";
ram(123) <= x"0000";
ram(124) <= x"FFFF";
ram(125) <= x"0000";
ram(126) <= x"0000";
ram(127) <= x"0000";
elsif r_w = '1' then
ram(conv_integer(unsigned(aBus(addrLength-1 downto 0)))) <= iBus;
end if;
end process;
oBus <= ram(conv_integer(unsigned(aBus(addrLength-1 downto 0))));
end ramArch;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.constants.all;
use work.ctypes.all;
entity UC is port (
clk : in std_logic;
reset : in std_logic;
ramRW : out std_logic;
pcInc : out std_logic;
addrSel : out std_logic_vector(1 downto 0);
mToIR : out std_logic;
mToA : out std_logic;
mToB : out std_logic;
updZF : out std_logic;
aluMode : out aluModes;
mToOut : out std_logic;
m_in : out std_logic;
co1 : in std_logic_vector(1 downto 0);
co2 : in std_logic_vector(1 downto 0);
zfOut : in std_logic;
aluZF : in std_logic);
end UC;
architecture UCArch of UC is
type State is (
fetch,
geta,
getb,
exec_add,
exec_nor,
exec_cmp,
exec_beq,
exec_rot,
exec_in,
exec_out
);
signal cState: state;
begin
process(clk,reset,cState,aluZF,co1,co2) is
begin
if reset = '1' then
cState <= fetch;
else
case cState is
when fetch =>
ramRW <= '0';
pcInc <= '1';
addrSel <= "00";
mToIR <= '1';
mToA <= '0';
mToB <= '0';
updZF <= '0';
aluMode <= mAdd;
mToOut <= '0';
m_in <= '0';
cState <= getb;
when getb =>
ramRW <= '0';
pcInc <= '0';
addrSel <= "11";
mToIR <= '0';
mToA <= '0';
mToB <= '1';
updZF <= '0';
aluMode <= mAdd;
mToOut <= '0';
m_in <= '0';
if ((co1="00") or (co1="01") or (co1="10")) then
cState <= geta;
elsif (co1 = "11") then
case co2 is
when "00" => --beq
if (aluZF = '1') then
cState <= exec_beq;
else
cState <= fetch;
end if;
when "01" => --rot
cState <= exec_rot;
when "10" => --in
cState <= exec_in;
when "11" => --out
cState <= exec_out;
when others => -- invalid co2 value
cState <= fetch;
end case;
else -- invalid co1 value
cState <= fetch;
end if;
when geta =>
ramRW <= '0';
pcInc <= '0';
addrSel <= "10";
mToIR <= '0';
mToA <= '1';
mToB <= '0';
updZF <= '0';
aluMode <= mAdd;
mToOut <= '0';
m_in <= '0';
case co1 is
when "00" =>
cState <= exec_add;
when "01" =>
cState <= exec_nor;
when "10" =>
cState <= exec_cmp;
when others =>
cState <= fetch;
end case;
when exec_add =>
ramRW <= '1';
pcInc <= '0';
addrSel <= "11";
mToIR <= '0';
mToA <= '0';
mToB <= '0';
updZF <= '1';
aluMode <= mAdd;
mToOut <= '0';
m_in <= '0';
cState <= fetch;
when exec_nor =>
ramRW <= '1';
pcInc <= '0';
addrSel <= "11";
mToIR <= '0';
mToA <= '0';
mToB <= '0';
updZF <= '1';
aluMode <= mNor; -- NOR
mToOut <= '0';
m_in <= '0';
cState <= fetch;
when exec_cmp =>
ramRW <= '0'; -- do not write the result
pcInc <= '0';
addrSel <= "11";
mToIR <= '0';
mToA <= '0';
mToB <= '0';
updZF <= '1';
aluMode <= mCmp; -- XOR
mToOut <= '0';
m_in <= '0';
cState <= fetch;
when exec_beq =>
ramRW <= '0';
pcInc <= '1';
addrSel <= "11";
mToIR <= '1';
mToA <= '0';
mToB <= '0';
updZF <= '0';
aluMode <= mAdd;
mToOut <= '0';
m_in <= '0';
cState <= getb;
when exec_rot =>
ramRW <= '1'; -- Write to RAM
pcInc <= '0';
addrSel <= "11"; -- D
mToIR <= '0';
mToA <= '0';
mToB <= '0';
updZF <= '1';
aluMode <= mRot; -- ROT
mToOut <= '0';
m_in <= '0';
cState <= fetch;
when exec_in =>
ramRW <= '0';
pcInc <= '0';
addrSel <= "11";
mToIR <= '0';
mToA <= '1'; -- write to A
mToB <= '1'; -- write to B
updZF <= '0';
aluMode <= mAdd;
mToOut <= '0';
m_in <= '1'; -- A <= IN; B <= 0;
cState <= fetch;
when exec_out =>
ramRW <= '0';
pcInc <= '0';
addrSel <= "11"; -- D
mToIR <= '0';
mToA <= '0';
mToB <= '0';
updZF <= '0';
aluMode <= mAdd;
mToOut <= '1'; -- Put D to Out
m_in <= '0';
cState <= fetch;
-- s'ha d'acavar (06/12/2005 01:50)
when others =>
ramRW <= '0';
pcInc <= '0';
addrSel <= "00";
mToIR <= '0';
mToA <= '0';
mToB <= '0';
updZF <= '0';
aluMode <= mAdd;
mToOut <= '0';
m_in <= '0';
cState <= fetch;
end case;
end if;
end process;
end UCArch;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.constants.all;
use work.ctypes.all;
entity UP is port (
clk : in std_logic;
reset : in std_logic;
ramRW : in std_logic;
pcInc : in std_logic;
addrSel : in std_logic_vector(1 downto 0);
mToIR : in std_logic;
mToA : in std_logic;
mToB : in std_logic;
updZF : in std_logic;
aluMode : in aluModes;
mToOut : in std_logic;
m_in : in std_logic;
co1 : out std_logic_vector(1 downto 0);
co2 : out std_logic_vector(1 downto 0);
zfOut : out std_logic;
zfAlu : in std_logic;
aBus : out std_logic_vector(wordLength-1 downto 0); -- sortida del registre A cap a la ALU
bBus : out std_logic_vector(wordLength-1 downto 0); -- sortida del registre A cap a la ALU
mrBus : in std_logic_vector(wordLength-1 downto 0); -- sortida de dades de la UP cap a la RAM
iBus : in std_logic_vector(wordLength-1 downto 0); -- entrada de dades del port d'E/S
oBus : out std_logic_vector(wordLength-1 downto 0); -- sortida de dades del port d'E/S
addrBus : out std_logic_vector(addrLength-1 downto 0)
);
end UP;
architecture UPArch of UP is
signal PC: std_logic_vector(addrLength-1 downto 0);
signal IR: std_logic_vector(wordLength-1 downto 0);
signal A: std_logic_vector(wordLength-1 downto 0);
signal B: std_logic_vector(wordLength-1 downto 0);
signal ZF: std_logic;
signal CAddr: std_logic_vector(addrLength-1 downto 0);
begin
IR <= mrBus when mToIR = '1';
A <= mrBus when ((mToA = '1') and (m_in = '0'));
A <= iBus when ((mToA = '1') and (m_in = '1'));
B <= mrBus when ((mToB = '1') and (m_in = '0'));
B <= (B'range => '0') when ((mToB = '1') and (m_in = '1'));
oBus <= mrBus when mToOut = '1';
ZF <= zfAlu when updZF = '1';
zfOut <= ZF;
co1 <= IR(wordLength-1 downto wordLength-2);
co2 <= IR(wordLength-3 downto wordLength-4);
process(reset,pcInc,addrSel) is
begin
case addrSel is
when "00" =>
CAddr <= PC;
when "10" =>
CAddr <= IR(6 downto 0);
when "11" =>
CAddr <= IR(13 downto 7);
when others =>
CAddr <= (CAddr'range => '0');
end case;
if reset = '1' then
PC <= (PC'range => '0');
elsif (pcInc = '1') then
PC <= (unsigned(CAddr)+1);
end if;
end process;
addrBus <= CAddr;
end UPArch;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment