]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/core_ctrl.vhd
Implement ITT conditional execution
[fpga/lx-cpu1/tumbl.git] / hw / core_ctrl.vhd
1 ---------------------------------------------------------------------------------
2 --
3 --  Entity:       core_ctrl
4 --  Filename:     core_ctrl.vhd
5 --  Description:  the control unit for the TUD MB-Lite implementation
6 --
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).
15 --  Remarks:
16 --
17 --------------------------------------------------------------------------------
18
19 LIBRARY IEEE;
20
21 USE IEEE.std_logic_1164.all;
22 USE WORK.mbl_Pkg.all;
23
24 --------------------------------------------------------------------------------
25 ENTITY core_ctrl IS
26 --------------------------------------------------------------------------------
27     GENERIC (
28         COMPATIBILITY_MODE_g : BOOLEAN := FALSE
29         );
30     PORT (
31         clk_i           :  IN STD_LOGIC;
32         rst_i           :  IN STD_LOGIC;
33         halt_i          :  IN STD_LOGIC;
34         bad_op_i        :  IN STD_LOGIC;
35         int_i           :  IN STD_LOGIC;
36         trace_i         :  IN STD_LOGIC;
37         trace_kick_i    :  IN STD_LOGIC;
38         core_clken_o    : OUT STD_LOGIC;
39         -- specific fetch i/o
40         imem_addr_o     : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
41         imem_clken_o    : OUT STD_LOGIC;
42         pc_ctrl_o       : OUT STD_LOGIC;
43         -- fetch to decode pipeline registers
44         IF2ID_REG_i     :  IN IF2ID_Type;
45         IF2ID_REG_o     : OUT IF2ID_Type;
46         -- decode to exeq pipeline registers
47         ID2EX_REG_i     :  IN ID2EX_Type;
48         ID2EX_REG_o     : OUT ID2EX_Type;
49         -- GPRF control
50         gprf_clken_o    : OUT STD_LOGIC;
51         -- exeq to fetch feedback registers
52         EX2IF_REG_i     :  IN EX2IF_Type;
53         EX2IF_REG_o     : OUT EX2IF_Type;
54         EX2CTRL_REG_i   :  IN EX2CTRL_Type;
55         -- exeq to core (halting)
56         exeq_halt_i     :  IN STD_LOGIC;
57         -- exeq to mem pipeline registers
58         EX2MEM_REG_i    :  IN EX2MEM_Type;
59         EX2MEM_REG_o    : OUT EX2MEM_Type;
60         -- mem pipeline register
61         MEM_REG_i       :  IN MEM_REG_Type;
62         MEM_REG_o       : OUT MEM_REG_Type;
63         -- decode control i/o
64         ID2CTRL_i       :  IN ID2CTRL_Type;
65         INT_CTRL_o      : OUT INT_CTRL_Type;
66         -- exeq control i/o
67         EX_WRB_i        :  IN WRB_Type;
68         EX_WRB_o        : OUT WRB_Type;
69         -- data hazard i/o
70         HAZARD_WRB_i    :  IN HAZARD_WRB_Type;
71         HAZARD_WRB_o    : OUT HAZARD_WRB_Type;
72         -- for handling the 'IMM' instruction
73         IMM_LOCK_i      :  IN IMM_LOCK_Type;
74         IMM_LOCK_o      : OUT IMM_LOCK_Type;
75         -- for handling the Machine Status Register
76         MSR_i           :  IN MSR_Type;
77         MSR_o           : OUT MSR_Type;
78         -- miscellaneous
79         MEM2CTRL_i      :  IN MEM2CTRL_Type
80         );
81 END ENTITY core_ctrl;
82
83 --------------------------------------------------------------------------------
84 ARCHITECTURE rtl OF core_ctrl IS
85 --------------------------------------------------------------------------------
86
87     SIGNAL rst_r          : STD_LOGIC;
88     SIGNAL reset_s        : STD_LOGIC;
89     SIGNAL core_clken_s   : STD_LOGIC;
90
91     SIGNAL ID2EX_REG_r    : ID2EX_Type;
92     SIGNAL EX2IF_REG_r    : EX2IF_Type;
93     SIGNAL IMM_LOCK_r     : IMM_LOCK_Type;
94     SIGNAL HAZARD_WRB_r   : HAZARD_WRB_Type;
95     SIGNAL flush_second_r : STD_LOGIC;
96     SIGNAL delayBit_r     : STD_LOGIC;
97     SIGNAL clken_s        : STD_LOGIC;
98     SIGNAL clken_pipe_s   : STD_LOGIC;
99     SIGNAL flush_ID2EX_s  : STD_LOGIC;
100     SIGNAL flush_ID2EX_r  : STD_LOGIC;
101     SIGNAL flush_EX2MEM_s : STD_LOGIC;
102
103     SIGNAL setup_int_r    : STD_LOGIC;
104     SIGNAL int_busy_r     : STD_LOGIC;
105
106 BEGIN
107
108     -- static connections
109     reset_s        <= rst_i OR rst_r;
110     pc_ctrl_o      <= NOT rst_r;
111     imem_addr_o    <= IF2ID_REG_i.program_counter;
112     -- Tracing
113     -- Reset_s is 1 when rst_i is one and then gets deactivated
114     core_clken_s  <= reset_s OR ((NOT bad_op_i) AND (((NOT trace_i) AND (NOT exeq_halt_i)) OR trace_kick_i));
115     core_clken_o  <= core_clken_s;
116     -- clock/wait control lines
117     clken_s        <= MEM2CTRL_i.clken OR rst_i;
118     clken_pipe_s   <= clken_s AND (NOT HAZARD_WRB_i.hazard);
119     imem_clken_o   <= clken_pipe_s;
120     gprf_clken_o   <= clken_s;
121     -- signals for clearing the ID2EX and EX2MEM registers during branches
122     flush_ID2EX_s  <= ((EX2IF_REG_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch) WHEN COMPATIBILITY_MODE_g = TRUE
123                       ELSE (EX2IF_REG_i.take_branch OR EX2IF_REG_r.take_branch OR EX2CTRL_REG_i.flush_first OR flush_second_r);
124     flush_EX2MEM_s <= HAZARD_WRB_i.hazard;
125     -- outputs that need to be readable too, so needing shadowing signals
126     ID2EX_REG_o    <= ID2EX_REG_r;
127     EX2IF_REG_o    <= EX2IF_REG_r;
128     IMM_LOCK_o     <= IMM_LOCK_r;
129     HAZARD_WRB_o   <= HAZARD_WRB_r;
130     --
131     INT_CTRL_o.setup_int   <= setup_int_r;
132     INT_CTRL_o.rti_target  <= ID2EX_REG_r.program_counter;
133     INT_CTRL_o.int_busy    <= int_busy_r;
134
135 regd_proc:
136     PROCESS ( clk_i, rst_i, halt_i, core_clken_s,
137               -- complete sensitivity list for synthesizer
138               reset_s, MEM2CTRL_i, clken_pipe_s, IF2ID_REG_i,
139               flush_ID2EX_s, flush_EX2MEM_s, HAZARD_WRB_i,
140               MEM_REG_i, ID2CTRL_i, int_i, MSR_i,
141               int_busy_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r,
142               EX2IF_REG_i, EX2CTRL_REG_i, EX_WRB_i, EX2MEM_REG_i )
143
144         -- some local procedures
145         PROCEDURE lp_rst_IF2ID_REG IS
146         BEGIN
147             IF2ID_REG_o.program_counter <= (OTHERS => '0');
148         END PROCEDURE;
149
150         PROCEDURE lp_rst_ID2EX_REG IS
151         BEGIN
152             -- reset and handle ID2EX_REG_r.program_counter separately,
153             -- since it will be needed during interrupt setup
154             ID2EX_REG_r.rdix_rA          <= (OTHERS => '0');
155             ID2EX_REG_r.rdix_rB          <= (OTHERS => '0');
156             ID2EX_REG_r.curr_rD          <= (OTHERS => '0');
157             ID2EX_REG_r.alu_Action       <= A_NOP;
158             ID2EX_REG_r.alu_Op1          <= ALU_IN_ZERO;
159             ID2EX_REG_r.alu_Op2          <= ALU_IN_IMM;
160             ID2EX_REG_r.alu_Cin          <= CIN_ZERO;
161             ID2EX_REG_r.IMM16            <= (OTHERS => '0');
162             ID2EX_REG_r.IMM_Lock         <= '0';
163             ID2EX_REG_r.msr_Action       <= KEEP_CARRY;
164             ID2EX_REG_r.branch_Action    <= NO_BR;
165             ID2EX_REG_r.mem_Action       <= NO_MEM;
166             ID2EX_REG_r.transfer_Size    <= WORD;
167             ID2EX_REG_r.wrb_Action       <= NO_WRB;
168         END PROCEDURE;
169
170         PROCEDURE lp_rst_EX2IF_REG IS
171         BEGIN
172             EX2IF_REG_r.take_branch   <= '0';
173             EX2IF_REG_r.branch_target <= (OTHERS => '0');
174         END PROCEDURE;
175
176         PROCEDURE lp_rst_EX2MEM_REG IS
177         BEGIN
178             EX2MEM_REG_o.mem_Action  <= NO_MEM;
179             EX2MEM_REG_o.wrb_Action  <= NO_WRB;
180             EX2MEM_REG_o.exeq_result <= (OTHERS => '0');
181             EX2MEM_REG_o.data_rD     <= (OTHERS => '0');
182             EX2MEM_REG_o.byte_Enable <= (OTHERS => '0');
183             EX2MEM_REG_o.wrix_rD     <= (OTHERS => '0');
184         END PROCEDURE;
185
186         PROCEDURE lp_rst_IMM_LOCK IS
187         BEGIN
188             IMM_LOCK_r.locked   <= '0';
189             IMM_LOCK_r.IMM_hi16 <= (OTHERS => '0');
190         END PROCEDURE;
191
192         PROCEDURE lp_rst_MSR IS
193         BEGIN
194             MSR_o.IE  <= '0';
195             MSR_o.C   <= '0';
196         END PROCEDURE;
197
198         PROCEDURE lp_rst_EX_WRB IS
199         BEGIN
200             EX_WRB_o.wrb_Action <= NO_WRB;
201             EX_WRB_o.wrix_rD    <= (OTHERS => '0');
202             EX_WRB_o.data_rD    <= (OTHERS => '0');
203         END PROCEDURE;
204
205         PROCEDURE lp_rst_HAZARD_WRB IS
206         BEGIN
207             HAZARD_WRB_r.hazard  <= '0';
208             HAZARD_WRB_r.save_rX <= NO_SAVE;
209             HAZARD_WRB_r.data_rX <= (OTHERS => '0');
210             HAZARD_WRB_r.data_rD <= (OTHERS => '0');
211         END PROCEDURE;
212
213         PROCEDURE lp_rst_MEM_REG IS
214         BEGIN
215             MEM_REG_o.wrb_Action  <= NO_WRB;
216             MEM_REG_o.exeq_result <= (OTHERS => '0');
217             MEM_REG_o.byte_Enable <= (OTHERS => '0');
218             MEM_REG_o.wrix_rD     <= (OTHERS => '0');
219         END PROCEDURE;
220
221     BEGIN
222
223         IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) AND halt_i = '0' AND
224                     core_clken_s = '1' THEN
225             rst_r <= rst_i;
226
227             IF (reset_s = '1') THEN     -- synchronous reset ...
228                 lp_rst_IF2ID_REG;       -- ... so lasts at least one clock_cycle
229                 lp_rst_MSR;
230                 lp_rst_HAZARD_WRB;
231                 lp_rst_MEM_REG;
232
233                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
234                     delayBit_r     <= '0';
235                 ELSE
236                     flush_second_r <= '0';
237                 END IF;
238
239                 flush_ID2EX_r <= '0';
240                 setup_int_r   <= '0';
241                 int_busy_r    <= '0';
242                 ID2EX_REG_r.program_counter <= (OTHERS => '0');
243             ELSE
244                 IF (clken_pipe_s = '1') THEN
245                     IF2ID_REG_o <= IF2ID_REG_i;
246                 END IF;
247                 flush_ID2EX_r <= flush_ID2EX_s;
248                 IF (COMPATIBILITY_MODE_g = FALSE) THEN
249                     flush_second_r <= EX2CTRL_REG_i.flush_second;
250                 END IF;
251                 HAZARD_WRB_r  <= HAZARD_WRB_i;
252                 MEM_REG_o     <= MEM_REG_i;
253                 int_busy_r    <= ID2CTRL_i.int_busy;
254             END IF;
255             -- decode-to-exeq unit registers
256             IF ((reset_s = '1') OR (flush_ID2EX_s = '1')) THEN
257                 setup_int_r <= '0';
258                 lp_rst_ID2EX_REG;
259                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
260                     delayBit_r <= '0';
261                 END IF;
262             -- check for the need and possibility to handle active interrupt requests
263             ELSIF (((int_i = '1') OR (MEM2CTRL_i.int = '1')) AND (MSR_i.IE = '1') AND
264                         (ID2CTRL_i.int_busy = '0') AND (int_busy_r = '0') AND
265                 -- pending branch should be taken before interrupt can be executed
266                 -- dectected by Matthis Meier, TU Dortmund (Sept 2012)
267                             (EX2IF_REG_i.take_branch = '0') AND
268                                 (EX2IF_REG_r.take_branch = '0') AND -- it is still pending a cycle after branching
269                                     (IMM_LOCK_i.locked = '0') AND
270                                         (HAZARD_WRB_i.hazard = '0')) THEN
271                 setup_int_r <= '1';
272                 ID2EX_REG_r.program_counter <= ID2EX_REG_i.program_counter;
273                 lp_rst_ID2EX_REG;
274             ELSIF (clken_pipe_s = '1') THEN
275                 setup_int_r <= '0';
276                 ID2EX_REG_r <= ID2EX_REG_i;
277                 IF (COMPATIBILITY_MODE_g = TRUE) THEN
278                     delayBit_r  <= ID2CTRL_i.delayBit;
279                 END IF;
280             END IF;
281             -- exeq-to-mem unit registers
282             IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN
283                 lp_rst_EX2IF_REG;
284                 lp_rst_EX2MEM_REG;
285                 lp_rst_EX_WRB;
286                 lp_rst_IMM_LOCK;
287             ELSE
288                 IF (clken_pipe_s = '1') THEN
289                     EX2IF_REG_r   <= EX2IF_REG_i;
290                     EX_WRB_o      <= EX_WRB_i;
291                 END IF;
292                 IF (clken_s = '1') THEN
293                     -- next test to prevent a flush from disrupting
294                     -- the write-back pipeline
295                     IF (flush_ID2EX_r = '0') THEN
296                         EX2MEM_REG_o <= EX2MEM_REG_i;
297                     END IF;
298                     IMM_LOCK_r <= IMM_LOCK_i;
299                     MSR_o      <= MSR_i;
300                 END IF;
301             END IF;
302         END IF;     -- rising edge clk_i ...
303     END PROCESS regd_proc;
304
305 END ARCHITECTURE rtl;