2 use ieee.std_logic_1164.all;
6 PIPELINE_DEPTH : natural := 2
12 complete_in : in std_ulogic;
13 valid_in : in std_ulogic;
14 flush_in : in std_ulogic;
15 sgl_pipe_in : in std_ulogic;
16 stop_mark_in : in std_ulogic;
18 gpr_write_valid_in : in std_ulogic;
19 gpr_write_in : in std_ulogic_vector(4 downto 0);
21 gpr_a_read_valid_in : in std_ulogic;
22 gpr_a_read_in : in std_ulogic_vector(4 downto 0);
24 gpr_b_read_valid_in : in std_ulogic;
25 gpr_b_read_in : in std_ulogic_vector(4 downto 0);
27 gpr_c_read_valid_in : in std_ulogic;
28 gpr_c_read_in : in std_ulogic_vector(4 downto 0);
30 cr_read_in : in std_ulogic;
31 cr_write_in : in std_ulogic;
33 valid_out : out std_ulogic;
34 stall_out : out std_ulogic;
35 stopped_out : out std_ulogic
39 architecture rtl of control is
40 type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE);
42 type reg_internal_type is record
44 outstanding : integer range -1 to PIPELINE_DEPTH+2;
46 constant reg_internal_init : reg_internal_type := (state => IDLE, outstanding => 0);
48 signal r_int, rin_int : reg_internal_type := reg_internal_init;
50 signal stall_a_out : std_ulogic;
51 signal stall_b_out : std_ulogic;
52 signal stall_c_out : std_ulogic;
53 signal cr_stall_out : std_ulogic;
55 signal gpr_write_valid : std_ulogic := '0';
56 signal cr_write_valid : std_ulogic := '0';
58 gpr_hazard0: entity work.gpr_hazard
65 gpr_write_valid_in => gpr_write_valid,
66 gpr_write_in => gpr_write_in,
67 gpr_read_valid_in => gpr_a_read_valid_in,
68 gpr_read_in => gpr_a_read_in,
70 stall_out => stall_a_out
73 gpr_hazard1: entity work.gpr_hazard
80 gpr_write_valid_in => gpr_write_valid,
81 gpr_write_in => gpr_write_in,
82 gpr_read_valid_in => gpr_b_read_valid_in,
83 gpr_read_in => gpr_b_read_in,
85 stall_out => stall_b_out
88 gpr_hazard2: entity work.gpr_hazard
95 gpr_write_valid_in => gpr_write_valid,
96 gpr_write_in => gpr_write_in,
97 gpr_read_valid_in => gpr_c_read_valid_in,
98 gpr_read_in => gpr_c_read_in,
100 stall_out => stall_c_out
103 cr_hazard0: entity work.cr_hazard
110 cr_read_in => cr_read_in,
111 cr_write_in => cr_write_valid,
113 stall_out => cr_stall_out
116 control0: process(clk)
118 if rising_edge(clk) then
119 assert r_int.outstanding >= 0 and r_int.outstanding <= (PIPELINE_DEPTH+1) report "Outstanding bad " & integer'image(r_int.outstanding) severity failure;
124 control1 : process(all)
125 variable v_int : reg_internal_type;
126 variable valid_tmp : std_ulogic;
127 variable stall_tmp : std_ulogic;
132 valid_tmp := valid_in and not flush_in;
135 if complete_in = '1' then
136 v_int.outstanding := r_int.outstanding - 1;
139 -- Handle debugger stop
141 if stop_mark_in = '1' and v_int.outstanding = 0 then
145 -- state machine to handle instructions that must be single
146 -- through the pipeline.
149 if valid_tmp = '1' then
150 if (sgl_pipe_in = '1') then
151 if v_int.outstanding /= 0 then
152 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
155 -- send insn out and wait on it to complete
156 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
159 -- let it go out if there are no GPR hazards
160 stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
164 when WAIT_FOR_PREV_TO_COMPLETE =>
165 if v_int.outstanding = 0 then
166 -- send insn out and wait on it to complete
167 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
172 when WAIT_FOR_CURR_TO_COMPLETE =>
173 if v_int.outstanding = 0 then
175 -- XXX Don't replicate this
176 if valid_tmp = '1' then
177 if (sgl_pipe_in = '1') then
178 if v_int.outstanding /= 0 then
179 v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
182 -- send insn out and wait on it to complete
183 v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
186 -- let it go out if there are no GPR hazards
187 stall_tmp := stall_a_out or stall_b_out or stall_c_out or cr_stall_out;
195 if stall_tmp = '1' then
199 if valid_tmp = '1' then
200 v_int.outstanding := v_int.outstanding + 1;
201 gpr_write_valid <= gpr_write_valid_in;
202 cr_write_valid <= cr_write_in;
204 gpr_write_valid <= '0';
205 cr_write_valid <= '0';
210 v_int.outstanding := 0;
215 valid_out <= valid_tmp;
216 stall_out <= stall_tmp;