Separate issue control into its own unit
Signed-off-by: Anton Blanchard <anton@linux.ibm.com>pull/100/head
parent
0a0fe03767
commit
d5346d0abf
@ -0,0 +1,113 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity control is
|
||||
generic (
|
||||
PIPELINE_DEPTH : natural := 2
|
||||
);
|
||||
port (
|
||||
clk : in std_ulogic;
|
||||
rst : in std_ulogic;
|
||||
|
||||
complete_in : in std_ulogic;
|
||||
valid_in : in std_ulogic;
|
||||
flush_in : in std_ulogic;
|
||||
sgl_pipe_in : in std_ulogic;
|
||||
stop_mark_in : in std_ulogic;
|
||||
|
||||
valid_out : out std_ulogic;
|
||||
stall_out : out std_ulogic;
|
||||
stopped_out : out std_ulogic
|
||||
);
|
||||
end entity control;
|
||||
|
||||
architecture rtl of control is
|
||||
type state_type is (IDLE, WAIT_FOR_PREV_TO_COMPLETE, WAIT_FOR_CURR_TO_COMPLETE);
|
||||
|
||||
type reg_internal_type is record
|
||||
state : state_type;
|
||||
outstanding : integer range -1 to PIPELINE_DEPTH+1;
|
||||
end record;
|
||||
constant reg_internal_init : reg_internal_type := (state => IDLE, outstanding => 0);
|
||||
|
||||
signal r_int, rin_int : reg_internal_type := reg_internal_init;
|
||||
begin
|
||||
control0: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
r_int <= rin_int;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
control1 : process(all)
|
||||
variable v_int : reg_internal_type;
|
||||
variable valid_tmp : std_ulogic;
|
||||
begin
|
||||
v_int := r_int;
|
||||
|
||||
-- asynchronous
|
||||
valid_tmp := valid_in and not flush_in;
|
||||
stall_out <= '0';
|
||||
|
||||
if complete_in = '1' then
|
||||
assert r_int.outstanding <= 1 report "Outstanding bad " & integer'image(r_int.outstanding) severity failure;
|
||||
v_int.outstanding := r_int.outstanding - 1;
|
||||
end if;
|
||||
|
||||
-- Handle debugger stop
|
||||
stopped_out <= '0';
|
||||
if stop_mark_in = '1' and v_int.outstanding = 0 then
|
||||
stopped_out <= '1';
|
||||
end if;
|
||||
|
||||
-- state machine to handle instructions that must be single
|
||||
-- through the pipeline.
|
||||
case r_int.state is
|
||||
when IDLE =>
|
||||
if (flush_in = '0') and (valid_tmp = '1') and (sgl_pipe_in = '1') then
|
||||
if v_int.outstanding /= 0 then
|
||||
v_int.state := WAIT_FOR_PREV_TO_COMPLETE;
|
||||
valid_tmp := '0';
|
||||
stall_out <= '1';
|
||||
else
|
||||
-- send insn out and wait on it to complete
|
||||
v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when WAIT_FOR_PREV_TO_COMPLETE =>
|
||||
if v_int.outstanding = 0 then
|
||||
-- send insn out and wait on it to complete
|
||||
v_int.state := WAIT_FOR_CURR_TO_COMPLETE;
|
||||
else
|
||||
valid_tmp := '0';
|
||||
stall_out <= '1';
|
||||
end if;
|
||||
|
||||
when WAIT_FOR_CURR_TO_COMPLETE =>
|
||||
if v_int.outstanding = 0 then
|
||||
v_int.state := IDLE;
|
||||
else
|
||||
valid_tmp := '0';
|
||||
stall_out <= '1';
|
||||
end if;
|
||||
end case;
|
||||
|
||||
-- track outstanding instructions
|
||||
if valid_tmp = '1' then
|
||||
v_int.outstanding := v_int.outstanding + 1;
|
||||
end if;
|
||||
|
||||
if rst = '1' then
|
||||
v_int.state := IDLE;
|
||||
v_int.outstanding := 0;
|
||||
stall_out <= '0';
|
||||
end if;
|
||||
|
||||
-- update outputs
|
||||
valid_out <= valid_tmp;
|
||||
|
||||
-- update registers
|
||||
rin_int <= v_int;
|
||||
end process;
|
||||
end;
|
Loading…
Reference in New Issue