-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontrol.vhd
131 lines (122 loc) · 3.7 KB
/
control.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity control is
port
(
clk, rst, Z : in std_logic;
Op : in std_logic_vector(5 downto 0);
IorD, MemWrite, MemRead,
MemtoReg, IRWrite, PCSource,
RegDst, RegWrite, ALUSrcA,
PCSel : out std_logic;
ALUOp, ALUSrcB : out std_logic_vector(1 downto 0);
DEBUG_STATE : out std_logic_vector(3 downto 0)
);
end control;
architecture behave of control is
-- Local Variables
signal PCWrite, PCWriteCond : std_logic;
signal state, next_state : std_logic_vector(3 downto 0);
-- Control Constants
constant IFETCH : std_logic_vector(3 downto 0) := "0000"; -- instruction fetch
constant IDECODE : std_logic_vector(3 downto 0) := "0001"; -- instruction decode / register fetch
constant ADDRESSCMP : std_logic_vector(3 downto 0) := "0010"; -- memory address computation
constant MEMLOAD : std_logic_vector(3 downto 0) := "0011"; -- Memory Access 'load word'
constant MEMSTORE : std_logic_vector(3 downto 0) := "0100"; -- Memory Access 'store word'
constant WRITEBACK : std_logic_vector(3 downto 0) := "0101"; -- Memory Access finished
constant EXECUTE : std_logic_vector(3 downto 0) := "0110";
constant RCOMPLETE : std_logic_vector(3 downto 0) := "0111"; -- R-type completion
constant BCOMPLETE : std_logic_vector(3 downto 0) := "1000"; -- Branch completion
begin
-- advance PC
PCSel <= (PCWrite or (PCWriteCond and Z));
DEBUG_STATE <= state; -- output to hex display
-- get next state
process (clk) begin
if rising_edge(clk) then
if(rst = '1') then
state <= IFETCH;
else
state <= next_state;
end if;
end if;
end process;
-- FSM next state
process(state, Op) begin
case(state) is
when IFETCH => next_state <= IDECODE;
when IDECODE =>
case(Op) is
when "000000" => next_state <= EXECUTE;
when "000100" => next_state <= BCOMPLETE;
when "100011" => next_state <= ADDRESSCMP;
when "101011" => next_state <= ADDRESSCMP;
when others => next_state <= IFETCH;
end case;
when ADDRESSCMP =>
case(Op) is
when "100011" => next_state <= MEMLOAD;
when "101011" => next_state <= MEMSTORE;
when others => next_state <= IFETCH;
end case;
when MEMLOAD => next_state <= WRITEBACK;
when MEMSTORE => next_state <= IFETCH;
when WRITEBACK => next_state <= IFETCH;
when EXECUTE => next_state <= RCOMPLETE;
when RCOMPLETE => next_state <= IFETCH;
when BCOMPLETE => next_state <= IFETCH;
when others => next_state <= IFETCH; -- when in doubt: IFETCH
end case;
end process;
process(state) begin
-- init to zero - eliminate carry-over errors
IorD <= '0'; -- instruction mode by default
MemRead <= '0';
MemWrite <= '0';
MemtoReg <= '0';
IRWrite <= '0';
RegWrite <= '0';
RegDst <= '0';
PCSource <= '0';
PCWrite <= '0';
PCWriteCond <= '0';
ALUSrcB <= "00";
ALUSrcA <= '0';
ALUOp <= "00";
-- FSM output
case (state) is
when IFETCH =>
MemRead <= '1';
IRWrite <= '1';
PCWrite <= '1';
ALUSrcB <= "01";
when IDECODE => ALUSrcB <= "11";
when ADDRESSCMP =>
ALUSrcA <= '1';
ALUSrcB <= "10";
when MEMLOAD =>
MemRead <= '1';
IorD <= '1'; -- switch to data
when MEMSTORE =>
MemWrite <= '1';
IorD <= '1'; -- switch to data
when WRITEBACK =>
RegDst <= '0';
RegWrite <= '1';
MemtoReg <= '1';
when EXECUTE =>
ALUSrcA <= '1';
ALUOp <= "10";
when RCOMPLETE =>
RegDst <= '1';
RegWrite <= '1';
when BCOMPLETE =>
PCWriteCond <= '1';
PCSource <= '1';
ALUSrcA <= '1';
ALUOp <= "01";
when others => null;
end case;
end process;
end behave;