6ae72693cfe60fa0f72199450df51f68eb18e80b
[microwatt.git] / fetch2.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.common.all;
7 use work.wishbone_types.all;
8
9 entity fetch2 is
10 port(
11 clk : in std_ulogic;
12 rst : in std_ulogic;
13
14 stall_in : in std_ulogic;
15 stall_out : out std_ulogic;
16
17 flush_in : in std_ulogic;
18
19 -- instruction memory interface
20 wishbone_in : in wishbone_slave_out;
21 wishbone_out : out wishbone_master_out;
22
23 f_in : in Fetch1ToFetch2Type;
24
25 f_out : out Fetch2ToDecode1Type
26 );
27 end entity fetch2;
28
29 architecture behaviour of fetch2 is
30 type state_type is (IDLE, JUST_IDLE, WAIT_ACK, WAIT_ACK_THROWAWAY);
31
32 type reg_internal_type is record
33 state : state_type;
34 nia : std_ulogic_vector(63 downto 0);
35 w : wishbone_master_out;
36 -- Trivial 64B cache
37 cache : std_ulogic_vector(63 downto 0);
38 tag : std_ulogic_vector(60 downto 0);
39 tag_valid : std_ulogic;
40 end record;
41
42 function wishbone_fetch(nia : std_ulogic_vector(63 downto 0)) return wishbone_master_out is
43 variable w : wishbone_master_out;
44 begin
45 assert nia(2 downto 0) = "000";
46
47 w.adr := nia;
48 w.dat := (others => '0');
49 w.cyc := '1';
50 w.stb := '1';
51 w.sel := "11111111";
52 w.we := '0';
53
54 return w;
55 end;
56
57 signal r, rin : Fetch2ToDecode1Type;
58 signal r_int, rin_int : reg_internal_type;
59 begin
60 regs : process(clk)
61 begin
62 if rising_edge(clk) then
63 -- Output state remains unchanged on stall, unless we are flushing
64 if rst = '1' or flush_in = '1' or stall_in = '0' then
65 r <= rin;
66 end if;
67 r_int <= rin_int;
68 end if;
69 end process;
70
71 comb : process(all)
72 variable v : Fetch2ToDecode1Type;
73 variable v_int : reg_internal_type;
74 begin
75 v := r;
76 v_int := r_int;
77
78 v.valid := '0';
79 v.nia := f_in.nia;
80
81 case v_int.state is
82 when IDLE | JUST_IDLE =>
83 v_int.state := IDLE;
84
85 if (v_int.tag_valid = '1') and (v_int.tag = f_in.nia(63 downto 3)) then
86 v.valid := '1';
87 if f_in.nia(2) = '0' then
88 v.insn := v_int.cache(31 downto 0);
89 else
90 v.insn := v_int.cache(63 downto 32);
91 end if;
92 else
93 v_int.state := WAIT_ACK;
94 v_int.nia := f_in.nia;
95 v_int.w := wishbone_fetch(f_in.nia(63 downto 3) & "000");
96 end if;
97
98 when WAIT_ACK =>
99 if wishbone_in.ack = '1' then
100 v_int.state := IDLE;
101 v_int.w := wishbone_master_out_init;
102 v_int.cache := wishbone_in.dat;
103 v_int.tag := v_int.nia(63 downto 3);
104 v_int.tag_valid := '1';
105
106 v.valid := '1';
107 if v_int.nia(2) = '0' then
108 v.insn := v_int.cache(31 downto 0);
109 else
110 v.insn := v_int.cache(63 downto 32);
111 end if;
112 end if;
113
114 when WAIT_ACK_THROWAWAY =>
115 if wishbone_in.ack = '1' then
116 -- Should we put the returned data in the cache? We went to the
117 -- trouble of fetching it and it might be useful in the future
118
119 v_int.w := wishbone_master_out_init;
120
121 -- We need to stall fetch1 for one more cycle, so transition through JUST_IDLE
122 v_int.state := JUST_IDLE;
123 end if;
124 end case;
125
126 stall_out <= '0';
127 if v_int.state /= IDLE then
128 stall_out <= '1';
129 end if;
130
131 if flush_in = '1' then
132 v.valid := '0';
133
134 -- Throw away in flight data
135 if v_int.state = WAIT_ACK then
136 v_int.state := WAIT_ACK_THROWAWAY;
137 end if;
138 end if;
139
140 if rst = '1' then
141 v := Fetch2ToDecode1Init;
142
143 v_int.state := IDLE;
144 v_int.nia := (others => '0');
145 v_int.w := wishbone_master_out_init;
146 v_int.cache := (others => '0');
147 v_int.tag := (others => '0');
148 v_int.tag_valid := '0';
149 end if;
150
151 -- Update registers
152 rin_int <= v_int;
153 rin <= v;
154
155 -- Update outputs
156 f_out <= r;
157 wishbone_out <= r_int.w;
158 end process;
159 end architecture behaviour;