Understanding Linear implementation of a round-robin arbiter - Page 1
Forum section: electronics / general

author: promach
author_rank: Frequent Contributor
timestamp: October 01, 2019, 09:56:52 am
content: ForEfficient microarchitecture for network-on-chip routers, do anyone know how this round-robin arbiter actually works ?Note: The corresponding verilog codes seem to be located atc_rr_arbiter_base.vandc_rr_arbiter.v

author: hamster_nz
author_rank: Super Contributor
timestamp: October 02, 2019, 06:48:07 am
content: The top box offers priority to the the next input after the last one granted.The the rest of the boxes are in a ring, and the first being request locks out the rest of the ring, until it gets back to the one being offered priority where the ring is broken.Quite nifty.

author: hamster_nz
author_rank: Super Contributor
timestamp: October 02, 2019, 07:17:01 am
content: Reset needs to be though through to ensure that one and only one bit is set in the 'who to offer to first' register, preventing the whole thing from latching up.

author: BrianHG
author_rank: Super Contributor
timestamp: October 02, 2019, 08:03:45 am
content: Damn that would have been useful a decade ago. I did it the hard way...I made a state machine. And I also required a 2 tier override priority for 2 specific sources.

author: RoGeorge
author_rank: Super Contributor
timestamp: October 02, 2019, 08:24:53 am
content: Quote from: promach on October 01, 2019, 09:56:52 amYou can visualize it as a round table with a moderator, where only one person is allowed to talk, and only for a certain amount of time. Then, the next person is allowed to talk, and so on. The moderator allows them to speak one by one, in circles around the table.What exactly was your question about? The idea, the schematic, or the HDL implementation?Later editNote: Using the words "Verilog code" is very misleading, better think about it as a Verilog circuit, or schematic diagram.

author: promach
author_rank: Frequent Contributor
timestamp: October 02, 2019, 12:17:18 pm
content: 1) What is the purpose of the OR and AND gates in the second box ?2) How is the above gate-level schematics different fromhttps://github.com/promach/noc/blob/master/arbiter.v?By the way, See waveform of myverilog codeimplementationCode:// Credit : https://www.reddit.com/r/FPGA/comments/dbr1xs/understanding_linear_implementation_of_a/module arbiter2 #(parameter WIDTH = 4) (clk, reset, req, grant);input clk, reset;input [WIDTH-1:0] req;output [WIDTH-1:0] grant;// 'grant' is one-hot vector, which means only one client request is granted/given green light to proceed// note that 'base' is one-hot vector,// 'base' signal helps round-robin arbiter to decide which 'req' to start servicingreg [WIDTH-1:0] base;always @(posedge clk)beginif(reset) base <= 1;else base <= (base[WIDTH-1]) ? 1 : (grant == 0) ? 1 : (grant << 1);endwire [WIDTH-1:0] priority_in;reg [WIDTH-1:0] priority_out;genvar index;generatefor(index = 0; index < WIDTH; index = index + 1)beginif(index > 0) assign priority_in = base | priority_out[index-1];else assign priority_in = base | priority_out[WIDTH-1];endendgenerateassign grant = (reset) ? 1 : req & priority_in;always @(posedge clk) priority_out <= (~req) & priority_in;`ifdef FORMALinitial assume(reset);reg first_clock_had_passed;initial first_clock_had_passed = 0;always @(posedge clk) first_clock_had_passed <= 1;always @(posedge clk) if(first_clock_had_passed && $past(first_clock_had_passed) && $past(first_clock_had_passed, 2) && $past(first_clock_had_passed, 3)) assume(req[WIDTH-1]); // ALL requests ON// covers the ability to handle requests properly even with ALL requests ONalways @(posedge clk) cover(first_clock_had_passed);`endifendmodule

author: promach
author_rank: Frequent Contributor
timestamp: October 03, 2019, 07:19:22 am
content: What is wrong with my updatedverilogcode that resulted in wrong waveform result ?Code:// Credit : https://www.reddit.com/r/FPGA/comments/dbr1xs/understanding_linear_implementation_of_a/module arbiter2 #(parameter WIDTH = 4) (clk, reset, req, grant);input clk, reset;input [WIDTH-1:0] req;output [WIDTH-1:0] grant;// 'grant' is one-hot vector, which means only one client request is granted/given green light to proceed// note that 'base' is one-hot vector,// 'base' signal helps round-robin arbiter to decide which 'req' to start servicingreg [WIDTH-1:0] base;always @(posedge clk)beginif(reset) base <= 1;else base <= (base[WIDTH-1]) ? 1 : (grant == 0) ? 1 : (grant << 1);endwire [WIDTH-1:0] priority_in;reg [WIDTH-1:0] priority_out;genvar index;generatefor(index = 0; index < WIDTH; index = index + 1)beginif(index > 0) assign priority_in = base | priority_out[index-1];else assign priority_in = base | priority_out[WIDTH-1];endendgenerateassign grant = (reset) ? 1 : req & priority_in;always @(posedge clk) priority_out <= (~req) & priority_in;`ifdef FORMALinitial assume(reset);reg first_clock_had_passed;initial first_clock_had_passed = 0;always @(posedge clk) first_clock_had_passed <= 1;always @(posedge clk) if(first_clock_had_passed && $past(first_clock_had_passed) && $past(first_clock_had_passed, 2) && $past(first_clock_had_passed, 3)) assume(&req); // ALL requests ON// covers the ability to handle requests properly even with ALL requests ONalways @(posedge clk) cover(first_clock_had_passed);`endifendmodule

author: hamster_nz
author_rank: Super Contributor
timestamp: October 03, 2019, 08:14:54 am
content: The way I read the orignal diagram, this bit feels wrong:Code:always @(posedge clk)beginif(reset) base <= 1;else base <= (base[WIDTH-1]) ? 1 : (grant == 0) ? 1 : (grant << 1);endSpecifically:(grant == 0) ? 1 : (grant << 1)That should be more like(grant == 0) ? base : { grant[WIDTH-2:0] , base[WIDTH-1] }Or how ever you do a rotate in Verilog.

author: hamster_nz
author_rank: Super Contributor
timestamp: October 03, 2019, 10:07:10 am
content: Warning: I don't do Verilog, so this code might be very poorly written.So this is that module in the picture, literally turned directly into Verilog:Code:`timescale 1ns / 1ps// Please credit Mike Field / hamster@snap.net.nzmodule arbit(input clk,input reset,input [7:0] request,output [7:0] grant);reg [7:0] granting = 8'b0;reg [7:0] first_offer = 8'b0;reg [7:0] available = 8'b0;reg [7:0] request_loop_in = 8'b0;reg [7:0] request_loop_out = 8'b0;assign grant = granting;always @(posedge clk)beginif(reset) beginfirst_offer = 1;end else beginif(granting != 0) beginfirst_offer = { granting[6:0], granting};endendend// This is yeachy async logic, that contains a loop, bit due to first_offer being// one-hot the the loop is always broken.always @(*) request_loop_in = { request_loop_out[6:0], request_loop_out};always @(*) available = request_loop_in | first_offer;always @(*) granting = available & request;always @(*) request_loop_out = available & ~request;endmoduleAnd attached is the simulation that confirms to me that it is working asIexpect and understand it should. It may not be working as you expect it will.If multiple requests are asserted at the same time it grants to the next highest, and wrapping back to zero.As I expected, the reset condition is particularly dodgy - should you have an 'X' it will propagate around the loop in the logic and turn the whole thing to custard.

author: promach
author_rank: Frequent Contributor
timestamp: October 03, 2019, 02:56:16 pm
content: QuoteThere is circular loop logic in your code...Besides, can I say thatfirst_offeris equivalent top[]?

author: hamster_nz
author_rank: Super Contributor
timestamp: October 03, 2019, 06:23:54 pm
content: Quote from: promach on October 03, 2019, 02:56:16 pmThat is the whole point. As there is a logic loop in the diagram, so there is a logic loop in the code.QuoteSure.

author: promach
author_rank: Frequent Contributor
timestamp: October 04, 2019, 02:00:48 am
content: Sorry but yosys synthesis tool just does not allow synthesis for code that contains circular loop ...

author: hamster_nz
author_rank: Super Contributor
timestamp: October 04, 2019, 02:49:48 am
content: Quote from: promach on October 04, 2019, 02:00:48 amDon't be sorry for that.From the diagram I could see that it is an interesting, useful piece of logic, that in practice actually works, but it was also apparent that due to the logic loop you would have difficulty to build it using standard FPGA/ASIC tools.You should have taken the time to read the very next block of text after figure 2.2. in the document you linked to:Commercially available timing analysis tools are typically unable to properly analyze circuits that contain combinational loops like the one generated by wrapping around the priority signals. This is particularly problematic when using a standard cell design flow, as it prevents synthesis from performing proper gate sizing.Which is exactly the problem you are facing.

author: promach
author_rank: Frequent Contributor
timestamp: October 04, 2019, 03:06:13 am
content: QuoteDo you have any practical workaround to get around this issue for synthesis tool ?

author: hamster_nz
author_rank: Super Contributor
timestamp: October 04, 2019, 03:15:23 am
content: Quote from: promach on October 04, 2019, 03:06:13 amReading the next sentence after the one quoted on Page 16 might be a very good place to start:We can avoid the combinational loop by severing the wraparound priority signal and connecting it to a chain of fixed-priority cells F as shown in Figure 2.32You don't seem very interested in the topic if you can't be bothered reading the relevant parts of the paperyoulinked to inyouroriginal post.

author: promach
author_rank: Frequent Contributor
timestamp: October 04, 2019, 04:11:33 am
content: QuoteWhat is actually thepurposeof the chain of fixed-priority cells F ?How does this chain actually help to eliminate the circular loop ?Update: I have just finished implementingfigure 2.3 in verilog codebelow :Code:// Credit : https://www.reddit.com/r/FPGA/comments/dbr1xs/understanding_linear_implementation_of_a/module arbiter2 #(parameter WIDTH = 4) (clk, reset, req, grant);input clk, reset;input [WIDTH-1:0] req;output [WIDTH-1:0] grant;// 'grant' is one-hot vector, which means only one client request is granted/given green light to proceed// note that 'base' is one-hot vector,// 'base' signal helps round-robin arbiter to decide which 'req' to start servicingreg [WIDTH-1:0] base;always @(posedge clk)beginif(reset) base <= 1;else base <= (base[WIDTH-1]) ? 1 : (grant == 0) ? base : { grant[WIDTH-2:0] , base[WIDTH-1] };endwire [WIDTH-1:0] priority_in;wire [(WIDTH << 1)-1:0] priority_out; // the two leftmost significant bit are left unusedwire [WIDTH-1:0] granting = req & priority_in;wire [WIDTH-1:0] approval; // the most significant bit is left unused, we only have (N-1) block Fgenvar index;generatefor(index = 0; index < WIDTH; index = index + 1)beginif(index == WIDTH-1) assign grant = granting;else assign grant = granting | approval;if(index > 0)beginassign priority_in = base | priority_out[index-1];assign approval = approval[index-1] & req;endelse beginassign priority_in = base;assign approval = priority_out[WIDTH-1] & req;endendendgenerategenvar priority_index;generatefor(priority_index = 0; priority_index < (WIDTH << 1); priority_index = priority_index + 1)begin : out_priorityif(priority_index < (WIDTH))assign priority_out = (~req) & priority_in;else assign priority_out = (~req[priority_index >> 1]) & priority_out[priority_index-1];endendgenerate`ifdef FORMALinitial assume(reset);reg first_clock_had_passed;initial first_clock_had_passed = 0;always @(posedge clk) first_clock_had_passed <= 1;always @(posedge clk) if(first_clock_had_passed && $past(first_clock_had_passed) && $past(first_clock_had_passed, 2) && $past(first_clock_had_passed, 3)) assume(&req); // ALL requests ON// covers the ability to handle requests properly even with ALL requests ONalways @(posedge clk) cover(first_clock_had_passed);`endifendmodule

author: hamster_nz
author_rank: Super Contributor
timestamp: October 04, 2019, 08:07:44 am
content: Taking it really slow...We have four 'things' trying to get granted access to a shared resource - CPUs accessing memory, people accessing a shower, whateverCall them 'A', 'B', 'C', and 'D'. We want to give them all fair access.So the following 'round robin' system is chosen:If 'A' last had access then the priorities will be 'B','C','D' and lowest will be 'A'If 'B' last had access then the priorities will be 'C','D','A' and lowest will be 'B'If 'C' last had access then the priorities will be 'D','A','B' and lowest will be 'C'If 'D' last had access then the priorities will be 'A','B','C' and lowest will be 'D'To make life simpler, rather than remembering who had the resource last, we will remember who has the highest priority.That is what figure 2.2 implements - the register in the top block holds who has priority to the resource, and the logic works out the new priorities.You end up with these patterns - when there are competing requests you take the first in the list, and set the highest priority to bethe next one after the one taken:Highest priority => complete list of priority, from highest to lowest.A => ABCDB => BCDAC => CDABD => DABCHopefully you follow me this far.The problem with the logic was the combinatorial loop caused by the priorities being reshuffled - the one that Verilator can't handle.Here's how that is solved.A N+(N-1) stage (7 stages where N = 4), fixed order arbiter is created, with the first N-1 being repeated.For our four resources the priority will be a never-changing "ABCDABC". What does change is that the first three stages can be disabled depending on who is the priority to the resource:A => ABCDABCB => -BCDABCC => --CDABCD => ---DABCYou end up with the same effective priority as the round robin, but you have fixed, unchanging priorities in the logic, and no loop.To make it clearer, the second repetition of a request has been removed (as the first one will always be granted as it has higher priority):A => ABCD---B => -BCDA--C => --CDAB-D => ---DABCThat is why in figure 2.3 the "request" lines for first N-1 inputs feed two blocks, and there are N-1 OR gates to merge the grant outputs.

author: promach
author_rank: Frequent Contributor
timestamp: October 04, 2019, 08:44:52 am
content: I need some time to digest your previous post just above.Could you comment on various ways ofdelay minimizationfor the gate schematics of Figure 2.3 ?Note: The PhD thesis author also pointed out another (besides figure 2.3) novel implementation ofFast Arbiters for On-Chip Network Switches

author: hamster_nz
author_rank: Super Contributor
timestamp: October 04, 2019, 09:48:10 am
content: Quote from: promach on October 04, 2019, 08:44:52 amThe opimization seems to be:Split the N+(N-1) arbiter in (almost) half, so our for a four input arbiter ABCDABC becomes ABCD and ABC,Calculate both halves independently - the second half is very simple to calculate as it doesn't have any dependency on the register that holds what signal was last granted:g = Ag = ~A & Bg = ~A & ~B & CAnd rather than using OR gates to combine g[2:0] with g[6:4], you must then use a 2:1 mux, selecting g[6:4] if the first four blocks of the arbiter haven't asserted an output.For an 4-input arbiter implemented as shown the critical path from the path though 7 blocks (maybe 14 gates) and an OR gateFor this enhanced version the delay is 4 blocks (maybe 8 gates) and a 2:1 mux.At least that is the gist of it - something like figure 3 inhttps://www.researchgate.net/publication/224371772_Fast_arbiters_for_on-chip_network_switches

author: hamster_nz
author_rank: Super Contributor
timestamp: October 05, 2019, 01:44:23 am
content: Literally a rainy day here so did some more experimentation, that will most likely only be of interest to me....When implemented in a Spartan6 FPGA, and implemented as per the acyclic diagram, a 4-input round-robin arbiter uses 14 LUTs and 4 flipflops.Implemented as below uses under half the logic resources (6 LUTs and 2 flipflops) - and is significantly faster too.Code:module arb2(input clk,input reset,input [3:0] request,output [3:0] grant);reg [5:0] lut_result;reg [1:0] hi_pri;assign grant = lut_result[3:0];always @(posedge clk)beginif(reset) beginhi_pri = 2'b0;end else beginhi_pri = lut_result[5:4];endendalways @(*)begincase ( { hi_pri, request } )// Verify this table yourself - it was manually generated!// request priority6'b000000: lut_result = 6'b000000;6'b000001: lut_result = 6'b010001;6'b000010: lut_result = 6'b100010;6'b000011: lut_result = 6'b010001;6'b000100: lut_result = 6'b110100;6'b000101: lut_result = 6'b010001;6'b000110: lut_result = 6'b100010;6'b000111: lut_result = 6'b010001;6'b001000: lut_result = 6'b001000;6'b001001: lut_result = 6'b010001;6'b001010: lut_result = 6'b100010;6'b001011: lut_result = 6'b010001;6'b001100: lut_result = 6'b110100;6'b001101: lut_result = 6'b010001;6'b001110: lut_result = 6'b110100;6'b001111: lut_result = 6'b010001;// request has priority6'b010000: lut_result = 6'b010000;6'b010001: lut_result = 6'b100001;6'b010010: lut_result = 6'b100010;6'b010011: lut_result = 6'b100010;6'b010100: lut_result = 6'b110100;6'b010101: lut_result = 6'b110100;6'b010110: lut_result = 6'b100010;6'b010111: lut_result = 6'b100010;6'b011000: lut_result = 6'b001000;6'b011001: lut_result = 6'b001000;6'b011010: lut_result = 6'b100010;6'b011011: lut_result = 6'b100010;6'b011100: lut_result = 6'b110100;6'b011101: lut_result = 6'b110100;6'b011110: lut_result = 6'b100010;6'b011111: lut_result = 6'b100010;// request has priority6'b100000: lut_result = 6'b100000;6'b100001: lut_result = 6'b010001;6'b100010: lut_result = 6'b100010;6'b100011: lut_result = 6'b010001;6'b100100: lut_result = 6'b110100;6'b100101: lut_result = 6'b110100;6'b100110: lut_result = 6'b110100;6'b100111: lut_result = 6'b110100;6'b101000: lut_result = 6'b001000;6'b101001: lut_result = 6'b001000;6'b101010: lut_result = 6'b001000;6'b101011: lut_result = 6'b001000;6'b101100: lut_result = 6'b110100;6'b101101: lut_result = 6'b110100;6'b101110: lut_result = 6'b110100;6'b101111: lut_result = 6'b110100;// request has priority6'b110000: lut_result = 6'b110000;6'b110001: lut_result = 6'b010001;6'b110010: lut_result = 6'b100010;6'b110011: lut_result = 6'b010001;6'b110100: lut_result = 6'b110100;6'b110101: lut_result = 6'b010001;6'b110110: lut_result = 6'b100010;6'b110111: lut_result = 6'b010001;6'b111000: lut_result = 6'b001000;6'b111001: lut_result = 6'b001000;6'b111010: lut_result = 6'b001000;6'b111011: lut_result = 6'b001000;6'b111100: lut_result = 6'b001000;6'b111101: lut_result = 6'b001000;6'b111110: lut_result = 6'b001000;6'b111111: lut_result = 6'b001000;default : lut_result = 6'b000000;endcaseendendmoduleOf course it doesn't scale well to wider arbiters, but is a perfect match for a LUT6 FPGA

author: promach
author_rank: Frequent Contributor
timestamp: October 05, 2019, 02:45:19 am
content: I really need some more time to understand your explanation on how the round-robin arbiter in the PhD thesis works.By the way, you were implementing it in pure lookup table which also resulted in thesameresource usage as my code in post above.Quote

author: promach
author_rank: Frequent Contributor
timestamp: October 05, 2019, 03:19:12 am
content: QuoteI do not understand why disabling the first three stages ?

author: hamster_nz
author_rank: Super Contributor
timestamp: October 05, 2019, 04:20:45 am
content: Quote from: promach on October 05, 2019, 03:19:12 amIf it has just granted a request to A, you now want 'B" to have the highest effective priority, so you disable the first stage, giving B the highest priority.If it has granted a request to B, you now want 'C" to have the highest effective priority, so you disable the first two stages, giving C the highest priority.If it has granted a request to C, you now want 'D" to have the highest effective priority, so you disable the first three stages, giving D the highest priority.If it has granted a request to D, you now want 'A" to have the highest effective priority, so you don't disable any, giving A the highest priority.

author: promach
author_rank: Frequent Contributor
timestamp: October 05, 2019, 04:22:49 am
content: QuoteAnd how does such disabling helps to eliminate the circular loop in figure 2.2 ?QuoteNo, note that the first block F requires Cnoutput from the Nth block R. Did you see that ?

author: hamster_nz
author_rank: Super Contributor
timestamp: October 05, 2019, 05:57:13 am
content: FIgure 2.2 has circular loops making it hard for tools to implement.That is why the scheme in figure 2.3 is used - to get rid of the loops.So how do you get rid of the loops in figure 2.2? You implement the functionally equivilent design that is in shown in figure 2.3!(have I been secretly become trapped into a piece of performance art? Some avant garde trolling?)

author: promach
author_rank: Frequent Contributor
timestamp: October 05, 2019, 06:02:36 am
content: Sorry , I will need to study figure 2.3 on my own then.I am not doing any trolling here. Sorry again.I am actually doing a personal research study on round-robin arbiter, hence what you meant by performance art.

author: hamster_nz
author_rank: Super Contributor
timestamp: October 06, 2019, 10:16:23 am
content: Quote from: promach on October 05, 2019, 06:02:36 amSorry if I was a bit short - just wanted to say thanks because it got me to do my first FPGA project for a while, a 4-input Arbiter with two different modes:http://hamsterworks.co.nz/mediawiki/index.php/Arbiter

author: promach
author_rank: Frequent Contributor
timestamp: October 22, 2019, 02:46:57 pm
content: I have justformally verifiedthe arbiter architecture (Figure 2.3) given in the thesis.TODO :1. Add more assert() formal coding for round-robin capability check2. Investigate ways to reduce tcombdelay as described at theend of section 2.3 of the thesis3. Includes the core ideas fromFast Arbiters for On-Chip Network SwitchesCode:// Credit : https://www.eevblog.com/forum/fpga/understanding-linear-implementation-of-a-round-robin-arbiter/module arbiter2 #(parameter WIDTH = 4) (clk, reset, req, grant);input clk, reset;input [WIDTH-1:0] req;output [WIDTH-1:0] grant;// 'grant' is one-hot vector, which means only one client request is granted/given green light to proceed// note that 'base' is one-hot vector,// 'base' signal helps round-robin arbiter to decide which 'req' to start servicingreg [WIDTH-1:0] base;always @(posedge clk)beginif(reset) base <= 1;else base <= (grant[WIDTH-1]) ? 1 : (grant == 0) ? base : ( grant << 1 );endwire [WIDTH-1:0] priority_in;wire [(WIDTH << 1)-1:0] priority_out; // the two leftmost significant bit are left unusedwire [WIDTH-1:0] granting = req & priority_in;wire [WIDTH-2:0] approval; // we only have (WIDTH-1) block Fgenvar index;generatefor(index = 0; index < WIDTH; index = index + 1)beginif(index == WIDTH-1) assign grant = (reset) ? 0 : granting;else assign grant = (reset) ? 0 : ( granting | approval );if(index < (WIDTH-1)) assign approval = ( priority_out[index+WIDTH-1] & req );if(index > 0) assign priority_in = ( base | priority_out[index-1] );else assign priority_in = base;endendgenerategenvar priority_index;generatefor(priority_index = 0; priority_index < (WIDTH << 1); priority_index = priority_index + 1)begin : out_priorityif(priority_index < (WIDTH))assign priority_out = (~req) & priority_in;else assign priority_out = (~req[priority_index-WIDTH]) & priority_out[priority_index-1];endendgenerate`ifdef FORMALinitial assume(reset);initial assume(req == 0); // only enable this assume() to test the cover() at line 100 properlygenvar grant_num;generatefor(grant_num = 0; grant_num < WIDTH; grant_num = grant_num + 1)always @(*)cover(first_clock_had_passed && grant); // covers grants to each of the clients' requestendgeneratereg [WIDTH-1:0] req_previous;always @(posedge clk) req_previous <= req;always @(posedge clk) cover(!$past(reset) && (grant == 0)); // covers the ability to go to an idle state// covers the ability to handle requests properly even with ALL requests ONalways @(posedge clk) cover((&$past(req_previous)) && (&$past(req)) && (&req) && first_clock_had_passed && $past(first_clock_had_passed) && ((grant & $past(req)) == grant));reg [WIDTH-1:0] grant_previous;always @(posedge clk) grant_previous <= grant;always @(posedge clk) cover(grant != grant_previous); // covers the ability to switch grants to any other requestsalways @(posedge clk) cover(first_clock_had_passed && $past(first_clock_had_passed) && (&req) && (req_previous == 4'b1100) && ($past(req_previous) == 4'b1011)); // covers round-robin ability`endif`ifdef FORMALreg first_clock_had_passed;initial first_clock_had_passed = 0;always @(posedge clk) first_clock_had_passed <= 1;// https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2wire grant_is_one_hot = (grant != 0) && ((grant & (grant - 1)) == 0);wire base_is_one_hot = (base != 0) && ((base & (base - 1)) == 0);// assertions for round-robin capabilityalways @(*)beginif(reset) assert(grant == 0);else beginif (|req) assert(grant_is_one_hot);else assert(grant == 0);endendalways @(posedge clk)beginif(first_clock_had_passed)begin// starts round-robin arbiter with req #0 getting prioritized firstif($past(reset)) assert(base == 1);// 'grant' is a one-hot signal, but 'req' is not a one-hot signal// 'base' is a one-hot signal which rotates// after the corresponding 'req' had been granted/given permission to proceed)// Rotation wraps around upon reaching MSBelse beginassert(base == $past(grant[WIDTH-1]) ? 1 : ($past(grant) == 0) ? $past(base) : ($past(grant) << 1) );assert(base_is_one_hot);endendendgenvar f_index;generatefor(f_index = 0; f_index < WIDTH; f_index = f_index + 1)beginalways @(*)beginif(reset) assert( grant == 0 );else beginif(f_index == WIDTH-1) assert( grant == granting );else assert( grant == ( granting | approval ) );endif(f_index < (WIDTH-1)) assert( approval == ( priority_out[f_index+WIDTH-1] & req ));if(f_index > 0) assert( priority_in == (base | priority_out[f_index-1] ));else assert( priority_in == base );endendendgenerategenvar f_priority_index;generatefor(f_priority_index = 0; f_priority_index < (WIDTH << 1); f_priority_index = f_priority_index + 1)begin : out_priorityalways @(*)beginif(f_priority_index < (WIDTH))assert( priority_out ==((~req) & priority_in) );else assert( priority_out ==((~req[f_priority_index-WIDTH]) & priority_out[f_priority_index-1]) );endendendgenerate`endifendmodule

author: promach
author_rank: Frequent Contributor
timestamp: March 13, 2020, 03:33:52 am
content: ForFast Arbiters for On-Chip Network Switches, what do you guys understand byGPandGR?