Line 191... |
Line 191... |
mar <= addr_i;
|
mar <= addr_i;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process mem_adr_reg;
|
end process mem_adr_reg;
|
|
|
-- read-back for exception controller --
|
-- address read-back for exception controller --
|
mar_o <= mar;
|
mar_o <= mar;
|
|
|
-- alignment check --
|
-- alignment check --
|
misaligned_d_check: process(mar, ctrl_i)
|
misaligned_d_check: process(mar, ctrl_i)
|
begin
|
begin
|
-- check data access --
|
|
d_misaligned <= '0'; -- default
|
|
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is -- data size
|
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is -- data size
|
when "00" => -- byte
|
when "00" => -- byte
|
d_misaligned <= '0';
|
d_misaligned <= '0';
|
when "01" => -- half-word
|
when "01" => -- half-word
|
if (mar(0) /= '0') then
|
if (mar(0) /= '0') then
|
d_misaligned <= '1';
|
d_misaligned <= '1';
|
|
else
|
|
d_misaligned <= '0';
|
end if;
|
end if;
|
when others => -- word
|
when others => -- word
|
if (mar(1 downto 0) /= "00") then
|
if (mar(1 downto 0) /= "00") then
|
d_misaligned <= '1';
|
d_misaligned <= '1';
|
|
else
|
|
d_misaligned <= '0';
|
end if;
|
end if;
|
end case;
|
end case;
|
end process misaligned_d_check;
|
end process misaligned_d_check;
|
|
|
|
|
Line 228... |
Line 230... |
end if;
|
end if;
|
end if;
|
end if;
|
end process mem_do_reg;
|
end process mem_do_reg;
|
|
|
-- byte enable and output data alignment --
|
-- byte enable and output data alignment --
|
byte_enable: process(mar, mdo, ctrl_i)
|
write_align: process(mar, mdo, ctrl_i)
|
begin
|
begin
|
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is -- data size
|
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is -- data size
|
when "00" => -- byte
|
when "00" => -- byte
|
d_bus_wdata(07 downto 00) <= mdo(07 downto 00);
|
d_bus_wdata(07 downto 00) <= mdo(7 downto 0);
|
d_bus_wdata(15 downto 08) <= mdo(07 downto 00);
|
d_bus_wdata(15 downto 08) <= mdo(7 downto 0);
|
d_bus_wdata(23 downto 16) <= mdo(07 downto 00);
|
d_bus_wdata(23 downto 16) <= mdo(7 downto 0);
|
d_bus_wdata(31 downto 24) <= mdo(07 downto 00);
|
d_bus_wdata(31 downto 24) <= mdo(7 downto 0);
|
case mar(1 downto 0) is
|
case mar(1 downto 0) is
|
when "00" => d_bus_ben <= "0001";
|
when "00" => d_bus_ben <= "0001";
|
when "01" => d_bus_ben <= "0010";
|
when "01" => d_bus_ben <= "0010";
|
when "10" => d_bus_ben <= "0100";
|
when "10" => d_bus_ben <= "0100";
|
when others => d_bus_ben <= "1000";
|
when others => d_bus_ben <= "1000";
|
end case;
|
end case;
|
when "01" => -- half-word
|
when "01" => -- half-word
|
d_bus_wdata(31 downto 16) <= mdo(15 downto 00);
|
d_bus_wdata(31 downto 16) <= mdo(15 downto 0);
|
d_bus_wdata(15 downto 00) <= mdo(15 downto 00);
|
d_bus_wdata(15 downto 00) <= mdo(15 downto 0);
|
if (mar(1) = '0') then
|
if (mar(1) = '0') then
|
d_bus_ben <= "0011"; -- low half-word
|
d_bus_ben <= "0011"; -- low half-word
|
else
|
else
|
d_bus_ben <= "1100"; -- high half-word
|
d_bus_ben <= "1100"; -- high half-word
|
end if;
|
end if;
|
when others => -- word
|
when others => -- word
|
d_bus_wdata <= mdo;
|
d_bus_wdata <= mdo;
|
d_bus_ben <= "1111"; -- full word
|
d_bus_ben <= "1111"; -- full word
|
end case;
|
end case;
|
end process byte_enable;
|
end process write_align;
|
|
|
|
|
-- Data Interface: Read Data --------------------------------------------------------------
|
-- Data Interface: Read Data --------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
mem_di_reg: process(rstn_i, clk_i)
|
mem_di_reg: process(rstn_i, clk_i)
|
Line 272... |
Line 274... |
end if;
|
end if;
|
end process mem_di_reg;
|
end process mem_di_reg;
|
|
|
-- input data alignment and sign extension --
|
-- input data alignment and sign extension --
|
read_align: process(mdi, mar, ctrl_i)
|
read_align: process(mdi, mar, ctrl_i)
|
variable byte_in_v : std_ulogic_vector(07 downto 0);
|
variable shifted_data_v : std_ulogic_vector(31 downto 0);
|
variable hword_in_v : std_ulogic_vector(15 downto 0);
|
|
begin
|
begin
|
-- sub-word input --
|
-- align input word --
|
case mar(1 downto 0) is
|
case mar(1 downto 0) is
|
when "00" => byte_in_v := mdi(07 downto 00); hword_in_v := mdi(15 downto 00); -- byte 0 / half-word 0
|
when "00" => shifted_data_v := mdi(31 downto 00);
|
when "01" => byte_in_v := mdi(15 downto 08); hword_in_v := mdi(15 downto 00); -- byte 1 / half-word 0
|
when "01" => shifted_data_v := x"00" & mdi(31 downto 08);
|
when "10" => byte_in_v := mdi(23 downto 16); hword_in_v := mdi(31 downto 16); -- byte 2 / half-word 1
|
when "10" => shifted_data_v := x"0000" & mdi(31 downto 16);
|
when others => byte_in_v := mdi(31 downto 24); hword_in_v := mdi(31 downto 16); -- byte 3 / half-word 1
|
when others => shifted_data_v := x"000000" & mdi(31 downto 24);
|
end case;
|
end case;
|
-- actual data size --
|
-- actual data size and sign-extension --
|
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is
|
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is
|
when "00" => -- byte
|
when "00" => -- byte
|
rdata_align(31 downto 08) <= (others => ((not ctrl_i(ctrl_bus_unsigned_c)) and byte_in_v(7))); -- sign extension
|
rdata_align(31 downto 08) <= (others => ((not ctrl_i(ctrl_bus_unsigned_c)) and shifted_data_v(7))); -- sign extension
|
rdata_align(07 downto 00) <= byte_in_v;
|
rdata_align(07 downto 00) <= shifted_data_v(07 downto 00);
|
when "01" => -- half-word
|
when "01" => -- half-word
|
rdata_align(31 downto 16) <= (others => ((not ctrl_i(ctrl_bus_unsigned_c)) and hword_in_v(15))); -- sign extension
|
rdata_align(31 downto 16) <= (others => ((not ctrl_i(ctrl_bus_unsigned_c)) and shifted_data_v(15))); -- sign extension
|
rdata_align(15 downto 00) <= hword_in_v; -- high half-word
|
rdata_align(15 downto 00) <= shifted_data_v(15 downto 00); -- high half-word
|
when others => -- word
|
when others => -- word
|
rdata_align <= mdi; -- full word
|
rdata_align <= shifted_data_v; -- full word
|
end case;
|
end case;
|
end process read_align;
|
end process read_align;
|
|
|
-- insert exclusive lock status for SC operations only --
|
-- insert exclusive lock status for SC operations only --
|
rdata_o <= exclusive_lock_status when (CPU_EXTENSION_RISCV_A = true) and (ctrl_i(ctrl_bus_ch_lock_c) = '1') else rdata_align;
|
rdata_o <= exclusive_lock_status when (CPU_EXTENSION_RISCV_A = true) and (ctrl_i(ctrl_bus_ch_lock_c) = '1') else rdata_align;
|
Line 317... |
Line 318... |
d_arbiter.rd_req <= ctrl_i(ctrl_bus_rd_c);
|
d_arbiter.rd_req <= ctrl_i(ctrl_bus_rd_c);
|
d_arbiter.err_align <= d_misaligned;
|
d_arbiter.err_align <= d_misaligned;
|
d_arbiter.err_bus <= '0';
|
d_arbiter.err_bus <= '0';
|
else -- in progress
|
else -- in progress
|
d_arbiter.err_align <= (d_arbiter.err_align or d_misaligned) and (not ctrl_i(ctrl_bus_derr_ack_c));
|
d_arbiter.err_align <= (d_arbiter.err_align or d_misaligned) and (not ctrl_i(ctrl_bus_derr_ack_c));
|
d_arbiter.err_bus <= (d_arbiter.err_bus or d_bus_err_i or (st_pmp_fault and d_arbiter.wr_req) or (ld_pmp_fault and d_arbiter.rd_req)) and
|
d_arbiter.err_bus <= (d_arbiter.err_bus or d_bus_err_i or (st_pmp_fault and d_arbiter.wr_req) or (ld_pmp_fault and d_arbiter.rd_req)) and (not ctrl_i(ctrl_bus_derr_ack_c));
|
(not ctrl_i(ctrl_bus_derr_ack_c));
|
|
if ((d_bus_ack_i = '1') and (d_bus_err_i = '0')) or (ctrl_i(ctrl_bus_derr_ack_c) = '1') then -- wait for normal termination / CPU abort
|
if ((d_bus_ack_i = '1') and (d_bus_err_i = '0')) or (ctrl_i(ctrl_bus_derr_ack_c) = '1') then -- wait for normal termination / CPU abort
|
d_arbiter.wr_req <= '0';
|
d_arbiter.wr_req <= '0';
|
d_arbiter.rd_req <= '0';
|
d_arbiter.rd_req <= '0';
|
end if;
|
end if;
|
end if;
|
end if;
|
Line 405... |
Line 405... |
-- instruction fetch request --
|
-- instruction fetch request --
|
if (i_arbiter.rd_req = '0') then -- idle
|
if (i_arbiter.rd_req = '0') then -- idle
|
i_arbiter.rd_req <= ctrl_i(ctrl_bus_if_c);
|
i_arbiter.rd_req <= ctrl_i(ctrl_bus_if_c);
|
i_arbiter.err_align <= i_misaligned;
|
i_arbiter.err_align <= i_misaligned;
|
i_arbiter.err_bus <= '0';
|
i_arbiter.err_bus <= '0';
|
else -- in progres
|
else -- in progress
|
i_arbiter.err_align <= (i_arbiter.err_align or i_misaligned) and (not ctrl_i(ctrl_bus_ierr_ack_c));
|
i_arbiter.err_align <= (i_arbiter.err_align or i_misaligned) and (not ctrl_i(ctrl_bus_ierr_ack_c));
|
i_arbiter.err_bus <= (i_arbiter.err_bus or i_bus_err_i or if_pmp_fault) and (not ctrl_i(ctrl_bus_ierr_ack_c));
|
i_arbiter.err_bus <= (i_arbiter.err_bus or i_bus_err_i or if_pmp_fault) and (not ctrl_i(ctrl_bus_ierr_ack_c));
|
if ((i_bus_ack_i = '1') and (i_bus_err_i = '0')) or (ctrl_i(ctrl_bus_ierr_ack_c) = '1') then -- wait for normal termination / CPU abort
|
if ((i_bus_ack_i = '1') and (i_bus_err_i = '0')) or (ctrl_i(ctrl_bus_ierr_ack_c) = '1') then -- wait for normal termination / CPU abort
|
i_arbiter.rd_req <= '0';
|
i_arbiter.rd_req <= '0';
|
end if;
|
end if;
|