1 ---------------------------------------------------------------------------------
4 -- Filename: core_ctrl.vhd
5 -- Description: the control unit for the TUD MB-Lite implementation
7 -- Author: Huib Lincklaen Arriens
8 -- Delft University of Technology
9 -- Faculty EEMCS, Department ME&CE, Circuits and Systems
10 -- Date: December, 2010
11 -- Modified: September, 2012: interrupt handling corrected to let
12 -- a pending branch be taken first
13 -- (with thanks to Matthis Meier, TU Dortmund,
14 -- for detecting this errror).
17 --------------------------------------------------------------------------------
21 USE IEEE.std_logic_1164.all;
25 --------------------------------------------------------------------------------
27 --------------------------------------------------------------------------------
31 halt_i : IN STD_LOGIC;
34 imem_addr_o : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
35 imem_clken_o : OUT STD_LOGIC;
36 pc_ctrl_o : OUT STD_LOGIC;
37 -- fetch to decode pipeline registers
38 IF2ID_REG_i : IN IF2ID_Type;
39 IF2ID_REG_o : OUT IF2ID_Type;
40 -- decode to exeq pipeline registers
41 ID2EX_REG_i : IN ID2EX_Type;
42 ID2EX_REG_o : OUT ID2EX_Type;
44 gprf_clken_o : OUT STD_LOGIC;
45 -- exeq to fetch feedback registers
46 EX2IF_REG_i : IN EX2IF_Type;
47 EX2IF_REG_o : OUT EX2IF_Type;
48 -- exeq to mem pipeline registers
49 EX2MEM_REG_i : IN EX2MEM_Type;
50 EX2MEM_REG_o : OUT EX2MEM_Type;
51 -- mem pipeline register
52 MEM_REG_i : IN MEM_REG_Type;
53 MEM_REG_o : OUT MEM_REG_Type;
55 ID2CTRL_i : IN ID2CTRL_Type;
56 INT_CTRL_o : OUT INT_CTRL_Type;
58 EX_WRB_i : IN WRB_Type;
59 EX_WRB_o : OUT WRB_Type;
61 HAZARD_WRB_i : IN HAZARD_WRB_Type;
62 HAZARD_WRB_o : OUT HAZARD_WRB_Type;
63 -- for handling the 'IMM' instruction
64 IMM_LOCK_i : IN IMM_LOCK_Type;
65 IMM_LOCK_o : OUT IMM_LOCK_Type;
66 -- for handling the Machine Status Register
70 MEM2CTRL_i : IN MEM2CTRL_Type;
71 done_o : OUT STD_LOGIC
75 --------------------------------------------------------------------------------
76 ARCHITECTURE rtl OF core_ctrl IS
77 --------------------------------------------------------------------------------
79 SIGNAL rst_r : STD_LOGIC;
80 SIGNAL reset_s : STD_LOGIC;
82 SIGNAL ID2EX_REG_r : ID2EX_Type;
83 SIGNAL EX2IF_REG_r : EX2IF_Type;
84 SIGNAL delayBit_r : STD_LOGIC;
85 SIGNAL delayBit_2r : STD_LOGIC;
86 SIGNAL IMM_LOCK_r : IMM_LOCK_Type;
87 SIGNAL HAZARD_WRB_r : HAZARD_WRB_Type;
89 SIGNAL clken_s : STD_LOGIC;
90 SIGNAL clken_pipe_s : STD_LOGIC;
91 SIGNAL flush_ID2EX_s : STD_LOGIC;
92 SIGNAL flush_ID2EX_r : STD_LOGIC;
93 SIGNAL flush_EX2MEM_s : STD_LOGIC;
95 SIGNAL setup_int_r : STD_LOGIC;
96 SIGNAL int_busy_r : STD_LOGIC;
101 -- static connections
102 reset_s <= rst_i OR rst_r;
103 pc_ctrl_o <= NOT rst_r;
104 imem_addr_o <= IF2ID_REG_i.program_counter;
105 -- clock/wait control lines
106 clken_s <= MEM2CTRL_i.clken OR rst_i;
107 clken_pipe_s <= clken_s AND (NOT HAZARD_WRB_i.hazard);
108 imem_clken_o <= clken_pipe_s;
109 gprf_clken_o <= clken_s;
110 -- signals for clearing the ID2EX and EX2MEM registers during branches
111 flush_ID2EX_s <= EX2IF_REG_r.take_branch;
112 flush_EX2MEM_s <= (flush_ID2EX_s AND (NOT delayBit_2r)) OR HAZARD_WRB_i.hazard;
113 -- outputs that need to be readable too, so needing shadowing signals
114 ID2EX_REG_o <= ID2EX_REG_r;
115 EX2IF_REG_o <= EX2IF_REG_r;
116 IMM_LOCK_o <= IMM_LOCK_r;
117 HAZARD_WRB_o <= HAZARD_WRB_r;
119 INT_CTRL_o.setup_int <= setup_int_r;
120 INT_CTRL_o.rti_target <= ID2EX_REG_r.program_counter;
121 INT_CTRL_o.int_busy <= int_busy_r;
124 PROCESS ( clk_i, rst_i, halt_i,
125 -- complete sensitivity list for synthesizer
126 reset_s, MEM2CTRL_i, clken_pipe_s, IF2ID_REG_i,
127 flush_ID2EX_s, flush_EX2MEM_s, HAZARD_WRB_i,
128 MEM_REG_i, ID2CTRL_i, int_i, MSR_i,
129 int_busy_r, delayBit_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r,
130 EX2IF_REG_i, EX_WRB_i, EX2MEM_REG_i )
132 -- some local procedures
133 PROCEDURE lp_rst_IF2ID_REG IS
135 IF2ID_REG_o.program_counter <= (OTHERS => '0');
138 PROCEDURE lp_rst_ID2EX_REG IS
140 -- reset and handle ID2EX_REG_r.program_counter separately,
141 -- since it will be needed during interrupt setup
142 ID2EX_REG_r.rdix_rA <= (OTHERS => '0');
143 ID2EX_REG_r.rdix_rB <= (OTHERS => '0');
144 ID2EX_REG_r.curr_rD <= (OTHERS => '0');
145 ID2EX_REG_r.alu_Action <= A_NOP;
146 ID2EX_REG_r.alu_Op1 <= ALU_IN_ZERO;
147 ID2EX_REG_r.alu_Op2 <= ALU_IN_IMM;
148 ID2EX_REG_r.alu_Cin <= CIN_ZERO;
149 ID2EX_REG_r.IMM16 <= (OTHERS => '0');
150 ID2EX_REG_r.IMM_Lock <= '0';
151 ID2EX_REG_r.msr_Action <= KEEP_CARRY;
152 ID2EX_REG_r.branch_Action <= NO_BR;
153 ID2EX_REG_r.mem_Action <= NO_MEM;
154 ID2EX_REG_r.transfer_Size <= WORD;
155 ID2EX_REG_r.wrb_Action <= NO_WRB;
158 PROCEDURE lp_rst_EX2IF_REG IS
160 EX2IF_REG_r.take_branch <= '0';
161 EX2IF_REG_r.branch_target <= (OTHERS => '0');
164 PROCEDURE lp_rst_EX2MEM_REG IS
166 EX2MEM_REG_o.mem_Action <= NO_MEM;
167 EX2MEM_REG_o.wrb_Action <= NO_WRB;
168 EX2MEM_REG_o.exeq_result <= (OTHERS => '0');
169 EX2MEM_REG_o.data_rD <= (OTHERS => '0');
170 EX2MEM_REG_o.byte_Enable <= (OTHERS => '0');
171 EX2MEM_REG_o.wrix_rD <= (OTHERS => '0');
174 PROCEDURE lp_rst_IMM_LOCK IS
176 IMM_LOCK_r.locked <= '0';
177 IMM_LOCK_r.IMM_hi16 <= (OTHERS => '0');
180 PROCEDURE lp_rst_MSR IS
186 PROCEDURE lp_rst_EX_WRB IS
188 EX_WRB_o.wrb_Action <= NO_WRB;
189 EX_WRB_o.wrix_rD <= (OTHERS => '0');
190 EX_WRB_o.data_rD <= (OTHERS => '0');
193 PROCEDURE lp_rst_HAZARD_WRB IS
195 HAZARD_WRB_r.hazard <= '0';
196 HAZARD_WRB_r.save_rX <= NO_SAVE;
197 HAZARD_WRB_r.data_rX <= (OTHERS => '0');
198 HAZARD_WRB_r.data_rD <= (OTHERS => '0');
201 PROCEDURE lp_rst_MEM_REG IS
203 MEM_REG_o.wrb_Action <= NO_WRB;
204 MEM_REG_o.exeq_result <= (OTHERS => '0');
205 MEM_REG_o.byte_Enable <= (OTHERS => '0');
206 MEM_REG_o.wrix_rD <= (OTHERS => '0');
210 IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) AND halt_i = '0' THEN
212 IF (reset_s = '1') THEN -- synchronous reset ...
213 lp_rst_IF2ID_REG; -- ... so lasts at least one clock_cycle
218 flush_ID2EX_r <= '0';
222 ID2EX_REG_r.program_counter <= (OTHERS => '0');
224 IF (clken_pipe_s = '1') THEN
225 IF2ID_REG_o <= IF2ID_REG_i;
227 flush_ID2EX_r <= flush_ID2EX_s;
228 HAZARD_WRB_r <= HAZARD_WRB_i;
229 MEM_REG_o <= MEM_REG_i;
230 int_busy_r <= ID2CTRL_i.int_busy;
232 -- decode-to-exeq unit registers
233 IF ((reset_s = '1') OR (flush_ID2EX_s = '1')) THEN
236 -- check for the need and possibility to handle active interrupt requests
237 ELSIF (((int_i = '1') OR (MEM2CTRL_i.int = '1')) AND (MSR_i.IE = '1') AND
238 (ID2CTRL_i.int_busy = '0') AND (int_busy_r = '0') AND
239 -- pending branch should be taken before interrupt can be executed
240 -- dectected by Matthis Meier, TU Dortmund (Sept 2012)
241 (EX2IF_REG_i.take_branch = '0') AND
242 (delayBit_r = '0') AND
243 (IMM_LOCK_i.locked = '0') AND
244 (HAZARD_WRB_i.hazard = '0')) THEN
246 ID2EX_REG_r.program_counter <= ID2EX_REG_i.program_counter;
248 ELSIF (clken_pipe_s = '1') THEN
250 ID2EX_REG_r <= ID2EX_REG_i;
251 delayBit_r <= ID2CTRL_i.delayBit;
253 -- exeq-to-mem unit registers
254 IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN
261 IF (clken_pipe_s = '1') THEN
262 EX2IF_REG_r <= EX2IF_REG_i;
263 delayBit_2r <= delayBit_r;
264 EX_WRB_o <= EX_WRB_i;
266 IF (clken_s = '1') THEN
267 -- next test to prevent a flush from disrupting
268 -- the write-back pipeline
269 IF (flush_ID2EX_r = '0') THEN
270 EX2MEM_REG_o <= EX2MEM_REG_i;
272 IMM_LOCK_r <= IMM_LOCK_i;
276 -- check on End-Of-Program viz. "bri 0x00"
277 -- use delayBit to distinguish between "bri" and "rtsd/rtid"
278 IF ((ID2EX_REG_r.branch_Action = BR) AND
279 (ID2EX_REG_r.alu_Op2 = ALU_IN_IMM) AND
280 (ID2EX_REG_r.IMM16 = C_16_ZEROS) AND
281 (delayBit_r = '0') AND (flush_EX2MEM_s = '0')) THEN
284 END IF; -- rising edge clk_i ...
285 END PROCESS regd_proc;
287 END ARCHITECTURE rtl;