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