KANE, Gerry.; HEINRICH, Joe.. MIPS RISc architecture. Upper Saddle River (NJ):
Prentice Hall PTR, c1992.. x-25 p. ISBN 0135904722.
Códigos
controlunit.vhd
entity controlUnit is port (
--- SINAIS
--- O relógio do processador.
clock : in bit;
-- Reseta a unidade de controle.
reset : in bit;
-- Flag da ULA que indica overflow da ULA !!
Overflow : in bit;
-- Flag Da Ula
Negativo : in bit;
-- Sinaliza quando S for zero
z : in bit;
-- Sinaliza se A=B
Igual : in bit;
-- Sinaliza se A>B
Maior : in bit;
-- Sinaliza se A<B
Menor : in bit;
-- Indica a operação a ser realizada pelo banco de registradores leitura (0) escrita (1).
reset_Bank : out bit;
RegWrite : out bit;
-- Indica o tipo do deslocamento
ShiftN : out bit_vector(1 downto 0);
-- Controla a caixa MULTDIV
MultDivStart : out bit; -- inicia a operacao
MultDiv : out bit; -- seleciona a mult ou div
DivByZero : in bit; -- indica se exceção divByZero occoreu MultDivFinished : in bit;
--- REGISTRADORES
--- Controla o registrador que guarda a primeira saída do banco de registradores.
LoadA : out bit;
ResetA : out bit;
-- Controla o registrador que guarda a segunda saída do banco de registradores.
LoadB : out bit;
ResetB : out bit;
-- Controla o registrador que guarda o resultado da ALU.
LoadALUOut : out bit;
ResetALUOut : out bit;
-- Registradores HI e LO
LoadHiLo : out bit;
ResetHiLo : out bit;
-- Saídas que controlam registrador que guarda PC (Program Counter).
PCWriteCond : out bit;
PCWrite : out bit;
PCReset : out bit;
-- Controla o Memory Data Register com Load, Reset e a operação a ser realizada(MdrType)
MdrLoad : out bit;
MdrReset : out bit;
MdrType : out bit_vector(1 downto 0); -- seta a operação(byte, half, word) do MDR de acordo com o valor passado
-- Registrador EPC que guarda onde houve erro (exceção) EPCLoad : out bit;
EPCReset : out bit;
--- MULTIPLEXADORES
-- Controlam os Multiplexadores das entradas de ALU.
ALUSrcA : out bit;
ALUSrcB : out bit_vector(1 downto 0);
-- Seleciona a operação que a ALU irá realizar.
ALUOp : out bit_vector(2 downto 0);
-- Controla o valor a ser carregado no PC.
PCSource : out bit_vector(2 downto 0);
-- Controla o mux que selecionará os dados a serem escritos no banco de registradores.
MemToReg : out bit_vector(2 downto 0);
-- Controla o mux que seleciona o endereço de memória a ser lido ou escrito.
IorD : out bit_vector(1 downto 0);
-- Seleciona o registrador a ser gravado no banco de registradores RegDst : out bit_vector(1 downto 0);
-- Seleciona o Mux que possui o valor da ULA e do Shift N
MuxOp : out bit;
-- -- Seleciona o Mux que possui constantes usadas no SLT, SLTI e Exceções.
EXCode : out bit_vector(1 downto 0)
);
end controlUnit;
architecture arqControlUnit of controlUnit is
type state is (resetCPU, -- Reseta a unidade de controle
Fetch, -- Carrega o novo valor de PC no seu registrador
ReadMemory1, -- Soma PC + 4
ReadMemory2,-- Espera que a memória seja lida LoadInstruction, -- Aguarda o valor lido na memória ser liberado no instruction register
LoadInstructionRegister, writeRegister, writememory,
-- decoder, -- Decodifica a instrução que será executada
DivByZeroHandler, WaitMultDiv, mult,
div,
shiftRightA, shiftRightL, shiftLeftL, -- Instruções de deslocamento
beq, bne1, bne2, bne3, -- Instruçoes de pulo condicional
slt, slti,
j, jr, jal, -- Pulo não condicional
LoadPC, --estado para escrever pc apos os jumps.
rte, -- Retorno de exceção loadPCEX,
writeReg31, --estado para carregar o pc no reg 31.
writeEPC0, writeEPC,
break -- Pára execução do programa
-- Nop -- Sem operacao
);
signal currentState : state;
signal SP : bit_vector(31 downto 0); -- Stack
point, posição do topo da pilha
signal next_of_next : state; -- State gambieirror pra fazer droga nenhuma e comer tempo !!
begin
process (clock, reset) begin
if (reset = '1') then
currentState <= resetCPU;
elsif (clock'event and clock = '1') then case currentState is
--- Idle state
when idleState =>
--IorD <= 0;
--MemWrite <= 0;
currentState <= next_of_next;
---when resetCPU =>
SP <= "00000000000000000000000011100011";
controlWrite <= "00";
IRWrite <= '0';
MemoryIO <= '0';
RegDst <= "00";
RegWrite <= '0';
MultDivStart <= '0';
MultDiv <= '0';
ResetA <= '1';
ResetB <= '1';
ResetHiLo <= '1';
reset_Bank <= '1';
ALUSrcA <= '0';
ALUSrcB <= "00";
MdrReset <= '1';
EPCLoad <= '0';
EPCReset <= '1';
ALUOp <= "000";
PCSource <= "000";
PCWrite <= '0';
PCWriteCond <= '0';
PCReset <= '1';
ShiftN <= "00";
MemToReg <= "000";
IorD <= "00";
MuxOp <= '0';
loadHiLo <= '0';
mdrLoad <= '0';
MdrType <= "00";
currentState <= Fetch;
--- Carrega PC e ativa leitura na memória
when Fetch =>
ResetA <= '0';
ResetB <= '0';
ResetALuOut <= '0';
ResetHilo <= '0';
PCReset <= '0';
MdrReset <= '0';
EPCReset <= '0';
reset_Bank <= '0';
mdrLoad <= '0';
LoadAluOut <= '0'; -- mantém valor no aluOut PCWrite <= '0'; -- mantém o valor de PC PcWriteCond <= '0'; -- mantém o valor de PC MemoryIO <= '0'; -- lê da memória IOrd <= "00"; -- MUX do PC e ALUout regWrite <= '0'; -- pra garantir que o
ALUSrcB <= "01"; -- seleciona 4 para somar com PC
PCSource <= "000"; -- deixa passar pelo multiplexador o valor da soma
PCWrite <= '0'; -- mantém o registrador que contém PC com o seu valor atual.00
currentState <= ReadMemory2;
--- Segundo estado de leitura da memória, teoricamente ao término desse o valor lido estará disponível
---- Grava novo valor no PC (PC + 4) when ReadMemory2 =>
IRWrite <= '1'; -- habilita carregamento de valor no IR
PCWrite <= '1';
--mdrLoad <= '1';
--mdrType <= "00";
currentState <= LoadInstructionRegister;
--- Aguarda o Intruction Register decompor o valor lido na memória e no próximo clock libera os resultados
when LoadInstructionRegister =>
PCWrite <= '0'; -- hold IRWrite <= '0'; -- hold
--mdrLoad <= '1';
currentState <= LoadInstruction;
--- Envia o valor lido da memória, já decomposto e carrega os valores do Registrador A e B
when LoadInstruction =>
-- Soma o valor do registradores para aumentar a perfomance de algumas intruções
loadA <= '1';
loadB <= '1';
ALUSrcA <= '1'; -- seleciona o
valor do registrador A
ALUSrcB <= "00"; -- seleciona o valor do registrador B
MuxOP <= '0'; -- seleciona o resultado ULA para ALUOut
ALUOP <= "001"; -- seleciona a SOMA na alu
currentState <= decoder;
--- Decodifica a instrução no Instruction Register a ser executada - Início do Big Ultra Monster CASE plus plus ++
---when decoder =>
IRWrite <= '0';
-- Carrega em aluOUt o resultado da soma realizada no ciclo anterior
-- LoadAluOut <= '0';
loadA <= '0';
loadB <= '0';
-- Decodifica a instrução
case instruction(31 downto 26) is -- checa o OP CODE when "000000" =>
case instruction(5 downto 0) is -- function when "000000" =>
if(instruction =
"00000000000000000000000000000000") then -- no operation
currentState <= Fetch;
else
shiftN <= "10";
muxOP <= '1';
memToReg <= "000";
RegDst <= "01";
--MultDiv <=
'1';
currentState <= loadALURe-sult;
end if;
---
--- mfhi
---
---when "010000" =>
MemToReg <=
"010";
RegDst <=
"01";
currentState <= WriteReg-ister;
---
--- mflo
---
---when "010010" =>
MemToReg <=
if(Overflow = '1') then
--PCSource <=
"101";-- seleciona posicao da memoria pra tratar o overflow
currentState <= Over-flowHandle;
else
LoadALUOut <=
'1';
MemtoReg <=
"000"; --seleciona valor a ser gravado
RegDst <=
"01"; -- registrador destino
currentState <= WriteReg-ister;
end if;
--- sub
---when "100010" =>
-- seleciona a subtração na ALU.
ALUOP <= "010";
MuxOp <= '0'; -- deixa passar o valor da ALU currentState <= OverflowHandle;
--- addu
---when "100001" =>
LoadALUOut <= '1';
MemtoReg <= "000";
RegDst <= "01";
MuxOp <= '0'; -- deixa passar o valor da ALU currentState <= writeRegister;
--- subu
---when "100011" =>
-- seleciona a subtração na ALU.
ALUOP <= "010";
MemtoReg <= "000"; --seleciona valor a ser gravado RegDst <= "01"; -- registrador destino
currentState <= loadALUResult;
--- and
---when "100100" =>
-- seleciona a operação de and na ULA ALUOP <= "011";
MemtoReg <= "000"; --seleciona valor a ser gravado RegDst <= "01"; -- registrador destino
currentState <= loadALUResult;
--- xor
---ALUOP <= "110";
MemtoReg <= "000"; --seleciona valor a ser gravado RegDst <= "01"; -- registrador destino
currentState <= loadALUResult;
--- Mult
---when "011000" =>
LoadA <= '0';
LoadB <= '0';
AlUSrcA <= '1'; -- seleciona o registrador A AlUSrcB <= "00"; --seleciona o registrador B currentState <= mult;
--- Div
---when "011010" =>
LoadA <= '0';
LoadB <= '0';
AlUSrcA <= '1'; -- seleciona o registrador A AlUSrcB <= "00"; --seleciona o registrador B currentState <= div;
--- Sra
---when "000011" =>
MemToReg <= "000";
shiftN <= "01";
RegDst <= "01";
MuxOp <= '1';
currentState <= loadALUResult;
--- Srl
---when "000010" =>
MemToReg <= "000";
RegDst <= "01";
shiftN <= "00";
MuxOp <= '1';
currentState <= loadALUResult;
---ALUOP <= "000"; --Seleciona carregar na saida da ula O reg. A.
MuxOP <= '0'; --seleciona muxOP para passar a saida da ULA.
currentState <= jr;
--- break
---when "001101" =>
currentState <= break;
when others =>
currentState <= resetCPU;-- ou LANÇAR EXCEÇÃO ??
end case; -- op CODE 000000
--- Load Word
---when "100011" =>
AluSrcA <= '1'; --seleciona a passagem do
Reg. a no mux ALUSrcA.
AluSrcB <= "10"; --seleciona a passagem do mdr no mux ALUSrcB.
ALUOP <= "001"; --seleciona a ula para somar.
next_of_next <= loadword; --estado padrao para os loads.
currentState <= load;
--- Load Byte
---when "100000" =>
ALUSrcA <= '1';
--seleciona a passagem do Reg. a no mux ALUSrcA.
ALUSrcB <= "10";
--seleciona a passagem do mdr no mux ALUSrcB.
ALUOP <= "001";
--seleciona a ula para somar.
next_of_next <= loadbyte; --estado padrao para os loads.
currentState <= load;
--- Load Half
---when "100001" =>
AluSrcA <= '1'; --eleciona a passagem do
Reg. a no mux ALUSrcA.
AluSrcB <= "10";
--seleciona a passagem do mdr no mux ALUSrcB.
ALUOP <= "001";
--seleciona a ula para somar.
next_of_next <= loadhalf; --estado padrao para os loads.
currentState <= load;
--- Store Word
---when "101011" =>
AluSrcA <= '1'; -- seleciona valor do registrador A e envia-o pra ULA
MuxOP <= '0'; --seleciona o conteúdo da ULA
controlwrite <= "00"; -- ajusta o preStore pra gravar a palavra inteira(o valor de entrada eh o registrador B)
-- next_of_next <= storeWord;
currentState <= store;
--- Store Byte
---when "101000" =>
AluSrcA <= '1'; -- seleciona valor do registrador A e envia-o pra ULA
AluSrcB <= "10"; -- seleciona o valor do Deslocamento
AluOp <= "001"; -- realiza soma na ULA
MuxOP <= '0'; --seleciona o
conteúdo da ULA
controlwrite <= "10"; -- manipula o byte menos significativo a ser gravado!
-- next_of_next <= storebyte;
currentState <= store;
--- Store Half
---when "101001" =>
AluSrcA <= '1'; -- seleciona valor do registrador A e envia-o pra ULA
AluSrcB <= "10"; -- seleciona o valor do Deslocamento
AluOp <= "001"; -- realiza soma na ULA
MuxOP <= '0'; --seleciona o
conteúdo da ULA
controlWrite <= "01"; -- manipula meia palavra pra ser gravada na memória
-- next_of_next <= storehalf;
currentState <= store;
--- Load upper Immediate
---when "001111" =>
regdst <= "00"; --seleciona o registrador destino memtoreg <= "111";
-- addiu
---when "001001" =>
ALUSrcB <= "10"; -- seleciona a constante ALUOP <= "001"; -- operação de add na ALU MemtoReg <= "000"; -- seleciona valor a ser gravado RegDst <= "00"; -- registrador destino
currentState <= writeRegister;
--- andi
---when "001101" =>
ALUSrcB <= "10"; -- seleciona a constante
ALUOP <= "011"; -- opreção de and na ALU
MemtoReg <= "000"; -- seleciona valor a ser gravado
RegDst <= "00"; -- registrador destino
currentState <= loadALUResult;
--- xori
---when "001110" =>
ALUSrcB <= "10" ; -- seleciona a constante
ALUOP <= "110" ; -- seleciona operação de xor na ALU
MemtoReg <= "000" ; -- seleciona valor a ser gravado
RegDst <= "00" ; -- registrador destino
currentState <= loadALUResult;
--- BEQ - ---
---when "000100" =>
AluSrcB <= "11"; -- seleciona o deslocamento
AluSrcA <= '0'; -- PC
ALUOP <= "001"; -- soma
loadAluOut <= '1'; -- carrega aluOut currentState <= beq;
--- BNE - ---
---when "000101" =>
AluSrcB <= "11"; -- seleciona o deslocamento
AluSrcA <= '0'; -- PC
ALUOP <= "001"; -- soma PC + deslocamento currentState <= bne1;
slti ---
---AluSrcA <= '1'; --seleciona o mux do reg. A para passar o valor do reg.
AluSrcB <= "10"; --seleciona o mux do reg. B para passar a constante com sinal extendido.
ALUOP <= "111"; --seleciona a ula para comparar.
currentState <= slti;
--- j --- ---
---when "000010" =>
PCSource <= "010"; --seleciona pcSource para passar o valor do pc.
currentState <= LoadPC;
--- jal --- ---
---when "000011" =>
ALUSrcA <= '0'; --seleciona o mux do reg. A para passar o valor do reg.
ALUOP <= "000"; --Seleciona a ULA para carregar A na saida (deixa passa A).
PcSource <= "010"; --seleciona pcSource para passar o valor do pc.
currentState <= jal;
--- rte --- ---
---when "010000" =>
PCSource <= "011"; -- seleciona valor do EPC pra o PC
PCwrite <= '1'; -- grava novo valor do PC
currentState <= fetch;
---UnKnow OpCode---
---when others =>
ALUSrcA <= '0';
ALUSrcB <= "01";
ALUOP <= "010";
-- tratamento de exceção de OverFlow if(Overflow = '1') then
-- seleciona posicao da memoria pra tratar o overflow
ALUSrcA <= '0';
ALUSrcB <= "01";
ALUOP <= "010";
muxOp <= '0'; -- seleciona o resultado da ULA
PCSource <= "100";
IorD <= "10";
MemoryIO <= '0';
EXCode <= "10";
PCSource <= "100";
currentState <= writeEPC0;
else
LoadALUOut <= '1';
MemtoReg <= "000"; --seleciona valor a ser gravado
--RegDst <= "01"; -- registrador destino
currentState <= WriteRegister;
end if;
--- Carrega o valor do resultado da ALU no registrador ALUout
---when loadALUResult =>
loadALUOut <= '1';
currentState <= writeRegister;
--- Reliza a gravavação no registrador.
---when WriteRegister =>
MdrLoad <= '0';
loadALUOut <= '0'; -- desabilita gravação do AluOut
regWrite <= '1';
currentState <= fetch;
--- Instruções de LOAD --- ---
---when load =>
Iord <= "01";
LoadAluOut <= '1';
currentState <= load1;
when load1 =>
MemoryIO <= '0';
currentState <= WaitReadMemory1;
--- Primeiro dos 2 ciclos de leitura da memória when WaitReadMemory1 =>
currentState <= WaitReadMemory2;
--- Último Ciclo de leitura da memória (ao término o valor da memória
MdrLoad <= '0';
currentState <= next_of_next;
--- Load Word --- ---
---when LoadWord =>
MdrLoad <= '1';
MdrType <= "00"; -- desabilita deslocamento
RegDst <= "00"; -- seleciona o registrador destino
MemtoReg <= "001"; -- seleciona valor lido da memória
currentState <= writeRegister;
--- Load Half --- ---
---when LoadHalf =>
MdrLoad <= '1';
MdrType <= "10"; -- Realiza 16 deslocamentos para a direita --OBS:Trocado por anti-patern
RegDst <= "00"; -- seleciona o registrador destino
MemtoReg <= "001"; -- seleciona valor lido da memória
currentState <= writeRegister;
--- Load Byte --- ---
---when LoadByte =>
MdrLoad <= '1';
MdrType <= "01"; -- Realiza 24 deslocamentos para a direita --OBS:Trocado por anti-patern
RegDst <= "00"; -- seleciona o registrador destino
MemtoReg <= "001"; -- seleciona valor lido da memória
currentState <= writeRegister;
--- Instruções de --- STORE---
---when store =>
--- Instruções de MULT/DIV ---
---when mult =>
MultDivStart <= '1';
MultDiv <= '0';
currentState <= WaitMultDiv;
when div =>
MultDivStart <= '1';
MultDiv <= '1';
currentState <= WaitMultDiv;
--- Wait Final Operation --- ---
---when WaitMultDiv =>
MultDivStart <= '0';
if(MultDivFinished = '1') then if(DivByZero = '1') then
currentState <= DivByZeroHandler; --trata-mento de exceção
else
LoadHiLo <='1';
currentState <= fetch;
end if;
else
currentState <= WaitMultDiv;
end if;
--- ESTADO DE TRATAMENTO DE EXCEÇÂO ---
---when DivByZeroHandler =>
-- seleciona posicao da memoria pra tratar a divisão por zero
ALUSrcA <= '0';
ALUSrcB <= "01";
ALUOP <= "010";
muxOp <= '0'; -- seleciona o resultado da ULA PCSource <= "100";
IorD <= "10";
MemoryIO <= '0';
EXCode <= "01";
PCSource <= "100";
currentState <= writeEPC0;
--- beq -- ---
---when beq =>
AluSrcA <= '1';
AluSrcB <= "00";
AluOp <= "010";
pcSource <= "001";
PcWriteCond <= '1';
currentState<= fetch;
---when bne1 =>
loadAluout <= '1';
currentState <= bne2;
when bne2 =>
loadAluout <= '0';
AluSrcA <= '1';
AluSrcB <= "00";
AluOp <= "111";
currentState <= bne3;
when bne3 =>
if(igual = '0') then
PCSource <="001";
PCWrite <= '1';
else PCWrite <= '0';
end if;
currentState <= fetch;
--- slt -- ---
---when slt =>
if(Menor = '1') then
MemToReg <= "101"; -- seleciona a entrada 5 do mux
else
MemToReg <= "100";
end if;
currentState <= writeRegister;
--- slti -- ---
---when slti =>
regDst <= "00"; --seleciona para passar o endereco do reg. a escrever.
if(Menor = '1') then
MemToReg <= "101"; -- seleciona a entrada 5 do mux
else
when LoadPC =>
LoadALUOut <= '0';
PCWrite <= '1';
currentState <= fetch;
--- jal -- ---
---when jal =>
LoadALUOut <= '1';
MemToReg <= "000";
RegDst <= "10";
PCWrite <= '1';
PCSource <= "010";
currentState <= writeReg31;
--- Write Reg31 --- ---
---when writeReg31 =>
PCWrite <= '0';
--PCSource <= "010";
LoadALUOut <= '0';
RegWrite <= '1';
currentState <= fetch;
--- break -- ---
---when break =>
currentState <= break; -- põe essa droga em Loop
--- WriteECP -- ---
---when writeEPC0 =>
-- EPCLoad <= '0';
currentState <= writeEPC;
--- WriteECP -- ---
---when writeEPC =>
EPCLoad <= '1';
currentState <= loadPCEX;
--- WriteECP -- ---
---when loadPCEX =>
EPCLoad <= '0';
PCWrite <= '1';
currentState <= fetch;
when others =>
currentState <= Fetch;
end case;
end if;
end arqControlUnit;