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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_slink.vhd] - Diff between revs 65 and 68

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

Rev 65 Rev 68
Line 124... Line 124...
  -- bus access control --
  -- bus access control --
  signal ack_read  : std_ulogic;
  signal ack_read  : std_ulogic;
  signal ack_write : std_ulogic;
  signal ack_write : std_ulogic;
  signal acc_en    : std_ulogic;
  signal acc_en    : std_ulogic;
  signal addr      : std_ulogic_vector(31 downto 0);
  signal addr      : std_ulogic_vector(31 downto 0);
 
  signal wren      : std_ulogic; -- word write enable
 
  signal rden      : std_ulogic; -- read enable
 
 
  -- control register --
  -- control register --
  signal enable : std_ulogic; -- global enable
  signal enable : std_ulogic; -- global enable
 
 
  -- IRQ configuration register --
  -- IRQ configuration register --
Line 146... Line 148...
  signal rx_fifo_avail : std_ulogic_vector(7 downto 0);
  signal rx_fifo_avail : std_ulogic_vector(7 downto 0);
  signal tx_fifo_free  : std_ulogic_vector(7 downto 0);
  signal tx_fifo_free  : std_ulogic_vector(7 downto 0);
  signal rx_fifo_half  : std_ulogic_vector(7 downto 0);
  signal rx_fifo_half  : std_ulogic_vector(7 downto 0);
  signal tx_fifo_half  : std_ulogic_vector(7 downto 0);
  signal tx_fifo_half  : std_ulogic_vector(7 downto 0);
 
 
 
  -- interrupt generator --
 
  type detect_t is array (0 to 7) of std_ulogic_vector(1 downto 0);
 
  type irq_t is record
 
    pending : std_ulogic; -- pending interrupt request
 
    detect  : detect_t; -- rising-edge detector
 
    trigger : std_ulogic_vector(7 downto 0);
 
    set     : std_ulogic_vector(7 downto 0);
 
    clr     : std_ulogic;
 
  end record;
 
  signal rx_irq, tx_irq : irq_t;
 
 
begin
begin
 
 
  -- Sanity Checks --------------------------------------------------------------------------
  -- Sanity Checks --------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  assert not (is_power_of_two_f(SLINK_TX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_TX_FIFO> has to be a power of two." severity error;
  assert not (is_power_of_two_f(SLINK_TX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_TX_FIFO> has to be a power of two." severity error;
Line 167... Line 180...
 
 
  -- Access Control -------------------------------------------------------------------------
  -- Access Control -------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = slink_base_c(hi_abb_c downto lo_abb_c)) else '0';
  acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = slink_base_c(hi_abb_c downto lo_abb_c)) else '0';
  addr   <= slink_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
  addr   <= slink_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
 
  wren   <= acc_en and wren_i;
 
  rden   <= acc_en and rden_i;
 
 
 
 
  -- Read/Write Access ----------------------------------------------------------------------
  -- Read/Write Access ----------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  rw_access: process(clk_i)
  rw_access: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      -- write access --
      -- write access --
      ack_write <= '0';
      ack_write <= '0';
      if (acc_en = '1') and (wren_i = '1') then
      if (wren = '1') then
        if (addr(5) = '0') then -- control/status/irq
        if (addr(5) = '0') then -- control/status/irq
          if (addr(4 downto 3) = "00") then -- control register
          if (addr(4 downto 3) = "00") then -- control register
            enable <= data_i(ctrl_en_c);
            enable <= data_i(ctrl_en_c);
          end if;
          end if;
          if (addr(4 downto 3) = "01") then -- IRQ configuration register
          if (addr(4 downto 3) = "01") then -- IRQ configuration register
Line 200... Line 215...
      end if;
      end if;
 
 
      -- read access --
      -- read access --
      data_o   <= (others => '0');
      data_o   <= (others => '0');
      ack_read <= '0';
      ack_read <= '0';
      if (acc_en = '1') and (rden_i = '1') then
      if (rden = '1') then
        if (addr(5) = '0') then -- control/status registers
        if (addr(5) = '0') then -- control/status registers
          ack_read <= '1';
          ack_read <= '1';
          case addr(4 downto 3) is
          case addr(4 downto 3) is
            when "00" => -- control register
            when "00" => -- control register
              data_o(ctrl_rx_num_msb_c  downto ctrl_rx_num_lsb_c)  <= std_ulogic_vector(to_unsigned(SLINK_NUM_RX, 4));
              data_o(ctrl_rx_num_msb_c  downto ctrl_rx_num_lsb_c)  <= std_ulogic_vector(to_unsigned(SLINK_NUM_RX, 4));
Line 244... Line 259...
  fifo_clear <= not enable;
  fifo_clear <= not enable;
 
 
 
 
  -- Interrupt Generator --------------------------------------------------------------------
  -- Interrupt Generator --------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  irq_arbiter: process(clk_i)
  irq_type: process(irq_rx_mode, rx_fifo_avail, rx_fifo_half,
    variable rx_tmp_v : std_ulogic_vector(SLINK_NUM_RX-1 downto 0);
                    irq_tx_mode, tx_fifo_free,  tx_fifo_half)
    variable tx_tmp_v : std_ulogic_vector(SLINK_NUM_TX-1 downto 0);
 
  begin
  begin
    if rising_edge(clk_i) then
 
      if (enable = '0') then -- no interrupts if unit is disabled
 
        irq_rx_o <= '0';
 
        irq_tx_o <= '0';
 
      else
 
 
 
        -- RX interrupt --
        -- RX interrupt --
 
    rx_irq.trigger <= (others => '0');
 
    for i in 0 to SLINK_NUM_RX-1 loop
        if (SLINK_RX_FIFO = 1) then
        if (SLINK_RX_FIFO = 1) then
          irq_rx_o <= or_reduce_f(irq_rx_en and rx_fifo_avail); -- fire if any RX_FIFO is not empty
        rx_irq.trigger(i) <= rx_fifo_avail(i); -- fire if any RX_FIFO is not empty
        else
        else
          rx_tmp_v := (others => '0');
 
          for i in 0 to SLINK_NUM_RX-1 loop
 
            if (irq_rx_mode(i) = '0') then -- fire if any RX_FIFO is at least half-full
            if (irq_rx_mode(i) = '0') then -- fire if any RX_FIFO is at least half-full
              rx_tmp_v(i) := rx_fifo_half(i);
          rx_irq.trigger(i) <= rx_fifo_half(i);
            else -- fire if any RX_FIFO is not empty (= data available)
            else -- fire if any RX_FIFO is not empty (= data available)
              rx_tmp_v(i) := rx_fifo_avail(i);
          rx_irq.trigger(i) <= rx_fifo_avail(i);
            end if;
            end if;
          end loop;
 
          irq_rx_o <= or_reduce_f(irq_rx_en and rx_tmp_v);
 
        end if;
        end if;
 
    end loop;
        -- TX interrupt --
        -- TX interrupt --
 
    tx_irq.trigger <= (others => '0');
 
    for i in 0 to SLINK_NUM_TX-1 loop
        if (SLINK_TX_FIFO = 1) then
        if (SLINK_TX_FIFO = 1) then
          irq_tx_o <= or_reduce_f(irq_tx_en and tx_fifo_free); -- fire if any TX_FIFO is not full
        tx_irq.trigger(i) <= tx_fifo_free(i); -- fire if any TX_FIFO is not full
        else
        else
          tx_tmp_v := (others => '0');
        if (irq_tx_mode(i) = '0') then -- fire if any TX_FIFO is less than half-full
 
          tx_irq.trigger(i) <= not tx_fifo_half(i);
 
        else -- fire if any TX_FIFO is not full (= free buffer space available)
 
          tx_irq.trigger(i) <= tx_fifo_free(i);
 
        end if;
 
      end if;
 
    end loop;
 
  end process irq_type;
 
 
 
  -- interrupt trigger --
 
  irq_trigger_sync: process(clk_i)
 
  begin
 
    if rising_edge(clk_i) then
 
      -- RX --
 
      rx_irq.detect <= (others => (others => '0')); -- default
 
      if (enable = '1') then
 
        for i in 0 to SLINK_NUM_RX-1 loop
 
          rx_irq.detect(i) <= rx_irq.detect(i)(0) & rx_irq.trigger(i);
 
        end loop;
 
      end if;
 
      -- TX --
 
      tx_irq.detect <= (others => (others => '0')); -- default
 
      if (enable = '1') then
          for i in 0 to SLINK_NUM_TX-1 loop
          for i in 0 to SLINK_NUM_TX-1 loop
            if (irq_tx_mode(i) = '0') then -- fire if any RX_FIFO is less than half-full
          tx_irq.detect(i) <= tx_irq.detect(i)(0) & tx_irq.trigger(i);
              tx_tmp_v(i) := not rx_fifo_half(i);
        end loop;
            else -- fire if any RX_FIFO is not full (= free buffer space available)
      end if;
              tx_tmp_v(i) := tx_fifo_free(i);
    end if;
 
  end process irq_trigger_sync;
 
 
 
  -- interrupt trigger --
 
  irq_trigger_comb: process(rx_irq, irq_rx_en, tx_irq, irq_tx_en)
 
  begin
 
    -- RX --
 
    rx_irq.set <= (others => '0');
 
    for i in 0 to SLINK_NUM_RX-1 loop
 
      if (rx_irq.detect(i) = "01") and (irq_rx_en(i) = '1') then -- rising-edge
 
        rx_irq.set(i) <= '1';
            end if;
            end if;
          end loop;
          end loop;
          irq_tx_o <= or_reduce_f(irq_tx_en and tx_tmp_v);
    -- TX --
 
    tx_irq.set <= (others => '0');
 
    for i in 0 to SLINK_NUM_TX-1 loop
 
      if (tx_irq.detect(i) = "01") and (irq_tx_en(i) = '1') then -- rising-edge
 
        tx_irq.set(i) <= '1';
        end if;
        end if;
 
    end loop;
 
  end process irq_trigger_comb;
 
 
 
  -- interrupt arbiter --
 
  irq_generator: process(clk_i)
 
  begin
 
    if rising_edge(clk_i) then
 
      if (enable = '0') then
 
        rx_irq.pending <= '0';
 
        tx_irq.pending <= '0';
 
      else
 
        -- RX --
 
        if (or_reduce_f(rx_irq.set) = '1') then
 
          rx_irq.pending <= '1';
 
        elsif (rx_irq.clr = '1') then
 
          rx_irq.pending <= '0';
      end if;
      end if;
 
        -- TX --
 
        if (or_reduce_f(tx_irq.set) = '1') then
 
          tx_irq.pending <= '1';
 
        elsif (tx_irq.clr = '1') then
 
          tx_irq.pending <= '0';
    end if;
    end if;
  end process irq_arbiter;
      end if;
 
    end if;
 
  end process irq_generator;
 
 
 
  -- IRQ requests to CPU --
 
  irq_rx_o <= rx_irq.pending;
 
  irq_tx_o <= tx_irq.pending;
 
 
 
  -- IRQ acknowledge --
 
  rx_irq.clr <= '1' when ((rden = '1') and (addr(5) = '1')) or ((wren = '1') and (addr(5 downto 3) = "000")) else '0'; -- read from data FIFO OR write to control register
 
  tx_irq.clr <= '1' when ((wren = '1') and (addr(5) = '1')) or ((wren = '1') and (addr(5 downto 3) = "000")) else '0'; -- write to data FIFO  OR write to control register
 
 
 
 
  -- Link Select ----------------------------------------------------------------------------
  -- Link Select ----------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  link_select: process(addr)
  link_select: process(addr)
Line 307... Line 382...
    end case;
    end case;
  end process link_select;
  end process link_select;
 
 
  fifo_access_gen:
  fifo_access_gen:
  for i in 0 to 7 generate
  for i in 0 to 7 generate
    tx_fifo_we(i) <= link_sel(i) and acc_en and wren_i;
    tx_fifo_we(i) <= link_sel(i) and wren;
    rx_fifo_re(i) <= link_sel(i) and acc_en and rden_i;
    rx_fifo_re(i) <= link_sel(i) and rden;
  end generate;
  end generate;
 
 
 
 
  -- TX Link FIFOs --------------------------------------------------------------------------
  -- TX Link FIFOs --------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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