├── .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 | ![simplified_block](./docs/simplified_block.jpg) 18 | 19 | **TYPE=1 :** Modified rotating scheme. Pointer is updated according to the winning requester at the end of each arbitration. 20 | 21 | ![modified_block](./docs/modified_block.jpg) 22 | 23 | **TYPE=2 :** Weighted rotating scheme. Winning requested is chosen based on both the instantaneous weights status and the pointer location. 24 | 25 | ![weighted_block](./docs/weighted_block.jpg) 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 | ![simplified_sim](./docs/simplified_sim.jpg) 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 | ![simplified_sim_zoom](./docs/simplified_sim_zoom.jpg) 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 | ![simplified_teminal](./docs/simplified_teminal.jpg) 51 | 52 | 53 | ### Modified rotating scheme (N=10) 54 | 55 | ![modified_sim](./docs/modified_sim.jpg) 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 | ![weighted_sim](./docs/weighted_sim.jpg) 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 | ![weighted_sim_zoom](./docs/weighted_sim_zoom.jpg) 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}}<>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; 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; 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 | --------------------------------------------------------------------------------