2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
10 RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0');
11 ALT_RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0')
18 stall_in : in std_ulogic;
19 flush_in : in std_ulogic;
20 stop_in : in std_ulogic;
21 alt_reset_in : in std_ulogic;
23 -- redirect from execution unit
24 e_in : in Execute1ToFetch1Type;
27 i_out : out Fetch1ToIcacheType
31 architecture behaviour of fetch1 is
32 type stop_state_t is (RUNNING, STOPPED, RESTARTING);
33 type reg_internal_t is record
34 stop_state: stop_state_t;
36 signal r, r_next : Fetch1ToIcacheType;
37 signal r_int, r_next_int : reg_internal_t;
42 if rising_edge(clk) then
44 report "fetch1 rst:" & std_ulogic'image(rst) &
45 " R:" & std_ulogic'image(e_in.redirect) &
46 " S:" & std_ulogic'image(stall_in) &
47 " T:" & std_ulogic'image(stop_in) &
48 " nia:" & to_hstring(r_next.nia) &
49 " SM:" & std_ulogic'image(r_next.stop_mark);
57 variable v : Fetch1ToIcacheType;
58 variable v_int : reg_internal_t;
59 variable increment : boolean;
65 if alt_reset_in = '1' then
66 v.nia := ALT_RESET_ADDRESS;
68 v.nia := RESET_ADDRESS;
70 v_int.stop_state := RUNNING;
71 elsif e_in.redirect = '1' then
72 v.nia := e_in.redirect_nia;
73 elsif stall_in = '0' then
75 -- For debug stop/step to work properly we need a little bit of
76 -- trickery here. If we just stop incrementing and send stop marks
77 -- when stop_in is set, then we'll increment on the cycle it clears
78 -- and end up never executing the instruction we were stopped on.
80 -- Avoid this along with the opposite issue when stepping (stop is
81 -- cleared for only one cycle) is handled by the state machine below
83 -- By default, increment addresses
85 case v_int.stop_state is
87 -- If we are running and stop_in is set, then stop incrementing,
88 -- we are now stopped.
91 v_int.stop_state := STOPPED;
94 -- When stopped, never increment. If stop is cleared, go to state
95 -- "restarting" but still don't increment that cycle. stop_in is
96 -- now 0 so we'll send the NIA down without a stop mark.
99 v_int.stop_state := RESTARTING;
102 -- We have just sent the NIA down, we can start incrementing again.
103 -- If stop_in is still not set, go back to running normally.
104 -- If stop_in is set again (that was a one-cycle "step"), go
105 -- back to "stopped" state which means we'll stop incrementing
106 -- on the next cycle. This ensures we increment the PC once after
107 -- sending one instruction without a stop mark. Since stop_in is
108 -- now set, the new PC will be sent with a stop mark and thus not
110 if stop_in = '0' then
111 v_int.stop_state := RUNNING;
113 v_int.stop_state := STOPPED;
118 v.nia := std_logic_vector(unsigned(v.nia) + 4);
123 v.stop_mark := stop_in;
128 -- Update outputs to the icache
133 end architecture behaviour;