2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
8 entity register_file is
10 SIM : boolean := false;
11 HAS_FPU : boolean := true;
12 -- Non-zero to enable log data collection
13 LOG_LENGTH : natural := 0
17 stall : in std_ulogic;
19 d1_in : in Decode1ToRegisterFileType;
20 d_in : in Decode2ToRegisterFileType;
21 d_out : out RegisterFileToDecode2Type;
23 w_in : in WritebackToRegisterFileType;
25 dbg_gpr_req : in std_ulogic;
26 dbg_gpr_ack : out std_ulogic;
27 dbg_gpr_addr : in gspr_index_t;
28 dbg_gpr_data : out std_ulogic_vector(63 downto 0);
31 sim_dump : in std_ulogic;
32 sim_dump_done : out std_ulogic;
34 log_out : out std_ulogic_vector(71 downto 0)
36 end entity register_file;
38 architecture behaviour of register_file is
39 type regfile is array(0 to 63) of std_ulogic_vector(63 downto 0);
40 signal registers : regfile := (others => (others => '0'));
41 signal dbg_data : std_ulogic_vector(63 downto 0);
42 signal dbg_ack : std_ulogic;
43 signal dbg_gpr_done : std_ulogic;
44 signal addr_1_reg : gspr_index_t;
45 signal addr_2_reg : gspr_index_t;
46 signal addr_3_reg : gspr_index_t;
47 signal rd_2 : std_ulogic;
48 signal fwd_1 : std_ulogic;
49 signal fwd_2 : std_ulogic;
50 signal fwd_3 : std_ulogic;
51 signal data_1 : std_ulogic_vector(63 downto 0);
52 signal data_2 : std_ulogic_vector(63 downto 0);
53 signal data_3 : std_ulogic_vector(63 downto 0);
54 signal prev_write_data : std_ulogic_vector(63 downto 0);
57 -- synchronous reads and writes
58 register_write_0: process(clk)
59 variable a_addr, b_addr, c_addr : gspr_index_t;
60 variable w_addr : gspr_index_t;
61 variable b_enable : std_ulogic;
63 if rising_edge(clk) then
64 if w_in.write_enable = '1' then
65 w_addr := w_in.write_reg;
66 if HAS_FPU and w_addr(5) = '1' then
67 report "Writing FPR " & to_hstring(w_addr(4 downto 0)) & " " & to_hstring(w_in.write_data);
70 report "Writing GPR " & to_hstring(w_addr) & " " & to_hstring(w_in.write_data);
72 assert not(is_x(w_in.write_data)) and not(is_x(w_in.write_reg)) severity failure;
73 registers(to_integer(unsigned(w_addr))) <= w_in.write_data;
76 a_addr := d1_in.reg_1_addr;
77 b_addr := d1_in.reg_2_addr;
78 c_addr := d1_in.reg_3_addr;
79 b_enable := d1_in.read_2_enable;
95 if w_in.write_enable = '1' then
96 if w_addr = a_addr then
99 if w_addr = b_addr then
102 if w_addr = c_addr then
107 -- Do debug reads to GPRs and FPRs using the B port when it is not in use
108 if dbg_gpr_req = '1' then
109 if b_enable = '0' then
110 b_addr := dbg_gpr_addr(5 downto 0);
118 -- Make it obvious that we only want 32 GSPRs for a no-FPU implementation
124 data_1 <= (others => 'X');
126 data_1 <= registers(to_integer(unsigned(a_addr)));
129 data_2 <= (others => 'X');
131 data_2 <= registers(to_integer(unsigned(b_addr)));
134 data_3 <= (others => 'X');
136 data_3 <= registers(to_integer(unsigned(c_addr)));
139 prev_write_data <= w_in.write_data;
141 end process register_write_0;
143 -- asynchronous forwarding of write data
144 register_read_0: process(all)
145 variable out_data_1 : std_ulogic_vector(63 downto 0);
146 variable out_data_2 : std_ulogic_vector(63 downto 0);
147 variable out_data_3 : std_ulogic_vector(63 downto 0);
149 out_data_1 := data_1;
150 out_data_2 := data_2;
151 out_data_3 := data_3;
153 out_data_1 := prev_write_data;
156 out_data_2 := prev_write_data;
159 out_data_3 := prev_write_data;
162 if d_in.read1_enable = '1' then
163 report "Reading GPR " & to_hstring(addr_1_reg) & " " & to_hstring(out_data_1);
165 if d_in.read2_enable = '1' then
166 report "Reading GPR " & to_hstring(addr_2_reg) & " " & to_hstring(out_data_2);
168 if d_in.read3_enable = '1' then
169 report "Reading GPR " & to_hstring(addr_3_reg) & " " & to_hstring(out_data_3);
172 d_out.read1_data <= out_data_1;
173 d_out.read2_data <= out_data_2;
174 d_out.read3_data <= out_data_3;
175 end process register_read_0;
177 -- Latch read data and ack if dbg read requested and B port not busy
178 dbg_register_read: process(clk)
180 if rising_edge(clk) then
181 if dbg_gpr_req = '1' then
182 if dbg_ack = '0' and dbg_gpr_done = '1' then
192 dbg_gpr_ack <= dbg_ack;
193 dbg_gpr_data <= dbg_data;
195 -- Dump registers if core terminates
196 sim_dump_test: if SIM generate
197 dump_registers: process(all)
199 if sim_dump = '1' then
200 loop_0: for i in 0 to 31 loop
201 report "GPR" & integer'image(i) & " " & to_hstring(registers(i));
203 sim_dump_done <= '1';
205 sim_dump_done <= '0';
210 -- Keep GHDL synthesis happy
211 sim_dump_test_synth: if not SIM generate
212 sim_dump_done <= '0';
215 rf_log: if LOG_LENGTH > 0 generate
216 signal log_data : std_ulogic_vector(71 downto 0);
218 reg_log: process(clk)
220 if rising_edge(clk) then
221 log_data <= w_in.write_data &
223 '0' & w_in.write_reg;
229 end architecture behaviour;