2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
8 use work.wishbone_types.all;
11 -- In this cycle we read or write any data and do sign extension and update if required.
17 l_in : in Loadstore1ToLoadstore2Type;
18 w_out : out Loadstore2ToWritebackType;
20 m_in : in wishbone_slave_out;
21 m_out : out wishbone_master_out
25 architecture behave of loadstore2 is
26 signal l_saved : Loadstore1ToLoadstore2Type;
27 signal w_tmp : Loadstore2ToWritebackType;
28 signal m_tmp : wishbone_master_out;
29 signal read_data : std_ulogic_vector(63 downto 0);
30 signal read_data_shift : std_ulogic_vector(2 downto 0);
31 signal sign_extend_byte_reverse: std_ulogic_vector(1 downto 0);
32 signal dlength : std_ulogic_vector(3 downto 0);
34 type state_t is (IDLE, WAITING_FOR_READ_ACK, WAITING_FOR_WRITE_ACK);
35 signal state : state_t := IDLE;
37 function length_to_sel(length : in std_logic_vector(3 downto 0)) return std_ulogic_vector is
51 end function length_to_sel;
53 function wishbone_data_shift(address : in std_ulogic_vector(63 downto 0)) return natural is
55 return to_integer(unsigned(address(2 downto 0))) * 8;
56 end function wishbone_data_shift;
58 function wishbone_data_sel(size : in std_logic_vector(3 downto 0); address : in std_logic_vector(63 downto 0)) return std_ulogic_vector is
60 return std_ulogic_vector(shift_left(unsigned(length_to_sel(size)), to_integer(unsigned(address(2 downto 0)))));
61 end function wishbone_data_sel;
64 loadstore2_1: process(all)
65 variable tmp : std_ulogic_vector(63 downto 0);
66 variable data : std_ulogic_vector(63 downto 0);
68 tmp := std_logic_vector(shift_right(unsigned(read_data), to_integer(unsigned(read_data_shift)) * 8));
69 data := (others => '0');
70 case to_integer(unsigned(dlength)) is
73 data(7 downto 0) := tmp(7 downto 0);
75 data(15 downto 0) := tmp(15 downto 0);
77 data(31 downto 0) := tmp(31 downto 0);
79 data(63 downto 0) := tmp(63 downto 0);
81 assert false report "invalid length" severity failure;
82 data(63 downto 0) := tmp(63 downto 0);
85 case sign_extend_byte_reverse is
87 w_tmp.write_data <= sign_extend(data, to_integer(unsigned(l_saved.length)));
89 w_tmp.write_data <= byte_reverse(data, to_integer(unsigned(l_saved.length)));
91 w_tmp.write_data <= data;
98 loadstore2_0: process(clk)
100 if rising_edge(clk) then
103 w_tmp.write_enable <= '0';
104 w_tmp.write_reg <= (others => '0');
107 read_data_shift <= "000";
108 sign_extend_byte_reverse <= "00";
111 case_0: case state is
113 if l_in.valid = '1' then
114 m_tmp <= wishbone_master_out_init;
116 m_tmp.sel <= wishbone_data_sel(l_in.length, l_in.addr);
117 m_tmp.adr <= l_in.addr(63 downto 3) & "000";
123 if l_in.load = '1' then
126 -- Load with update instructions write two GPR destinations.
127 -- We don't want the expense of two write ports, so make it
128 -- single in the pipeline and write back the update GPR now
129 -- and the load once we get the data back. We'll have to
130 -- revisit this when loads can take exceptions.
131 if l_in.update = '1' then
132 w_tmp.write_enable <= '1';
133 w_tmp.write_reg <= l_in.update_reg;
134 read_data <= l_in.addr;
137 state <= WAITING_FOR_READ_ACK;
141 m_tmp.dat <= std_logic_vector(shift_left(unsigned(l_in.data), wishbone_data_shift(l_in.addr)));
143 assert l_in.sign_extend = '0' report "sign extension doesn't make sense for stores" severity failure;
145 state <= WAITING_FOR_WRITE_ACK;
149 when WAITING_FOR_READ_ACK =>
150 if m_in.ack = '1' then
151 read_data <= m_in.dat;
152 read_data_shift <= l_saved.addr(2 downto 0);
153 dlength <= l_saved.length;
154 sign_extend_byte_reverse <= l_saved.sign_extend & l_saved.byte_reverse;
156 -- write data to register file
158 w_tmp.write_enable <= '1';
159 w_tmp.write_reg <= l_saved.write_reg;
161 m_tmp <= wishbone_master_out_init;
165 when WAITING_FOR_WRITE_ACK =>
166 if m_in.ack = '1' then
168 if l_saved.update = '1' then
169 w_tmp.write_enable <= '1';
170 w_tmp.write_reg <= l_saved.update_reg;
171 read_data <= l_saved.addr;
174 m_tmp <= wishbone_master_out_init;