vme_cr_csr_space.vhd 24 KB
Newer Older
Tom Levens's avatar
Tom Levens committed
1 2 3 4 5 6
--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
-- VME64x Core
-- http://www.ohwr.org/projects/vme64x-core
--------------------------------------------------------------------------------
--
7
-- unit name:     vme_cr_csr_space
Tom Levens's avatar
Tom Levens committed
8 9 10 11 12 13
--
-- 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
--
--------------------------------------------------------------------------------
-- 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;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
102
use work.vme64x_pkg.all;
Tom Levens's avatar
Tom Levens committed
103

104
entity vme_cr_csr_space is
Tom Levens's avatar
Tom Levens committed
105
  generic (
106 107 108 109 110 111 112 113 114 115 116 117 118
    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);
119
    g_DECODER         : t_vme64x_decoder_arr);
Tom Levens's avatar
Tom Levens committed
120 121
  port (
    clk_i               : in  std_logic;
Tom Levens's avatar
Tom Levens committed
122
    rst_n_i             : in  std_logic;
Tom Levens's avatar
Tom Levens committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142

    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);
    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);

143
    ader_o              : out t_ader_array);
144
end vme_cr_csr_space;
Tom Levens's avatar
Tom Levens committed
145

146
architecture rtl of vme_cr_csr_space is
Tom Levens's avatar
Tom Levens committed
147

Tom Levens's avatar
Tom Levens committed
148 149 150 151 152 153
  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);
154 155 156 157

  -- It is expected to have unconnected bits in this register, since they
  -- are and'ed with ADEM bits (so some are always 0).
  signal s_reg_ader         : t_ader_array(ader_o'range);
Tom Levens's avatar
Tom Levens committed
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

  -- 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
174

Tom Levens's avatar
Tom Levens committed
175 176 177
  -- 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
178

Tom Levens's avatar
Tom Levens committed
179 180
  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
181

Tom Levens's avatar
Tom Levens committed
182 183
  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
184

185 186 187 188 189
  -- 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";
190

Tom Levens's avatar
Tom Levens committed
191 192 193 194 195 196 197 198 199 200
  -- 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
201
  subtype crcsr_addr is unsigned(18 downto 2);
Tristan Gingold's avatar
Tristan Gingold committed
202 203 204 205
  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);
206 207 208 209 210 211
  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
212 213 214 215 216 217 218 219 220 221 222

  -- 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
223

Tom Levens's avatar
Tom Levens committed
224 225 226 227
  ------------------------------------------------------------------------------
  -- 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
228

Tom Levens's avatar
Tom Levens committed
229 230
  -- 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
231
    variable a : t_cr_array(0 to v'length / 8 - 1);
Tom Levens's avatar
Tom Levens committed
232 233
  begin
    for i in 0 to a'length-1 loop
Tristan Gingold's avatar
Tristan Gingold committed
234
      a(i) := v(v'length - (i*8) - 1 downto v'length - (i*8) - 8);
Tom Levens's avatar
Tom Levens committed
235 236 237
    end loop;
    return a;
  end function;
Tom Levens's avatar
Tom Levens committed
238

Tom Levens's avatar
Tom Levens committed
239 240
  -- Function to encode the configuration ROM
  function f_cr_encode return t_cr_array is
241
    variable cr  : t_cr_array(0 to 511) := (others => x"00");
Tom Levens's avatar
Tom Levens committed
242 243
    variable crc : unsigned(7 downto 0)  := x"00";
  begin
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
    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
267
    for i in 0 to 7 loop
268 269 270
      cr(16#040# + i)                     := g_DECODER(i).dawpr;
      cr(16#048# + i*8  to 16#04f# + i*8) := f_cr_vec(g_DECODER(i).amcap);
      cr(16#188# + i*4  to 16#18b# + i*4) := f_cr_vec(g_DECODER(i).adem);
Tom Levens's avatar
Tom Levens committed
271
    end loop;
272
    for i in cr'range loop
Tom Levens's avatar
Tom Levens committed
273 274 275 276 277
      crc := crc + unsigned(cr(i));
    end loop;
    cr(16#000#)            := std_logic_vector(crc);              -- Checksum
    return cr;
  end;
278

279
  constant s_cr_rom : t_cr_array(0 to 511) := f_cr_encode;
280

Tom Levens's avatar
Tom Levens committed
281
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
282

dpedrett's avatar
dpedrett committed
283
begin
Tom Levens's avatar
Tom Levens committed
284

Tom Levens's avatar
Tom Levens committed
285
  s_addr <= unsigned(addr_i);
Tom Levens's avatar
Tom Levens committed
286

Tom Levens's avatar
Tom Levens committed
287 288 289
  ------------------------------------------------------------------------------
  -- Defined CR
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
290 291
  s_cr_access  <= '1' when s_addr >= c_BEG_CR and
                           s_addr <= c_END_CR
Tom Levens's avatar
Tom Levens committed
292 293 294
                      else '0';

  process (clk_i)
Tom Levens's avatar
Tom Levens committed
295 296
  begin
    if rising_edge(clk_i) then
297 298 299 300 301
      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
302 303 304
    end if;
  end process;

Tom Levens's avatar
Tom Levens committed
305 306 307
  ------------------------------------------------------------------------------
  -- Defined CSR
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
308 309
  s_csr_access <= '1' when s_addr >= c_BEG_CSR and
                           s_addr <= c_END_CSR
Tom Levens's avatar
Tom Levens committed
310
                      else '0';
Tom Levens's avatar
Tom Levens committed
311

Tom Levens's avatar
Tom Levens committed
312 313 314 315
  -- 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
316

Tom Levens's avatar
Tom Levens committed
317 318
  -- Write
  process (clk_i)
319 320
    -- Write to ADER bytes, if implemented. Take advantage of VITAL-1-1 Rule
    -- 10.19
321
    procedure Set_ADER (idx : natural range 0 to 7) is
322 323
      variable v_byte  : integer;
    begin
324
      if idx <= ader_o'high then
325
        v_byte  := 3 - to_integer(s_addr(3 downto 2));
326
        s_reg_ader(idx)(8*v_byte + 7 downto 8*v_byte) <= data_i;
327
      end if;
Tristan Gingold's avatar
Tristan Gingold committed
328
    end Set_ADER;
329 330 331

    variable csr_idx   : unsigned(7 downto 4);
    variable csr_boff : unsigned(3 downto 2);
Tom Levens's avatar
Tom Levens committed
332 333
  begin
    if rising_edge(clk_i) then
Tom Levens's avatar
Tom Levens committed
334
      if rst_n_i = '0' then
Tom Levens's avatar
Tom Levens committed
335 336 337 338 339 340 341 342
        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";
343
        s_reg_ader        <= (others => x"00000000");
Tom Levens's avatar
Tom Levens committed
344 345
      else
        if we_i = '1' and s_csr_access = '1' then
346 347 348 349 350
          --  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';
351

352 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 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
          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
412 413 414

            when others =>
              null;
Tom Levens's avatar
Tom Levens committed
415 416
          end case;
        end if;
Tom Levens's avatar
Tom Levens committed
417

Tom Levens's avatar
Tom Levens committed
418
        if vme_berr_n_i = '0' then
Tom Levens's avatar
Tom Levens committed
419
          s_reg_bit_reg(c_BERR_BIT) <= '1';
Tom Levens's avatar
Tom Levens committed
420
        end if;
Tom Levens's avatar
Tom Levens committed
421

422
        -- Could handle sysfail (if it was supported).
Tom Levens's avatar
Tom Levens committed
423 424 425
      end if;
    end if;
  end process;
dpedrett's avatar
dpedrett committed
426

Tom Levens's avatar
Tom Levens committed
427
  bar_o             <= s_reg_bar(7 downto 3);
Tom Levens's avatar
Tom Levens committed
428 429
  module_enable_o   <= s_reg_bit_reg(c_ENABLE_BIT);
  module_reset_o    <= s_reg_bit_reg(c_RESET_BIT);
430

431 432
  -- Only keep ADER bits that are used for comparison.  Save a little bit of
  -- resources.
433 434
  gen_ader_o: for i in s_reg_ader'range generate
    ader_o (i) <=
435
      s_reg_ader (i) and ((g_DECODER(i).adem and c_ADEM_MASK) or c_ADER_MASK);
436
  end generate;
437

Tom Levens's avatar
Tom Levens committed
438 439
  -- Read
  process (clk_i)
440
    procedure Get_ADER(idx : natural range 0 to 7)
441 442
    is
      variable v_byte  : integer;
443
      variable ader : std_logic_vector(31 downto 0);
444
    begin
445
      if idx <= ader_o'high then
446
        v_byte  := 3 - to_integer(s_addr(3 downto 2));
447
        ader := s_reg_ader(idx)
448
                and ((g_DECODER(idx).adem and c_ADEM_MASK) or c_ADER_MASK);
Tristan Gingold's avatar
Tristan Gingold committed
449
        s_csr_data <= ader(8*v_byte + 7 downto 8*v_byte);
450 451 452 453 454
      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
455
  begin
Tom Levens's avatar
Tom Levens committed
456
    if rising_edge(clk_i) then
Tom Levens's avatar
Tom Levens committed
457
      if rst_n_i = '0' then
458
        s_csr_data <= x"00";
Tom Levens's avatar
Tom Levens committed
459
      else
460 461 462 463 464 465 466 467 468 469 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
        -- 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
508 509

          when others =>
510
            null;
Tom Levens's avatar
Tom Levens committed
511 512 513
        end case;
      end if;
    end if;
Tom Levens's avatar
Tom Levens committed
514
  end process;
dpedrett's avatar
dpedrett committed
515

Tom Levens's avatar
Tom Levens committed
516
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
517
  -- CRAM
Tom Levens's avatar
Tom Levens committed
518
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
519 520 521
  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
522 523 524
                         else '0';

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

528 529
    process (clk_i)
    begin
Tom Levens's avatar
Tom Levens committed
530 531 532 533 534 535 536
      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
537
  end generate;
Tom Levens's avatar
Tom Levens committed
538
  gen_cram_dis: if c_CRAM_ENA = false  generate
Tom Levens's avatar
Tom Levens committed
539
    s_cram_access <= '0';
Tom Levens's avatar
Tom Levens committed
540 541
    s_cram_raddr  <= (others => '0');
    s_cram_waddr  <= (others => '0');
Tom Levens's avatar
Tom Levens committed
542 543 544 545
    s_cram_data   <= x"00";
  end generate;

  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
546
  -- User CR
Tom Levens's avatar
Tom Levens committed
547
  ------------------------------------------------------------------------------
Tom Levens's avatar
Tom Levens committed
548 549 550
  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
551 552
                            else '0';

Tom Levens's avatar
Tom Levens committed
553
    user_cr_addr_o   <= std_logic_vector(s_addr - c_BEG_USER_CR);
Tom Levens's avatar
Tom Levens committed
554
  end generate;
Tom Levens's avatar
Tom Levens committed
555
  gen_user_cr_dis: if c_USER_CR_ENA = false generate
Tom Levens's avatar
Tom Levens committed
556 557 558 559
    s_user_cr_access <= '0';
    user_cr_addr_o   <= (others => '0');
  end generate;

Tom Levens's avatar
Tom Levens committed
560 561 562 563 564 565
  ------------------------------------------------------------------------------
  -- 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
566 567
                             else '0';

Tom Levens's avatar
Tom Levens committed
568
    user_csr_addr_o   <= std_logic_vector(s_addr - c_BEG_USER_CSR);
Tom Levens's avatar
Tom Levens committed
569
  end generate;
Tom Levens's avatar
Tom Levens committed
570
  gen_user_csr_dis: if c_USER_CSR_ENA = false generate
Tom Levens's avatar
Tom Levens committed
571 572 573 574 575 576 577 578
    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
579
  -- Read multiplexer
Tom Levens's avatar
Tom Levens committed
580 581 582 583 584 585
  ------------------------------------------------------------------------------
  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,
586 587
    s_user_csr_access, user_csr_data_i)
  begin
Tom Levens's avatar
Tom Levens committed
588 589 590 591 592 593 594 595 596 597 598
    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
599
      data_o <= c_UNUSED;
Tom Levens's avatar
Tom Levens committed
600 601
    end if;
  end process;
dpedrett's avatar
dpedrett committed
602

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