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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [riverlib/] [dsu/] [axi_dsu.vhd] - Rev 5

Compare with Previous | Blame | View Log

-----------------------------------------------------------------------------
--! @file
--! @copyright Copyright 2015 GNSS Sensor Ltd. All right reserved.
--! @author    Sergey Khabarov - sergeykhbr@gmail.com
--! @brief     Debug Support Unit (DSU) with AXI4 interface.
--! @details   DSU provides access to the internal CPU registers via
--!            'Debug port' bus interface available only on <b>RIVER</b> CPU.
--!            It is also implements a set of registers collecting bus
--!            utilization statistic and additional debug information.
-----------------------------------------------------------------------------
 
--! VHDL base library.
library ieee;
--! VHDL base types import
use ieee.std_logic_1164.all;
--! VHDL base numeric import
use ieee.numeric_std.all;
--! SoC common functionality library.
library commonlib;
--! SoC common types import
use commonlib.types_common.all;
--! AMBA system bus specific library.
library ambalib;
--! AXI4 configuration constants.
use ambalib.types_amba4.all;
--! RIVER CPU specific library.
library riverlib;
--! RIVER CPU configuration constants.
use riverlib.river_cfg.all;
--! River top level with AMBA interface module declaration
use riverlib.types_river.all;
 
entity axi_dsu is
  generic (
    xaddr    : integer := 0;
    xmask    : integer := 16#fffff#
  );
  port 
  (
    clk    : in std_logic;
    nrst   : in std_logic;
    o_cfg  : out nasti_slave_config_type;
    i_axi  : in nasti_slave_in_type;
    o_axi  : out nasti_slave_out_type;
    o_dporti : out dport_in_type;
    i_dporto : in dport_out_type;
    --! reset CPU and interrupt controller
    o_soft_rst : out std_logic;
    -- Platfrom run-time statistic
    i_miss_irq  : in std_logic;
    i_miss_addr : in std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0);
    i_bus_util_w : in std_logic_vector(CFG_NASTI_MASTER_TOTAL-1 downto 0);
    i_bus_util_r : in std_logic_vector(CFG_NASTI_MASTER_TOTAL-1 downto 0)
  );
end;
 
architecture arch_axi_dsu of axi_dsu is
 
  constant xconfig : nasti_slave_config_type := (
     descrtype => PNP_CFG_TYPE_SLAVE,
     descrsize => PNP_CFG_SLAVE_DESCR_BYTES,
     irq_idx => 0,
     xaddr => conv_std_logic_vector(xaddr, CFG_NASTI_CFG_ADDR_BITS),
     xmask => conv_std_logic_vector(xmask, CFG_NASTI_CFG_ADDR_BITS),
     vid => VENDOR_GNSSSENSOR,
     did => GNSSSENSOR_DSU
  );
 
type state_type is (reading, writting, dport_response, ready);
 
type mst_utilization_type is array (0 to CFG_NASTI_MASTER_TOTAL-1) 
       of std_logic_vector(63 downto 0);
 
type mst_utilization_map_type is array (0 to 2*CFG_NASTI_MASTER_TOTAL-1) 
       of std_logic_vector(63 downto 0);
 
type registers is record
  bank_axi : nasti_slave_bank_type;
  --! Message multiplexer to form 32->64 request message
  state         : state_type;
  waddr : std_logic_vector(13 downto 0);
  wdata : std_logic_vector(63 downto 0);
  rdata : std_logic_vector(63 downto 0);
  soft_rst : std_logic;
  -- Platform statistic:
  clk_cnt : std_logic_vector(63 downto 0);
  miss_access_cnt : std_logic_vector(63 downto 0);
  miss_access_addr : std_logic_vector(CFG_NASTI_ADDR_BITS-1 downto 0);
  util_w_cnt : mst_utilization_type;
  util_r_cnt : mst_utilization_type;
end record;
 
signal r, rin: registers;
begin
 
  comblogic : process(nrst, i_axi, i_dporto, i_miss_irq, i_miss_addr,
                      i_bus_util_w, i_bus_util_r, r)
    variable v : registers;
    variable mux_rdata : std_logic_vector(CFG_NASTI_DATA_BITS-1 downto 0);
    variable vdporti : dport_in_type;
    variable iraddr : integer;
    variable wb_bus_util_map : mst_utilization_map_type;
  begin
    v := r;
    v.rdata := (others => '0');
    vdporti.valid := '0';
    vdporti.write := '0';
    vdporti.region := (others => '0');
    vdporti.addr := (others => '0');
    vdporti.wdata := (others => '0');
 
    -- Update statistic:
    v.clk_cnt := r.clk_cnt + 1;
    if i_miss_irq = '1' then
      v.miss_access_addr := i_miss_addr;
      v.miss_access_cnt := r.miss_access_cnt + 1;
    end if;
 
    for n in 0 to CFG_NASTI_MASTER_TOTAL-1 loop
       if i_bus_util_w(n) = '1' then
         v.util_w_cnt(n) := r.util_w_cnt(n) + 1;
       end if;
       if i_bus_util_r(n) = '1' then
         v.util_r_cnt(n) := r.util_r_cnt(n) + 1;
       end if;
    end loop;
 
    for n in 0 to CFG_NASTI_MASTER_TOTAL-1 loop
      wb_bus_util_map(2*n) := r.util_w_cnt(n);
      wb_bus_util_map(2*n+1) := r.util_r_cnt(n);
    end loop;
 
    procedureAxi4(i_axi, xconfig, r.bank_axi, v.bank_axi);
    --! redefine value 'always ready' inserting waiting states.
    v.bank_axi.rwaitready := '0';
 
    if r.bank_axi.wstate = wtrans then
      -- 32-bits burst transaction
      v.waddr := r.bank_axi.waddr(0)(16 downto 3);
      if r.bank_axi.wburst = NASTI_BURST_INCR and r.bank_axi.wsize = 4 then
         if r.bank_axi.waddr(0)(2) = '1' then
             v.state := writting;
             v.wdata(63 downto 32) := i_axi.w_data(31 downto 0);
         else
             v.wdata(31 downto 0) := i_axi.w_data(31 downto 0);
         end if;
      else
         -- Write data on next clock.
         if i_axi.w_strb /= X"00" then
            v.wdata := i_axi.w_data;
         end if;
         v.state := writting;
      end if;
    end if;
 
    case r.state is
      when reading =>
           if r.bank_axi.rstate = rtrans then
              if r.bank_axi.raddr(0)(16 downto 15) = "11" then
                --! local region
                v.bank_axi.rwaitready := '1';
                iraddr := conv_integer(r.bank_axi.raddr(0)(14 downto 3));
                case iraddr is
                when 0 =>
                  v.rdata(0) := r.soft_rst;
                when 1 =>
                  v.rdata := r.miss_access_cnt;
                when 2 =>
                  v.rdata(CFG_NASTI_ADDR_BITS-1 downto 0) := r.miss_access_addr;
                when others =>
                  if (iraddr >= 8) and (iraddr < (8 + 2*CFG_NASTI_MASTER_TOTAL)) then
                      v.rdata := wb_bus_util_map(iraddr - 8);
                  end if;
                end case;
                v.state := ready;
              else
                --! debug port regions: 0 to 2
                vdporti.valid := '1';
                vdporti.write := '0';
                vdporti.region := r.bank_axi.raddr(0)(16 downto 15);
                vdporti.addr := r.bank_axi.raddr(0)(14 downto 3);
                vdporti.wdata := (others => '0');
                v.state := dport_response;
              end if;
           end if;
      when writting =>
           v.state := reading;
           if r.waddr(13 downto 12) = "11" then
             --! local region
             case conv_integer(r.waddr(11 downto 0)) is
             when 0 =>
               v.soft_rst := r.wdata(0);
             when others =>
             end case;
           else
             --! debug port regions: 0 to 2
             vdporti.valid := '1';
             vdporti.write := '1';
             vdporti.region := r.waddr(13 downto 12);
             vdporti.addr := r.waddr(11 downto 0);
             vdporti.wdata := r.wdata;
           end if;
      when dport_response =>
             v.state := ready;
             v.bank_axi.rwaitready := '1';
             v.rdata := i_dporto.rdata;
      when ready =>
             v.state := reading;
      when others =>
    end case;
 
    if r.bank_axi.raddr(0)(2) = '0' then
       mux_rdata(31 downto 0) := r.rdata(31 downto 0);
    else
       -- 32-bits aligned access (can be generated by MAC)
       mux_rdata(31 downto 0) := r.rdata(63 downto 32);
    end if;
    mux_rdata(63 downto 32) := r.rdata(63 downto 32);
 
    o_axi <= functionAxi4Output(r.bank_axi, mux_rdata);
 
    if nrst = '0' then 
       v.bank_axi := NASTI_SLAVE_BANK_RESET;
       v.state := reading;
       v.waddr := (others => '0');
       v.wdata := (others => '0');
       v.rdata := (others => '0');
       v.soft_rst := '0';
       v.clk_cnt := (others => '0');
       v.miss_access_cnt := (others => '0');
       v.miss_access_addr := (others => '0');
       v.util_w_cnt := (others => (others => '0'));
       v.util_r_cnt := (others => (others => '0'));
    end if;
 
    rin <= v;
 
    o_dporti <= vdporti;
  end process;
 
  o_cfg  <= xconfig;
  o_soft_rst <= r.soft_rst;
 
 
  -- registers:
  regs : process(clk)
  begin 
    if rising_edge(clk) then 
       r <= rin; 
    end if; 
  end process;
end;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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