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.
		
		
		
		
		
			
		
			
				
	
	
		
			181 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			VHDL
		
	
			
		
		
	
	
			181 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			VHDL
		
	
| library ieee;
 | |
| use ieee.std_logic_1164.all;
 | |
| use ieee.numeric_std.all;
 | |
| 
 | |
| library work;
 | |
| use work.common.all;
 | |
| use work.helpers.all;
 | |
| use work.wishbone_types.all;
 | |
| 
 | |
| -- 2 cycle LSU
 | |
| -- In this cycle we read or write any data and do sign extension and update if required.
 | |
| 
 | |
| entity loadstore2 is
 | |
|     port (
 | |
|         clk   : in std_ulogic;
 | |
| 
 | |
|         l_in  : in Loadstore1ToLoadstore2Type;
 | |
|         w_out : out Loadstore2ToWritebackType;
 | |
| 
 | |
|         m_in  : in wishbone_slave_out;
 | |
|         m_out : out wishbone_master_out
 | |
|         );
 | |
| end loadstore2;
 | |
| 
 | |
| architecture behave of loadstore2 is
 | |
|     signal l_saved : Loadstore1ToLoadstore2Type;
 | |
|     signal w_tmp   : Loadstore2ToWritebackType;
 | |
|     signal m_tmp   : wishbone_master_out;
 | |
|     signal read_data : std_ulogic_vector(63 downto 0);
 | |
|     signal read_data_shift : std_ulogic_vector(2 downto 0);
 | |
|     signal sign_extend_byte_reverse: std_ulogic_vector(1 downto 0);
 | |
|     signal dlength : std_ulogic_vector(3 downto 0);
 | |
| 
 | |
|     type state_t is (IDLE, WAITING_FOR_READ_ACK, WAITING_FOR_WRITE_ACK);
 | |
|     signal state   : state_t := IDLE;
 | |
| 
 | |
|     function length_to_sel(length : in std_logic_vector(3 downto 0)) return std_ulogic_vector is
 | |
|     begin
 | |
|         case length is
 | |
|             when "0001" =>
 | |
|                 return "00000001";
 | |
|             when "0010" =>
 | |
|                 return "00000011";
 | |
|             when "0100" =>
 | |
|                 return "00001111";
 | |
|             when "1000" =>
 | |
|                 return "11111111";
 | |
|             when others =>
 | |
|                 return "00000000";
 | |
|         end case;
 | |
|     end function length_to_sel;
 | |
| 
 | |
|     function wishbone_data_shift(address : in std_ulogic_vector(63 downto 0)) return natural is
 | |
|     begin
 | |
|         return to_integer(unsigned(address(2 downto 0))) * 8;
 | |
|     end function wishbone_data_shift;
 | |
| 
 | |
|     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
 | |
|     begin
 | |
|         return std_ulogic_vector(shift_left(unsigned(length_to_sel(size)), to_integer(unsigned(address(2 downto 0)))));
 | |
|     end function wishbone_data_sel;
 | |
| begin
 | |
| 
 | |
|     loadstore2_1: process(all)
 | |
|         variable tmp     : std_ulogic_vector(63 downto 0);
 | |
|         variable data    : std_ulogic_vector(63 downto 0);
 | |
|     begin
 | |
|         tmp := std_logic_vector(shift_right(unsigned(read_data), to_integer(unsigned(read_data_shift)) * 8));
 | |
|         data := (others => '0');
 | |
|         case to_integer(unsigned(dlength)) is
 | |
|             when 0 =>
 | |
|             when 1 =>
 | |
|                 data(7 downto 0) := tmp(7 downto 0);
 | |
|             when 2 =>
 | |
|                 data(15 downto 0) := tmp(15 downto 0);
 | |
|             when 4 =>
 | |
|                 data(31 downto 0) := tmp(31 downto 0);
 | |
|             when 8 =>
 | |
|                 data(63 downto 0) := tmp(63 downto 0);
 | |
|             when others =>
 | |
|                 assert false report "invalid length" severity failure;
 | |
|                 data(63 downto 0) := tmp(63 downto 0);
 | |
|         end case;
 | |
| 
 | |
|         case sign_extend_byte_reverse is
 | |
|             when "10" =>
 | |
|                 w_tmp.write_data <= sign_extend(data, to_integer(unsigned(l_saved.length)));
 | |
|             when "01" =>
 | |
|                 w_tmp.write_data <= byte_reverse(data, to_integer(unsigned(l_saved.length)));
 | |
|             when others =>
 | |
|                 w_tmp.write_data <= data;
 | |
|         end case;
 | |
|     end process;
 | |
| 
 | |
|     w_out <= w_tmp;
 | |
|     m_out <= m_tmp;
 | |
| 
 | |
|     loadstore2_0: process(clk)
 | |
|     begin
 | |
|         if rising_edge(clk) then
 | |
| 
 | |
|             w_tmp.valid <= '0';
 | |
|             w_tmp.write_enable <= '0';
 | |
|             w_tmp.write_reg <= (others => '0');
 | |
| 
 | |
|             l_saved <= l_saved;
 | |
|             read_data_shift <= "000";
 | |
|             sign_extend_byte_reverse <= "00";
 | |
|             dlength <= "1000";
 | |
| 
 | |
|             case_0: case state is
 | |
|                 when IDLE =>
 | |
|                     if l_in.valid = '1' then
 | |
|                         m_tmp <= wishbone_master_out_init;
 | |
| 
 | |
|                         m_tmp.sel <= wishbone_data_sel(l_in.length, l_in.addr);
 | |
|                         m_tmp.adr <= l_in.addr(63 downto 3) & "000";
 | |
|                         m_tmp.cyc <= '1';
 | |
|                         m_tmp.stb <= '1';
 | |
| 
 | |
|                         l_saved <= l_in;
 | |
| 
 | |
|                         if l_in.load = '1' then
 | |
|                             m_tmp.we <= '0';
 | |
| 
 | |
|                             -- Load with update instructions write two GPR destinations.
 | |
|                             -- We don't want the expense of two write ports, so make it
 | |
|                             -- single in the pipeline and write back the update GPR now
 | |
|                             -- and the load once we get the data back. We'll have to
 | |
|                             -- revisit this when loads can take exceptions.
 | |
|                             if l_in.update = '1' then
 | |
|                                 w_tmp.write_enable <= '1';
 | |
|                                 w_tmp.write_reg <= l_in.update_reg;
 | |
|                                 read_data <= l_in.addr;
 | |
|                             end if;
 | |
| 
 | |
|                             state <= WAITING_FOR_READ_ACK;
 | |
|                         else
 | |
|                             m_tmp.we <= '1';
 | |
| 
 | |
|                             m_tmp.dat <= std_logic_vector(shift_left(unsigned(l_in.data), wishbone_data_shift(l_in.addr)));
 | |
| 
 | |
|                             assert l_in.sign_extend = '0' report "sign extension doesn't make sense for stores" severity failure;
 | |
| 
 | |
|                             state <= WAITING_FOR_WRITE_ACK;
 | |
|                         end if;
 | |
|                     end if;
 | |
| 
 | |
|                 when WAITING_FOR_READ_ACK =>
 | |
|                     if m_in.ack = '1' then
 | |
|                         read_data <= m_in.dat;
 | |
|                         read_data_shift <= l_saved.addr(2 downto 0);
 | |
|                         dlength <= l_saved.length;
 | |
|                         sign_extend_byte_reverse <= l_saved.sign_extend & l_saved.byte_reverse;
 | |
| 
 | |
|                         -- write data to register file
 | |
|                         w_tmp.valid <= '1';
 | |
|                         w_tmp.write_enable <= '1';
 | |
|                         w_tmp.write_reg <= l_saved.write_reg;
 | |
| 
 | |
|                         m_tmp <= wishbone_master_out_init;
 | |
|                         state <= IDLE;
 | |
|                     end if;
 | |
| 
 | |
|                 when WAITING_FOR_WRITE_ACK =>
 | |
|                     if m_in.ack = '1' then
 | |
|                         w_tmp.valid <= '1';
 | |
|                         if l_saved.update = '1' then
 | |
|                             w_tmp.write_enable <= '1';
 | |
|                             w_tmp.write_reg <= l_saved.update_reg;
 | |
|                             read_data <= l_saved.addr;
 | |
|                         end if;
 | |
| 
 | |
|                         m_tmp <= wishbone_master_out_init;
 | |
|                         state <= IDLE;
 | |
|                     end if;
 | |
|             end case;
 | |
|         end if;
 | |
|     end process;
 | |
| end;
 |