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

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [sparc/] [pci_arb.vhd] - Blame information for rev 5

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 tarookumic
 
2
 
3
 
4
 
5
----------------------------------------------------------------------------
6
--  This file is a part of the LEON VHDL model
7
--  Copyright (C) 1999  European Space Agency (ESA)
8
--
9
--  This library is free software; you can redistribute it and/or
10
--  modify it under the terms of the GNU Lesser General Public
11
--  License as published by the Free Software Foundation; either
12
--  version 2 of the License, or (at your option) any later version.
13
--
14
--  See the file COPYING.LGPL for the full details of the license.
15
 
16
 
17
--============================================================================--
18
-- Design unit  : pci_arb
19
--
20
-- File name    : pci_arb.vhd
21
--
22
-- Purpose      : Arbiter for the PCI bus
23
--                - configurable size: 4, 8, 16, 32 agents
24
--                - nested round-robbing in two different priority levels
25
--                - priority assignment hard-coded or APB-programmable
26
--
27
-- Reference    : PCI Local Bus Specification, Revision 2.1,
28
--                PCI Special Interest Group, 1st June 1995
29
--                (for information: http: 
30
-- Reference    : AMBA(TM) Specification (Rev 2.0), ARM IHI 0011A,
31
--                13th May 1999, issue A, first release, ARM Limited
32
--                The document can be retrieved from http: 
33
--
34
-- Note         : Numbering for req_n, gnt_n, or priority levels is in
35
--                increasing order <0 = left> to <NUMBER-1 = right>.
36
--                APB data/address arrays are in the conventional order: 
37
--                The least significant bit is located to the
38
--                right, carrying the lower index number (usually 0).
39
--                The arbiter considers strong signal levels ('1' and '0')
40
--                only. Weak levels ('H', 'L') are not considered. The
41
--                appropriate translation function (to_X01) must be applied
42
--                to the inputs. This is usually done by the pads,
43
--                and therefore not contained in this model.
44
--                
45
-- Configuration: The arbiter can be configured to NB_AGENTS = 4, 8, 16 or 32.
46
--                A priority level (0 = high, 1 = low) is assigned to each device.
47
--                Exception is agent NB_AGENTS-1, which has always lowest priority.
48
--
49
--                a) The priority levels are hard-coded, when APB_PRIOS = false.
50
--                In this case, the APB ports (pbi/pbo) are unconnected.
51
--                The constant ARB_LVL_C must then be set to appropriate values.
52
--
53
--                b) When APB_PRIOS = true, the levels are programmable via the
54
--                APB-address 0x80 (allows to be ored with the PCI interface):
55
--                Bit 31 (leftmost) = master 31 . . bit 0 (rightmost) = master 0.
56
--                Bit NB_AGENTS-1 is dont care at write and reads 1.
57
--                Bits NB_AGENTS to 31, if existing, are dont care and read 0.
58
--                The constant ARB_LVL_C is then the reset value.
59
--                
60
-- Algorithm    : The algorithm is described in the implementation note of
61
--                section 3.4 of the PCI standard:
62
--                The bus is granted by two nested round-robbing loops.
63
--                An agent number and a priority level is assigned to each agent.
64
--                The agent number determines, the pair of req_n/gnt_n lines.
65
--                Agents are counted from 0 to NB_AGENTS-1.
66
--                All agents in one level have equal access to the bus
67
--                (round-robbing); all agents of level 1 as a group have access
68
--                equal to each agent of level 0.
69
--                Re-arbitration occurs, when frame_n is asserted, as soon
70
--                as any other master has requested the bus, but only
71
--                once per transaction.
72
--                
73
--                b) With programmable priorities. The priority level of all
74
--                   agents (except NB_AGENTS-1) is  programmable via APB.
75
--                   In a 256 byte APB address range, the priority level of
76
--                   agent N is accessed via the address 0x80 + 4*N. The APB
77
--                   slave returns 0 on all non-implemented addresses, the
78
--                   address bits (1:0) are not decoded. Since only addresses
79
--                   >= 0x80 are occupied, it can be used in parallel (ored
80
--                   read data) with our PCI interface (uses <= 0x78).
81
--                   The constant ARB_LVL_C in pci_arb_pkg is the reset value.
82
--
83
-- Timeout:       The "broken master" timeout is another reason for
84
--                re-arbitration (section 3.4.1 of the standard). Grant is
85
--                removed from an agent, which has not started a cycle
86
--                within 16 cycles after request (and grant). Reporting of
87
--                such a 'broken' master is not implemented.
88
--
89
-- Turnover:      A turnover cycle is required by the standard, when re-
90
--                arbitration occurs during idle state of the bus.
91
--                Notwithstanding to the standard, "idle state" is assumed,
92
--                when frame_n is high for more than 1 cycle.
93
--
94
-- Bus parking  : The bus is parked to agent 0 after reset, it remains granted
95
--                to the last owner, if no other agent requests the bus.
96
--                When another request is asserted, re-arbitration occurs
97
--                after one turnover cycle.
98
--
99
-- Lock         : Lock is defined as a resource lock by the PCI standard.
100
--                The optional bus lock mentioned in the standard is not
101
--                considered here and there are no special conditions to
102
--                handle when lock_n is active.
103
--                in arbitration.
104
--
105
-- Latency      : Latency control in PCI is via the latency counters of each
106
--                agent. The arbiter does not perform any latency check and
107
--                a once granted agent continues its transaction until its
108
--                grant is removed AND its own latency counter has expired.
109
--                Even though, a bus re-arbitration occurs during a
110
--                transaction, the hand-over only becomes effective,
111
--                when the current owner deasserts frame_n.
112
--
113
-- Limitations  : [add here known bugs and limitations]
114
-- 
115
-- Library      : work
116
--
117
-- Dependencies : LEON config package
118
--                package amba, can be retrieved from:
119
--                http: 
120
--
121
-- Author       : Roland Weigand  <Roland.Weigand@gmx.net>
122
--                European Space Agency (ESA)
123
--                Microelectronics Section (TOS-ESM)
124
--                P.O. Box 299
125
--                NL-2200 AG Noordwijk ZH
126
--                The Netherlands
127
--
128
-- Contact      : mailto:microelectronics@estec.esa.int
129
--                http: 
130
 
131
-- Copyright (C): European Space Agency (ESA) 2002. 
132
--                This source code is free software; you can redistribute it 
133
--                and/or modify it under the terms of the GNU Lesser General 
134
--                Public License as published by the Free Software Foundation; 
135
--                either version 2 of the License, or (at your option) any 
136
--                later version. For full details of the license see file
137
--                http: 
138
--
139
--                It is recommended that any use of this VHDL source code is
140
--                reported to the European Space Agency. It is also recommended 
141
--                that any use of the VHDL source code properly acknowledges the 
142
--                European Space Agency as originator. 
143
 
144
-- Disclaimer   : All information is provided "as is", there is no warranty that
145
--                the information is correct or suitable for any purpose,
146
--                neither implicit nor explicit. This information does not
147
--                necessarily reflect the policy of the European Space Agency.
148
--
149
-- Simulator    : Modelsim 5.5e on Linux RedHat 7.2
150
--
151
-- Synthesis    : Synopsys Version 1999.10 on Sparc + Solaris 5.5.1
152
-- 
153
--------------------------------------------------------------------------------
154
-- Version  Author   Date       Changes
155
--
156
-- 0.0      R. W.    2000/11/02 File created
157
-- 0.1      J.Gaisler     2001/04/10   Integrated in LEON
158
-- 0.2      R. Weigand    2001/04/25   Connect arb_lvl reg to AMBA clock/reset
159
-- 0.3      R. Weigand    2002/03/19   Default assignment to owneri in find_next
160
-- 1.0      RW.           2002/04/08   Implementation of TMR registers
161
--                                     Removed recursive function call
162
--                                     Fixed ARB_LEVELS = 2
163
-- 3.0      R. Weigand    2002/04/16   Released for leon2
164
-- $Log: not supported by cvs2svn $
165
-- Revision 3.1  2002/07/31 13:22:09  weigand
166
-- Bugfix for cases where no valid request in level 0 (level 1 was not rearbitrated)
167
--
168
-- Revision 3.0  2002/07/24 12:19:38  weigand
169
-- Installed RCS with version 3.0
170
--
171
--------------------------------------------------------------------------------
172
library IEEE;
173
use IEEE.std_logic_1164.all;
174
-- use IEEE.std_logic_arith.all;
175
use work.leon_config.all;
176
package pci_arb_pkg is
177
   -- The following constants are defined by the target/device/config packages:
178
   -- The number of agents can be only 4, 8, 16, 32
179
   -- constant NB_AGENTS : natural range 3 to 32 := 4; -- Nb. of agents (4, 8, 16, 32)
180
   -- constant ARB_SIZE : natural range 2 to 5 := 2;  -- round up log2(NB_AGENTS) 
181
   -- constant APB_PRIOS : boolean := true;  -- levels programmable via APB
182
 
183
   subtype agent_t is std_logic_vector(ARB_SIZE-1 downto 0);
184
   subtype arb_lvl_t is std_logic_vector(NB_AGENTS-1 downto 0);
185
   subtype agentno_t is integer range 0 to NB_AGENTS-1;
186
 
187
   -- Note: the agent with the highest index (3, 7, 15, 31) is always in level 1
188
   -- Example: x010 = prio 0 for agent 2 and 0, prio 1 for agent 3 and 1.
189
   -- Default: start with all devices equal priority at level 1.
190
   constant ARB_LVL_C : arb_lvl_t := (others => '1');
191
 
192
   constant all_ones : std_logic_vector(0 to NB_AGENTS-1) := (others => '1');
193
 
194
end pci_arb_pkg;
195
 
196
library IEEE;
197
use IEEE.std_logic_1164.all;
198
use IEEE.std_logic_unsigned."+";
199
use IEEE.std_logic_unsigned.conv_integer;
200
use IEEE.std_logic_arith.conv_unsigned;
201
use work.pci_arb_pkg.all;
202
use work.leon_config.all;
203
use work.amba.all;
204
use work.leon_iface.all;
205
 
206
entity pci_arb is
207
 
208
   port (clk     : in  clk_type;                            -- clock
209
         rst_n   : in  std_logic;                           -- async reset active low
210
         req_n   : in  std_logic_vector(0 to NB_AGENTS-1);  -- bus request
211
         frame_n : in  std_logic;
212
         gnt_n   : out std_logic_vector(0 to NB_AGENTS-1);  -- bus grant
213
         pclk    : in  clk_type;                            -- APB clock
214
         prst_n  : in  std_logic;                           -- APB reset
215
         pbi     : in  APB_Slv_In_Type;                     -- APB inputs
216
         pbo     : out APB_Slv_Out_Type                     -- APB outputs
217
         );
218
 
219
end pci_arb;
220
 
221
 
222
architecture rtl of pci_arb is
223
   signal owner0, owneri0   : agent_t;  -- current owner in level 0
224
   signal owner1, owneri1   : agent_t;  -- current owner in level 1
225
   signal cown, cowni       : agent_t;  -- current level
226
   signal rearb, rearbi     : std_logic;            -- re-arbitration flag
227
   signal tout, touti       : std_logic_vector(3 downto 0);  -- timeout counter
228
   signal turn, turni       : std_logic;            -- turnaround cycle
229
   signal arb_lvl, arb_lvli : arb_lvl_t := ARB_LVL_C;  -- level registers
230
 
231
   type nmstarr is array (0 to 3) of agentno_t;
232
   type nvalarr is array (0 to 3) of boolean;
233
 
234
 
235
begin  -- rtl
236
 
237
   ----------------------------------------------------------------------------
238
   -- PCI ARBITER 
239
   ----------------------------------------------------------------------------
240
   -- purpose: Grants the bus depending on the request signals. All agents have
241
   -- equal priority, if another request occurs during a transaction, the bus is
242
   -- granted to the new agent. However, PCI protocol specifies that the master
243
   -- can finish the current transaction within the limit of its latency timer.
244
   arbiter : process(cown, owner0, owner1, req_n, rearb, tout, turn, frame_n,
245
                     arb_lvl, rst_n)
246
 
247
      variable owner0v, owner1v : agentno_t;  -- integer variables for current owner
248
      variable new_request      : agentno_t := 0;  -- detected request
249
      variable nmst             : nmstarr;
250
      variable nvalid           : nvalarr;
251
 
252
   begin  -- process arbiter
253
 
254
      -- default assignments
255
      rearbi  <= rearb;
256
      owneri0 <= owner0;
257
      owneri1 <= owner1;
258
      cowni   <= cown;
259
      touti   <= tout;
260
      turni   <= '0';                    -- no turnaround
261
 
262
      -- re-arbitrate once during the transaction,
263
      -- or when timeout counter expired (bus idle).
264
      if (frame_n = '0' and rearb = '0') or turn = '1' then
265
 
266
         owner0v        := conv_integer(owner0);
267
         owner1v        := conv_integer(owner1);
268
         new_request    := conv_integer(cown);
269
         nvalid(0 to 3) := (others => false);
270
         nmst(0 to 3)   := (others => 0);
271
 
272
         -- Determine next request in both priority levels
273
         rob : for i in NB_AGENTS-1 downto 0 loop
274
            -- consider all masters with valid request
275
            if req_n(i) = '0' then
276
               -- next in prio level 0
277
               if arb_lvl(i) = '0' then
278
                  if i > owner0v then
279
                     nmst(0) := i; nvalid(0) := true;
280
                  elsif i < owner0v then
281
                     nmst(1) := i; nvalid(1) := true;
282
                  end if;
283
               -- next in prio level 1
284
               elsif arb_lvl(i) = '1' then
285
                  if i > owner1v then
286
                     nmst(2) := i; nvalid(2) := true;
287
                  elsif i < owner1v then
288
                     nmst(3) := i; nvalid(3) := true;
289
                  end if;
290
               end if;                  -- arb_lvl
291
            end if;                     -- req_n
292
         end loop rob;
293
 
294
         -- select new master
295
         if nvalid(0) then              -- consider level 0 before wrap
296
            new_request    := nmst(0);
297
            owner0v        := nmst(0);
298
         -- consider level 1 only once, except when no request in level 0
299
         elsif owner0v /= NB_AGENTS-1 or not nvalid(1) then
300
            if nvalid(2) then           -- level 1 before wrap
301
               new_request := nmst(2);
302
               owner0v     := NB_AGENTS-1;
303
               owner1v     := nmst(2);
304
            elsif nvalid(3) then        -- level 1 after wrap
305
               new_request := nmst(3);
306
               owner0v     := NB_AGENTS-1;
307
               owner1v     := nmst(3);
308
            end if;
309
         elsif nvalid(1) then           -- level 0 after wrap
310
            new_request    := nmst(1);
311
            owner0v        := nmst(1);
312
         end if;
313
 
314
         owneri0 <= std_logic_vector(conv_unsigned(owner0v, ARB_SIZE));
315
         owneri1 <= std_logic_vector(conv_unsigned(owner1v, ARB_SIZE));
316
 
317
         -- rearbitration if any request asserted & different from current owner
318
         if conv_integer(cown) /= new_request then
319
            -- if idle state: turnaround cycle required by PCI standard
320
            cowni <= std_logic_vector(conv_unsigned(new_request, ARB_SIZE));
321
            touti <= "0000";                 -- reset timeout counter
322
            if turn = '0' then
323
               rearbi <= '1';           -- only one re-arbitration
324
            end if;
325
         end if;
326
      elsif frame_n = '1' then
327
         rearbi <= '0';
328
      end if;
329
 
330
      -- if frame deasserted, but request asserted: count timeout
331
      if req_n = all_ones then          -- no request: prepare timeout counter
332
         touti <= "1111";
333
      elsif frame_n = '1' then          -- request, but no transaction
334
         if tout = "1111" then              -- timeout expired, re-arbitrate
335
            turni <= '1';               -- remove grant, turnaround cycle
336
            touti <= "0000";                 -- next cycle re-arbitrate
337
         else
338
            touti <= tout + 1;
339
         end if;
340
      end if;
341
 
342
      grant : for i in 0 to NB_AGENTS-1 loop
343
         if i = conv_integer(cown) and turn = '0' then
344
            gnt_n(i) <= '0';
345
         else
346
            gnt_n(i) <= '1';
347
         end if;
348
      end loop grant;
349
 
350
      -- synchronous reset
351
      if rst_n = '0' then
352
         touti    <= "0000";
353
         cowni    <= (others => '0');
354
         owneri0  <= (others => '0');
355
         owneri1  <= (others => '0');
356
         rearbi   <= '0';
357
         turni    <= '0';
358
      end if;
359
 
360
   end process arbiter;
361
 
362
   arb_lvl(NB_AGENTS-1) <= '1';  -- always prio 1.
363
 
364
   fixed_prios : if not APB_PRIOS generate  -- assign constant value
365
      arb_lvl(NB_AGENTS-2 downto 0) <= ARB_LVL_C(NB_AGENTS-2 downto 0);
366
   end generate fixed_prios;
367
 
368
   -- Generate APB regs and APB slave
369
   apbgen : if APB_PRIOS generate
370
      -- purpose: APB read and write of arb_lvl configuration registers
371
      -- type:    memoryless
372
      -- inputs:  pbi, arb_lvl, prst_n
373
      -- outputs: pbo, arb_lvli
374
      config : process (pbi, arb_lvl, prst_n)
375
 
376
      begin  -- process config
377
         arb_lvli <= arb_lvl;
378
 
379
         pbo.PRDATA <= (others => '0');  -- default for unimplemented addresses
380
 
381
         -- register select at (byte-) addresses 0x80
382
         if pbi.PADDR(7 downto 0) = "10000000" and pbi.PSEL = '1' then -- address select
383
            if (pbi.PWRITE and pbi.PENABLE) = '1' then  -- APB write
384
                  arb_lvli <= pbi.PWDATA(NB_AGENTS-1 downto 0);
385
            end if;
386
            pbo.PRDATA(NB_AGENTS-1 downto 0) <= arb_lvl;
387
         end if;
388
         -- synchronous reset
389
         if prst_n = '0' then
390
            arb_lvli <= ARB_LVL_C;          -- assign default value
391
         end if;
392
      end process config;
393
 
394
      -- APB registers
395
 
396
      apb_regs : process (pclk)
397
      begin  -- process regs
398
         -- activities triggered by asynchronous reset (active low)
399
         if pclk'event and pclk = '1' then  -- '
400
            arb_lvl(NB_AGENTS-2 downto 0) <= arb_lvli(NB_AGENTS-2 downto 0);
401
         end if;
402
      end process apb_regs;
403
 
404
   end generate apbgen;
405
 
406
   -- PCI registers
407
 
408
   regs0 : process (clk)
409
 
410
   begin  -- process regs
411
      if clk'event and clk = '1' then  -- '
412
         tout    <= touti;
413
         owner0  <= owneri0;
414
         owner1  <= owneri1;
415
         cown    <= cowni;
416
         rearb   <= rearbi;
417
         turn    <= turni;
418
      end if;
419
   end process regs0;
420
 
421
end rtl;
422
 
423
 
424
 

powered by: WebSVN 2.1.0

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