VME_CR_CSR_Space.vhd 24.3 KB
Newer Older
Tom Levens's avatar
Tom Levens committed
1 2 3 4 5 6 7 8 9 10 11 12 13
--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
-- VME64x Core
-- http://www.ohwr.org/projects/vme64x-core
--------------------------------------------------------------------------------
--
-- unit name:     VME_CR_CSR_Space (VME_CR_CSR_Space.vhd)
--
-- author:        Pablo Alvarez Sanchez <pablo.alvarez.sanchez@cern.ch>
--                Davide Pedretti       <davide.pedretti@cern.ch>
--
-- description:
--
Tom Levens's avatar
Tom Levens committed
14
--   Implementation of CR/CSR space.
Tom Levens's avatar
Tom Levens committed
15
--
Tom Levens's avatar
Tom Levens committed
16
--                            width = 1 byte
Tom Levens's avatar
Tom Levens committed
17 18
--                 /---------------------------------/
--                 _________________________________
Tom Levens's avatar
Tom Levens committed
19
--                |                                 | 0x7ffff
Tom Levens's avatar
Tom Levens committed
20 21 22 23 24 25
--                |     Defined and Reserved CSR    |
--                |                                 |
--                |   Table 10-13 "Defined Control  |
--                |   Status register Assignments"  |
--                |       ANSI/VITA 1.1-1997        |
--                |        VME64 Extensions         |
Tom Levens's avatar
Tom Levens committed
26 27 28 29 30 31 32
--                |_________________________________| 0x7fc00
--                |_________________________________|
--                |                                 | 0xXXXXX
--                |            User CSR             |
--                |_________________________________| 0xXXXXX
--                |_________________________________|
--                |                                 | 0xXXXXX
Tom Levens's avatar
Tom Levens committed
33
--                |              CRAM               |
Tom Levens's avatar
Tom Levens committed
34 35 36 37 38 39 40
--                |_________________________________| 0xXXXXX
--                |_________________________________|
--                |                                 | 0xXXXXX
--                |             User CR             |
--                |_________________________________| 0xXXXXX
--                |_________________________________|
--                |                                 | 0x00fff
Tom Levens's avatar
Tom Levens committed
41 42 43 44 45 46
--                |     Defined and reserved CR     |
--                |                                 |
--                |     Table 10-12 "Defined        |
--                |  Configuration ROM Assignments" |
--                |       ANSI/VITA 1.1-1997        |
--                |        VME64 Extensions         |
Tom Levens's avatar
Tom Levens committed
47
--                |_________________________________| 0x00000
Tom Levens's avatar
Tom Levens committed
48
--
Tom Levens's avatar
Tom Levens committed
49 50 51 52
--   Please note that only every fourth location in the CR/CSR space is used,
--   so it is possible read and write the CR/CSR by selecting the data transfer
--   mode D08 (byte 3), D16 (bytes 2 & 3) or D32. If other data transfer modes
--   are used the operation will not be successful.
Tom Levens's avatar
Tom Levens committed
53
--
Tom Levens's avatar
Tom Levens committed
54 55
--   If the size of the register is bigger than 1 byte, (e.g. ADER is 4 bytes)
--   these bytes are stored in BIG ENDIAN order.
dpedrett's avatar
dpedrett committed
56
--
Tom Levens's avatar
Tom Levens committed
57
--   How to use the CRAM:
dpedrett's avatar
dpedrett committed
58
--
Tom Levens's avatar
Tom Levens committed
59 60 61 62 63 64 65 66 67 68 69 70 71
--     1) The Master first reads the CRAM_OWNER register (location 0x7fff3).
--        If it is zero the CRAM is available.
--     2) The Master writes his ID to the CRAM_OWNER register.
--     3) If the Master can readback his ID from the CRAM_OWNER register it
--        means that he is the owner of the CRAM and has exclusive access.
--     4) If other Masters write their ID to the CRAM_OWNER register when it
--        contains a non-zero value, the write operation will not be successful.
--        This allows the first Master that writes a non-zero value to acquire
--        ownership.
--     5) When a Master has ownership of the CRAM, bit 2 of the Bit Set Register
--        (location 0x7fffb) will be set.
--     6) The Master can release the ownership by writing '1' to bit 2 of the
--        Bit Clr Register (location 0x7fff7).
72
--
Tom Levens's avatar
Tom Levens committed
73
--   Bit Set Register control bits (location 0x7fffb):
dpedrett's avatar
dpedrett committed
74
--
Tom Levens's avatar
Tom Levens committed
75 76 77 78 79 80
--     7: RESET -----------> When high the module is held in reset.
--     6: SYSFAIL ENABLE --> When high the VME_SYSFAIL output driver is enabled.
--     5: FAILED ----------> When high the module has failed.
--     4: ENABLE ----------> When high the WB accesses are enabled.
--     3: BERR ------------> When high the module has asserted BERR.
--     2: CRAM OWNER ------> When high the CRAM is owned.
Tom Levens's avatar
Tom Levens committed
81
--
Tom Levens's avatar
Tom Levens committed
82 83
--   The Master can clear these bits by writing '1' in the corresponding bits
--   to the Bit Clr Register (location 0x7fff7).
Tom Levens's avatar
Tom Levens committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
--
-- dependencies:
--
--------------------------------------------------------------------------------
-- 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
--------------------------------------------------------------------------------
-- last changes: see log.
--------------------------------------------------------------------------------
-- TODO: -
--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
dpedrett's avatar
dpedrett committed
108
use work.vme64x_pack.all;
Tom Levens's avatar
Tom Levens committed
109

dpedrett's avatar
dpedrett committed
110
entity VME_CR_CSR_Space is
Tom Levens's avatar
Tom Levens committed
111
  generic (
112 113 114 115 116 117 118 119 120 121 122 123 124
    g_MANUFACTURER_ID : std_logic_vector(23 downto 0);
    g_BOARD_ID        : std_logic_vector(31 downto 0);
    g_REVISION_ID     : std_logic_vector(31 downto 0);
    g_PROGRAM_ID      : std_logic_vector(7 downto 0);
    g_ASCII_PTR       : std_logic_vector(23 downto 0);
    g_BEG_USER_CR     : std_logic_vector(23 downto 0);
    g_END_USER_CR     : std_logic_vector(23 downto 0);
    g_BEG_CRAM        : std_logic_vector(23 downto 0);
    g_END_CRAM        : std_logic_vector(23 downto 0);
    g_BEG_USER_CSR    : std_logic_vector(23 downto 0);
    g_END_USER_CSR    : std_logic_vector(23 downto 0);
    g_BEG_SN          : std_logic_vector(23 downto 0);
    g_END_SN          : std_logic_vector(23 downto 0);
125
    g_ADEM            : t_adem_array(0 to 7);
Tom Levens's avatar
Tom Levens committed
126 127
    g_AMCAP           : t_amcap_array(0 to 7);
    g_DAWPR           : t_dawpr_array(0 to 7)
Tom Levens's avatar
Tom Levens committed
128 129 130
  );
  port (
    clk_i               : in  std_logic;
Tom Levens's avatar
Tom Levens committed
131
    rst_n_i             : in  std_logic;
Tom Levens's avatar
Tom Levens committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

    vme_ga_i            : in  std_logic_vector(5 downto 0);
    vme_berr_n_i        : in  std_logic;
    bar_o               : out std_logic_vector(4 downto 0);
    vme_sysfail_i       : in  std_logic;
    vme_sysfail_ena_o   : out std_logic;
    module_enable_o     : out std_logic;
    module_reset_o      : out std_logic;

    addr_i              : in  std_logic_vector(18 downto 2);
    data_i              : in  std_logic_vector( 7 downto 0);
    data_o              : out std_logic_vector( 7 downto 0);
    we_i                : in  std_logic;

    user_csr_addr_o     : out std_logic_vector(18 downto 2);
    user_csr_data_i     : in  std_logic_vector( 7 downto 0);
    user_csr_data_o     : out std_logic_vector( 7 downto 0);
    user_csr_we_o       : out std_logic;

    user_cr_addr_o      : out std_logic_vector(18 downto 2);
    user_cr_data_i      : in  std_logic_vector( 7 downto 0);

154
    ader_o              : out t_ader_array(0 to 7)
Tom Levens's avatar
Tom Levens committed
155
  );
dpedrett's avatar
dpedrett committed
156
end VME_CR_CSR_Space;
Tom Levens's avatar
Tom Levens committed
157

Tom Levens's avatar
Tom Levens committed
158 159
architecture rtl of VME_CR_CSR_Space is

Tom Levens's avatar
Tom Levens committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
  signal s_addr             : unsigned(18 downto 2);
  signal s_ga_parity        : std_logic;
  signal s_reg_bar          : std_logic_vector(7 downto 0);
  signal s_reg_bit_reg      : std_logic_vector(7 downto 0);
  signal s_reg_cram_owner   : std_logic_vector(7 downto 0);
  signal s_reg_usr_bit_reg  : std_logic_vector(7 downto 0);
  signal s_reg_ader         : t_ader_array(0 to 7);

  -- CR/CSR
  signal s_cr_access        : std_logic;
  signal s_csr_access       : std_logic;
  signal s_cram_access      : std_logic;
  signal s_user_cr_access   : std_logic;
  signal s_user_csr_access  : std_logic;

  signal s_cr_data          : std_logic_vector(7 downto 0);
  signal s_csr_data         : std_logic_vector(7 downto 0);

  -- Function to calculate the size of a CR/CSR area
  function f_size (s, e : std_logic_vector) return integer is
  begin
    return ((to_integer(unsigned(e)) - to_integer(unsigned(s))) / 4) + 1;
  end;
Tom Levens's avatar
Tom Levens committed
183

Tom Levens's avatar
Tom Levens committed
184 185 186
  -- User CR/CSR and CRAM enabled when size of area greater than 1
  constant c_CRAM_SIZE      : integer := f_size(g_BEG_CRAM, g_END_CRAM);
  constant c_CRAM_ENA       : boolean := c_CRAM_SIZE > 1;
Tom Levens's avatar
Tom Levens committed
187

Tom Levens's avatar
Tom Levens committed
188 189
  constant c_USER_CR_SIZE   : integer := f_size(g_BEG_USER_CR, g_END_USER_CR);
  constant c_USER_CR_ENA    : boolean := c_USER_CR_SIZE > 1;
Tom Levens's avatar
Tom Levens committed
190

Tom Levens's avatar
Tom Levens committed
191 192
  constant c_USER_CSR_SIZE  : integer := f_size(g_BEG_USER_CSR, g_END_USER_CSR);
  constant c_USER_CSR_ENA   : boolean := c_USER_CSR_SIZE > 1;
Tom Levens's avatar
Tom Levens committed
193

194 195 196 197 198
  -- ADER bits to be stored, in addition to the corresponding ADEM ones.
  -- (ie AM + XAM).
  constant c_ADER_MASK : std_logic_vector(31 downto 0) := x"0000_00fd";
  -- Corresponding ADEM bits.
  constant c_ADEM_MASK : std_logic_vector(31 downto 0) := x"ffff_ff00";
199

Tom Levens's avatar
Tom Levens committed
200 201 202 203 204 205 206 207 208 209
  -- CRAM
  type t_cram is array (c_CRAM_SIZE-1 downto 0) of std_logic_vector(7 downto 0);

  signal s_cram             : t_cram;
  signal s_cram_data        : std_logic_vector(7 downto 0);
  signal s_cram_waddr       : unsigned(18 downto 2);
  signal s_cram_raddr       : unsigned(18 downto 2);
  signal s_cram_we          : std_logic;

  -- Addresses
210
  subtype crcsr_addr is unsigned(18 downto 2);
Tristan Gingold's avatar
Tristan Gingold committed
211 212 213 214
  constant c_BEG_CR       : crcsr_addr := to_unsigned(16#00000# / 4, 17);
  constant c_END_CR       : crcsr_addr := to_unsigned(16#00fff# / 4, 17);
  constant c_BEG_CSR      : crcsr_addr := to_unsigned(16#7ff60# / 4, 17);
  constant c_END_CSR      : crcsr_addr := to_unsigned(16#7ffff# / 4, 17);
215 216 217 218 219 220
  constant c_BEG_USER_CR  : crcsr_addr := unsigned(g_BEG_USER_CR(18 downto 2));
  constant c_END_USER_CR  : crcsr_addr := unsigned(g_END_USER_CR(18 downto 2));
  constant c_BEG_USER_CSR : crcsr_addr := unsigned(g_BEG_USER_CSR(18 downto 2));
  constant c_END_USER_CSR : crcsr_addr := unsigned(g_END_USER_CSR(18 downto 2));
  constant c_BEG_CRAM     : crcsr_addr := unsigned(g_BEG_CRAM(18 downto 2));
  constant c_END_CRAM     : crcsr_addr := unsigned(g_END_CRAM(18 downto 2));
Tom Levens's avatar
Tom Levens committed
221 222 223 224 225 226 227 228 229 230 231

  -- Indexes in bit set/clr register
  constant c_RESET_BIT      : integer := 7;
  constant c_SYSFAIL_EN_BIT : integer := 6;
  constant c_FAILED_BIT     : integer := 5;
  constant c_ENABLE_BIT     : integer := 4;
  constant c_BERR_BIT       : integer := 3;
  constant c_CRAM_OWNER_BIT : integer := 2;

  -- Value for unused memory locations
  constant c_UNUSED         : std_logic_vector(7 downto 0) := x"ff";
Tom Levens's avatar
Tom Levens committed
232

Tom Levens's avatar
Tom Levens committed
233 234 235 236
  ------------------------------------------------------------------------------
  -- Generate configuration ROM
  ------------------------------------------------------------------------------
  type t_cr_array is array (natural range <>) of std_logic_vector(7 downto 0);
Tom Levens's avatar
Tom Levens committed
237

Tom Levens's avatar
Tom Levens committed
238 239
  -- Function to generate a CR sub-array from a std_logic_vector
  function f_cr_vec (v : std_logic_vector) return t_cr_array is
Tristan Gingold's avatar
Tristan Gingold committed
240
    variable a : t_cr_array(0 to v'length / 8 - 1);
Tom Levens's avatar
Tom Levens committed
241 242
  begin
    for i in 0 to a'length-1 loop
Tristan Gingold's avatar
Tristan Gingold committed
243
      a(i) := v(v'length - (i*8) - 1 downto v'length - (i*8) - 8);
Tom Levens's avatar
Tom Levens committed
244 245 246
    end loop;
    return a;
  end function;
Tom Levens's avatar
Tom Levens committed
247

Tom Levens's avatar
Tom Levens committed
248 249
  -- Function to encode the configuration ROM
  function f_cr_encode return t_cr_array is
250
    variable cr  : t_cr_array(0 to 511) := (others => x"00");
Tom Levens's avatar
Tom Levens committed
251 252
    variable crc : unsigned(7 downto 0)  := x"00";
  begin
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
    cr(16#001# to 16#003#)  := (x"00", x"03", x"ff");       -- Length of CR
    cr(16#004#)             := x"81";                       -- CR DAW
    cr(16#005#)             := x"81";                       -- CSR DAW
    cr(16#006#)             := x"02";                       -- CR/CSR spec id
    cr(16#007#)             := x"43";                       -- ASCII "C"
    cr(16#008#)             := x"52";                       -- ASCII "R"
    cr(16#009# to 16#00b#)  := f_cr_vec(g_MANUFACTURER_ID); -- Manufacturer ID
    cr(16#00c# to 16#00f#)  := f_cr_vec(g_BOARD_ID);        -- Board ID
    cr(16#010# to 16#013#)  := f_cr_vec(g_REVISION_ID);     -- Revision ID
    cr(16#014# to 16#016#)  := f_cr_vec(g_ASCII_PTR);       -- String ptr
    cr(16#01f#)             := g_PROGRAM_ID;                -- Program ID
    cr(16#020# to 16#022#)  := f_cr_vec(g_BEG_USER_CR);     -- Beg user CR
    cr(16#023# to 16#025#)  := f_cr_vec(g_END_USER_CR);     -- End user CR
    cr(16#026# to 16#028#)  := f_cr_vec(g_BEG_CRAM);        -- Beg CRAM
    cr(16#029# to 16#02b#)  := f_cr_vec(g_END_CRAM);        -- End CRAM
    cr(16#02c# to 16#02e#)  := f_cr_vec(g_BEG_USER_CSR);    -- Beg user CSR
    cr(16#02f# to 16#031#)  := f_cr_vec(g_END_USER_CSR);    -- End user CSR
    cr(16#032# to 16#034#)  := f_cr_vec(g_BEG_SN);          -- Beg serial number
    cr(16#035# to 16#037#)  := f_cr_vec(g_END_SN);          -- End serial number
    cr(16#038#)             := x"04";                       -- Slave param
    cr(16#039#)             := x"00";                       -- User-defined
    cr(16#03d#)             := x"0e";                       -- Interrupt cap
    cr(16#03f#)             := x"81";                       -- CRAM DAW
Tom Levens's avatar
Tom Levens committed
276
    for i in 0 to 7 loop
Tristan Gingold's avatar
Tristan Gingold committed
277 278 279
      cr(16#040# + i)                     := g_DAWPR(i);             -- DAWPR
      cr(16#048# + i*8  to 16#04f# + i*8) := f_cr_vec(g_AMCAP(i));   -- AMCAP
      cr(16#188# + i*4  to 16#18b# + i*4) := f_cr_vec(g_ADEM(i));    -- ADEM
Tom Levens's avatar
Tom Levens committed
280
    end loop;
281
    for i in cr'range loop
Tom Levens's avatar
Tom Levens committed
282 283 284 285 286
      crc := crc + unsigned(cr(i));
    end loop;
    cr(16#000#)            := std_logic_vector(crc);              -- Checksum
    return cr;
  end;
287

288
  constant s_cr_rom : t_cr_array(0 to 511) := f_cr_encode;
289

Tom Levens's avatar
Tom Levens committed
290
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
291

dpedrett's avatar
dpedrett committed
292
begin
Tom Levens's avatar
Tom Levens committed
293

Tom Levens's avatar
Tom Levens committed
294
  s_addr <= unsigned(addr_i);
Tom Levens's avatar
Tom Levens committed
295

Tom Levens's avatar
Tom Levens committed
296 297 298
  ------------------------------------------------------------------------------
  -- Defined CR
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
299 300
  s_cr_access  <= '1' when s_addr >= c_BEG_CR and
                           s_addr <= c_END_CR
Tom Levens's avatar
Tom Levens committed
301 302 303
                      else '0';

  process (clk_i)
Tom Levens's avatar
Tom Levens committed
304 305
  begin
    if rising_edge(clk_i) then
306 307 308 309 310
      if s_addr(11) = '0' then
        s_cr_data <= s_cr_rom(to_integer(s_addr(10 downto 2)));
      else
        s_cr_data <= x"00";
      end if;
Tom Levens's avatar
Tom Levens committed
311 312 313
    end if;
  end process;

Tom Levens's avatar
Tom Levens committed
314 315 316
  ------------------------------------------------------------------------------
  -- Defined CSR
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
317 318
  s_csr_access <= '1' when s_addr >= c_BEG_CSR and
                           s_addr <= c_END_CSR
Tom Levens's avatar
Tom Levens committed
319
                      else '0';
Tom Levens's avatar
Tom Levens committed
320

Tom Levens's avatar
Tom Levens committed
321 322 323 324
  -- If the crate is not driving the GA lines or the parity is even the BAR
  -- register is set to 0x00 and the board will not answer CR/CSR accesses.
  s_ga_parity  <= vme_ga_i(5) xor vme_ga_i(4) xor vme_ga_i(3) xor
                  vme_ga_i(2) xor vme_ga_i(1) xor vme_ga_i(0);
Tom Levens's avatar
Tom Levens committed
325

Tom Levens's avatar
Tom Levens committed
326 327
  -- Write
  process (clk_i)
328 329
    -- Write to ADER bytes, if implemented. Take advantage of VITAL-1-1 Rule
    -- 10.19
Tristan Gingold's avatar
Tristan Gingold committed
330
    procedure Set_ADER (Idx : natural range 0 to 7) is
331 332 333 334
      variable v_byte  : integer;
    begin
      if g_ADEM (Idx) /= x"0000_0000" then
        v_byte  := 3 - to_integer(s_addr(3 downto 2));
Tristan Gingold's avatar
Tristan Gingold committed
335
        s_reg_ader(Idx)(8*v_byte + 7 downto 8*v_byte) <= data_i;
336
      end if;
Tristan Gingold's avatar
Tristan Gingold committed
337
    end Set_ADER;
338 339 340

    variable csr_idx   : unsigned(7 downto 4);
    variable csr_boff : unsigned(3 downto 2);
Tom Levens's avatar
Tom Levens committed
341 342
  begin
    if rising_edge(clk_i) then
Tom Levens's avatar
Tom Levens committed
343
      if rst_n_i = '0' then
Tom Levens's avatar
Tom Levens committed
344 345 346 347 348 349 350 351
        if s_ga_parity = '1' then
          s_reg_bar       <= (not vme_ga_i(4 downto 0)) & "000";
        else
          s_reg_bar       <= x"00";
        end if;
        s_reg_bit_reg     <= x"00";
        s_reg_cram_owner  <= x"00";
        s_reg_usr_bit_reg <= x"00";
352
        s_reg_ader        <= (others => x"00000000");
Tom Levens's avatar
Tom Levens committed
353 354
      else
        if we_i = '1' and s_csr_access = '1' then
355 356 357 358 359
          --  FIXME: the SVEC linux driver assume that this bit is just a
          --  pulse, and doesn't clear it. Follow this legacy (and incorrect)
          --  behaviour to be compatible with the driver.  The reset bit will
          --  be cleared at the next CSR write access.
          s_reg_bit_reg(c_RESET_BIT) <= '0';
360

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
          csr_idx := s_addr(7 downto 4);
          csr_boff := s_addr(3 downto 2);
          case csr_idx is
            when x"f" =>
              case csr_boff is
                when "11" => -- BAR
                  s_reg_bar <= data_i;
                when "10" => -- Bit Set
                  s_reg_bit_reg <= s_reg_bit_reg or data_i;
                when "01" => -- Bit Clr
                  s_reg_bit_reg <= s_reg_bit_reg and not data_i;
                  --  VITAL-1-1 Rule 10.27
                  --  4) Ownership shall be released by writing any value with
                  --     bit 2 set (eg 0x04) to the CSR Bit Clear Register
                  --     located at 0x7fff7. This clears the CRAM_OWNER
                  --     register and leaves it with a value of zero and also
                  --     clears the CRAM owned status.
                  if data_i(c_CRAM_OWNER_BIT) = '1' then
                    s_reg_cram_owner <= x"00";
                  end if;
                when "00" => -- CRAM_OWNER
                  --  VITAL-1-1 Rule 10.27
                  --  2) Writing to CRAM_OWNER register when it contains a non-
                  --     zero value shall not change the value of the
                  --     CRAM_OWNER. That allows the first master that writes
                  --     a non-zero value to acquire ownership.
                  if s_reg_cram_owner = x"00" then
                    s_reg_cram_owner <= data_i;
                    s_reg_bit_reg(c_CRAM_OWNER_BIT) <= '1';
                  end if;
                when others =>
                  null;
              end case;
            when x"e" =>
              case csr_boff is
                when "11" => -- User Set
                  s_reg_usr_bit_reg <= s_reg_usr_bit_reg or data_i;
                when "10" => -- User Clr
                  s_reg_usr_bit_reg <= s_reg_usr_bit_reg and not data_i;
                when others =>
                  null;
              end case;

            --  Decompose ADER so that unimplemented one can be removed.
            when x"d" => -- ADER 7
              Set_ADER(7);
            when x"c" => -- ADER 6
              Set_ADER(6);
            when x"b" => -- ADER 5
              Set_ADER(5);
            when x"a" => -- ADER 4
              Set_ADER(4);
            when x"9" => -- ADER 3
              Set_ADER(3);
            when x"8" => -- ADER 2
              Set_ADER(2);
            when x"7" => -- ADER 1
              Set_ADER(1);
            when x"6" => -- ADER 0
              Set_ADER(0);
Tom Levens's avatar
Tom Levens committed
421 422 423

            when others =>
              null;
Tom Levens's avatar
Tom Levens committed
424 425
          end case;
        end if;
Tom Levens's avatar
Tom Levens committed
426

Tom Levens's avatar
Tom Levens committed
427
        if vme_berr_n_i = '0' then
Tom Levens's avatar
Tom Levens committed
428
          s_reg_bit_reg(c_BERR_BIT) <= '1';
Tom Levens's avatar
Tom Levens committed
429
        end if;
Tom Levens's avatar
Tom Levens committed
430

Tom Levens's avatar
Tom Levens committed
431
        if vme_sysfail_i = '1' then
Tom Levens's avatar
Tom Levens committed
432
          s_reg_bit_reg(c_FAILED_BIT) <= '1';
Tom Levens's avatar
Tom Levens committed
433 434 435 436
        end if;
      end if;
    end if;
  end process;
dpedrett's avatar
dpedrett committed
437

Tom Levens's avatar
Tom Levens committed
438
  bar_o             <= s_reg_bar(7 downto 3);
Tom Levens's avatar
Tom Levens committed
439 440 441
  module_enable_o   <= s_reg_bit_reg(c_ENABLE_BIT);
  vme_sysfail_ena_o <= s_reg_bit_reg(c_SYSFAIL_EN_BIT);
  module_reset_o    <= s_reg_bit_reg(c_RESET_BIT);
442 443 444 445 446

  gen_ader_o: for i in s_reg_ader'range generate
    ader_o (i) <=
      s_reg_ader (i) and ((g_ADEM(i) and c_ADEM_MASK) or c_ADER_MASK);
  end generate;
447

Tom Levens's avatar
Tom Levens committed
448 449
  -- Read
  process (clk_i)
450 451 452
    procedure Get_ADER(Idx : natural range 0 to 7)
    is
      variable v_byte  : integer;
453
      variable ader : std_logic_vector(31 downto 0);
454 455 456
    begin
      if g_ADEM(Idx) /= x"0000_0000" then
        v_byte  := 3 - to_integer(s_addr(3 downto 2));
457 458
        ader := s_reg_ader(Idx)
                and ((g_ADEM(Idx) and c_ADEM_MASK) or c_ADER_MASK);
Tristan Gingold's avatar
Tristan Gingold committed
459
        s_csr_data <= ader(8*v_byte + 7 downto 8*v_byte);
460 461 462 463 464
      end if;
    end Get_ADER;

    variable csr_idx   : unsigned(7 downto 4);
    variable csr_boff : unsigned(3 downto 2);
Tom Levens's avatar
Tom Levens committed
465
  begin
Tom Levens's avatar
Tom Levens committed
466
    if rising_edge(clk_i) then
Tom Levens's avatar
Tom Levens committed
467
      if rst_n_i = '0' then
468
        s_csr_data <= x"00";
Tom Levens's avatar
Tom Levens committed
469
      else
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
        -- VITAL-1-1 Rule 10.14
        -- All unimplemented locations in the Defined CSR Area shall read as
        -- 0x00
        s_csr_data <= x"00";

        csr_idx := s_addr(7 downto 4);
        csr_boff := s_addr(3 downto 2);
        case csr_idx is
          when x"f" =>
            case csr_boff is
              when "11" => -- BAR
                s_csr_data <= s_reg_bar;
              when "10" => -- Bit Set
                s_csr_data <= s_reg_bit_reg;
              when "01" => -- Bit Clr
                s_csr_data <= s_reg_bit_reg;
              when "00" => -- CRAM_OWNER
                s_csr_data <= s_reg_cram_owner;
              when others =>
                null;
            end case;
          when x"e" =>
            case csr_boff is
              when "11" => -- User Set
                s_csr_data <= s_reg_usr_bit_reg;
              when "10" => -- User Clr
                s_csr_data <= s_reg_usr_bit_reg;
              when others =>
                null;
            end case;

          --  Unroll to disable unused ADER. Not the best readable style.
          when x"d" =>
            Get_ADER(7);
          when x"c" =>
            Get_ADER(6);
          when x"b" =>
            Get_ADER(5);
          when x"a" =>
            Get_ADER(4);
          when x"9" =>
            Get_ADER(3);
          when x"8" =>
            Get_ADER(2);
          when x"7" =>
            Get_ADER(1);
          when x"6" =>
            Get_ADER(0);
Tom Levens's avatar
Tom Levens committed
518 519

          when others =>
520
            null;
Tom Levens's avatar
Tom Levens committed
521 522 523
        end case;
      end if;
    end if;
Tom Levens's avatar
Tom Levens committed
524
  end process;
dpedrett's avatar
dpedrett committed
525

Tom Levens's avatar
Tom Levens committed
526
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
527
  -- CRAM
Tom Levens's avatar
Tom Levens committed
528
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
529 530 531
  gen_cram_ena: if c_CRAM_ENA = true generate
    s_cram_access <= '1' when s_addr >= c_BEG_CRAM and
                              s_addr <= c_END_CRAM
Tom Levens's avatar
Tom Levens committed
532 533 534
                         else '0';

    s_cram_we     <= we_i and s_cram_access;
Tom Levens's avatar
Tom Levens committed
535
    s_cram_waddr  <= s_addr - c_BEG_CRAM;
536
    s_cram_data   <= s_cram(to_integer(s_cram_raddr) mod c_CRAM_SIZE);
Tom Levens's avatar
Tom Levens committed
537

538 539
    process (clk_i)
    begin
Tom Levens's avatar
Tom Levens committed
540 541 542 543 544 545 546
      if rising_edge(clk_i) then
        if s_cram_we = '1' then
          s_cram(to_integer(s_cram_waddr)) <= data_i;
        end if;
        s_cram_raddr <= s_cram_waddr;
      end if;
    end process;
Tom Levens's avatar
Tom Levens committed
547
  end generate;
Tom Levens's avatar
Tom Levens committed
548
  gen_cram_dis: if c_CRAM_ENA = false  generate
Tom Levens's avatar
Tom Levens committed
549
    s_cram_access <= '0';
Tom Levens's avatar
Tom Levens committed
550 551
    s_cram_raddr  <= (others => '0');
    s_cram_waddr  <= (others => '0');
Tom Levens's avatar
Tom Levens committed
552 553 554 555
    s_cram_data   <= x"00";
  end generate;

  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
556
  -- User CR
Tom Levens's avatar
Tom Levens committed
557
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
558 559 560
  gen_user_cr_ena: if c_USER_CR_ENA = true generate
    s_user_cr_access <= '1' when s_addr >= c_BEG_USER_CR and
                                 s_addr <= c_END_USER_CR
Tom Levens's avatar
Tom Levens committed
561 562
                            else '0';

Tom Levens's avatar
Tom Levens committed
563
    user_cr_addr_o   <= std_logic_vector(s_addr - c_BEG_USER_CR);
Tom Levens's avatar
Tom Levens committed
564
  end generate;
Tom Levens's avatar
Tom Levens committed
565
  gen_user_cr_dis: if c_USER_CR_ENA = false generate
Tom Levens's avatar
Tom Levens committed
566 567 568 569
    s_user_cr_access <= '0';
    user_cr_addr_o   <= (others => '0');
  end generate;

Tom Levens's avatar
Tom Levens committed
570 571 572 573 574 575
  ------------------------------------------------------------------------------
  -- User CSR
  ------------------------------------------------------------------------------
  gen_user_csr_ena: if c_USER_CSR_ENA = true generate
    s_user_csr_access <= '1' when s_addr >= c_BEG_USER_CSR and
                                  s_addr <= c_END_USER_CSR
Tom Levens's avatar
Tom Levens committed
576 577
                             else '0';

Tom Levens's avatar
Tom Levens committed
578
    user_csr_addr_o   <= std_logic_vector(s_addr - c_BEG_USER_CSR);
Tom Levens's avatar
Tom Levens committed
579
  end generate;
Tom Levens's avatar
Tom Levens committed
580
  gen_user_csr_dis: if c_USER_CSR_ENA = false generate
Tom Levens's avatar
Tom Levens committed
581 582 583 584 585 586 587 588
    s_user_csr_access <= '0';
    user_csr_addr_o   <= (others => '0');
  end generate;

  user_csr_data_o <= data_i;
  user_csr_we_o   <= we_i and s_user_csr_access;

  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
589
  -- Read multiplexer
Tom Levens's avatar
Tom Levens committed
590 591 592 593 594 595
  ------------------------------------------------------------------------------
  process (
    s_cr_access,       s_cr_data,
    s_csr_access,      s_csr_data,
    s_cram_access,     s_cram_data,
    s_user_cr_access,  user_cr_data_i,
596 597
    s_user_csr_access, user_csr_data_i)
  begin
Tom Levens's avatar
Tom Levens committed
598 599 600 601 602 603 604 605 606 607 608
    if s_cr_access = '1' then
      data_o <= s_cr_data;
    elsif s_csr_access = '1' then
      data_o <= s_csr_data;
    elsif s_cram_access = '1' then
      data_o <= s_cram_data;
    elsif s_user_cr_access = '1' then
      data_o <= user_cr_data_i;
    elsif s_user_csr_access = '1' then
      data_o <= user_csr_data_i;
    else
Tom Levens's avatar
Tom Levens committed
609
      data_o <= c_UNUSED;
Tom Levens's avatar
Tom Levens committed
610 611
    end if;
  end process;
dpedrett's avatar
dpedrett committed
612

Tom Levens's avatar
Tom Levens committed
613
end rtl;