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

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.hwp.communication/] [hibi/] [3.0/] [vhd/] [tx_control.vhd] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
-------------------------------------------------------------------------------
2
-- Title      : HIBI TX control
3
-- Project    : Nocbench, Funbase 
4
-- Description: TX controller for hibi
5
--
6
--              Arbitrates and forwards data to the bus from tx fifo (=from IP)
7
--              or CFG mem.
8
--              Reply to config mem read will only be sent at the
9
--              beginning of our turn, so it won't come out immediately.
10
--
11
-- File       : tx_control.vhd
12
-- Authors    : Antti Alhonen,
13
--              Lasse Lehtonen
14
-- Company    : Tampere University of Technology
15
-------------------------------------------------------------------------------
16
-- Last update: 2012-02-06
17
-- Standard   : VHDL'93
18
-- TO DO:
19
--              keep_slot_g,
20
--              dyn_arb_enable_c should be generic param
21
-------------------------------------------------------------------------------
22
-- Revisions  :
23
-- Date        Version  Author    Description
24
--
25
-- 2010-07-02  1.0      alho-nenä Created
26
-- Outputs data_out and fifo_re are now COMBINATORIAL. Only address has
27
-- to be registered because it needs to be retransferred if a transfer is
28
-- suspended and restarted. No retransferring is needed in case of FULL.
29
-- Output data mux is simple.
30
-- 
31
-- Old version had internal path of 7.0 ns + bus path of 7.8 ns on STRATIX II.
32
-- This version is much simpler and the combined path seems to be only 8.8 ns.
33
-- This version needs a version of rx_ctrl that has no combinatorial path from
34
-- comm_in to fifo_full.
35
--
36
-- 2010-10-13           ase       Added support for config mem reading
37
-- 2010-10-24           ase       Added support for SAD mode
38
--
39
-------------------------------------------------------------------------------
40
-------------------------------------------------------------------------------
41
-- Funbase IP library Copyright (C) 2011 TUT Department of Computer Systems
42
--
43
-- This file is part of HIBI
44
--
45
-- This source file may be used and distributed without
46
-- restriction provided that this copyright statement is not
47
-- removed from the file and that any derivative work contains
48
-- the original copyright notice and the associated disclaimer.
49
--
50
-- This source file is free software; you can redistribute it
51
-- and/or modify it under the terms of the GNU Lesser General
52
-- Public License as published by the Free Software Foundation;
53
-- either version 2.1 of the License, or (at your option) any
54
-- later version.
55
--
56
-- This source is distributed in the hope that it will be
57
-- useful, but WITHOUT ANY WARRANTY; without even the implied
58
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
59
-- PURPOSE.  See the GNU Lesser General Public License for more
60
-- details.
61
--
62
-- You should have received a copy of the GNU Lesser General
63
-- Public License along with this source; if not, download it
64
-- from http://www.opencores.org/lgpl.shtml
65
-------------------------------------------------------------------------------
66
 
67
library ieee;
68
use ieee.std_logic_1164.all;
69
use ieee.numeric_std.all;
70
 
71
use work.hibiv3_pkg.all;
72
 
73
entity tx_control is
74
 
75
  generic (
76
    counter_width_g : integer;
77
    id_width_g      : integer;
78
    data_width_g    : integer;
79
    addr_width_g    : integer;
80
    comm_width_g    : integer;
81
    n_agents_g      : integer;
82
    cfg_re_g        : integer;
83
    keep_slot_g     : integer;
84
    separate_addr_g : integer
85
    );
86
  port (
87
    clk   : in std_logic;
88
    rst_n : in std_logic;
89
 
90
    lock_in : in std_logic;
91
    full_in : in std_logic;
92
 
93
    cfg_ret_addr_in : in std_logic_vector(addr_width_g-1 downto 0);
94
    cfg_data_in     : in std_logic_vector
95
    (data_width_g-1-(separate_addr_g*addr_width_g) downto 0);
96
    cfg_re_in       : in std_logic;
97
 
98
    curr_slot_own_in    : in std_logic;
99
    curr_slot_ends_in   : in std_logic;
100
    next_slot_own_in    : in std_logic;
101
    next_slot_starts_in : in std_logic;
102
    max_send_in         : in std_logic_vector(counter_width_g-1 downto 0);
103
    n_agents_in         : in std_logic_vector(id_width_g-1 downto 0);
104
    prior_in            : in std_logic_vector(id_width_g-1 downto 0);
105
    -- 0 round-robin, 1 priority, 2 combined, 3 dyn_arb (rand)
106
    arb_type_in         : in std_logic_vector(1 downto 0);
107
 
108
    av_in    : in std_logic;
109
    data_in  : in std_logic_vector(data_width_g-1 downto 0);
110
    comm_in  : in std_logic_vector(comm_width_g-1 downto 0);
111
    one_d_in : in std_logic;
112
    empty_in : in std_logic;
113
 
114
    av_out         : out std_logic;
115
    data_out       : out std_logic_vector(data_width_g-1 downto 0);
116
    comm_out       : out std_logic_vector(comm_width_g-1 downto 0);
117
    lock_out       : out std_logic;
118
    cfg_rd_rdy_out : out std_logic;
119
    re_out         : out std_logic
120
    );
121
 
122
end tx_control;
123
 
124
 
125
architecture rtl of tx_control is
126
 
127
  -- Select arbitation type.
128
  -- Move to this to generic parameter!
129
  constant dyn_arb_enable_c : integer := 1;
130
 
131
  -- Internal signals and registers for arbitration
132
  signal prior_match         : std_logic;
133
  signal prior               : std_logic_vector(id_width_g-1 downto 0);
134
  signal dyn_arb_prior       : std_logic_vector(id_width_g-1 downto 0);
135
  signal prior_counter_arb_r : std_logic_vector(id_width_g-1 downto 0);
136
  signal arb_type_r          : std_logic_vector(1 downto 0);
137
  signal can_write_r         : std_logic;
138
  signal can_write_r_r       : std_logic;
139
  signal new_turn            : std_logic;  -- pulse when turn starts
140
  signal new_turn_stay_r     : std_logic;
141
  signal new_turn_ack        : std_logic;
142
  signal new_turn_ack_r      : std_logic;
143
 
144
  constant switch_arb_c : integer := 4096;  -- how often change between prior
145
                                            -- and round-robin, [cycles]
146
  signal   switch_arb_r : integer range 0 to switch_arb_c-1;
147
 
148
 
149
  -- Retransfer needs registers for storing one word tx
150
  signal addr_r           : std_logic_vector(addr_width_g-1 downto 0);
151
  signal comm_r           : std_logic_vector(comm_width_g-1 downto 0);
152
  signal data_r           : std_logic_vector(data_width_g-1 downto 0);
153
  signal tx_interrupted_r : std_logic;  -- for separate addr
154
  signal retransfer       : std_logic;  -- for separate addr
155
  signal retransfer_r     : std_logic;  -- for separate addr
156
 
157
  -- Keep track what we are doing and how many have been sent
158
  signal writing        : std_logic;    -- writing to bus
159
  signal reading        : std_logic;    -- reading the FIFO
160
  signal reading_r      : std_logic;
161
  signal send_counter_r : unsigned(counter_width_g-1 downto 0);  -- #words
162
  signal av_out_s       : std_logic;    -- combinatorial output (must be read also)
163
 
164
 
165
  -- Signals for responding to confg read operations
166
  signal cfg_rd_rdy_r      : std_logic;
167
  signal cfg_rd_ack        : std_logic;
168
  signal last_was_cfg_rd_r : std_logic;
169
  signal cfg_data_in_r     : std_logic_vector
170
    (data_width_g-1-(separate_addr_g*addr_width_g) downto 0);
171
 
172
 
173
  -- Dynamic Arbitration Algorithm is implemented with a separate component
174
  component dyn_arb
175
    generic (
176
      id_width_g : integer;
177
      n_agents_g : integer
178
      );
179
    port (
180
      clk           : in  std_logic;
181
      rst_n         : in  std_logic;
182
      bus_lock_in   : in  std_logic;
183
      arb_agent_out : out std_logic_vector(id_width_g-1 downto 0));
184
  end component;
185
 
186
 
187
begin  -- rtl
188
 
189
  av_out <= av_out_s;
190
 
191
  -----------------------------------------------------------------------------
192
  -- 1. CONFIG READ, rest affecting this can be found in connect_output process
193
  -----------------------------------------------------------------------------
194
  config_read_enabled : if cfg_re_g = 1 generate
195
 
196
    cfg_rd_rdy_out <= cfg_rd_rdy_r;
197
 
198
    cfg_rd_rdy_p : process (clk, rst_n) is
199
      variable cfg_rd_rdy_v : std_logic;
200
    begin  -- process cfg_rd_rdy_p
201
      if rst_n = '0' then               -- asynchronous reset (active low)
202
 
203
        cfg_rd_rdy_r      <= '1';
204
        last_was_cfg_rd_r <= '0';
205
        cfg_data_in_r     <= (others => '0');
206
 
207
      elsif clk'event and clk = '1' then  -- rising clock edge
208
 
209
        -- Block the rx ctrl from accessing config memory until reply has been sent
210
        if cfg_re_in = '1' then
211
          cfg_rd_rdy_v  := '0';
212
          cfg_data_in_r <= cfg_data_in;
213
        elsif cfg_rd_ack = '1' then
214
          cfg_rd_rdy_v := '1';
215
        else
216
          cfg_rd_rdy_v := cfg_rd_rdy_r;
217
        end if;
218
 
219
        cfg_rd_rdy_r <= cfg_rd_rdy_v;
220
 
221
        if separate_addr_g = 0 then
222
          last_was_cfg_rd_r <= cfg_rd_ack;
223
        else
224
          last_was_cfg_rd_r <= writing and not cfg_rd_rdy_v and new_turn_ack;
225
        end if;
226
 
227
 
228
      end if;
229
    end process cfg_rd_rdy_p;
230
 
231
  end generate config_read_enabled;
232
 
233
  config_read_disabled : if cfg_re_g = 0 generate
234
 
235
    cfg_rd_rdy_out    <= '1';
236
    last_was_cfg_rd_r <= '0';
237
    cfg_data_in_r     <= (others => '0');
238
 
239
  end generate config_read_disabled;
240
 
241
 
242
  -------------------------------------------------------------------------------
243
  -- 2. OLD VALUE REGISTERING 
244
  -------------------------------------------------------------------------------
245
  -- Old thingys (command, address and data) are needed when a transfer
246
  -- got interrupted and will be restarted later
247
 
248
  register_olds : process (clk, rst_n)
249
    variable tx_interrupted_v : std_logic;
250
  begin
251
    if rst_n = '0' then                 -- asynchronous reset (active low)
252
 
253
      can_write_r_r    <= '0';
254
      new_turn_ack_r   <= '0';
255
      new_turn_stay_r  <= '0';
256
      --addr_r <= (others => '0');
257
      --comm_r <= (others => '0');
258
      --data_r <= (others => '0');
259
      tx_interrupted_r <= '0';
260
      retransfer_r     <= '0';
261
      reading_r        <= '0';
262
 
263
    elsif clk'event and clk = '1' then  -- rising clock edge
264
 
265
      reading_r <= reading;
266
 
267
      -- Check if the previous transfer completed
268
      if separate_addr_g = 1 then
269
 
270
        retransfer_r <= retransfer;
271
 
272
        if reading_r = '1' and can_write_r_r = '1' and full_in = '1' then
273
          tx_interrupted_v := '1';
274
        elsif retransfer_r = '1' and full_in = '0' then
275
          tx_interrupted_v := '0';
276
        else
277
          tx_interrupted_v := tx_interrupted_r;
278
        end if;
279
 
280
        tx_interrupted_r <= tx_interrupted_v;
281
 
282
      else
283
        tx_interrupted_v := '0';
284
      end if;
285
 
286
 
287
      -- Multiplexed mode stores all the addresses, separate addr style onyl
288
      -- when interrupted
289
      if separate_addr_g = 0 and av_in = '1' and empty_in = '0' then
290
        addr_r <= data_in(addr_width_g-1 downto 0);
291
 
292
      elsif separate_addr_g = 1
293
        and tx_interrupted_v = '0' and full_in = '0' then
294
 
295
        data_r <= data_in;
296
        comm_r <= comm_in;
297
 
298
      end if;
299
 
300
 
301
      can_write_r_r  <= can_write_r;
302
      new_turn_ack_r <= new_turn_ack;
303
 
304
      -- The register new_turn_stay_r gets '1' when own turn starts. It returns to '0'
305
      -- when it's acknowledged by rising edge of new_turn_ack.
306
      if new_turn = '1' then
307
        new_turn_stay_r <= '1';
308
      end if;
309
 
310
      if new_turn_ack = '1' and new_turn_ack_r = '0' then
311
        new_turn_stay_r <= '0';
312
      end if;
313
 
314
    end if;
315
  end process register_olds;
316
 
317
  -------------------------------------------------------------------------------
318
  -- 3. Count how many words have been sent. No effect during TDMA slot, though.
319
  -------------------------------------------------------------------------------
320
  send_counting : process (clk, rst_n)
321
  begin  -- process send_counting
322
    if rst_n = '0' then                 -- asynchronous reset (active low)
323
      send_counter_r <= (others => '0');
324
    elsif clk'event and clk = '1' then  -- rising clock edge
325
      if writing = '1' and curr_slot_own_in = '0' then
326
        send_counter_r <= send_counter_r +1;
327
      else
328
        send_counter_r <= (others => '0');
329
      end if;
330
    end if;
331
  end process send_counting;
332
 
333
  -------------------------------------------------------------------------------
334
  -- 4. CHECK IF IT'S OUR TURN OR NOT
335
  -------------------------------------------------------------------------------
336
  -- Register can_write_r is up when it's our turn and we can take the bus
337
  evaluate_can_write : process (clk, rst_n)
338
  begin  -- process evaluate_can_write
339
    if rst_n = '0' then                 -- asynchronous reset (active low)    
340
      can_write_r <= '0';
341
 
342
    elsif clk'event and clk = '1' then  -- rising clock edge      
343
 
344
      can_write_r <= '0';
345
 
346
      if curr_slot_own_in = '1' then
347
        -- Own TDMA slot
348
        can_write_r <= '1';
349
 
350
      elsif can_write_r = '1' then
351
        -- We already have the turn, check if it ends or not
352
        can_write_r <= '1';
353
 
354
        -- Own turn ends, if max #words sent, own slot ends, another wrapper's
355
        -- slot starts, or 
356
        if (send_counter_r >= unsigned(max_send_in (counter_width_g-1 downto 0))
357
            and (av_out_s = '0' or separate_addr_g = 1))  -- 
358
          or ((curr_slot_own_in = '1' and curr_slot_ends_in = '1')  -- tdma slot ends
359
              or (next_slot_own_in = '0' and next_slot_starts_in = '1'))
360
          or (lock_in = '1' and writing = '0')  -- someone takes it
361
          or writing = '0'              -- we stop using it for some reason
362
        then
363
          can_write_r <= '0';
364
        end if;
365
 
366
      elsif prior_match = '1' and lock_in = '0' then
367
        -- We got a turn through competition reserving.
368
        if can_write_r = '0' and can_write_r_r = '0' then
369
          -- This condition prevents us from taking the bus again right away
370
          -- when we lost it.
371
          can_write_r <= '1';
372
        end if;
373
 
374
      end if;
375
 
376
    end if;
377
  end process evaluate_can_write;
378
 
379
 
380
  new_turn <= can_write_r and not can_write_r_r;
381
 
382
  -------------------------------------------------------------------------------
383
  -- 5. OUTPUT DATA MUX AND CONTROL
384
  -- 5a) MULTIPLEXED ADDRESS AND DATA BUSES
385
  -----------------------------------------------------------------------------
386
  norm_connect_output : if separate_addr_g = 0 generate
387
 
388
    connect_output : process (empty_in, new_turn, new_turn_stay_r, av_in,
389
                              comm_in, can_write_r, data_in, addr_r, full_in,
390
                              last_was_cfg_rd_r, cfg_rd_rdy_r, cfg_ret_addr_in,
391
                              cfg_data_in_r, new_turn_ack_r)
392
    begin
393
 
394
      new_turn_ack <= '0';              -- defaults
395
      cfg_rd_ack   <= '0';
396
      writing      <= '0';
397
      reading      <= '0';
398
      lock_out     <= '0';
399
 
400
      if cfg_rd_rdy_r = '0' and can_write_r = '1'
401
        and (new_turn = '1' or new_turn_stay_r = '1') then
402
        -- Send the config return address
403
 
404
        -- This branch should be optimized away when cfg_re_g == 0
405
        --  as condition will always be false
406
 
407
        av_out_s                          <= '1';
408
        comm_out                          <= MSG_WRNP_c;
409
        data_out                          <= (others => '0');
410
        data_out(addr_width_g-1 downto 0) <= cfg_ret_addr_in;
411
 
412
        if full_in = '0' then
413
          lock_out     <= '1';
414
          reading      <= '0';
415
          writing      <= '1';
416
          new_turn_ack <= '1';
417
        end if;
418
 
419
      elsif cfg_rd_rdy_r = '0' and new_turn_ack_r = '1'
420
        and can_write_r = '1' then
421
        -- Send the read config data
422
 
423
        -- This branch should be optimized away when cfg_re_g == 0
424
        --  as condition will always be false
425
 
426
        av_out_s <= '0';
427
        comm_out <= MSG_WRNP_c;
428
        data_out <= cfg_data_in_r;
429
 
430
        if full_in = '0' then
431
          reading    <= '0';
432
          writing    <= '1';
433
          cfg_rd_ack <= '1';
434
          lock_out   <= '1';
435
        end if;
436
 
437
      elsif empty_in = '0' and can_write_r = '1'
438
        and (new_turn = '1' or new_turn_stay_r = '1' or last_was_cfg_rd_r = '1')
439
      then
440
        -- We want to send some data, and we just* got our turn
441
        -- First we always send address
442
 
443
        --  *Reply to config read may have been sent already, if cfg_re_g == 1
444
 
445
 
446
        if full_in = '0' then
447
          writing      <= '1';
448
          lock_out     <= '1';
449
          new_turn_ack <= not last_was_cfg_rd_r;  -- don't ack if not necessary
450
        end if;
451
 
452
        if av_in = '1' then
453
          -- We have a new address in FIFO
454
          data_out <= data_in;
455
          if full_in = '0' then
456
            reading <= '1';
457
          end if;
458
        else
459
          -- Retransfer the old address from register, don't read fifo.
460
          data_out                          <= (others => '0');
461
          data_out(addr_width_g-1 downto 0) <= addr_r;
462
          reading                           <= '0';
463
        end if;
464
 
465
        av_out_s <= '1';
466
        comm_out <= comm_in;
467
 
468
 
469
      elsif empty_in = '0' and can_write_r = '1' then
470
        -- Just transfer the data.
471
        if full_in = '0' then
472
          writing  <= '1';
473
          lock_out <= '1';
474
          reading  <= '1';
475
        end if;
476
 
477
        data_out <= data_in;
478
        av_out_s <= av_in;
479
        comm_out <= comm_in;
480
 
481
      else
482
        -- Nothing to transfer.
483
        writing  <= '0';
484
        data_out <= (others => '0');
485
        lock_out <= '0';
486
        comm_out <= (others => '0');
487
        av_out_s <= '0';
488
        reading  <= '0';
489
 
490
 
491
      end if;
492
    end process connect_output;
493
 
494
  end generate norm_connect_output;
495
 
496
  -----------------------------------------------------------------------------
497
  -- 5. OUTPUT DATA MUX AND CONTROL
498
  -- 5b) SEPARATED ADDRESS AND DATA BUSES
499
  -----------------------------------------------------------------------------
500
  sad_connect_output : if separate_addr_g = 1 generate
501
 
502
    sad_connect_output : process (empty_in, new_turn, new_turn_stay_r, av_in,
503
                                  comm_in, can_write_r, data_in,
504
                                  full_in, last_was_cfg_rd_r, cfg_rd_rdy_r,
505
                                  cfg_ret_addr_in, cfg_data_in_r,
506
                                  tx_interrupted_r, data_r, comm_r)
507
    begin
508
 
509
      new_turn_ack <= '0';              -- defaults
510
      cfg_rd_ack   <= '0';
511
      retransfer   <= '0';
512
      writing      <= '0';
513
      lock_out     <= '0';
514
      reading      <= '0';
515
 
516
      if last_was_cfg_rd_r = '1' and full_in = '0' then
517
        cfg_rd_ack <= '1';
518
      end if;
519
 
520
      if cfg_rd_rdy_r = '0' and can_write_r = '1'
521
        and (new_turn = '1' or new_turn_stay_r = '1') then
522
        -- Send config return address
523
 
524
        -- This branch should be optimized away when cfg_re_g == 0
525
        --  as condition will always be false
526
 
527
        av_out_s <= '1';
528
 
529
        comm_out                                                  <= MSG_WRNP_c;
530
        data_out(data_width_g-1 downto data_width_g-addr_width_g) <=
531
          cfg_ret_addr_in;
532
        data_out(data_width_g-addr_width_g-1 downto 0) <=
533
          cfg_data_in_r;
534
 
535
        if full_in = '0' then
536
          reading      <= '0';
537
          writing      <= '1';
538
          new_turn_ack <= '1';
539
          lock_out     <= '1';
540
        end if;
541
 
542
      elsif (empty_in = '0' or tx_interrupted_r = '1') and can_write_r = '1'
543
        and (new_turn = '1' or new_turn_stay_r = '1' or last_was_cfg_rd_r = '1')
544
      then
545
        -- We want to send, and we just* got our turn
546
        --  *Reply to config read may have been sent already, if cfg_re_g == 1
547
 
548
        if full_in = '0' then
549
          writing      <= '1';
550
          lock_out     <= '1';
551
          new_turn_ack <= not last_was_cfg_rd_r;  -- don't ack if not necessary
552
        end if;
553
 
554
        if tx_interrupted_r = '1' then
555
          -- We need to retransfer the previous data(incl. addr)
556
          data_out <= data_r;
557
          comm_out <= comm_r;
558
          if full_in = '0' then
559
            reading    <= '0';
560
            retransfer <= '1';
561
          end if;
562
        else
563
          data_out <= data_in;
564
          comm_out <= comm_in;
565
          if full_in = '0' then
566
            reading <= '1';
567
          end if;
568
        end if;
569
 
570
        av_out_s <= '1';
571
 
572
 
573
      elsif empty_in = '0' and can_write_r = '1' then
574
        -- Just transfer the data.        
575
        data_out <= data_in;
576
        av_out_s <= av_in;
577
        comm_out <= comm_in;
578
 
579
        if full_in = '0' then
580
          writing  <= '1';
581
          lock_out <= '1';
582
          reading  <= '1';
583
        end if;
584
 
585
      else
586
        -- Nothing to transfer.
587
        writing  <= '0';
588
        data_out <= (others => '0');
589
        lock_out <= '0';
590
        comm_out <= (others => '0');
591
        av_out_s <= '0';
592
        reading  <= '0';
593
 
594
 
595
      end if;
596
    end process sad_connect_output;
597
 
598
  end generate sad_connect_output;
599
 
600
  re_out <= reading;
601
 
602
  -------------------------------------------------------------------------------
603
  -- 6. ARBITRATION SCHEMES
604
  -------------------------------------------------------------------------------
605
 
606
  -- Process Count_Priorities:
607
  -- Arbitration type depends port on arb_type_in:
608
  -- round-robin ("00"), priority ("01") and
609
  -- prior+round-robin ("10").
610
  -- Dynamic arbitration ("11") is done in a separate entity.
611
  Count_Priorities : process (clk, rst_n)
612
  begin  -- process Count_Priorities
613
    if rst_n = '0' then                 -- asynchronous reset (active low)
614
      prior_counter_arb_r <= (others => '0');
615
      switch_arb_r        <= 0;
616
      arb_type_r          <= (others => '0');
617
 
618
    elsif clk'event and clk = '1' then  -- rising clock edge
619
 
620
      -- Assign internal arb_type-register according to ctrl-signal coming from
621
      -- cfg_mem. 
622
      if arb_type_in = "00" then
623
        -- round-robin
624
        arb_type_r <= "00";
625
 
626
      elsif arb_type_in = "01" then
627
        -- priority, actually 01
628
        arb_type_r <= "01";
629
 
630
      elsif arb_type_in = "10" then
631
        -- prior+roundrob, "10"
632
 
633
        if switch_arb_r = switch_arb_c - 1 then
634
          switch_arb_r <= 0;
635
          arb_type_r   <= "0" & not arb_type_r (0);
636
 
637
        else
638
          switch_arb_r <= switch_arb_r + 1;
639
          arb_type_r   <= arb_type_r;
640
        end if;
641
 
642
      else
643
        arb_type_r <= "11";
644
      end if;  -- arb_type_in
645
 
646
 
647
      -- Increase priority_counter when bus is idle
648
      if lock_in = '0' and arb_type_r /= "11" then
649
 
650
        if prior_counter_arb_r = n_agents_in (id_width_g-1 downto 0) then
651
          -- Priorities rollover and start from 1 (zero is not allowed)
652
          prior_counter_arb_r <= std_logic_vector(to_unsigned(1, id_width_g));
653
        else
654
          prior_counter_arb_r <= std_logic_vector(unsigned(prior_counter_arb_r) +1);
655
        end if;
656
 
657
 
658
      else
659
        -- real arbitration types. now only prior + round rob
660
        if arb_type_r = "00" then
661
          -- In round-robin, priority remains the samem when
662
          -- bus reserved, 
663
          prior_counter_arb_r <= prior_counter_arb_r;
664
 
665
        elsif arb_type_r = "01" then
666
          -- In priority, priority counter starts over from 1 when bus gets reserved
667
          prior_counter_arb_r <= std_logic_vector(to_unsigned(1, id_width_g));
668
 
669
        else
670
          -- "lottery"
671
          -- counter is assigned below in separate process (inside if-generate)
672
          --          prior_counter_arb_r <= arb_agent_r;
673
        end if;
674
 
675
      end if;  -- lock & arb_type
676
    end if;  --rst_n      
677
 
678
  end process Count_Priorities;
679
 
680
  -- This component randomizes who gets the turn. Number of
681
  -- lottery tickets changes dynamically so that active units get more.
682
  -- This can be disabled to minimize area.
683
  dyn : if dyn_arb_enable_c = 1 generate
684
    dyn_arb_1 : dyn_arb
685
      generic map (
686
        id_width_g => id_width_g,
687
        n_agents_g => n_agents_g
688
        )
689
      port map (
690
        clk           => clk,
691
        rst_n         => rst_n,
692
        bus_lock_in   => lock_in,
693
        arb_agent_out => dyn_arb_prior
694
      );
695
 
696
  -- Select either counter value or one from dyn_arb
697
  assign_priocount : process (dyn_arb_prior, arb_type_in, prior_counter_arb_r)
698
    begin  -- process assign priocount
699
      if arb_type_in = "11" then
700
        prior <= dyn_arb_prior;
701
      else
702
        prior <= prior_counter_arb_r;
703
      end if;
704
    end process assign_priocount;
705
  end generate dyn;
706
 
707
  -- Check if own priority matches (=own turn begins)
708
  Check_Prior : process (prior_in, prior)
709
  begin
710
    if prior = prior_in (id_width_g-1 downto 0) then
711
      prior_match <= '1';
712
    else
713
      prior_match <= '0';
714
    end if;
715
  end process Check_Prior;
716
 
717
 
718
  notdyn : if dyn_arb_enable_c /= 1 generate
719
    assert arb_type_in /= "11"
720
      report "ERROR! ARB TYPE RANDOM BUT DYN ARB ENABLE = 0"
721
      severity failure;
722
    prior <= prior_counter_arb_r;
723
  end generate notdyn;
724
 
725
 
726
end rtl;

powered by: WebSVN 2.1.0

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