Skip to content
Snippets Groups Projects
wishbone_pkg.vhd 89.7 KiB
Newer Older
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
-- description: Collection of Wishbone modules and definitions used in various
-- OHWR projects.
--------------------------------------------------------------------------------
-- Copyright CERN 2011-2018
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;

use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.genram_pkg.all;
  constant c_wishbone_address_width : integer := 32;
  constant c_wishbone_data_width    : integer := 32;

  subtype t_wishbone_address is
    std_logic_vector(c_wishbone_address_width-1 downto 0);
  subtype t_wishbone_data is
    std_logic_vector(c_wishbone_data_width-1 downto 0);
  subtype t_wishbone_byte_select is
    std_logic_vector((c_wishbone_address_width/8)-1 downto 0);
  subtype t_wishbone_cycle_type is
    std_logic_vector(2 downto 0);
  subtype t_wishbone_burst_type is
    std_logic_vector(1 downto 0);

  type t_wishbone_interface_mode is (CLASSIC, PIPELINED);
  type t_wishbone_address_granularity is (BYTE, WORD);
  type t_wishbone_master_out is record
    cyc : std_logic;
    stb : std_logic;
    adr : t_wishbone_address;
    sel : t_wishbone_byte_select;
    we  : std_logic;
    dat : t_wishbone_data;
  end record t_wishbone_master_out;

  subtype t_wishbone_slave_in is t_wishbone_master_out;

  type t_wishbone_slave_out is record
    ack   : std_logic;
    err   : std_logic;
    rty   : std_logic;
    stall : std_logic;
    dat   : t_wishbone_data;
  end record t_wishbone_slave_out;
  subtype t_wishbone_master_in is t_wishbone_slave_out;
  -- variants for 64-bit data
  subtype t_wishbone_data64 is
    std_logic_vector(63 downto 0);
  subtype t_wishbone_byte_select_data64 is
    std_logic_vector(7 downto 0);

  type t_wishbone_master_data64_out is record
    cyc : std_logic;
    stb : std_logic;
    adr : t_wishbone_address;
    sel : t_wishbone_byte_select_data64;
    we  : std_logic;
    dat : t_wishbone_data64;
  end record t_wishbone_master_data64_out;

  subtype t_wishbone_slave_data64_in is t_wishbone_master_data64_out;

  type t_wishbone_slave_data64_out is record
    ack   : std_logic;
    err   : std_logic;
    rty   : std_logic;
    stall : std_logic;
    dat   : t_wishbone_data64;
  end record t_wishbone_slave_data64_out;

  subtype t_wishbone_master_data64_in is t_wishbone_slave_data64_out;

  type t_wishbone_master_data64_out_array is array (natural range <>) of t_wishbone_master_data64_out;
  subtype t_wishbone_slave_data64_in_array is t_wishbone_master_data64_out_array;
  type t_wishbone_slave_data64_out_array is array (natural range <>) of t_wishbone_slave_data64_out;
  subtype t_wishbone_master_data64_in_array is t_wishbone_slave_data64_out_array;

  subtype t_wishbone_device_descriptor is std_logic_vector(255 downto 0);
  type t_wishbone_byte_select_array is array(natural range <>) of t_wishbone_byte_select; 
  type t_wishbone_data_array is array(natural range <>) of t_wishbone_data; 
  type t_wishbone_address_array is array(natural range <>) of t_wishbone_address;
  type t_wishbone_master_out_array is array (natural range <>) of t_wishbone_master_out;
  subtype t_wishbone_slave_in_array is t_wishbone_master_out_array;
  type t_wishbone_slave_out_array is array (natural range <>) of t_wishbone_slave_out;
  subtype t_wishbone_master_in_array is t_wishbone_slave_out_array;
  constant c_DUMMY_WB_ADDR : std_logic_vector(c_WISHBONE_ADDRESS_WIDTH-1 downto 0) :=
  constant c_DUMMY_WB_DATA : std_logic_vector(c_WISHBONE_DATA_WIDTH-1 downto 0) :=
  constant c_DUMMY_WB_SEL : std_logic_vector(c_WISHBONE_DATA_WIDTH/8-1 downto 0) :=
  constant c_DUMMY_WB_SLAVE_IN   : t_wishbone_slave_in :=
    ('0', '0', c_DUMMY_WB_ADDR, c_DUMMY_WB_SEL, 'X', c_DUMMY_WB_DATA);
  constant c_DUMMY_WB_MASTER_OUT : t_wishbone_master_out := c_DUMMY_WB_SLAVE_IN;
  constant c_DUMMY_WB_SLAVE_OUT  : t_wishbone_slave_out :=
    ('1', '0', '0', '0', c_DUMMY_WB_DATA);
  constant c_DUMMY_WB_MASTER_IN  : t_wishbone_master_in := c_DUMMY_WB_SLAVE_OUT;
  constant c_DUMMY_WB_ADDR_ARRAY : t_wishbone_address_array(0 downto 0) := (0 => c_DUMMY_WB_ADDR);
  -- Dangerous! c_STALL_WB_SLAVE_OUT and c_STALL_WB_MASTER_IN will stall the bus.
  -- Kept here for backward compatibility, if anyone was using cc_dummy_slave_out.
  constant c_STALL_WB_SLAVE_OUT  : t_wishbone_slave_out := ('X', 'X', 'X', 'X', c_DUMMY_WB_DATA);
  constant c_STALL_WB_MASTER_IN  : t_wishbone_master_in := c_DUMMY_WB_SLAVE_OUT;

  -- For backward compatibility
  constant cc_dummy_address : std_logic_vector(c_wishbone_address_width-1 downto 0) := c_DUMMY_WB_ADDR;
  constant cc_dummy_data : std_logic_vector(c_wishbone_data_width-1 downto 0) := c_DUMMY_WB_DATA;
  constant cc_dummy_sel : std_logic_vector(c_wishbone_data_width/8-1 downto 0) := c_DUMMY_WB_SEL;
  constant cc_dummy_slave_in : t_wishbone_slave_in := c_DUMMY_WB_SLAVE_IN;
  constant cc_dummy_master_out : t_wishbone_master_out := c_DUMMY_WB_MASTER_OUT;
  constant cc_dummy_slave_out : t_wishbone_slave_out := c_STALL_WB_SLAVE_OUT;
  constant cc_dummy_master_in : t_wishbone_master_in := c_STALL_WB_MASTER_IN;
  constant cc_dummy_address_array : t_wishbone_address_array(0 downto 0) := c_DUMMY_WB_ADDR_ARRAY;
  -- A generally useful function.
  function f_bits2string(s : std_logic_vector) return string;
  function f_string2bits(s : string) return std_logic_vector;
  function f_string2svl (s : string) return std_logic_vector;
  function f_slv2string (slv : std_logic_vector) return string;

  function f_string_fix_len( s : string; ret_len : natural := 10; fill_char : character := '0'; justify_right : boolean := true ) return string;
  function f_hot_to_bin(x : std_logic_vector) return natural;
  
  -- *** Wishbone slave interface functions ***
  -- f_wb_wr:
  -- processes an incoming write reqest to a register while honoring the select lines
  -- valid modes are overwrite "owr", set "set" (bits are or'ed) and clear "clr" (bits are nand'ed)
  function f_wb_wr(pval : std_logic_vector; ival : std_logic_vector; sel : std_logic_vector; mode : string := "owr") return std_logic_vector;
------------------------------------------------------------------------------
------------------------------------------------------------------------------

  constant c_sdb_device_length : natural := 512;  -- bits
  subtype  t_sdb_record is std_logic_vector(c_sdb_device_length-1 downto 0);
  type     t_sdb_record_array is array(natural range <>) of t_sdb_record;
  type t_sdb_product is record
    vendor_id : std_logic_vector(63 downto 0);
    device_id : std_logic_vector(31 downto 0);
    version   : std_logic_vector(31 downto 0);
    date      : std_logic_vector(31 downto 0);
    name      : string(1 to 19);
  end record t_sdb_product;
  type t_sdb_component is record
    addr_first : std_logic_vector(63 downto 0);
    addr_last  : std_logic_vector(63 downto 0);
    product    : t_sdb_product;
  end record t_sdb_component;
  constant c_sdb_endian_big    : std_logic := '0';
  constant c_sdb_endian_little : std_logic := '1';
    abi_class     : std_logic_vector(15 downto 0);
    abi_ver_major : std_logic_vector(7 downto 0);
    abi_ver_minor : std_logic_vector(7 downto 0);
    wbd_endian    : std_logic;          -- 0 = big, 1 = little
    wbd_width     : std_logic_vector(3 downto 0);  -- 3=64-bit, 2=32-bit, 1=16-bit, 0=8-bit
    sdb_component : t_sdb_component;
  end record t_sdb_device;
  type t_sdb_msi is record
    wbd_endian    : std_logic;          -- 0 = big, 1 = little
    wbd_width     : std_logic_vector(3 downto 0);  -- 3=64-bit, 2=32-bit, 1=16-bit, 0=8-bit
    sdb_component : t_sdb_component;
  end record t_sdb_msi;

  type t_sdb_bridge is record
    sdb_child     : std_logic_vector(63 downto 0);
    sdb_component : t_sdb_component;
  end record t_sdb_bridge;
  type t_sdb_integration is record
    product : t_sdb_product;
  end record t_sdb_integration;

  type t_sdb_repo_url is record
    repo_url : string(1 to 63);
  end record t_sdb_repo_url;

  type t_sdb_synthesis is record
    syn_module_name  : string(1 to 16);
    syn_commit_id    : string(1 to 32);
    syn_tool_name    : string(1 to 8);
    syn_tool_version : std_logic_vector(31 downto 0);
    syn_date         : std_logic_vector(31 downto 0);
    syn_username     : string(1 to 15);
  end record t_sdb_synthesis;
  -- If you have a Wishbone master that does not receive MSI,
  -- list it in the layout as 'f_sdb_auto_msi(c_null_msi, false)'
  constant c_null_msi : t_sdb_msi := (
   wbd_endian    => c_sdb_endian_big,
   wbd_width     => x"0",
   sdb_component => (
   addr_first    => x"0000000000000000",
   addr_last     => x"0000000000000000",
   product => (
   vendor_id     => x"0000000000000000",
   device_id     => x"00000000",
   version       => x"00000000",
   date          => x"00000000",
   name          => "                   ")));  
  -- general crossbar building functions
  function f_sdb_create_array(g_enum_dev_id  : boolean := false;
                              g_dev_id_offs    : natural := 0;
                              g_enum_dev_name  : boolean := false;
                              g_dev_name_offs  : natural := 0;       
                              device           : t_sdb_device; 
                              instances        : natural := 1) return t_sdb_record_array;  
  function f_sdb_join_arrays(a : t_sdb_record_array; b : t_sdb_record_array) return t_sdb_record_array;
  function f_sdb_extract_base_addr(sdb_record : t_sdb_record) return std_logic_vector;
  function f_sdb_extract_end_addr(sdb_record : t_sdb_record)  return std_logic_vector;
  function f_sdb_automap_array(sdb_array : t_sdb_record_array; start_offset : t_wishbone_address := (others => '0')) return t_sdb_record_array;  
  function f_align_addr_offset(offs : unsigned; this_rng : unsigned; prev_rng : unsigned) return unsigned; 
  function f_sdb_create_rom_addr(sdb_array : t_sdb_record_array) return t_wishbone_address;


Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
  -- Used to configure a device at a certain address
  function f_sdb_embed_device(device : t_sdb_device; address : t_wishbone_address) return t_sdb_record;
  function f_sdb_embed_bridge(bridge : t_sdb_bridge; address : t_wishbone_address) return t_sdb_record;
  function f_sdb_embed_msi(msi : t_sdb_msi; address : t_wishbone_address) return t_sdb_record;
  function f_sdb_embed_integration(integr : t_sdb_integration) return t_sdb_record;
  function f_sdb_embed_repo_url(url : t_sdb_repo_url) return t_sdb_record;
  function f_sdb_embed_synthesis(syn : t_sdb_synthesis) return t_sdb_record;
  function f_sdb_extract_device(sdb_record : t_sdb_record) return t_sdb_device;
  function f_sdb_extract_bridge(sdb_record : t_sdb_record) return t_sdb_bridge;
  function f_sdb_extract_msi(sdb_record : t_sdb_record) return t_sdb_msi;
  function f_sdb_extract_integration(sdb_record : t_sdb_record) return t_sdb_integration;
  function f_sdb_extract_repo_url(sdb_record : t_sdb_record) return t_sdb_repo_url;
  function f_sdb_extract_synthesis(sdb_record : t_sdb_record) return t_sdb_synthesis;
  -- Automatic crossbar mapping functions
  function f_sdb_auto_device(device : t_sdb_device; enable : boolean := true; name: string := "") return t_sdb_record;
  function f_sdb_auto_bridge(bridge : t_sdb_bridge; enable : boolean := true; name: string := "") return t_sdb_record;
  function f_sdb_auto_msi   (msi    : t_sdb_msi;    enable : boolean := true) return t_sdb_record;
  function f_sdb_auto_layout(records: t_sdb_record_array)                               return t_sdb_record_array;
  function f_sdb_auto_layout(slaves : t_sdb_record_array; masters : t_sdb_record_array) return t_sdb_record_array;
  function f_sdb_auto_sdb   (records: t_sdb_record_array)                               return t_wishbone_address;
  function f_sdb_auto_sdb   (slaves : t_sdb_record_array; masters : t_sdb_record_array) return t_wishbone_address;
  -- For internal use by the crossbar
  function f_sdb_bus_end(g_wraparound : boolean; g_layout : t_sdb_record_array; g_sdb_addr : t_wishbone_address; msi : boolean) return unsigned;
  function f_sdb_embed_product(product         : t_sdb_product) return std_logic_vector;  -- (319 downto 8)
  function f_sdb_embed_component(sdb_component : t_sdb_component; address : t_wishbone_address) return std_logic_vector;  -- (447 downto 8)
  function f_sdb_extract_product(sdb_record    : std_logic_vector(319 downto 8)) return t_sdb_product;
  function f_sdb_extract_component(sdb_record  : std_logic_vector(447 downto 8)) return t_sdb_component;

------------------------------------------------------------------------------
-- Components declaration
-------------------------------------------------------------------------------

      g_master_use_struct  : boolean;
      g_master_mode        : t_wishbone_interface_mode;
      g_master_granularity : t_wishbone_address_granularity;
      g_slave_use_struct   : boolean;
      g_slave_mode         : t_wishbone_interface_mode;
      g_slave_granularity  : t_wishbone_address_granularity);
    port (
      clk_sys_i  : in  std_logic;
      rst_n_i    : in  std_logic;
      sl_adr_i   : in  std_logic_vector(c_wishbone_address_width-1 downto 0) := cc_dummy_address;
      sl_dat_i   : in  std_logic_vector(c_wishbone_data_width-1 downto 0)    := cc_dummy_data;
      sl_sel_i   : in  std_logic_vector(c_wishbone_data_width/8-1 downto 0)  := cc_dummy_sel;
      sl_cyc_i   : in  std_logic                                             := '0';
      sl_stb_i   : in  std_logic                                             := '0';
      sl_we_i    : in  std_logic                                             := '0';
      sl_dat_o   : out std_logic_vector(c_wishbone_data_width-1 downto 0);
      sl_err_o   : out std_logic;
      sl_rty_o   : out std_logic;
      sl_ack_o   : out std_logic;
      sl_stall_o : out std_logic;
      slave_i    : in  t_wishbone_slave_in                                   := cc_dummy_slave_in;
      ma_adr_o   : out std_logic_vector(c_wishbone_address_width-1 downto 0);
      ma_dat_o   : out std_logic_vector(c_wishbone_data_width-1 downto 0);
      ma_sel_o   : out std_logic_vector(c_wishbone_data_width/8-1 downto 0);
      ma_cyc_o   : out std_logic;
      ma_stb_o   : out std_logic;
      ma_we_o    : out std_logic;
      ma_dat_i   : in  std_logic_vector(c_wishbone_data_width-1 downto 0)    := cc_dummy_data;
      ma_err_i   : in  std_logic                                             := '0';
      ma_rty_i   : in  std_logic                                             := '0';
      ma_ack_i   : in  std_logic                                             := '0';
      ma_stall_i : in  std_logic                                             := '0';
      master_i   : in  t_wishbone_master_in                                  := cc_dummy_slave_out;
      master_o   : out t_wishbone_master_out);
  component wb_async_bridge
    generic (
      g_simulation          : integer;
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_cpu_address_width   : integer);
    port (
      rst_n_i     : in    std_logic;
      clk_sys_i   : in    std_logic;
      cpu_cs_n_i  : in    std_logic;
      cpu_wr_n_i  : in    std_logic;
      cpu_rd_n_i  : in    std_logic;
      cpu_bs_n_i  : in    std_logic_vector(3 downto 0);
      cpu_addr_i  : in    std_logic_vector(g_cpu_address_width-1 downto 0);
      cpu_data_b  : inout std_logic_vector(31 downto 0);
      cpu_nwait_o : out   std_logic;
      wb_adr_o    : out   std_logic_vector(c_wishbone_address_width - 1 downto 0);
      wb_dat_o    : out   std_logic_vector(31 downto 0);
      wb_stb_o    : out   std_logic;
      wb_we_o     : out   std_logic;
      wb_sel_o    : out   std_logic_vector(3 downto 0);
      wb_cyc_o    : out   std_logic;
      wb_dat_i    : in    std_logic_vector (c_wishbone_data_width-1 downto 0);
      wb_ack_i    : in    std_logic;
      wb_stall_i  : in    std_logic := '0');
  end component;

  component xwb_async_bridge
    generic (
      g_simulation          : integer;
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_cpu_address_width   : integer);
    port (
      rst_n_i     : in    std_logic;
      clk_sys_i   : in    std_logic;
      cpu_cs_n_i  : in    std_logic;
      cpu_wr_n_i  : in    std_logic;
      cpu_rd_n_i  : in    std_logic;
      cpu_bs_n_i  : in    std_logic_vector(3 downto 0);
      cpu_addr_i  : in    std_logic_vector(g_cpu_address_width-1 downto 0);
      cpu_data_b  : inout std_logic_vector(31 downto 0);
      cpu_nwait_o : out   std_logic;
      master_o    : out   t_wishbone_master_out;
      master_i    : in    t_wishbone_master_in);
  end component;

  component xwb_bus_fanout
    generic (
      g_num_outputs          : natural;
      g_bits_per_slave       : integer;
      g_address_granularity  : t_wishbone_address_granularity := WORD;
      g_slave_interface_mode : t_wishbone_interface_mode      := CLASSIC);
    port (
      clk_sys_i : in  std_logic;
      rst_n_i   : in  std_logic;
      slave_i   : in  t_wishbone_slave_in;
      slave_o   : out t_wishbone_slave_out;
      master_i  : in  t_wishbone_master_in_array(0 to g_num_outputs-1);
      master_o  : out t_wishbone_master_out_array(0 to g_num_outputs-1));
  end component;

  component xwb_crossbar
    generic (
      g_num_masters : integer;
      g_num_slaves  : integer;
      g_registered  : boolean;
      g_address     : t_wishbone_address_array;
      g_mask        : t_wishbone_address_array;
      g_verbose     : boolean := true);
      clk_sys_i : in  std_logic;
      rst_n_i   : in  std_logic;
      slave_i   : in  t_wishbone_slave_in_array(g_num_masters-1 downto 0);
      slave_o   : out t_wishbone_slave_out_array(g_num_masters-1 downto 0);
      master_i  : in  t_wishbone_master_in_array(g_num_slaves-1 downto 0);
      master_o  : out t_wishbone_master_out_array(g_num_slaves-1 downto 0);
      sdb_sel_o : out std_logic_vector(g_num_masters-1 downto 0)); -- leave open!
  -- Use the f_xwb_bridge_*_sdb to bridge a crossbar to another
  function f_xwb_bridge_manual_sdb(     -- take a manual bus size
    g_size     : t_wishbone_address;
    g_sdb_addr : t_wishbone_address) return t_sdb_bridge;

  function f_xwb_bridge_layout_sdb(     -- determine bus size from layout
    g_wraparound : boolean := true;
    g_layout     : t_sdb_record_array;
    g_sdb_addr   : t_wishbone_address) return t_sdb_bridge;
  function f_xwb_msi_manual_sdb(        -- take a manual bus size
    g_size     : t_wishbone_address) return t_sdb_msi;

  function f_xwb_msi_layout_sdb(     -- determine MSI size from layout
    g_layout     : t_sdb_record_array) return t_sdb_msi;
  component xwb_sdb_crossbar
      g_num_masters : integer;
      g_num_slaves  : integer;
      g_registered  : boolean := false;
      g_wraparound  : boolean := true;
      g_layout      : t_sdb_record_array;
      g_sdb_name    : string := "WB4-Crossbar-GSI   ");
      clk_sys_i     : in  std_logic;
      rst_n_i       : in  std_logic;
      slave_i       : in  t_wishbone_slave_in_array  (g_num_masters-1 downto 0);
      slave_o       : out t_wishbone_slave_out_array (g_num_masters-1 downto 0);
      msi_master_i  : in  t_wishbone_master_in_array (g_num_masters-1 downto 0) := (others => cc_dummy_master_in);
      msi_master_o  : out t_wishbone_master_out_array(g_num_masters-1 downto 0);
      master_i      : in  t_wishbone_master_in_array (g_num_slaves -1 downto 0);
      master_o      : out t_wishbone_master_out_array(g_num_slaves -1 downto 0);
      msi_slave_i   : in  t_wishbone_slave_in_array  (g_num_slaves -1 downto 0) := (others => cc_dummy_slave_in);
      msi_slave_o   : out t_wishbone_slave_out_array (g_num_slaves -1 downto 0));
  component xwb_register_link  -- puts a register of delay between crossbars
    generic (
      g_WB_IN_MODE         : t_wishbone_interface_mode      := PIPELINED;
      g_WB_IN_GRANULARITY  : t_wishbone_address_granularity := BYTE;
      g_WB_OUT_MODE        : t_wishbone_interface_mode      := PIPELINED;
      g_WB_OUT_GRANULARITY : t_wishbone_address_granularity := BYTE);
    port (
      clk_sys_i : in  std_logic;
      rst_n_i   : in  std_logic;
      slave_i   : in  t_wishbone_slave_in;
      slave_o   : out t_wishbone_slave_out;
      master_i  : in  t_wishbone_master_in;
      master_o  : out t_wishbone_master_out);
  end component;
  component xwb_register is
    generic (
      g_WB_MODE  : t_wishbone_interface_mode := PIPELINED);
    port (
      rst_n_i  : in  std_logic;
      clk_i    : in  std_logic;
      slave_i  : in  t_wishbone_slave_in;
      slave_o  : out t_wishbone_slave_out;
      master_i : in  t_wishbone_master_in;
      master_o : out t_wishbone_master_out);
  end component xwb_register;

  -- skidpad. acts like a fifo in wb flow control, but costs less
  component wb_skidpad is
  generic(
     g_adrbits   : natural   := 32
  );
  Port(
     clk_i        : std_logic;
     rst_n_i      : std_logic;

     push_i       : in  std_logic;
     pop_i        : in  std_logic;
     full_o       : out std_logic;
     empty_o      : out std_logic;

     adr_i        : in  std_logic_vector(g_adrbits-1 downto 0);
     dat_i        : in  std_logic_vector(32-1 downto 0);
     sel_i        : in  std_logic_vector(4-1 downto 0);
     we_i         : in  std_logic;

     adr_o        : out std_logic_vector(g_adrbits-1 downto 0);
     dat_o        : out std_logic_vector(32-1 downto 0);
     sel_o        : out std_logic_vector(4-1 downto 0);
     we_o         : out std_logic
  );
  end component;

  component sdb_rom is
      g_layout   : t_sdb_record_array;
      g_masters  : natural;
      g_bus_end  : unsigned(63 downto 0);
      g_wb_mode  : t_wishbone_interface_mode := CLASSIC;
      g_sdb_name : string                    := "WB4-Crossbar-GSI   ");
      master_i  : in  std_logic_vector(g_masters-1 downto 0);
      slave_i   : in  t_wishbone_slave_in;
      slave_o   : out t_wishbone_slave_out);
  constant c_xwb_dma_sdb : t_sdb_device := (
    abi_ver_major => x"01",
    abi_ver_minor => x"00",
    wbd_endian    => c_sdb_endian_big,
    sdb_component => (
      addr_first  => x"0000000000000000",
      addr_last   => x"000000000000001f",
      product     => (
        vendor_id => x"0000000000000651",  -- GSI
        device_id => x"cababa56",
        version   => x"00000001",
        date      => x"20120518",
        name      => "WB4-Streaming-DMA_0")));
  component xwb_dma is
    generic(
      -- Value 0 cannot stream
      -- Value 1 only slaves with async ACK can stream
      -- Value 2 only slaves with combined latency <= 2 can stream
      -- Value 3 only slaves with combined latency <= 6 can stream
      -- Value 4 only slaves with combined latency <= 14 can stream
      -- ....
      logRingLen : integer := 4
      clk_i       : in  std_logic;
      rst_n_i     : in  std_logic;
      slave_i     : in  t_wishbone_slave_in;
      slave_o     : out t_wishbone_slave_out;
      r_master_i  : in  t_wishbone_master_in;
      r_master_o  : out t_wishbone_master_out;
      w_master_i  : in  t_wishbone_master_in;
      w_master_o  : out t_wishbone_master_out;
Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
  -- If you reset one clock domain, you must reset BOTH!
  -- Release of the reset lines may be arbitrarily out-of-phase
      g_size : natural := 16);
Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
      slave_clk_i    : in  std_logic;
      slave_rst_n_i  : in  std_logic;
      slave_i        : in  t_wishbone_slave_in;
      slave_o        : out t_wishbone_slave_out;
Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
      master_clk_i   : in  std_logic;
      master_rst_n_i : in  std_logic;
      master_i       : in  t_wishbone_master_in;
      master_o       : out t_wishbone_master_out;
      -- Flow control back-channel for acks
      slave_ready_o : out std_logic;
      slave_stall_i : in  std_logic := '0');
  component xwb_clock_bridge is
    generic (
      g_SLAVE_PORT_WB_MODE  : t_wishbone_interface_mode := PIPELINED;
      g_MASTER_PORT_WB_MODE : t_wishbone_interface_mode := PIPELINED;
      g_SIZE                : natural                   := 16);
    port (
      slave_clk_i    : in  std_logic;
      slave_rst_n_i  : in  std_logic;
      slave_i        : in  t_wishbone_slave_in;
      slave_o        : out t_wishbone_slave_out;
      master_clk_i   : in  std_logic;
      master_rst_n_i : in  std_logic;
      master_i       : in  t_wishbone_master_in;
      master_o       : out t_wishbone_master_out);
  end component xwb_clock_bridge;

  function f_xwb_dpram(g_size : natural) return t_sdb_device;
  component xwb_dpram
    generic (
      g_size                  : natural;
      g_init_file             : string                         := "";
      g_must_have_init_file   : boolean                        := true;
      g_slave1_interface_mode : t_wishbone_interface_mode      := CLASSIC;
      g_slave2_interface_mode : t_wishbone_interface_mode      := CLASSIC;
      g_slave1_granularity    : t_wishbone_address_granularity := WORD;
      g_slave2_granularity    : t_wishbone_address_granularity := WORD);
    port (
      clk_sys_i : in  std_logic;
      rst_n_i   : in  std_logic;
      slave1_i  : in  t_wishbone_slave_in;
      slave1_o  : out t_wishbone_slave_out;
      slave2_i  : in  t_wishbone_slave_in;
      slave2_o  : out t_wishbone_slave_out);
  end component;

  component xwb_dpram_mixed
  generic(
    g_size                  : natural := 16384;
    g_init_file             : string  := "";
    g_must_have_init_file   : boolean := true;
    g_swap_word_endianness  : boolean := true;
    g_slave1_interface_mode : t_wishbone_interface_mode;
    g_slave2_interface_mode : t_wishbone_interface_mode;
    g_dpram_port_a_width    : integer := 16;
    g_dpram_port_b_width    : integer := 32;
    g_slave1_granularity    : t_wishbone_address_granularity;
    g_slave2_granularity    : t_wishbone_address_granularity);
  port(
    clk_slave1_i  : in std_logic;
    clk_slave2_i  : in std_logic;
    rst_n_i       : in std_logic;

    slave1_i      : in  t_wishbone_slave_in;
    slave1_o      : out t_wishbone_slave_out;
    slave2_i      : in  t_wishbone_slave_in;
    slave2_o      : out t_wishbone_slave_out);
  end component;
  
  -- Just like the DMA controller, but constantly at address 0
  component xwb_streamer is
    generic(
      -- Value 0 cannot stream
      -- Value 1 only slaves with async ACK can stream
      -- Value 2 only slaves with combined latency = 2 can stream
      -- Value 3 only slaves with combined latency = 6 can stream
      -- Value 4 only slaves with combined latency = 14 can stream
      -- ....
      logRingLen : integer := 4
    );
    port(
      -- Common wishbone signals
      clk_i       : in  std_logic;
      rst_n_i     : in  std_logic;
      -- Master reader port
      r_master_i  : in  t_wishbone_master_in;
      r_master_o  : out t_wishbone_master_out;
      -- Master writer port
      w_master_i  : in  t_wishbone_master_in;
      w_master_o  : out t_wishbone_master_out);
  constant c_xwb_gpio_port_sdb : t_sdb_device := (
    abi_class     => x"0000",              -- undocumented device
    abi_ver_major => x"01",
    abi_ver_minor => x"01",
    wbd_endian    => c_sdb_endian_big,
      addr_first  => x"0000000000000000",
      addr_last   => x"00000000000000ff",
      product     => (
        vendor_id => x"000000000000CE42",  -- CERN
        device_id => x"441c5143",
        version   => x"00000001",
        date      => x"20121129",
        name      => "WB-GPIO-Port       ")));


  component wb_gpio_port
    generic (
      g_interface_mode         : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity    : t_wishbone_address_granularity := WORD;
      g_num_pins               : natural range 1 to 256;
      g_with_builtin_sync      : boolean                        := true;
      g_with_builtin_tristates : boolean                        := false);
    port (
      clk_sys_i  : in    std_logic;
      rst_n_i    : in    std_logic;
      wb_sel_i   : in    std_logic_vector(c_wishbone_data_width/8-1 downto 0);
      wb_cyc_i   : in    std_logic;
      wb_stb_i   : in    std_logic;
      wb_we_i    : in    std_logic;
      wb_adr_i   : in    std_logic_vector(7 downto 0);
      wb_dat_i   : in    std_logic_vector(c_wishbone_data_width-1 downto 0);
      wb_dat_o   : out   std_logic_vector(c_wishbone_data_width-1 downto 0);
      wb_ack_o   : out   std_logic;
      wb_stall_o : out   std_logic;
      gpio_b     : inout std_logic_vector(g_num_pins-1 downto 0);
      gpio_out_o : out   std_logic_vector(g_num_pins-1 downto 0);
      gpio_in_i  : in    std_logic_vector(g_num_pins-1 downto 0);
      gpio_oen_o : out   std_logic_vector(g_num_pins-1 downto 0));
  end component;

  component xwb_gpio_port
    generic (
      g_interface_mode         : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity    : t_wishbone_address_granularity := WORD;
      g_num_pins               : natural range 1 to 256;
      g_with_builtin_sync      : boolean                        := true;
      g_with_builtin_tristates : boolean                        := false);
    port (
      clk_sys_i  : in    std_logic;
      rst_n_i    : in    std_logic;
      slave_i    : in    t_wishbone_slave_in;
      slave_o    : out   t_wishbone_slave_out;
      desc_o     : out   t_wishbone_device_descriptor;
      gpio_b     : inout std_logic_vector(g_num_pins-1 downto 0);
      gpio_out_o : out   std_logic_vector(g_num_pins-1 downto 0);
      gpio_in_i  : in    std_logic_vector(g_num_pins-1 downto 0);
      gpio_oen_o : out   std_logic_vector(g_num_pins-1 downto 0));
  end component;

  constant c_xwb_i2c_master_sdb : t_sdb_device := (
    abi_class     => x"0000",              -- undocumented device
    abi_ver_major => x"01",
    abi_ver_minor => x"01",
    wbd_endian    => c_sdb_endian_big,
      addr_first  => x"0000000000000000",
      addr_last   => x"00000000000000ff",
      product     => (
        vendor_id => x"000000000000CE42",  -- CERN
        device_id => x"123c5443",
        version   => x"00000001",
        date      => x"20121129",
        name      => "WB-I2C-Master      ")));


  component wb_i2c_master
    generic (
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_num_interfaces      : integer := 1);
    port (
      clk_sys_i    : in  std_logic;
      rst_n_i      : in  std_logic;
      wb_adr_i     : in  std_logic_vector(4 downto 0);
      wb_dat_i     : in  std_logic_vector(31 downto 0);
      wb_dat_o     : out std_logic_vector(31 downto 0);
      wb_sel_i     : in  std_logic_vector(3 downto 0);
      wb_stb_i     : in  std_logic;
      wb_cyc_i     : in  std_logic;
      wb_we_i      : in  std_logic;
      wb_ack_o     : out std_logic;
      wb_stall_o   : out std_logic;
      scl_pad_i    : in  std_logic_vector(g_num_interfaces-1 downto 0);
      scl_pad_o    : out std_logic_vector(g_num_interfaces-1 downto 0);
      scl_padoen_o : out std_logic_vector(g_num_interfaces-1 downto 0);
      sda_pad_i    : in  std_logic_vector(g_num_interfaces-1 downto 0);
      sda_pad_o    : out std_logic_vector(g_num_interfaces-1 downto 0);
      sda_padoen_o : out std_logic_vector(g_num_interfaces-1 downto 0));
  end component;

  component xwb_i2c_master
    generic (
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_num_interfaces      : integer := 1);
    port (
      clk_sys_i    : in  std_logic;
      rst_n_i      : in  std_logic;
      slave_i      : in  t_wishbone_slave_in;
      slave_o      : out t_wishbone_slave_out;
      desc_o       : out t_wishbone_device_descriptor;
      scl_pad_i    : in  std_logic_vector(g_num_interfaces-1 downto 0);
      scl_pad_o    : out std_logic_vector(g_num_interfaces-1 downto 0);
      scl_padoen_o : out std_logic_vector(g_num_interfaces-1 downto 0);
      sda_pad_i    : in  std_logic_vector(g_num_interfaces-1 downto 0);
      sda_pad_o    : out std_logic_vector(g_num_interfaces-1 downto 0);
      sda_padoen_o : out std_logic_vector(g_num_interfaces-1 downto 0));
      g_reset_vector : std_logic_vector(31 downto 0) := x"00000000";
      g_sdb_address  : std_logic_vector(31 downto 0) := x"00000000");
    port (
      clk_sys_i : in  std_logic;
      rst_n_i   : in  std_logic;
      irq_i     : in  std_logic_vector(31 downto 0);
      dwb_o     : out t_wishbone_master_out;
      dwb_i     : in  t_wishbone_master_in;
      iwb_o     : out t_wishbone_master_out;
      iwb_i     : in  t_wishbone_master_in);
  end component;

  constant c_xwb_onewire_master_sdb : t_sdb_device := (
    abi_class     => x"0000",              -- undocumented device
    abi_ver_major => x"01",
    abi_ver_minor => x"01",
    wbd_endian    => c_sdb_endian_big,
      addr_first  => x"0000000000000000",
      addr_last   => x"00000000000000ff",
      product     => (
        vendor_id => x"000000000000CE42",  -- CERN
        device_id => x"779c5443",
        version   => x"00000001",
        date      => x"20121129",
        name      => "WB-OneWire-Master  ")));

  component wb_onewire_master
    generic (
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_num_ports           : integer;
      g_ow_btp_normal       : string;
      g_ow_btp_overdrive    : string;
      g_CDR_N               : integer;
      g_CDR_O               : integer);
    port (
      clk_sys_i   : in  std_logic;
      rst_n_i     : in  std_logic;
      wb_cyc_i    : in  std_logic;
      wb_sel_i    : in  std_logic_vector(c_wishbone_data_width/8-1 downto 0);
      wb_stb_i    : in  std_logic;
      wb_we_i     : in  std_logic;
      wb_adr_i    : in  std_logic_vector(2 downto 0);
      wb_dat_i    : in  std_logic_vector(c_wishbone_data_width-1 downto 0);
      wb_dat_o    : out std_logic_vector(c_wishbone_data_width-1 downto 0);
      wb_ack_o    : out std_logic;
      wb_stall_o  : out std_logic;
      owr_pwren_o : out std_logic_vector(g_num_ports -1 downto 0);
      owr_en_o    : out std_logic_vector(g_num_ports -1 downto 0);
      owr_i       : in  std_logic_vector(g_num_ports -1 downto 0));
  end component;

  component xwb_onewire_master
    generic (
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_num_ports           : integer;
      g_ow_btp_normal       : string                         := "5.0";
      g_ow_btp_overdrive    : string                         := "1.0");
    port (
      clk_sys_i   : in  std_logic;
      rst_n_i     : in  std_logic;
      slave_i     : in  t_wishbone_slave_in;
      slave_o     : out t_wishbone_slave_out;
      desc_o      : out t_wishbone_device_descriptor;
      owr_pwren_o : out std_logic_vector(g_num_ports -1 downto 0);
      owr_en_o    : out std_logic_vector(g_num_ports -1 downto 0);
      owr_i       : in  std_logic_vector(g_num_ports -1 downto 0));
  end component;

  constant c_xwb_spi_sdb : t_sdb_device := (
    abi_class     => x"0000",              -- undocumented device
    abi_ver_major => x"01",
    abi_ver_minor => x"01",
    wbd_endian    => c_sdb_endian_big,
    wbd_width     => x"7",                 -- 8/16/32-bit port granularity
    sdb_component => (
      addr_first  => x"0000000000000000",
      addr_last   => x"000000000000001F",
      product     => (
        vendor_id => x"000000000000CE42",  -- CERN
        device_id => x"e503947e",       -- echo "WB-SPI.Control     " | md5sum | cut -c1-8
        version   => x"00000001",
        date      => x"20121116",
        name      => "WB-SPI.Control     ")));

  component wb_spi
    generic (
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_divider_len         : integer := 16;
      g_max_char_len        : integer := 128;
      g_num_slaves          : integer := 8);
    port (
      clk_sys_i  : in  std_logic;
      rst_n_i    : in  std_logic;
      wb_adr_i   : in  std_logic_vector(4 downto 0);
      wb_dat_i   : in  std_logic_vector(31 downto 0);
      wb_dat_o   : out std_logic_vector(31 downto 0);
      wb_sel_i   : in  std_logic_vector(3 downto 0);
      wb_stb_i   : in  std_logic;
      wb_cyc_i   : in  std_logic;
      wb_we_i    : in  std_logic;
      wb_ack_o   : out std_logic;
      wb_err_o   : out std_logic;
      wb_stall_o : out std_logic;
      pad_cs_o   : out std_logic_vector(g_num_slaves-1 downto 0);
      pad_sclk_o : out std_logic;
      pad_mosi_o : out std_logic;
      pad_miso_i : in  std_logic);
  end component;

  component xwb_spi
    generic (
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_divider_len         : integer := 16;
      g_max_char_len        : integer := 128;
      g_num_slaves          : integer := 8);
    port (
      clk_sys_i  : in  std_logic;
      rst_n_i    : in  std_logic;
      slave_i    : in  t_wishbone_slave_in;
      slave_o    : out t_wishbone_slave_out;
      desc_o     : out t_wishbone_device_descriptor;
      pad_cs_o   : out std_logic_vector(g_num_slaves-1 downto 0);
      pad_sclk_o : out std_logic;
      pad_mosi_o : out std_logic;
      pad_miso_i : in  std_logic);
  end component;

  component wb_simple_uart
    generic (
      g_with_virtual_uart   : boolean                        := false;
      g_with_physical_uart  : boolean                        := true;
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_vuart_fifo_size     : integer := 1024);
    port (
      clk_sys_i  : in  std_logic;
      rst_n_i    : in  std_logic;
      wb_adr_i   : in  std_logic_vector(4 downto 0);
      wb_dat_i   : in  std_logic_vector(31 downto 0);
      wb_dat_o   : out std_logic_vector(31 downto 0);
      wb_cyc_i   : in  std_logic;
      wb_sel_i   : in  std_logic_vector(3 downto 0);
      wb_stb_i   : in  std_logic;
      wb_we_i    : in  std_logic;
      wb_ack_o   : out std_logic;
      wb_stall_o : out std_logic;
      int_o      : out std_logic;
      uart_rxd_i : in  std_logic := '1';
      uart_txd_o : out std_logic);
  end component;

  component xwb_simple_uart
    generic (
      g_with_virtual_uart   : boolean                        := false;
      g_with_physical_uart  : boolean                        := true;
      g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
      g_address_granularity : t_wishbone_address_granularity := WORD;
      g_vuart_fifo_size     : integer := 1024);
    port (
      clk_sys_i  : in  std_logic;
      rst_n_i    : in  std_logic;
      slave_i    : in  t_wishbone_slave_in;
      slave_o    : out t_wishbone_slave_out;
      desc_o     : out t_wishbone_device_descriptor;
      int_o      : out std_logic;
      uart_rxd_i : in  std_logic := '1';
      uart_txd_o : out std_logic);
  end component;

  component wb_simple_pwm
    generic (
      g_num_channels        : integer range 1 to 8;
      g_regs_size           : integer range 1 to 16 := 16;
      g_default_period      : integer range 0 to 255 := 0;
      g_default_presc       : integer range 0 to 255 := 0;
      g_default_val         : integer range 0 to 255 := 0;
      g_interface_mode      : t_wishbone_interface_mode      := PIPELINED;
      g_address_granularity : t_wishbone_address_granularity := BYTE);
    port (
      clk_sys_i  : in  std_logic;
      rst_n_i    : in  std_logic;
      wb_adr_i   : in  std_logic_vector(5 downto 0);
      wb_dat_i   : in  std_logic_vector(31 downto 0);
      wb_dat_o   : out std_logic_vector(31 downto 0);
      wb_cyc_i   : in  std_logic;
      wb_sel_i   : in  std_logic_vector(3 downto 0);
      wb_stb_i   : in  std_logic;
      wb_we_i    : in  std_logic;
      wb_ack_o   : out std_logic;
      wb_stall_o : out std_logic;
      pwm_o      : out std_logic_vector(g_num_channels-1 downto 0));
  end component;

  component xwb_simple_pwm
    generic (
      g_num_channels        : integer range 1 to 8;
      g_regs_size           : integer range 1 to 16 := 16;
      g_default_period      : integer range 0 to 255 := 0;
      g_default_presc       : integer range 0 to 255 := 0;
      g_default_val         : integer range 0 to 255 := 0;
      g_interface_mode      : t_wishbone_interface_mode      := PIPELINED;
      g_address_granularity : t_wishbone_address_granularity := BYTE);
    port (
      clk_sys_i : in  std_logic;
      rst_n_i   : in  std_logic;