Created
October 14, 2013 19:28
-
-
Save gigaherz/6980749 to your computer and use it in GitHub Desktop.
An implementation of a simple 4-instruction CPU, in VHDL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package constants is | |
constant wordLength: integer := 16; -- Tamany de paraula | |
constant addrLength: integer := 7; -- Tamany d'adreça | |
end package constants; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ctypes is | |
type aluModes is (mAdd,mNor,mCmp,mRot); | |
end package ctypes; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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