You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			119 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			VHDL
		
	
			
		
		
	
	
			119 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			VHDL
		
	
| library ieee;
 | |
| use ieee.std_logic_1164.all;
 | |
| use ieee.numeric_std.all;
 | |
| 
 | |
| library work;
 | |
| use work.common.all;
 | |
| use work.wishbone_types.all;
 | |
| 
 | |
| entity fetch2 is
 | |
|     port(
 | |
| 	clk          : in std_ulogic;
 | |
| 	rst          : in std_ulogic;
 | |
| 
 | |
| 	stall_in     : in std_ulogic;
 | |
| 	flush_in     : in std_ulogic;
 | |
| 
 | |
| 	-- Results from icache
 | |
| 	i_in         : in IcacheToFetch2Type;
 | |
| 
 | |
| 	-- Output to decode
 | |
| 	f_out        : out Fetch2ToDecode1Type
 | |
| 	);
 | |
| end entity fetch2;
 | |
| 
 | |
| architecture behaviour of fetch2 is
 | |
| 
 | |
|     -- The icache cannot stall, so we need to stash a cycle
 | |
|     -- of output from it when we stall.
 | |
|     type reg_internal_type is record
 | |
| 	stash       : IcacheToFetch2Type;
 | |
| 	stash_valid : std_ulogic;
 | |
| 	stopped     : std_ulogic;
 | |
|     end record;
 | |
| 
 | |
|     signal r_int, rin_int : reg_internal_type;
 | |
|     signal r, rin : Fetch2ToDecode1Type;
 | |
| 
 | |
| begin
 | |
|     regs : process(clk)
 | |
|     begin
 | |
| 	if rising_edge(clk) then
 | |
| 
 | |
| 	    if (r /= rin) then
 | |
| 		report "fetch2 rst:" & std_ulogic'image(rst) &
 | |
| 		    " S:" & std_ulogic'image(stall_in) &
 | |
| 		    " F:" & std_ulogic'image(flush_in) &
 | |
| 		    " T:" & std_ulogic'image(rin.stop_mark) &
 | |
| 		    " V:" & std_ulogic'image(rin.valid) &
 | |
| 		    " nia:" & to_hstring(rin.nia);
 | |
| 	    end if;
 | |
| 
 | |
| 	    -- Output state remains unchanged on stall, unless we are flushing
 | |
| 	    if rst = '1' or flush_in = '1' or stall_in = '0' then
 | |
| 		r <= rin;
 | |
| 	    end if;
 | |
| 
 | |
| 	    -- Internal state is updated on every clock
 | |
| 	    r_int <= rin_int;
 | |
| 	end if;
 | |
|     end process;
 | |
| 
 | |
|     comb : process(all)
 | |
| 	variable v      : Fetch2ToDecode1Type;
 | |
| 	variable v_int  : reg_internal_type;
 | |
| 	variable v_i_in : IcacheToFetch2Type;
 | |
|     begin
 | |
| 	v := r;
 | |
| 	v_int := r_int;
 | |
| 
 | |
| 	-- If stalling, stash away the current input from the icache
 | |
| 	if stall_in = '1' and v_int.stash_valid = '0' then
 | |
| 	    v_int.stash := i_in;
 | |
| 	    v_int.stash_valid := '1';
 | |
| 	end if;
 | |
| 
 | |
| 	-- If unstalling, source input from the stash and invalidate it,
 | |
| 	-- otherwise source normally from the icache.
 | |
| 	--
 | |
| 	v_i_in := i_in;
 | |
| 	if v_int.stash_valid = '1' and stall_in = '0' then
 | |
| 	    v_i_in := v_int.stash;
 | |
| 	    v_int.stash_valid := '0';
 | |
| 	end if;
 | |
| 
 | |
| 	v.valid := v_i_in.valid;
 | |
| 	v.stop_mark := v_i_in.stop_mark;
 | |
| 	v.nia := v_i_in.nia;
 | |
| 	v.insn := v_i_in.insn;
 | |
| 
 | |
| 	-- Clear stash internal valid bit on flush. We still mark
 | |
| 	-- the stash itself as valid since we still want to override
 | |
| 	-- whatever comes form icache when unstalling, but we'll
 | |
| 	-- override it with something invalid.
 | |
| 	--
 | |
| 	if flush_in = '1' then
 | |
| 	    v_int.stash.valid := '0';
 | |
| 	end if;
 | |
| 
 | |
| 	-- If we are flushing or the instruction comes with a stop mark
 | |
| 	-- we tag it as invalid so it doesn't get decoded and executed
 | |
| 	if flush_in = '1' or v.stop_mark = '1' then
 | |
| 	    v.valid := '0';
 | |
| 	end if;
 | |
| 
 | |
| 	-- Clear stash on reset
 | |
| 	if rst = '1' then
 | |
| 	    v_int.stash_valid := '0';
 | |
| 	end if;
 | |
| 
 | |
| 	-- Update registers
 | |
| 	rin <= v;
 | |
| 	rin_int <= v_int;
 | |
| 
 | |
| 	-- Update outputs
 | |
| 	f_out <= r;
 | |
|     end process;
 | |
| 
 | |
| end architecture behaviour;
 |