234 lines
8.5 KiB
VHDL
Executable File
234 lines
8.5 KiB
VHDL
Executable File
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
entity controller is
|
|
port(
|
|
clk : in std_logic;
|
|
reset_n : in std_logic;
|
|
-- instruction opcode
|
|
op : in std_logic_vector(5 downto 0);
|
|
opx : in std_logic_vector(5 downto 0);
|
|
-- activates branch condition
|
|
branch_op : out std_logic;
|
|
-- immediate value sign extention
|
|
imm_signed : out std_logic;
|
|
-- instruction register enable
|
|
ir_en : out std_logic;
|
|
-- PC control signals
|
|
pc_add_imm : out std_logic;
|
|
pc_en : out std_logic;
|
|
pc_sel_a : out std_logic;
|
|
pc_sel_imm : out std_logic;
|
|
-- register file enable
|
|
rf_wren : out std_logic;
|
|
-- multiplexers selections
|
|
sel_addr : out std_logic;
|
|
sel_b : out std_logic;
|
|
sel_mem : out std_logic;
|
|
sel_pc : out std_logic;
|
|
sel_ra : out std_logic;
|
|
sel_rC : out std_logic;
|
|
-- write memory output
|
|
read : out std_logic;
|
|
write : out std_logic;
|
|
-- alu op
|
|
op_alu : out std_logic_vector(5 downto 0)
|
|
);
|
|
end controller;
|
|
|
|
architecture synth of controller is
|
|
|
|
type state is (FETCH1, FETCH2, DECODE, R_OP, STORE, BREAK, LOAD1, I_OP, LOAD2, BRANCH, CALL,CALLR, JMP, JMPI, UI_OP, RI_OP);
|
|
signal s_cur : state;
|
|
signal s_next : state;
|
|
|
|
begin
|
|
|
|
--FSM masuta controls
|
|
fsm_ctrl : process(clk, reset_n) is
|
|
begin
|
|
if(reset_n = '0') then
|
|
s_cur <= FETCH1;
|
|
elsif(rising_edge(clk)) then
|
|
s_cur <= s_next;
|
|
end if;
|
|
end process;
|
|
|
|
--control states
|
|
s_next <= FETCH2 when s_cur = FETCH1 else
|
|
DECODE when s_cur = FETCH2 else
|
|
BREAK when s_cur = BREAK else
|
|
LOAD2 when s_cur = LOAD1 else
|
|
FETCH1 when (s_cur = LOAD2 or s_cur = STORE or
|
|
s_cur = R_OP or s_cur = I_OP or s_cur = RI_OP or s_cur = UI_OP or
|
|
s_cur = BRANCH or s_cur = CALL or s_cur = CALLR or s_cur = JMP or s_cur = JMPI) else
|
|
R_OP when (s_cur = DECODE and op = "111010" and (opx = "011011" or --srl
|
|
opx = "110001" or --add
|
|
opx = "111001" or --sub
|
|
opx = "001000" or --cmple
|
|
opx = "010000" or --cmpgt
|
|
opx = "000110" or --nor
|
|
opx = "001110" or --and
|
|
opx = "010110" or --or
|
|
opx = "011110" or --xnor
|
|
opx = "010011" or --sll
|
|
opx = "111011" or --sra
|
|
opx = "011000" or --cmpne
|
|
opx = "100000" or --cmpeq
|
|
opx = "101000" or --cmpleu
|
|
opx = "110000" or --cmpgtu
|
|
opx = "000011" or --rol
|
|
opx = "001011") --ror
|
|
) else
|
|
I_OP when (s_cur = DECODE and (op = "000100" or --addi
|
|
op = "001000" or --cmplei
|
|
op = "010000" or --cmpgti
|
|
op = "011000" or --cmpnei
|
|
op = "100000") --cmpeqi
|
|
-- op = "001010") --????????????????????????????????????????
|
|
) else
|
|
UI_OP when (s_cur = DECODE and (op = "001100" or --andi
|
|
op = "010100" or --ori
|
|
op = "011100" or --xnori
|
|
op = "101000" or --cmpleui
|
|
op = "110000") --cmpgtui
|
|
) else
|
|
RI_OP when (s_cur = DECODE and op = "111010" and (opx = "010010" or --slli
|
|
opx = "011010" or --srli
|
|
opx = "111010" or --srai
|
|
opx = "000010") --roli
|
|
) else
|
|
LOAD1 when (s_cur = DECODE and op = "010111") else --ldw
|
|
STORE when (s_cur = DECODE and op = "010101") else --stw
|
|
BRANCH when (s_cur = DECODE and (op = "000110" or --br
|
|
op = "001110" or --ble
|
|
op = "010110" or --bgt
|
|
op = "011110" or --bne
|
|
op = "100110" or --beq
|
|
op = "101110" or --bleu
|
|
op = "110110") --bgtu
|
|
) else
|
|
CALL when (s_cur = DECODE and op = "000000") else --call
|
|
CALLR when (s_cur = DECODE and opx = "011101") else --callr
|
|
JMP when (s_cur = DECODE and (opx = "001101" or --jmp
|
|
opx = "000101") --ret
|
|
) else
|
|
JMPI when (s_cur = DECODE and op = "000001") else --jmpi
|
|
BREAK when (s_cur = DECODE and op = "111010" and opx = "110100"); --break
|
|
|
|
--====== All state handlers =======--
|
|
pc_add_imm <= '1' when (s_cur = BRANCH) else '0';
|
|
|
|
pc_sel_a <= '1' when (s_cur = JMP or s_cur = CALLR) else'0';
|
|
|
|
pc_sel_imm <= '1' when (s_cur = CALL or s_cur = JMPI) else '0';
|
|
|
|
sel_pc <= '1' when s_cur = CALL or s_cur = CALLR else '0';
|
|
|
|
|
|
branch_op <= '1' when s_cur = BRANCH else '0';
|
|
|
|
pc_en <= '1' when (s_cur = FETCH1 or s_cur = CALL or s_cur = CALLR or s_cur = JMP or s_cur = JMPI) else '0';
|
|
|
|
read <= '1' when (s_cur = FETCH1 or
|
|
s_cur = LOAD1) else '0';
|
|
|
|
write <= '1' when (s_cur = STORE) else '0';
|
|
|
|
ir_en <= '1' when (s_cur = FETCH2) else '0';
|
|
|
|
rf_wren <= '1' when (s_cur = R_OP or
|
|
s_cur = RI_OP or
|
|
s_cur = I_OP or
|
|
s_cur = UI_OP or
|
|
s_cur = CALL or
|
|
s_cur = CALLR or
|
|
s_cur = LOAD2) else '0';
|
|
|
|
sel_rC <= '1' when (s_cur = R_OP or s_cur = RI_OP or s_cur = CALLR) else '0';
|
|
|
|
sel_b <= '1' when (s_cur = R_OP or s_cur = BRANCH) else '0';
|
|
|
|
sel_ra <= '1' when (s_cur = CALL or s_cur = CALLR) else '0';
|
|
|
|
sel_addr <= '1' when (s_cur = LOAD1 or
|
|
s_cur = STORE) else '0';
|
|
|
|
sel_mem <= '1' when s_cur = LOAD2 else '0';
|
|
|
|
imm_signed <= '1' when (s_cur = I_OP or
|
|
s_cur = LOAD1 or
|
|
s_cur = STORE) else '0';
|
|
|
|
-- Alu state
|
|
op_alu <= "000000" when (op = "000100" or --addi
|
|
op = "010111" or --ldw
|
|
op = "010101" --stw
|
|
) else --rA + (signed)imm
|
|
"000110" when (op = "111010" and opx = "110001" --add
|
|
) else --rA + rB
|
|
"001111" when (op = "111010" and opx = "111001" --sub
|
|
) else --rA - rB
|
|
"100001" when (op = "111010" and opx = "001110" --and
|
|
) else --rA & rB
|
|
"100001" when (op = "001100" --andi
|
|
) else --rA & (unsigned)imm
|
|
"100010" when (op = "111010" and opx = "010110" --or
|
|
) else --rA | rB
|
|
"101010" when (op = "010100" --ori
|
|
) else --rA | (unsigned)imm
|
|
"100011" when (op = "111010" and opx = "011110" --xnor
|
|
) else --rA xnor rB
|
|
"100011" when (op = "011100" --xnori
|
|
) else --rA xnor (unsigned)imm
|
|
"100000" when (op = "111010" and opx = "000110" --nor
|
|
) else --rA nor rB
|
|
"111011" when (op = "111010" and opx = "011010" --srli
|
|
) else --(unsigned)rA >> imm
|
|
"110011" when (op = "111010" and opx = "011011" --srl
|
|
) else --(unsigned)rA >> rB
|
|
"111010" when (op = "111010" and opx = "010010" --slli
|
|
) else --(unsigned)rA << imm
|
|
"110010" when (op = "111010" and opx = "010011" --sll
|
|
) else --(unsigned)rA << rB
|
|
"111111" when (op = "111010" and opx = "111010" --srai
|
|
) else --(signed)rA >> imm
|
|
"110111" when (op = "111010" and opx = "111011" --sra
|
|
) else --(signed)rA >> rB
|
|
"011001" when (op = "001110" or --ble
|
|
op = "001000" or --cmplei
|
|
(op = "111010" and opx = "001000") --cmple
|
|
) else -- rA <= rB , rA <= (signed)imm
|
|
"011010" when (op = "010110" or --bgt
|
|
op = "010000" or --cmpgti
|
|
(op = "111010" and opx = "010000") --cmpgt
|
|
) else -- rA > rB , rA > (signed)imm
|
|
"011011" when (op = "011110" or --bne
|
|
op = "011000" or --cmpnei
|
|
(op = "111010" and opx = "011000") --cmpne
|
|
) else -- rA != rB , rA != (signed)imm
|
|
"011100" when (op = "100110" or --beq
|
|
op = "100000" or --cmpeqi
|
|
(op = "111010" and opx = "100000") --cmpeq
|
|
) else --rA = rB , rA = (signed)imm
|
|
"011101" when (op = "101110" or --bleu
|
|
op = "101000" or --cmpleui
|
|
(op = "111010" and opx = "101000") --cmpleu
|
|
) else --(unsigned)rA <= (unsigned)rB , (unsigned)rA <= (unsigned)imm
|
|
"011110" when (op = "110110" or --bgtu
|
|
op = "110000" or --cmpgtui
|
|
(op = "111010" and opx = "110000") --cmpgtu
|
|
) else --(unsigned)rA > (unsigned)rB , (unsigned)rA > (unsigned)imm
|
|
"110000" when (op = "111010" and opx = "000011" --rol
|
|
) else --rA rol rB
|
|
"111000" when (op = "111010" and opx = "000010" --roli
|
|
) else --rA rol imm
|
|
"110001" when (op = "111010" and opx = "001011" --ror
|
|
) else --rA ror rB
|
|
"000000"; --DEFAULT
|
|
|
|
|
|
|
|
|
|
end synth;
|