]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/core_ctrl.vhd
596bc223f0f82760ae34525687f37616f494caf7
[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 --------------------------------------------------------------------------------
26 ENTITY core_ctrl IS
27 --------------------------------------------------------------------------------
28     PORT (
29         clk_i           :  IN STD_LOGIC;
30         rst_i           :  IN STD_LOGIC;
31         halt_i          :  IN STD_LOGIC;
32         int_i           :  IN STD_LOGIC;
33         -- specific fetch i/o
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;
43         -- GPRF control
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;
54         -- FSL to mem data delay register(s)
55         FSL_S2MEM_REG_i :  IN FSL_S2MEM_Type;
56         FSL_S2MEM_REG_o : OUT FSL_S2MEM_Type;
57         -- decode control i/o
58         ID2CTRL_i       :  IN ID2CTRL_Type;
59         INT_CTRL_o      : OUT INT_CTRL_Type;
60         -- exeq control i/o
61         EX_WRB_i        :  IN WRB_Type;
62         EX_WRB_o        : OUT WRB_Type;
63         -- data hazard i/o
64         HAZARD_WRB_i    :  IN HAZARD_WRB_Type;
65         HAZARD_WRB_o    : OUT HAZARD_WRB_Type;
66         -- for handling the 'IMM' instruction
67         IMM_LOCK_i      :  IN IMM_LOCK_Type;
68         IMM_LOCK_o      : OUT IMM_LOCK_Type;
69         -- for handling the Machine Status Register
70         MSR_i           :  IN MSR_Type;
71         MSR_o           : OUT MSR_Type;
72         -- miscellaneous
73         MEM2CTRL_i      :  IN MEM2CTRL_Type;
74         FSL_nStall_i    :  IN STD_LOGIC;
75         done_o          : OUT STD_LOGIC
76         );
77 END ENTITY core_ctrl;
78
79 --------------------------------------------------------------------------------
80 ARCHITECTURE rtl OF core_ctrl IS
81 --------------------------------------------------------------------------------
82
83     SIGNAL rst_r          : STD_LOGIC;
84     SIGNAL reset_s        : STD_LOGIC;
85
86     SIGNAL ID2EX_REG_r    : ID2EX_Type;
87     SIGNAL EX2IF_REG_r    : EX2IF_Type;
88     SIGNAL delayBit_r     : STD_LOGIC;
89     SIGNAL delayBit_2r    : STD_LOGIC;
90     SIGNAL IMM_LOCK_r     : IMM_LOCK_Type;
91     SIGNAL HAZARD_WRB_r   : HAZARD_WRB_Type;
92
93     SIGNAL clken_s        : STD_LOGIC;
94     SIGNAL clken_pipe_s   : STD_LOGIC;
95     SIGNAL flush_ID2EX_s  : STD_LOGIC;
96     SIGNAL flush_ID2EX_r  : STD_LOGIC;
97     SIGNAL flush_EX2MEM_s : STD_LOGIC;
98
99     SIGNAL setup_int_r    : STD_LOGIC;
100     SIGNAL int_busy_r     : STD_LOGIC;
101
102     SIGNAL S_Data_r       : STD_LOGIC_VECTOR (31 DOWNTO 0);
103     SIGNAL S_Data_2r      : STD_LOGIC_VECTOR (31 DOWNTO 0);
104
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     -- clock/wait control lines
113     clken_s        <= (MEM2CTRL_i.clken AND FSL_nStall_i) OR rst_i;
114     clken_pipe_s   <= clken_s AND (NOT HAZARD_WRB_i.hazard);
115     imem_clken_o   <= clken_pipe_s;
116     gprf_clken_o   <= clken_s;
117     -- signals for clearing the ID2EX and EX2MEM registers during branches
118     flush_ID2EX_s  <= EX2IF_REG_r.take_branch;
119     flush_EX2MEM_s <= (flush_ID2EX_s AND (NOT delayBit_2r)) OR HAZARD_WRB_i.hazard;
120     -- outputs that need to be readable too, so needing shadowing signals
121     ID2EX_REG_o    <= ID2EX_REG_r;
122     EX2IF_REG_o    <= EX2IF_REG_r;
123     IMM_LOCK_o     <= IMM_LOCK_r;
124     HAZARD_WRB_o   <= HAZARD_WRB_r;
125     --
126     INT_CTRL_o.setup_int   <= setup_int_r;
127     INT_CTRL_o.rti_target  <= ID2EX_REG_r.program_counter;
128     INT_CTRL_o.int_busy    <= int_busy_r;
129     --
130     FSL_S2MEM_REG_o.S_Data <= S_Data_2r;
131
132 regd_proc:
133     PROCESS ( clk_i, rst_i, halt_i,
134               -- complete sensitivity list for synthesizer
135               reset_s, MEM2CTRL_i, clken_pipe_s, IF2ID_REG_i,
136               flush_ID2EX_s, flush_EX2MEM_s, HAZARD_WRB_i,
137               MEM_REG_i, ID2CTRL_i, int_i, MSR_i,
138               int_busy_r, delayBit_r, IMM_LOCK_i, ID2EX_REG_i, ID2EX_REG_r,
139               EX2IF_REG_i, EX_WRB_i, S_Data_r, FSL_S2MEM_REG_i, EX2MEM_REG_i )
140
141         -- some local procedures
142         PROCEDURE lp_rst_IF2ID_REG IS
143         BEGIN
144             IF2ID_REG_o.program_counter <= (OTHERS => '0');
145         END PROCEDURE;
146
147         PROCEDURE lp_rst_ID2EX_REG IS
148         BEGIN
149             -- reset and handle ID2EX_REG_r.program_counter separately,
150             -- since it will be needed during interrupt setup
151             ID2EX_REG_r.rdix_rA          <= (OTHERS => '0');
152             ID2EX_REG_r.rdix_rB          <= (OTHERS => '0');
153             ID2EX_REG_r.curr_rD          <= (OTHERS => '0');
154             ID2EX_REG_r.alu_Action       <= A_NOP;
155             ID2EX_REG_r.alu_Op1          <= ALU_IN_ZERO;
156             ID2EX_REG_r.alu_Op2          <= ALU_IN_IMM;
157             ID2EX_REG_r.alu_Cin          <= CIN_ZERO;
158             ID2EX_REG_r.IMM16            <= (OTHERS => '0');
159             ID2EX_REG_r.IMM_Lock         <= '0';
160             ID2EX_REG_r.msr_Action       <= KEEP_CARRY;
161             ID2EX_REG_r.branch_Action    <= NO_BR;
162             ID2EX_REG_r.mem_Action       <= NO_MEM;
163             ID2EX_REG_r.transfer_Size    <= WORD;
164             ID2EX_REG_r.wrb_Action       <= NO_WRB;
165             ID2EX_REG_r.FSL_Test         <= '1';
166             ID2EX_REG_r.FSL_Non_blocking <= '1';
167             ID2EX_REG_r.FSL_Control      <= '0';
168             ID2EX_REG_r.FSL_Atomic       <= '0';
169         END PROCEDURE;
170
171         PROCEDURE lp_rst_EX2IF_REG IS
172         BEGIN
173             EX2IF_REG_r.take_branch   <= '0';
174             EX2IF_REG_r.branch_target <= (OTHERS => '0');
175         END PROCEDURE;
176
177         PROCEDURE lp_rst_EX2MEM_REG IS
178         BEGIN
179             EX2MEM_REG_o.mem_Action  <= NO_MEM;
180             EX2MEM_REG_o.wrb_Action  <= NO_WRB;
181             EX2MEM_REG_o.exeq_result <= (OTHERS => '0');
182             EX2MEM_REG_o.data_rD     <= (OTHERS => '0');
183             EX2MEM_REG_o.byte_Enable <= (OTHERS => '0');
184             EX2MEM_REG_o.wrix_rD     <= (OTHERS => '0');
185         END PROCEDURE;
186
187         PROCEDURE lp_rst_FSL2MEM_REG IS
188         BEGIN
189             S_Data_r  <= (OTHERS => '0');
190             S_Data_2r <= (OTHERS => '0');
191         END PROCEDURE;
192
193         PROCEDURE lp_rst_IMM_LOCK IS
194         BEGIN
195             IMM_LOCK_r.locked   <= '0';
196             IMM_LOCK_r.IMM_hi16 <= (OTHERS => '0');
197         END PROCEDURE;
198
199         PROCEDURE lp_rst_MSR IS
200         BEGIN
201             MSR_o.IE  <= '0';
202             MSR_o.C   <= '0';
203             MSR_o.FSL <= '0';
204         END PROCEDURE;
205
206         PROCEDURE lp_rst_EX_WRB IS
207         BEGIN
208             EX_WRB_o.wrb_Action <= NO_WRB;
209             EX_WRB_o.wrix_rD    <= (OTHERS => '0');
210             EX_WRB_o.data_rD    <= (OTHERS => '0');
211         END PROCEDURE;
212
213         PROCEDURE lp_rst_HAZARD_WRB IS
214         BEGIN
215             HAZARD_WRB_r.hazard  <= '0';
216             HAZARD_WRB_r.save_rX <= NO_SAVE;
217             HAZARD_WRB_r.data_rX <= (OTHERS => '0');
218             HAZARD_WRB_r.data_rD <= (OTHERS => '0');
219         END PROCEDURE;
220
221         PROCEDURE lp_rst_MEM_REG IS
222         BEGIN
223             MEM_REG_o.wrb_Action  <= NO_WRB;
224             MEM_REG_o.exeq_result <= (OTHERS => '0');
225             MEM_REG_o.byte_Enable <= (OTHERS => '0');
226             MEM_REG_o.wrix_rD     <= (OTHERS => '0');
227         END PROCEDURE;
228
229     BEGIN
230         IF (RISING_EDGE (clk_i) AND (MEM2CTRL_i.clken = '1')) AND halt_i = '0' THEN
231             rst_r <= rst_i;
232             IF (reset_s = '1') THEN     -- synchronous reset ...
233                 lp_rst_IF2ID_REG;       -- ... so lasts at least one clock_cycle
234                 lp_rst_MSR;
235                 lp_rst_HAZARD_WRB;
236                 lp_rst_MEM_REG;
237                 lp_rst_FSL2MEM_REG;
238                 delayBit_r    <= '0';
239                 flush_ID2EX_r <= '0';
240                 setup_int_r   <= '0';
241                 int_busy_r    <= '0';
242                 done_o        <= '0';
243                 ID2EX_REG_r.program_counter <= (OTHERS => '0');
244             ELSE
245                 IF (clken_pipe_s = '1') THEN
246                     IF2ID_REG_o <= IF2ID_REG_i;
247                 END IF;
248                 flush_ID2EX_r <= flush_ID2EX_s;
249                 HAZARD_WRB_r  <= HAZARD_WRB_i;
250                 MEM_REG_o     <= MEM_REG_i;
251                 int_busy_r    <= ID2CTRL_i.int_busy;
252             END IF;
253             -- decode-to-exeq unit registers
254             IF ((reset_s = '1') OR (flush_ID2EX_s = '1')) THEN
255                 lp_rst_ID2EX_REG;
256                 delayBit_r <= '0';
257             -- check for the need and possibility to handle active interrupt requests
258             ELSIF (((int_i = '1') OR (MEM2CTRL_i.int = '1')) AND (MSR_i.IE = '1') AND
259                         (ID2CTRL_i.int_busy = '0') AND (int_busy_r = '0') AND
260                 -- pending branch should be taken before interrupt can be executed
261                 -- dectected by Matthis Meier, TU Dortmund (Sept 2012)
262                             (EX2IF_REG_i.take_branch = '0') AND
263                                 (delayBit_r = '0') AND
264                                     (IMM_LOCK_i.locked = '0') AND
265                                         (HAZARD_WRB_i.hazard = '0')) THEN
266                 setup_int_r <= '1';
267                 ID2EX_REG_r.program_counter <= ID2EX_REG_i.program_counter;
268                 lp_rst_ID2EX_REG;
269             ELSIF (clken_pipe_s = '1') THEN
270                 setup_int_r <= '0';
271                 ID2EX_REG_r <= ID2EX_REG_i;
272                 delayBit_r  <= ID2CTRL_i.delayBit;
273             END IF;
274             -- exeq-to-mem unit registers
275             IF ((reset_s = '1') OR (flush_EX2MEM_s = '1')) THEN
276                 lp_rst_EX2IF_REG;
277                 lp_rst_EX2MEM_REG;
278                 lp_rst_EX_WRB;
279                 lp_rst_IMM_LOCK;
280                 delayBit_2r <= '0';
281             ELSE
282                 IF (clken_pipe_s = '1') THEN
283                     EX2IF_REG_r <= EX2IF_REG_i;
284                     delayBit_2r <= delayBit_r;
285                     EX_WRB_o    <= EX_WRB_i;
286                     S_Data_2r   <= S_Data_r;
287                     S_Data_r    <= FSL_S2MEM_REG_i.S_Data;
288                 END IF;
289                 IF (clken_s = '1') THEN
290                     -- next test to prevent a flush from disrupting
291                     -- the write-back pipeline
292                     IF (flush_ID2EX_r = '0') THEN
293                         EX2MEM_REG_o <= EX2MEM_REG_i;
294                     END IF;
295                     IMM_LOCK_r <= IMM_LOCK_i;
296                     MSR_o      <= MSR_i;
297                 END IF;
298             END IF;
299             -- check on End-Of-Program viz. "bri 0x00"
300             -- use delayBit to distinguish between "bri" and "rtsd/rtid"
301             IF ((ID2EX_REG_r.branch_Action = BR) AND
302                     (ID2EX_REG_r.alu_Op2 = ALU_IN_IMM) AND
303                         (ID2EX_REG_r.IMM16 = C_16_ZEROS) AND
304                             (delayBit_r = '0') AND (flush_EX2MEM_s = '0')) THEN
305                 done_o <= '1';
306             END IF;
307         END IF;     -- rising edge clk_i ...
308     END PROCESS regd_proc;
309
310 END ARCHITECTURE rtl;