Merge pull request #198 from ozbenh/litedram
[microwatt.git] / control.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3
4 library work;
5 use work.common.all;
6
7 entity control is
8 generic (
9 PIPELINE_DEPTH : natural := 2
10 );
11 port (
12 clk : in std_ulogic;
13 rst : in std_ulogic;
14
15 complete_in : in std_ulogic;
16 valid_in : in std_ulogic;
17 flush_in : in std_ulogic;
18 stall_in : in std_ulogic;
19 sgl_pipe_in : in std_ulogic;
20 stop_mark_in : in std_ulogic;
21
22 gpr_write_valid_in : in std_ulogic;
23 gpr_write_in : in gspr_index_t;
24 gpr_bypassable : in std_ulogic;
25
26 gpr_a_read_valid_in : in std_ulogic;
27 gpr_a_read_in : in gspr_index_t;
28
29 gpr_b_read_valid_in : in std_ulogic;
30 gpr_b_read_in : in gspr_index_t;
31
32 gpr_c_read_valid_in : in std_ulogic;
33 gpr_c_read_in : in gpr_index_t;
34
35 cr_read_in : in std_ulogic;
36 cr_write_in : in std_ulogic;
37
38 valid_out : out std_ulogic;
39 stall_out : out std_ulogic;
40 stopped_out : out std_ulogic;
41
42 gpr_bypass_a : out std_ulogic;
43 gpr_bypass_b : out std_ulogic;
44 gpr_bypass_c : out std_ulogic
45 );
46 end entity control;
47
48 architecture rtl of control is
49 type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE);
50
51 type reg_internal_type is record
52 state : state_type;
53 outstanding : integer range -1 to PIPELINE_DEPTH+2;
54 end record;
55 constant reg_internal_init : reg_internal_type := (state => IDLE, outstanding => 0);
56
57 signal r_int, rin_int : reg_internal_type := reg_internal_init;
58
59 signal stall_a_out : std_ulogic;
60 signal stall_b_out : std_ulogic;
61 signal stall_c_out : std_ulogic;
62 signal cr_stall_out : std_ulogic;
63
64 signal gpr_write_valid : std_ulogic := '0';
65 signal cr_write_valid : std_ulogic := '0';
66
67 signal gpr_c_read_in_fmt : std_ulogic_vector(5 downto 0);
68 begin
69 gpr_hazard0: entity work.gpr_hazard
70 generic map (
71 PIPELINE_DEPTH => PIPELINE_DEPTH
72 )
73 port map (
74 clk => clk,
75 stall_in => stall_in,
76
77 gpr_write_valid_in => gpr_write_valid,
78 gpr_write_in => gpr_write_in,
79 bypass_avail => gpr_bypassable,
80 gpr_read_valid_in => gpr_a_read_valid_in,
81 gpr_read_in => gpr_a_read_in,
82
83 stall_out => stall_a_out,
84 use_bypass => gpr_bypass_a
85 );
86
87 gpr_hazard1: entity work.gpr_hazard
88 generic map (
89 PIPELINE_DEPTH => PIPELINE_DEPTH
90 )
91 port map (
92 clk => clk,
93 stall_in => stall_in,
94
95 gpr_write_valid_in => gpr_write_valid,
96 gpr_write_in => gpr_write_in,
97 bypass_avail => gpr_bypassable,
98 gpr_read_valid_in => gpr_b_read_valid_in,
99 gpr_read_in => gpr_b_read_in,
100
101 stall_out => stall_b_out,
102 use_bypass => gpr_bypass_b
103 );
104
105 gpr_c_read_in_fmt <= "0" & gpr_c_read_in;
106
107 gpr_hazard2: entity work.gpr_hazard
108 generic map (
109 PIPELINE_DEPTH => PIPELINE_DEPTH
110 )
111 port map (
112 clk => clk,
113 stall_in => stall_in,
114
115 gpr_write_valid_in => gpr_write_valid,
116 gpr_write_in => gpr_write_in,
117 bypass_avail => gpr_bypassable,
118 gpr_read_valid_in => gpr_c_read_valid_in,
119 gpr_read_in => gpr_c_read_in_fmt,
120
121 stall_out => stall_c_out,
122 use_bypass => gpr_bypass_c
123 );
124
125 cr_hazard0: entity work.cr_hazard
126 generic map (
127 PIPELINE_DEPTH => PIPELINE_DEPTH
128 )
129 port map (
130 clk => clk,
131 stall_in => stall_in,
132
133 cr_read_in => cr_read_in,
134 cr_write_in => cr_write_valid,
135
136 stall_out => cr_stall_out
137 );
138
139 control0: process(clk)
140 begin
141 if rising_edge(clk) then
142 assert r_int.outstanding >= 0 and r_int.outstanding <= (PIPELINE_DEPTH+1) report "Outstanding bad " & integer'image(r_int.outstanding) severity failure;
143 r_int <= rin_int;
144 end if;
145 end process;
146
147 control1 : process(all)
148 variable v_int : reg_internal_type;
149 variable valid_tmp : std_ulogic;
150 variable stall_tmp : std_ulogic;
151 begin
152 v_int := r_int;
153
154 -- asynchronous
155 valid_tmp := valid_in and not flush_in and not stall_in;
156 stall_tmp := stall_in;
157
158 if complete_in = '1' then
159 v_int.outstanding := r_int.outstanding - 1;
160 end if;
161
162 if rst = '1' then
163 v_int.state := IDLE;
164 v_int.outstanding := 0;
165 stall_tmp := '0';
166 valid_tmp := '0';
167 end if;
168
169 -- Handle debugger stop
170 stopped_out <= '0';
171 if stop_mark_in = '1' and v_int.outstanding = 0 then
172 stopped_out <= '1';
173 end if;
174
175 -- state machine to handle instructions that must be single
176 -- through the pipeline.
177 case r_int.state is
178 when IDLE =>
179 if valid_tmp = '1' then
180 if (sgl_pipe_in = '1') then
181 if v_int.outstanding /= 0 then
182 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
183 stall_tmp := '1';
184 else
185 -- send insn out and wait on it to complete
186 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
187 end if;
188 else
189 -- let it go out if there are no GPR hazards
190 stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
191 end if;
192 end if;
193
194 when WAIT_FOR_PREV_TO_COMPLETE =>
195 if v_int.outstanding = 0 then
196 -- send insn out and wait on it to complete
197 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
198 else
199 stall_tmp := '1';
200 end if;
201
202 when WAIT_FOR_CURR_TO_COMPLETE =>
203 if v_int.outstanding = 0 then
204 v_int.state := IDLE;
205 -- XXX Don't replicate this
206 if valid_tmp = '1' then
207 if (sgl_pipe_in = '1') then
208 if v_int.outstanding /= 0 then
209 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
210 stall_tmp := '1';
211 else
212 -- send insn out and wait on it to complete
213 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
214 end if;
215 else
216 -- let it go out if there are no GPR hazards
217 stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
218 end if;
219 end if;
220 else
221 stall_tmp := '1';
222 end if;
223 end case;
224
225 if stall_tmp = '1' then
226 valid_tmp := '0';
227 end if;
228
229 if valid_tmp = '1' then
230 v_int.outstanding := v_int.outstanding + 1;
231 gpr_write_valid <= gpr_write_valid_in;
232 cr_write_valid <= cr_write_in;
233 else
234 gpr_write_valid <= '0';
235 cr_write_valid <= '0';
236 end if;
237
238 -- update outputs
239 valid_out <= valid_tmp;
240 stall_out <= stall_tmp;
241
242 -- update registers
243 rin_int <= v_int;
244 end process;
245 end;