├── .DS_Store
├── .gitattributes
├── docs
├── modified_block.jpg
├── modified_sim.jpg
├── simplified_sim.jpg
├── weighted_block.jpg
├── weighted_sim.jpg
├── simplified_block.jpg
├── simplified_sim_zoom.jpg
├── simplified_teminal.jpg
└── weighted_sim_zoom.jpg
├── README.md
├── round_robin.sv
└── round_robin_TB.sv
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/.DS_Store
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/docs/modified_block.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/docs/modified_block.jpg
--------------------------------------------------------------------------------
/docs/modified_sim.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/docs/modified_sim.jpg
--------------------------------------------------------------------------------
/docs/simplified_sim.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/docs/simplified_sim.jpg
--------------------------------------------------------------------------------
/docs/weighted_block.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/docs/weighted_block.jpg
--------------------------------------------------------------------------------
/docs/weighted_sim.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/docs/weighted_sim.jpg
--------------------------------------------------------------------------------
/docs/simplified_block.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/docs/simplified_block.jpg
--------------------------------------------------------------------------------
/docs/simplified_sim_zoom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/docs/simplified_sim_zoom.jpg
--------------------------------------------------------------------------------
/docs/simplified_teminal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/docs/simplified_teminal.jpg
--------------------------------------------------------------------------------
/docs/weighted_sim_zoom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tom-urkin/Round-Robin/HEAD/docs/weighted_sim_zoom.jpg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Round Robin Arbiter
2 |
3 | > SystemVerilog Round Robin arbiter
4 |
5 | ## Get Started
6 |
7 | The source files are located at the repository root:
8 |
9 | - [Round Robin arbiter module](./round_robin.sv)
10 | - [Round Robin arbiter TB](./round_robin_TB.sv)
11 |
12 | ##
13 | This repository containts a SystemVerilog implementation of a parametrized Round Robin arbiter with three instantiation options:
14 |
15 | **TYPE=0 :** Conventional rotating scheme. Pointer is increased by one after each arbitration.
16 |
17 | 
18 |
19 | **TYPE=1 :** Modified rotating scheme. Pointer is updated according to the winning requester at the end of each arbitration.
20 |
21 | 
22 |
23 | **TYPE=2 :** Weighted rotating scheme. Winning requested is chosen based on both the instantaneous weights status and the pointer location.
24 |
25 | 
26 |
27 | ## Testbench
28 | In the following testbenches the following variables were randomized:
29 | 1. enable signal - Arbitration is carried only when the enable signal is logic high at the capturing clock edge (rising).
30 | 2. request vector - N-bit request vector is generated and routed to both the arbiter module as well as the verification logic.
31 |
32 | ### Conventional rotating scheme (N=8)
33 |
34 | 
35 |
36 | As can be seen, when the enable signal is logic high at the rising edge of the clock a new request vector is generated and arbitration is carried. Since this is a standard circular realization, the 'priority' vector (marked in red) changes in a circular manner.
37 |
38 | 
39 |
40 | **Examplary events marked on the zoom-in figure:**
41 | 1) Arbitration is not carrried since the enable signal is logic low
42 | 2) The enable signal is logic high, therefore arbitration is carried. The pointer's value is '4', however only req[1] is logic high and therefore the grant vector matched the request vector.
43 | 3) The enable signal is logic high, therefore arbitration is carried. The pointer's value is '5' but req[5] is logic low (i.e. the requester with the instantaneous priority does not request access to the shared resource) the access is given to the next in line which is requester '6'.
44 | 4) Arbitration is not carrried since the enable signal is logic low
45 | 5) The enable signal is logic high, therefore arbitration is carried. The pointer's value is '6' and req[6] is logic high, therefore the requester with the instanteous priority is given access to the shared resource.
46 | 6) Please note that the pointer value is updated to '0' for the 8-requesters scenario shown here.
47 |
48 | Please run the testbench and observe the teminal messages for in-depth understanding, for example:
49 |
50 | 
51 |
52 |
53 | ### Modified rotating scheme (N=10)
54 |
55 | 
56 |
57 | As can be seen, when the enable signal is logic high at the rising edge of the clock a new request vector is generated and arbitration is carried. In this realization, the priority pointer is updated according to the arbitration outcome. Please see the block diagram above.
58 |
59 | **Examplary events marked on the zoom-in figure:**
60 | 1) Arbitration is not carrried since the enable signal is logic low
61 | 2) The pointer's value is '0' and req[0] is logic high. Therefore, requester '0' is granted access and the pointer is updated to '1'
62 | 3) Arbitration is not carrried since the enable signal is logic low
63 | 4) The pointer's value is '3' but this requester does not request access. Therefore the next in line is granted, i.e. requester number '4'. The pointer is updated to '5', i.e. the winning requester incremented by 1.
64 |
65 | Please run the testbench and observe the teminal messages for in-depth understanding using the log messages.
66 |
67 | ### Weighted rotating scheme (N=10)
68 |
69 | 
70 |
71 | As can be seen, when the enable signal is logic high at the rising edge of the clock a new request vector is generated and arbitration is carried. In this realization, the priority pointer is updated according to the arbitration outcome which considers both the pointer location and the weight vector status (please see the block diagram above). Marked on the timing diagram is a weight vector update event.
72 |
73 | 
74 |
75 | For better understading two arbitration events are discussed here in detail.
76 |
77 | **Case '1'**
78 | Request vector : 1-1-0-1-0-1-1-0-1-0
79 | Weight vector : 2-4-3-5-4-0-6-2-5-7
80 | Masked vector : 2-4-0-5-0-0-6-0-5-0
81 | Max : 6
82 | Internal request vector : 0-0-0-0-0-0-1-0-0-0
83 |
84 | The internal request vector is then processed by the same logic as in 'modified RR' case to produce the grant vector which is : 0-0-0-0-0-0-1-0-0-0.
85 | After the arbitration event the weight status is updated and the winning requester weight is decreased (requester number 3) from 6-->5.
86 |
87 | **Case '2'**
88 | Request vector : 0-1-0-1-0-1-1-1-1-1
89 | Weight vector : 2-4-3-5-4-0-5-2-5-6
90 | Masked vector : 0-4-0-5-0-0-5-2-5-6
91 | Max : 6
92 | Internal request vector : 0-0-0-0-0-0-0-0-0-1
93 |
94 | The internal request vector is then processed by the same logic as in 'modified RR' case to produce the grant vector which is : 0-0-0-0-0-0-1-0-0-0.
95 | After the arbitration event the weight status is updated and the winning requester weight is decreased (requester number 3) from 6-->5.
96 |
97 | Please run the testbench and observe the teminal messages for in-depth understanding using the log messages.
98 |
99 | ## Support
100 |
101 | I will be happy to answer any questions.
102 | Approach me here using GitHub Issues or at tom.urkin@gmail.com
--------------------------------------------------------------------------------
/round_robin.sv:
--------------------------------------------------------------------------------
1 | //Round Robin arbiter module
2 | //TYPE==0 : Conventional RR arbitration : pointer is increased by one after each arbitration
3 | //TYPE==1 : Modified RR arbitration : pointer is updated according to the winning requester
4 | //TYPE==2 : Weighted RR arbitration : arbitration is carried with respect to the instantaneous weight vectors. Pointer update scheme follows modified Round Robin arbitration logic.
5 | module round_robin(i_clk,i_rstn,i_en,i_req,i_load,i_weights,o_gnt);
6 |
7 | //Parameters
8 | parameter N=8; //Number of requesters
9 | parameter TYPE = 1; //Arbitration logic (see above description)
10 | parameter W =3; //Width of weight counters. Each requester may be assigned up to 2**W 'priority tokens' ('0' is the lowest priority, 2**W-1 is the highest priority)
11 | localparam M = $clog2(N); //log2 of N, required width of the pointer signal
12 | //Inputs
13 | input logic i_clk; //RR arbiter clock
14 | input logic i_rstn; //RR arbiter reset signal (active high)
15 | input logic i_en; //Arbitration takes place only when the enable signal is logic high (i.e. not carried every clock edge)
16 | input logic [N-1:0] i_req; //Request vector
17 | input logic i_load; //Pulse shaped input signal. Weights vector is loaded when logic high.
18 | input logic [N-1:0] [W-1:0] i_weights; //Internal registers holding the instantaneous priority order. Each requester has an W-bit register assigned to it.
19 |
20 | //Outputs
21 | output logic [N-1:0] o_gnt; //Output grant vector
22 |
23 | //Internal signals
24 | logic [M-1:0] ptr; //Round Robitn arbitration pointer
25 | logic [N-1:0] tmp_r, tmp_l, rotate_r; //Temporary and internal signals used in the Rotate-Priority_Rotate scheme
26 | logic [N-1:0] priority_out; //Priority logic result
27 | logic [M-1:0] ptr_arb; //Holds the winning requester index (basically an encoding operation on gnt)
28 | logic [N-1:0] gnt; //Combinatorial calculation of the grant vector (continious)
29 |
30 |
31 | logic [N-1:0] [W-1:0] weight_counters; //Each requester is assigned a counter that holds its 'priority tokens'
32 | logic [N-1:0] [W-1:0] masked; //Holds the 'priority tokens' values for each requesting requester
33 | logic [N-1:0] req_w; //An internal request vector obtained by considerign both the priority status and the input request signal
34 | logic [W-1:0] max; //Holds the maximal weight between all requesting requesters.
35 |
36 | //HDL body
37 | generate
38 |
39 | //------Conventional RR arbitration---//
40 | if (TYPE==0) begin
41 | //Rotate right
42 | assign {tmp_r,rotate_r} = {2{i_req}}>>ptr;
43 |
44 | //Priority encoder logic
45 | assign priority_out = rotate_r&~(rotate_r-1);
46 |
47 | //Rotate left
48 | assign {gnt,tmp_l} = {2{priority_out}}<>ptr;
69 |
70 | //Priority encoder logic
71 | assign priority_out = rotate_r&~(rotate_r-1);
72 |
73 | //Rotate left
74 | assign {gnt,tmp_l} = {2{priority_out}}<max)
114 | max=masked[i];
115 | end
116 |
117 | always @(*) begin
118 | req_w='0;
119 | for (int i=0; i>ptr;
128 |
129 | //Priority logic
130 | assign priority_out = rotate_r&~(rotate_r-1);
131 |
132 | //Rotate left
133 | assign {gnt,tmp_l} = {2{priority_out}}<0)) //update winning counter only if arbitration has occured and the counter is not 0 (lowest value)
153 | weight_counters[ptr_arb]<=weight_counters[ptr_arb]-1;
154 |
155 | if (i_en) begin
156 | if (ptr_arb==N-1)
157 | ptr<='0;
158 | else
159 | ptr<=ptr_arb+$bits(ptr_arb)'(1);
160 | o_gnt<=gnt;
161 | end
162 | end
163 |
164 | end
165 |
166 | endgenerate
167 |
168 | endmodule
--------------------------------------------------------------------------------
/round_robin_TB.sv:
--------------------------------------------------------------------------------
1 | //Round Robin arbiter TB
2 | module round_robin_TB();
3 | //Parameters
4 | parameter CLK_PERIOD = 20; //Clock period
5 | parameter N = 10; //Number of requesters
6 | parameter W = 3; //Width of weight counters. Each requester may be assigned up to 2**W 'priority tokens' ('0' is the lowest priority, 2**W-1 is the highest priority)
7 | localparam M = $clog2(N); //log2 of N, required width of the pointer signal
8 | parameter TYPE = 2; //Arbitration scheme select parameter (please see the arbiter module for more details)
9 |
10 | //Internal signals
11 | logic clk; //RR arbiter clock
12 | logic rstn; //RR arbiter reset signal (active high)
13 | logic en_rand; //Arbitration takes place only when the enable signal is logic high (i.e. not carried every clock edge)
14 | logic load_weights; //Pulse shaped input signal. Weights vector is loaded when logic high (for WRR scheme).
15 | logic [N-1:0] [W-1:0] weights; //weights hold the instantaneous priority order. Each requester has an W-bit register assigned to it (for WRR scheme).
16 | logic [N-1:0] req; //Request vector supplied to the RR arbiter module
17 | logic [N-1:0] gnt; //Grant vector produced by the RR arbiter module
18 |
19 | logic [M-1:0] ptr_ver; //Round Robin pointer calculated in the verification environment
20 | logic [M-1:0] ptr_tmp; //Temporary pointer used in the ptr_ver clculations
21 | logic [N-1:0] gnt_ver; //Grant vector calculated in the verification environment for comparison purposes
22 |
23 | logic [N-1:0] [W-1:0] weights_mim; //Mimic priority order for verification
24 | logic [N-1:0] [W-1:0] masked_mim; //Mimic masked vector for verification
25 | logic [W-1:0] max_mim; //Max value of the masked_mimic vector
26 | logic [N-1:0] req_w_mim; //Internally generated request vector in the verification environment
27 |
28 | integer SEED=18; //Used as the seed for the randomization tasks
29 | //Round Robin arbiter intsntiation
30 | round_robin #(.N(N), .W(W), .TYPE(TYPE)) rr_tst(
31 | .i_clk(clk),
32 | .i_rstn(rstn),
33 | .i_en(en_rand),
34 | .i_req(req),
35 | .i_load(load_weights),
36 | .i_weights(weights),
37 | .o_gnt(gnt)
38 | );
39 |
40 | //Initial block
41 | initial begin
42 | //Initializations
43 | clk=1'b0;
44 | rstn=1'b0;
45 | ptr_ver='0;
46 | gnt_ver='0;
47 | en_rand=1'b0;
48 |
49 | load_weights=1'b0;
50 | weights_mim='0;
51 |
52 | //Exit from reset mode
53 | @(posedge clk)
54 | rstn=1'b1;
55 |
56 |
57 | //------Conventional RR arbitration---//
58 | if (TYPE==0) begin
59 | $display("Initiate test - conventional Round Robin arbiter \n");
60 |
61 | for(int k=0; k<50; k++) begin
62 |
63 | if (en_rand==1'b1) begin
64 | req= $dist_uniform(SEED,0,2**N-1); //Randomize the N-bit long requesting vector
65 | $display("Randomized request vector is %b", req);
66 |
67 | @(posedge clk)
68 |
69 | gnt_ver='0;
70 | ptr_tmp=ptr_ver;
71 |
72 | //Calculating the grant vector for comparison with the round_robin module 'gnt' signal
73 | if (req[ptr_ver]==1'b1)
74 | gnt_ver[ptr_ver]=1'b1;
75 | else begin
76 | for (int i=ptr_ver-1; i>=0; i--)
77 | if (req[i]==1'b1)
78 | ptr_tmp=i;
79 |
80 | for (int i=N-1; i>ptr_ver; i--)
81 | if (req[i]==1'b1)
82 | ptr_tmp=i;
83 |
84 | gnt_ver[ptr_tmp] = req[ptr_tmp];
85 | end
86 |
87 | if (ptr_ver==N-1)
88 | ptr_ver='0;
89 | else
90 | ptr_ver=ptr_ver+$bits(ptr_ver)'(1); //In conventional RR the pointer is increased by one in a cyclic manner regardless of the arbitration result
91 |
92 | en_rand= $dist_uniform(SEED,0,1);
93 |
94 | @(negedge clk)
95 | if (gnt==gnt_ver) //Comparing the two grant vectors
96 | $display("Grant vector is %b. Verification grant vector is %b. SUCCESS!\n", gnt, gnt_ver);
97 | else begin
98 | $display("Grant vector is %b. Verification grant vector is %b. FAILURE!\n", gnt, gnt_ver);
99 | $finish;
100 | end
101 |
102 | end
103 | else begin //Do not execute arbitration if the enable signal is logic low
104 | @(posedge clk);
105 | en_rand= $dist_uniform(SEED,0,1);
106 | end
107 | end
108 | en_rand=1'b0;
109 | $display("End of conventional Round Robin Arbiter verification - SUCCESS");
110 | end
111 |
112 | //------Modified RR arbitration-------//
113 | if (TYPE==1) begin
114 | $display("Initiate test - modified Round Robin arbiter \n");
115 |
116 | for(int k=0; k<400; k++) begin
117 |
118 | if (en_rand==1'b1) begin
119 | req=$dist_uniform(SEED,0,2**N-1); //Randomize the N-bit long requesting vector
120 | $display("Randomized request vector is %b", en_rand);
121 |
122 | @(posedge clk);
123 |
124 | gnt_ver='0;
125 | ptr_tmp=ptr_ver;
126 |
127 | //Calculating the grant vector for comparison with the round_robin module 'gnt' signal
128 | if (req[ptr_ver]==1'b1)
129 | gnt_ver[ptr_ver]=1'b1;
130 | else begin
131 | for (int i=ptr_ver-1; i>=0; i--)
132 | if (req[i]==1'b1)
133 | ptr_tmp=i;
134 |
135 | for (int i=N-1; i>ptr_ver; i--)
136 | if (req[i]==1'b1)
137 | ptr_tmp=i;
138 |
139 | gnt_ver[ptr_tmp] = req[ptr_tmp];
140 | end
141 |
142 | for (int i=0; imax_mim)
207 | max_mim=masked_mim[i];
208 |
209 | req_w_mim='0;
210 | for (int i=0; i=0; i--)
220 | if (req_w_mim[i]==1'b1)
221 | ptr_tmp=i;
222 |
223 | for (int i=N-1; i>ptr_ver; i--)
224 | if (req_w_mim[i]==1'b1)
225 | ptr_tmp=i;
226 |
227 | gnt_ver[ptr_tmp] = 1'b1;
228 | end
229 |
230 | if (ptr_tmp==N-1)
231 | ptr_ver='0;
232 | else
233 | ptr_ver=ptr_tmp+$bits(ptr_tmp)'(1);
234 |
235 | if (load_weights==1'b1)
236 | weights_mim=weights;
237 | else if ((en_rand==1'b1)&&(|gnt_ver)&&(weights_mim[ptr_tmp]>0))
238 | weights_mim[ptr_tmp]=weights_mim[ptr_tmp]-1;
239 |
240 | en_rand= $dist_uniform(SEED,0,1);
241 |
242 | //Compare to verification
243 | @(negedge clk)
244 | if (gnt==gnt_ver) //Comparing the two grant vectors
245 | $display("Grant vector is %b. Verification grant vector is %b. SUCCESS!\n", gnt, gnt_ver);
246 | else begin
247 | $display("Grant vector is %b. Verification grant vector is %b. FAILURE at time %t!\n", gnt, gnt_ver, $realtime);
248 | $finish;
249 | end
250 | end
251 | else begin //Do not execute arbitration if the enable signal is logic low
252 | @(posedge clk);
253 | if (load_weights==1'b1)
254 | weights_mim=weights;
255 | en_rand= $dist_uniform(SEED,0,1);
256 | end
257 |
258 | end
259 |
260 | en_rand=1'b0;
261 | $display("End of weighted Round Robin Arbiter verification - SUCCESS");
262 | end
263 |
264 | end //End of initial block
265 |
266 | //Clock generation
267 | always
268 | begin
269 | #(CLK_PERIOD/2);
270 | clk=~clk;
271 | end
272 |
273 |
274 | endmodule
275 |
--------------------------------------------------------------------------------