OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_bus.vhd] - Diff between revs 31 and 36

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 31 Rev 36
Line 50... Line 50...
    PMP_GRANULARITY       : natural := 16 -- granularity (1=8B, 2=16B, 3=32B, ...)
    PMP_GRANULARITY       : natural := 16 -- granularity (1=8B, 2=16B, 3=32B, ...)
  );
  );
  port (
  port (
    -- global control --
    -- global control --
    clk_i          : in  std_ulogic; -- global clock, rising edge
    clk_i          : in  std_ulogic; -- global clock, rising edge
    rstn_i         : in  std_ulogic; -- global reset, low-active, async
 
    ctrl_i         : in  std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
    ctrl_i         : in  std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
    -- cpu instruction fetch interface --
    -- cpu instruction fetch interface --
    fetch_pc_i     : in  std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
    fetch_pc_i     : in  std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
    instr_o        : out std_ulogic_vector(data_width_c-1 downto 0); -- instruction
    instr_o        : out std_ulogic_vector(data_width_c-1 downto 0); -- instruction
    i_wait_o       : out std_ulogic; -- wait for fetch to complete
    i_wait_o       : out std_ulogic; -- wait for fetch to complete
Line 73... Line 72...
    be_load_o      : out std_ulogic; -- bus error on load data access
    be_load_o      : out std_ulogic; -- bus error on load data access
    be_store_o     : out std_ulogic; -- bus error on store data access
    be_store_o     : out std_ulogic; -- bus error on store data access
    -- physical memory protection --
    -- physical memory protection --
    pmp_addr_i     : in  pmp_addr_if_t; -- addresses
    pmp_addr_i     : in  pmp_addr_if_t; -- addresses
    pmp_ctrl_i     : in  pmp_ctrl_if_t; -- configs
    pmp_ctrl_i     : in  pmp_ctrl_if_t; -- configs
    priv_mode_i    : in  std_ulogic_vector(1 downto 0); -- current CPU privilege level
 
    -- instruction bus --
    -- instruction bus --
    i_bus_addr_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
    i_bus_addr_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
    i_bus_rdata_i  : in  std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
    i_bus_rdata_i  : in  std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
    i_bus_wdata_o  : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
    i_bus_wdata_o  : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
    i_bus_ben_o    : out std_ulogic_vector(03 downto 0); -- byte enable
    i_bus_ben_o    : out std_ulogic_vector(03 downto 0); -- byte enable
Line 103... Line 101...
 
 
architecture neorv32_cpu_bus_rtl of neorv32_cpu_bus is
architecture neorv32_cpu_bus_rtl of neorv32_cpu_bus is
 
 
  -- PMP modes --
  -- PMP modes --
  constant pmp_off_mode_c   : std_ulogic_vector(1 downto 0) := "00"; -- null region (disabled)
  constant pmp_off_mode_c   : std_ulogic_vector(1 downto 0) := "00"; -- null region (disabled)
  constant pmp_tor_mode_c   : std_ulogic_vector(1 downto 0) := "01"; -- top of range
--constant pmp_tor_mode_c   : std_ulogic_vector(1 downto 0) := "01"; -- top of range
  constant pmp_na4_mode_c   : std_ulogic_vector(1 downto 0) := "10"; -- naturally aligned four-byte region
--constant pmp_na4_mode_c   : std_ulogic_vector(1 downto 0) := "10"; -- naturally aligned four-byte region
  constant pmp_napot_mode_c : std_ulogic_vector(1 downto 0) := "11"; -- naturally aligned power-of-two region (>= 8 bytes)
  constant pmp_napot_mode_c : std_ulogic_vector(1 downto 0) := "11"; -- naturally aligned power-of-two region (>= 8 bytes)
 
 
  -- PMP configuration register bits --
  -- PMP configuration register bits --
  constant pmp_cfg_r_c  : natural := 0; -- read permit
  constant pmp_cfg_r_c  : natural := 0; -- read permit
  constant pmp_cfg_w_c  : natural := 1; -- write permit
  constant pmp_cfg_w_c  : natural := 1; -- write permit
Line 161... Line 159...
 
 
begin
begin
 
 
  -- Data Interface: Access Address ---------------------------------------------------------
  -- Data Interface: Access Address ---------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  mem_adr_reg: process(rstn_i, clk_i)
  mem_adr_reg: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      if (ctrl_i(ctrl_bus_mar_we_c) = '1') then
      if (ctrl_i(ctrl_bus_mar_we_c) = '1') then
        mar <= addr_i;
        mar <= addr_i;
      end if;
      end if;
Line 199... Line 197...
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  mem_do_reg: process(clk_i)
  mem_do_reg: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      if (ctrl_i(ctrl_bus_mdo_we_c) = '1') then
      if (ctrl_i(ctrl_bus_mdo_we_c) = '1') then
        mdo <= wdata_i;
        mdo <= wdata_i; -- memory data out register (MDO)
      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 --
Line 213... Line 211...
      when "00" => -- byte
      when "00" => -- byte
        d_bus_wdata(07 downto 00) <= mdo(07 downto 00);
        d_bus_wdata(07 downto 00) <= mdo(07 downto 00);
        d_bus_wdata(15 downto 08) <= mdo(07 downto 00);
        d_bus_wdata(15 downto 08) <= mdo(07 downto 00);
        d_bus_wdata(23 downto 16) <= mdo(07 downto 00);
        d_bus_wdata(23 downto 16) <= mdo(07 downto 00);
        d_bus_wdata(31 downto 24) <= mdo(07 downto 00);
        d_bus_wdata(31 downto 24) <= mdo(07 downto 00);
        d_bus_ben <= (others => '0');
        case mar(1 downto 0) is
        d_bus_ben(to_integer(unsigned(mar(1 downto 0)))) <= '1';
          when "00"   => d_bus_ben <= "0001";
 
          when "01"   => d_bus_ben <= "0010";
 
          when "10"   => d_bus_ben <= "0100";
 
          when others => d_bus_ben <= "1000";
 
        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 00);
        d_bus_wdata(15 downto 00) <= mdo(15 downto 00);
        d_bus_wdata(15 downto 00) <= mdo(15 downto 00);
        if (mar(1) = '0') then
        if (mar(1) = '0') then
          d_bus_ben <= "0011"; -- low half-word
          d_bus_ben <= "0011"; -- low half-word
Line 235... Line 237...
  -- Data Interface: Read Data --------------------------------------------------------------
  -- Data Interface: Read Data --------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  mem_out_buf: process(clk_i)
  mem_out_buf: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      -- memory data in register (MDI) --
 
      if (ctrl_i(ctrl_bus_mdi_we_c) = '1') then
      if (ctrl_i(ctrl_bus_mdi_we_c) = '1') then
        mdi <= d_bus_rdata;
        mdi <= d_bus_rdata; -- memory data in register (MDI)
      end if;
      end if;
    end if;
    end if;
  end process mem_out_buf;
  end process mem_out_buf;
 
 
  -- 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 signed_v : std_ulogic;
    variable byte_in_v  : std_ulogic_vector(07 downto 0);
 
    variable hword_in_v : std_ulogic_vector(15 downto 0);
  begin
  begin
    signed_v := not ctrl_i(ctrl_bus_unsigned_c);
    -- sub-word input --
    case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is -- data size
 
      when "00" => -- byte
 
        case mar(1 downto 0) is
        case mar(1 downto 0) is
          when "00" =>
      when "00"   => byte_in_v := mdi(07 downto 00); hword_in_v := mdi(15 downto 00); -- byte 0 / half-word 0
            rdata_o(31 downto 08) <= (others => (signed_v and mdi(07)));
      when "01"   => byte_in_v := mdi(15 downto 08); hword_in_v := mdi(15 downto 00); -- byte 1 / half-word 0
            rdata_o(07 downto 00) <= mdi(07 downto 00); -- byte 0
      when "10"   => byte_in_v := mdi(23 downto 16); hword_in_v := mdi(31 downto 16); -- byte 2 / half-word 1
          when "01" =>
      when others => byte_in_v := mdi(31 downto 24); hword_in_v := mdi(31 downto 16); -- byte 3 / half-word 1
            rdata_o(31 downto 08) <= (others => (signed_v and mdi(15)));
 
            rdata_o(07 downto 00) <= mdi(15 downto 08); -- byte 1
 
          when "10" =>
 
            rdata_o(31 downto 08) <= (others => (signed_v and mdi(23)));
 
            rdata_o(07 downto 00) <= mdi(23 downto 16); -- byte 2
 
          when others =>
 
            rdata_o(31 downto 08) <= (others => (signed_v and mdi(31)));
 
            rdata_o(07 downto 00) <= mdi(31 downto 24); -- byte 3
 
        end case;
        end case;
 
    -- actual data size --
 
    case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is
 
      when "00" => -- byte
 
        rdata_o(31 downto 08) <= (others => ((not ctrl_i(ctrl_bus_unsigned_c)) and byte_in_v(7))); -- sign extension
 
        rdata_o(07 downto 00) <= byte_in_v;
      when "01" => -- half-word
      when "01" => -- half-word
        if (mar(1) = '0') then
        rdata_o(31 downto 16) <= (others => ((not ctrl_i(ctrl_bus_unsigned_c)) and hword_in_v(15))); -- sign extension
          rdata_o(31 downto 16) <= (others => (signed_v and mdi(15)));
        rdata_o(15 downto 00) <= hword_in_v; -- high half-word
          rdata_o(15 downto 00) <= mdi(15 downto 00); -- low half-word
 
        else
 
          rdata_o(31 downto 16) <= (others => (signed_v and mdi(31)));
 
          rdata_o(15 downto 00) <= mdi(31 downto 16); -- high half-word
 
        end if;
 
      when others => -- word
      when others => -- word
        rdata_o <= mdi; -- full word
        rdata_o <= mdi; -- full word
    end case;
    end case;
  end process read_align;
  end process read_align;
 
 
Line 295... Line 287...
  end process misaligned_i_check;
  end process misaligned_i_check;
 
 
 
 
  -- Instruction Fetch Arbiter --------------------------------------------------------------
  -- Instruction Fetch Arbiter --------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  ifetch_arbiter: process(rstn_i, clk_i)
  ifetch_arbiter: process(clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if rising_edge(clk_i) then
      i_arbiter.rd_req    <= '0';
 
      i_arbiter.wr_req    <= '0';
 
      i_arbiter.err_align <= '0';
 
      i_arbiter.err_bus   <= '0';
 
      i_arbiter.timeout   <= (others => '0');
 
    elsif rising_edge(clk_i) then
 
      i_arbiter.wr_req <= '0'; -- instruction fetch is read-only
 
 
 
      -- 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';
        i_arbiter.timeout   <= std_ulogic_vector(to_unsigned(bus_timeout_c, index_size_f(bus_timeout_c)));
        i_arbiter.timeout   <= std_ulogic_vector(to_unsigned(bus_timeout_c, index_size_f(bus_timeout_c)));
      else -- in progress
      else -- in progress
        i_arbiter.timeout   <= std_ulogic_vector(unsigned(i_arbiter.timeout) - 1);
        i_arbiter.timeout   <= std_ulogic_vector(unsigned(i_arbiter.timeout) - 1);
        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 (not or_all_f(i_arbiter.timeout)) or i_bus_err_i) and (not ctrl_i(ctrl_bus_ierr_ack_c));
        i_arbiter.err_bus   <= (i_arbiter.err_bus   or (not or_all_f(i_arbiter.timeout)) or i_bus_err_i) and (not ctrl_i(ctrl_bus_ierr_ack_c));
        --if (i_arbiter.err_align = '1') or (i_arbiter.err_bus = '1') then -- any error?
 
        --  if (ctrl_i(ctrl_bus_ierr_ack_c) = '1') then -- wait for controller to acknowledge error
 
        --    i_arbiter.rd_req <= '0';
 
        --  end if;
 
        if (i_bus_ack_i = '1') or (ctrl_i(ctrl_bus_ierr_ack_c) = '1') then -- wait for normal termination / CPU abort
        if (i_bus_ack_i = '1') 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;
      end if;
      end if;
    end if;
    end if;
  end process ifetch_arbiter;
  end process ifetch_arbiter;
 
 
 
  i_arbiter.wr_req <= '0'; -- instruction fetch is read-only
 
 
  -- cancel bus access --
  -- cancel bus access --
  i_bus_cancel_o <= i_arbiter.rd_req and ctrl_i(ctrl_bus_ierr_ack_c);
  i_bus_cancel_o <= i_arbiter.rd_req and ctrl_i(ctrl_bus_ierr_ack_c);
 
 
  -- wait for bus transaction to finish --
  -- wait for bus transaction to finish --
  i_wait_o <= i_arbiter.rd_req and (not i_bus_ack_i);
  i_wait_o <= i_arbiter.rd_req and (not i_bus_ack_i);
Line 349... Line 331...
  instr_o       <= i_bus_rdata_i;
  instr_o       <= i_bus_rdata_i;
 
 
 
 
  -- Data Access Arbiter --------------------------------------------------------------------
  -- Data Access Arbiter --------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  data_access_arbiter: process(rstn_i, clk_i)
  data_access_arbiter: process(clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if rising_edge(clk_i) then
      d_arbiter.rd_req    <= '0';
 
      d_arbiter.wr_req    <= '0';
 
      d_arbiter.err_align <= '0';
 
      d_arbiter.err_bus   <= '0';
 
      d_arbiter.timeout   <= (others => '0');
 
    elsif rising_edge(clk_i) then
 
 
 
      -- data access request --
      -- data access request --
      if (d_arbiter.wr_req = '0') and (d_arbiter.rd_req = '0') then -- idle
      if (d_arbiter.wr_req = '0') and (d_arbiter.rd_req = '0') then -- idle
        d_arbiter.wr_req    <= ctrl_i(ctrl_bus_wr_c);
        d_arbiter.wr_req    <= ctrl_i(ctrl_bus_wr_c);
        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;
Line 370... Line 345...
        d_arbiter.timeout   <= std_ulogic_vector(to_unsigned(bus_timeout_c, index_size_f(bus_timeout_c)));
        d_arbiter.timeout   <= std_ulogic_vector(to_unsigned(bus_timeout_c, index_size_f(bus_timeout_c)));
      else -- in progress
      else -- in progress
        d_arbiter.timeout   <= std_ulogic_vector(unsigned(d_arbiter.timeout) - 1);
        d_arbiter.timeout   <= std_ulogic_vector(unsigned(d_arbiter.timeout) - 1);
        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 (not or_all_f(d_arbiter.timeout)) or d_bus_err_i) and (not ctrl_i(ctrl_bus_derr_ack_c));
        d_arbiter.err_bus   <= (d_arbiter.err_bus   or (not or_all_f(d_arbiter.timeout)) or d_bus_err_i) and (not ctrl_i(ctrl_bus_derr_ack_c));
        --if (d_arbiter.err_align = '1') or (d_arbiter.err_bus = '1') then -- any error?
 
        --  if (ctrl_i(ctrl_bus_derr_ack_c) = '1') then -- wait for controller to acknowledge error
 
        --    d_arbiter.wr_req <= '0';
 
        --    d_arbiter.rd_req <= '0';
 
        --  end if;
 
        if (d_bus_ack_i = '1') or (ctrl_i(ctrl_bus_derr_ack_c) = '1') then -- wait for normal termination / CPU abort
        if (d_bus_ack_i = '1') 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 454... Line 424...
    end loop; -- r
    end loop; -- r
  end process pmp_addr_check;
  end process pmp_addr_check;
 
 
 
 
  -- check access type and regions's permissions --
  -- check access type and regions's permissions --
  pmp_check_permission: process(pmp, pmp_ctrl_i, priv_mode_i)
  pmp_check_permission: process(pmp, pmp_ctrl_i, ctrl_i)
  begin
  begin
    for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
    for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
      if ((priv_mode_i = priv_mode_u_c) or (pmp_ctrl_i(r)(pmp_cfg_l_c) = '1')) and -- user privilege level or locked pmp entry -> enforce permissions also for machine mode
      if ((ctrl_i(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) = priv_mode_u_c) or (pmp_ctrl_i(r)(pmp_cfg_l_c) = '1')) and -- user privilege level or locked pmp entry -> enforce permissions also for machine mode
          (pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) /= pmp_off_mode_c) then -- active entry
          (pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) /= pmp_off_mode_c) then -- active entry
        pmp.if_fault(r) <= pmp.i_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_x_c)); -- fetch access match no execute permission
        pmp.if_fault(r) <= pmp.i_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_x_c)); -- fetch access match no execute permission
        pmp.ld_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_r_c)); -- load access match no read permission
        pmp.ld_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_r_c)); -- load access match no read permission
        pmp.st_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_w_c)); -- store access match no write permission
        pmp.st_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_w_c)); -- store access match no write permission
      else
      else

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.