xvme64x_core.vhd 17.6 KB
Newer Older
1 2
--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
Tom Levens's avatar
Tom Levens committed
3
-- VME64x Core
4 5 6
-- http://www.ohwr.org/projects/vme64x-core
--------------------------------------------------------------------------------
--
Tom Levens's avatar
Tom Levens committed
7
-- unit name:     xvme64x_core (xvme64x_core.vhd)
8
--
9 10 11 12 13 14 15 16 17 18 19 20
-- description:
--
--   This core implements an interface to transfer data between the VMEbus and
--   the WBbus. This core is a Slave in the VME side and Master in the WB side.
--
--   All the output signals on the WB bus are registered.
--   The Input signals from the WB bus aren't registered indeed the WB is a
--   synchronous protocol and some registers in the WB side will introduce a
--   delay that make impossible reproduce the WB PIPELINED protocol.
--   The main component of this core is the VME_bus on the left in the block
--   diagram. Inside this component you can find the main finite state machine
--   that coordinates all the synchronisms.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
--
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- This source file is free software; you can redistribute it and/or modify it
-- under the terms of the GNU Lesser General Public License as published by the
-- Free Software Foundation; either version 2.1 of the License, or (at your
-- option) any later version. This source is distributed in the hope that it
-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Lesser General Public License for more details. You should have
-- received a copy of the GNU Lesser General Public License along with this
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------------

library ieee;
Tom Levens's avatar
Tom Levens committed
37 38
use ieee.std_logic_1164.all;
use work.wishbone_pkg.all;
39
use work.vme64x_pkg.all;
40 41

entity xvme64x_core is
42
  generic (
43 44
    -- Clock period (ns). Used for DS synchronization. A value is required.
    g_CLOCK_PERIOD    : natural;
45 46 47 48 49 50 51 52 53 54

    -- Consider AM field of ADER to decode addresses. This is what the VME64x
    -- standard says. However, for compatibility with previous implementations
    -- (or to reduce resources), it is possible for a decoder to allow all AM
    -- declared in the AMCAP.
    g_DECODE_AM       : boolean := true;

    -- Use external user CSR
    g_USER_CSR_EXT    : boolean := false;

55 56 57 58 59 60 61
    -- Address granularity on the WB bus. Value can be:
    -- WORD: VME address bits 31:2 are translated to WB address bits 29:0,
    --       the WB data represents bytes for VME address bits 1:0.
    -- BYTE: VME address bits 31:2 are translated to WB address bits 31:2,
    --       WB address bits 1:0 are always 0.
    g_WB_GRANULARITY  : t_wishbone_address_granularity;

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    -- Manufacturer ID: IEEE OUID
    --                  e.g. CERN is 0x080030
    g_MANUFACTURER_ID : std_logic_vector(23 downto 0);

    -- Board ID: Per manufacturer, each board shall have an unique ID
    --           e.g. SVEC = 408 (CERN IDs: http://cern.ch/boardid)
    g_BOARD_ID        : std_logic_vector(31 downto 0);

    -- Revision ID: user defined revision code
    g_REVISION_ID     : std_logic_vector(31 downto 0);

    -- Program ID: Defined per VME64:
    --               0x00      = Not used
    --               0x01      = No program, ID ROM only
    --               0x02-0x4F = Manufacturer defined
    --               0x50-0x7F = User defined
    --               0x80-0xEF = Reserved for future use
    --               0xF0-0xFE = Reserved for Boot Firmware (P1275)
    --               0xFF      = Not to be used
    g_PROGRAM_ID      : std_logic_vector( 7 downto 0);

    -- Pointer to a user defined ASCII string.
    g_ASCII_PTR       : std_logic_vector(23 downto 0)  := x"000000";

    -- User CR/CSR, CRAM & serial number pointers
    g_BEG_USER_CR     : std_logic_vector(23 downto 0)  := x"000000";
    g_END_USER_CR     : std_logic_vector(23 downto 0)  := x"000000";
    g_BEG_CRAM        : std_logic_vector(23 downto 0)  := x"000000";
    g_END_CRAM        : std_logic_vector(23 downto 0)  := x"000000";
    g_BEG_USER_CSR    : std_logic_vector(23 downto 0)  := x"07ff33";
    g_END_USER_CSR    : std_logic_vector(23 downto 0)  := x"07ff5f";
    g_BEG_SN          : std_logic_vector(23 downto 0)  := x"000000";
    g_END_SN          : std_logic_vector(23 downto 0)  := x"000000";

Tristan Gingold's avatar
Tristan Gingold committed
96
    -- Function decoder parameters.
97 98 99 100 101 102 103 104 105 106
    g_DECODER         : t_vme64x_decoder_arr := c_vme64x_decoders_default);
  port (
    -- Main clock and reset.
    clk_i           : in  std_logic;
    rst_n_i         : in  std_logic;

    -- Reset for wishbone core.
    rst_n_o         : out std_logic;

    -- VME slave interface.
Tristan Gingold's avatar
Tristan Gingold committed
107
    vme_i           : in  t_vme64x_in;
108 109 110 111 112 113
    vme_o           : out t_vme64x_out;

    -- Wishbone interface.
    wb_i            : in  t_wishbone_master_in;
    wb_o            : out t_wishbone_master_out;

114 115 116
    -- Interrupt input from the master side.
    -- Previously it was part of the wishbone interface, but is now separate
    -- as interrupt is not defined by wishbone.
117
    int_i           : in std_logic := '0';
118

119 120 121 122 123 124 125
    -- When the IRQ controller acknowledges the Interrupt cycle it sends a
    -- pulse to the IRQ Generator.
    irq_ack_o       : out std_logic;

    -- User CSR
    -- The following signals are used when g_USER_CSR_EXT = true
    -- otherwise they are connected to the internal user CSR.
126
    irq_level_i     : in  std_logic_vector( 2 downto 0) := (others => '0');
127 128 129 130 131 132 133 134 135
    irq_vector_i    : in  std_logic_vector( 7 downto 0) := (others => '0');
    user_csr_addr_o : out std_logic_vector(18 downto 2);
    user_csr_data_i : in  std_logic_vector( 7 downto 0) := (others => '0');
    user_csr_data_o : out std_logic_vector( 7 downto 0);
    user_csr_we_o   : out std_logic;

    -- User CR
    user_cr_addr_o  : out std_logic_vector(18 downto 2);
    user_cr_data_i  : in  std_logic_vector( 7 downto 0) := (others => '0'));
136 137
end xvme64x_core;

138 139
architecture rtl of xvme64x_core is

140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
  -- Compute the index of the last function decoder used.  Assume sequential
  -- use of decoders (ie decoders 0 to N - 1 are used, and decoders N to 7
  -- are not used; holes are supported but not efficiently).
  function compute_last_ader (decoder : t_vme64x_decoder_arr)
    return t_vme_func_index is
  begin
    for i in decoder'reverse_range loop
      if decoder(i).adem /= x"0000_0000" then
        return i;
      end if;
    end loop;
    assert false report "no ADEM defined" severity failure;
    return 0;
  end compute_last_ader;

  constant c_last_ader          : natural := compute_last_ader (g_DECODER);

157 158
  signal s_reset_n              : std_logic;

159
  signal s_vme_irq_n_o          : std_logic_vector( 7 downto 1);
160 161 162 163 164 165 166 167
  signal s_irq_ack              : std_logic;
  signal s_irq_pending          : std_logic;

  -- CR/CSR
  signal s_cr_csr_addr          : std_logic_vector(18 downto 2);
  signal s_cr_csr_data_o        : std_logic_vector( 7 downto 0);
  signal s_cr_csr_data_i        : std_logic_vector( 7 downto 0);
  signal s_cr_csr_we            : std_logic;
168
  signal s_ader                 : t_ader_array(0 to c_last_ader);
169 170 171 172 173 174 175 176 177 178 179 180 181
  signal s_module_reset         : std_logic;
  signal s_module_enable        : std_logic;
  signal s_bar                  : std_logic_vector( 4 downto 0);
  signal s_vme_berr_n           : std_logic;

  signal s_irq_vector           : std_logic_vector( 7 downto 0);
  signal s_irq_level            : std_logic_vector( 2 downto 0);
  signal s_user_csr_addr        : std_logic_vector(18 downto 2);
  signal s_user_csr_data_i      : std_logic_vector( 7 downto 0);
  signal s_user_csr_data_o      : std_logic_vector( 7 downto 0);
  signal s_user_csr_we          : std_logic;

  -- Function decoders
182 183
  signal s_addr_decoder_i       : std_logic_vector(31 downto 1);
  signal s_addr_decoder_o       : std_logic_vector(31 downto 1);
184 185 186 187 188 189
  signal s_decode_start         : std_logic;
  signal s_decode_done          : std_logic;
  signal s_decode_sel           : std_logic;
  signal s_am                   : std_logic_vector( 5 downto 0);

  -- Oversampled input signals
190 191 192 193 194 195
  signal s_vme_rst_n            : std_logic;
  signal s_vme_as_n             : std_logic;
  signal s_vme_write_n          : std_logic;
  signal s_vme_ds_n             : std_logic_vector(1 downto 0);
  signal s_vme_iack_n           : std_logic;
  signal s_vme_iackin_n         : std_logic;
196 197 198

  -- List of supported AM.
  constant c_AMCAP_ALLOWED : std_logic_vector(63 downto 0) :=
199
    (16#38# to 16#3f# => '1', --  A24
200
     16#2d# | 16#29#  => '1', --  A16
201
     16#08# to 16#0f# => '1', --  A32
202 203 204 205 206 207 208
     others => '0');
begin
  assert g_CLOCK_PERIOD > 0 report "g_CLOCK_PERIOD generic must be set"
    severity failure;

  --  Check for invalid bits in ADEM/AMCAP
  gen_gchecks: for i in 7 downto 0 generate
209 210
    constant adem  : std_logic_vector(31 downto 0) := g_DECODER(i).adem;
    constant amcap : std_logic_vector(63 downto 0) := g_DECODER(i).amcap;
211 212
  begin
    assert adem(c_ADEM_FAF) = '0' report "FAF bit set in ADEM"
213
      severity failure;
214
    assert adem(c_ADEM_DFS) = '0' report "DFS bit set in ADEM"
215
      severity failure;
216
    assert adem(c_ADEM_EFM) = '0' report "EFM bit set in ADEM"
217
      severity failure;
218
    assert (amcap and c_AMCAP_ALLOWED) = amcap
219 220 221 222 223 224 225 226 227 228 229
      report "bit set in AMCAP for not supported AM"
      severity failure;
  end generate;

  ------------------------------------------------------------------------------
  -- Metastability
  ------------------------------------------------------------------------------
  -- Input oversampling: oversampling the input data is
  -- necessary to avoid metastability problems, but of course the transfer rate
  -- will be slow down a little.
  -- NOTE: the reset value is '0', which means that all signals are active
230
  -- at reset. But not for a long time and so is s_vme_rst_n.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
  inst_vme_rst_resync: entity work.gc_sync_register
    generic map (g_width => 1)
    port map (clk_i => clk_i,
              rst_n_a_i => rst_n_i,
              d_i(0) => vme_i.rst_n,
              q_o(0) => s_vme_rst_n);
  inst_vme_as_resync: entity work.gc_sync_register
    generic map (g_width => 1)
    port map (clk_i => clk_i,
              rst_n_a_i => rst_n_i,
              d_i(0) => vme_i.as_n,
              q_o(0) => s_vme_as_n);
  inst_vme_write_resync: entity work.gc_sync_register
    generic map (g_width => 1)
    port map (clk_i => clk_i,
              rst_n_a_i => rst_n_i,
              d_i(0) => vme_i.write_n,
              q_o(0) => s_vme_write_n);
249
  -- The two bits of DS are synchronized by the vme_bus FSM. Instantiate two
Tristan Gingold's avatar
Tristan Gingold committed
250
  -- synchronizers to make clear that they should be considered as independant
251 252 253 254 255 256 257 258 259
  -- signals until they are handled by the FSM.
  inst_vme_ds0_resync: entity work.gc_sync_register
    generic map (g_width => 1)
    port map (clk_i => clk_i,
              rst_n_a_i => rst_n_i,
              d_i(0) => vme_i.ds_n(0),
              q_o(0) => s_vme_ds_n(0));
  inst_vme_ds1_resync: entity work.gc_sync_register
    generic map (g_width => 1)
260 261
    port map (clk_i => clk_i,
              rst_n_a_i => rst_n_i,
262 263
              d_i(0) => vme_i.ds_n(1),
              q_o(0) => s_vme_ds_n(1));
264 265 266 267 268 269 270 271 272 273 274
  inst_vme_iack_resync: entity work.gc_sync_register
    generic map (g_width => 1)
    port map (clk_i => clk_i,
              rst_n_a_i => rst_n_i,
              d_i(0) => vme_i.iack_n,
              q_o(0) => s_vme_iack_n);
  inst_vme_iackin_resync: entity work.gc_sync_register
    generic map (g_width => 1)
    port map (clk_i => clk_i,
              rst_n_a_i => rst_n_i,
              d_i(0) => vme_i.iackin_n,
275
              q_o(0) => s_vme_iackin_n);
276 277 278 279 280 281

  ------------------------------------------------------------------------------
  -- VME Bus
  ------------------------------------------------------------------------------
  inst_vme_bus : entity work.vme_bus
    generic map (
282 283
      g_CLOCK_PERIOD   => g_CLOCK_PERIOD,
      g_WB_GRANULARITY => g_WB_GRANULARITY)
284 285
    port map (
      clk_i           => clk_i,
286
      rst_n_i         => s_reset_n,
287 288

      -- VME
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
      vme_as_n_i      => s_vme_as_n,
      vme_lword_n_o   => vme_o.lword_n,
      vme_lword_n_i   => vme_i.lword_n,
      vme_retry_n_o   => vme_o.retry_n,
      vme_retry_oe_o  => vme_o.retry_oe,
      vme_write_n_i   => s_vme_write_n,
      vme_ds_n_i      => s_vme_ds_n,
      vme_dtack_n_o   => vme_o.dtack_n,
      vme_dtack_oe_o  => vme_o.dtack_oe,
      vme_berr_n_o    => s_vme_berr_n,
      vme_addr_i      => vme_i.addr,
      vme_addr_o      => vme_o.addr,
      vme_addr_dir_o  => vme_o.addr_dir,
      vme_addr_oe_n_o => vme_o.addr_oe_n,
      vme_data_i      => vme_i.data,
      vme_data_o      => vme_o.data,
      vme_data_dir_o  => vme_o.data_dir,
      vme_data_oe_n_o => vme_o.data_oe_n,
      vme_am_i        => vme_i.am,
      vme_iackin_n_i  => s_vme_iackin_n,
      vme_iack_n_i    => s_vme_iack_n,
      vme_iackout_n_o => vme_o.iackout_n,
311 312

      -- WB signals
313 314 315 316 317 318 319 320 321 322
      wb_stb_o        => wb_o.stb,
      wb_ack_i        => wb_i.ack,
      wb_dat_o        => wb_o.dat,
      wb_dat_i        => wb_i.dat,
      wb_adr_o        => wb_o.adr,
      wb_sel_o        => wb_o.sel,
      wb_we_o         => wb_o.we,
      wb_cyc_o        => wb_o.cyc,
      wb_err_i        => wb_i.err,
      wb_stall_i      => wb_i.stall,
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339

      -- Function decoder
      addr_decoder_i  => s_addr_decoder_o,
      addr_decoder_o  => s_addr_decoder_i,
      decode_start_o  => s_decode_start,
      decode_done_i   => s_decode_done,
      am_o            => s_am,
      decode_sel_i    => s_decode_sel,

      -- CR/CSR signals
      cr_csr_addr_o   => s_cr_csr_addr,
      cr_csr_data_i   => s_cr_csr_data_o,
      cr_csr_data_o   => s_cr_csr_data_i,
      cr_csr_we_o     => s_cr_csr_we,
      module_enable_i => s_module_enable,
      bar_i           => s_bar,

340 341
      int_level_i     => s_irq_level,
      int_vector_i    => s_irq_vector,
342
      irq_pending_i   => s_irq_pending,
343
      irq_ack_o       => s_irq_ack);
344

345
  s_reset_n  <= rst_n_i and s_vme_rst_n;
346
  rst_n_o    <= s_reset_n and (not s_module_reset);
347 348 349 350 351

  vme_o.berr_n <= s_vme_berr_n;

  inst_vme_funct_match : entity work.vme_funct_match
    generic map (
352
      g_DECODER   => g_DECODER,
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
      g_DECODE_AM => g_DECODE_AM
    )
    port map (
      clk_i          => clk_i,
      rst_n_i        => s_reset_n,

      addr_i         => s_addr_decoder_i,
      addr_o         => s_addr_decoder_o,
      decode_start_i => s_decode_start,
      am_i           => s_am,
      ader_i         => s_ader,
      decode_sel_o   => s_decode_sel,
      decode_done_o  => s_decode_done
    );

  ------------------------------------------------------------------------------
  -- Output
  ------------------------------------------------------------------------------
  irq_ack_o  <= s_irq_ack;

  ------------------------------------------------------------------------------
  --  Interrupter
  ------------------------------------------------------------------------------
  inst_vme_irq_controller : entity work.vme_irq_controller
    generic map (
      g_RETRY_TIMEOUT => 1000000 / g_CLOCK_PERIOD   -- 1ms timeout
    )
    port map (
      clk_i           => clk_i,
382
      rst_n_i         => s_reset_n,
383 384
      int_level_i     => s_irq_level,
      int_req_i       => int_i,
385 386
      irq_pending_o   => s_irq_pending,
      irq_ack_i       => s_irq_ack,
387
      vme_irq_n_o     => vme_o.irq_n
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
    );

  ------------------------------------------------------------------------------
  -- CR/CSR space
  ------------------------------------------------------------------------------
  inst_vme_cr_csr_space : entity work.vme_cr_csr_space
    generic map (
      g_MANUFACTURER_ID  => g_MANUFACTURER_ID,
      g_BOARD_ID         => g_BOARD_ID,
      g_REVISION_ID      => g_REVISION_ID,
      g_PROGRAM_ID       => g_PROGRAM_ID,
      g_ASCII_PTR        => g_ASCII_PTR,
      g_BEG_USER_CR      => g_BEG_USER_CR,
      g_END_USER_CR      => g_END_USER_CR,
      g_BEG_CRAM         => g_BEG_CRAM,
      g_END_CRAM         => g_END_CRAM,
      g_BEG_USER_CSR     => g_BEG_USER_CSR,
      g_END_USER_CSR     => g_END_USER_CSR,
      g_BEG_SN           => g_BEG_SN,
      g_END_SN           => g_END_SN,
408
      g_DECODER          => g_DECODER
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
    )
    port map (
      clk_i               => clk_i,
      rst_n_i             => s_reset_n,

      vme_ga_i            => vme_i.ga,
      vme_berr_n_i        => s_vme_berr_n,
      bar_o               => s_bar,
      module_enable_o     => s_module_enable,
      module_reset_o      => s_module_reset,

      addr_i              => s_cr_csr_addr,
      data_i              => s_cr_csr_data_i,
      data_o              => s_cr_csr_data_o,
      we_i                => s_cr_csr_we,

      user_csr_addr_o     => s_user_csr_addr,
      user_csr_data_i     => s_user_csr_data_i,
      user_csr_data_o     => s_user_csr_data_o,
      user_csr_we_o       => s_user_csr_we,

      user_cr_addr_o      => user_cr_addr_o,
      user_cr_data_i      => user_cr_data_i,

      ader_o              => s_ader
    );
435

436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
  -- User CSR space
  gen_int_user_csr : if g_USER_CSR_EXT = false generate
    inst_vme_user_csr : entity work.vme_user_csr
      port map (
        clk_i        => clk_i,
        rst_n_i      => s_reset_n,
        addr_i       => s_user_csr_addr,
        data_i       => s_user_csr_data_o,
        data_o       => s_user_csr_data_i,
        we_i         => s_user_csr_we,
        irq_vector_o => s_irq_vector,
        irq_level_o  => s_irq_level
      );
  end generate;
  gen_ext_user_csr : if g_USER_CSR_EXT = true generate
    s_user_csr_data_i <= user_csr_data_i;
    s_irq_vector      <= irq_vector_i;
    s_irq_level       <= irq_level_i(2 downto 0);
  end generate;
455

456 457 458
  user_csr_addr_o <= s_user_csr_addr;
  user_csr_data_o <= s_user_csr_data_o;
  user_csr_we_o   <= s_user_csr_we;
459

460
  assert wb_i.rty = '0' report "rty not supported";
461
end rtl;