URL
https://opencores.org/ocsvn/scalable_arbiter/scalable_arbiter/trunk
Subversion Repositories scalable_arbiter
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/trunk/bench/verilog/tb_arbiter.txt
File deleted
\ No newline at end of file
/trunk/bench/verilog/tb_arbiter2.txt
File deleted
\ No newline at end of file
/trunk/bench/verilog/tb_arbiter.v
File deleted
/trunk/bench/verilog/tb_abrbiter2.v
File deleted
/trunk/rtl/verilog/stretcher.v
File deleted
/trunk/rtl/verilog/shifter.v
File deleted
/trunk/rtl/verilog/debouncer.v
File deleted
/trunk/rtl/verilog/arbiter.v
File deleted
/trunk/rtl/verilog/functions.v
File deleted
\ No newline at end of file
/trunk/rtl/verilog/pulser.v
File deleted
/trunk/rtl/verilog/demo_arbiter.v
File deleted
/trunk/rtl/verilog/demo_filters.v
File deleted
/trunk/doc/arbiter_diagram.odg
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
trunk/doc/arbiter_diagram.odg
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: trunk/doc/arbiter_diagram.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: trunk/doc/arbiter_diagram.pdf
===================================================================
--- trunk/doc/arbiter_diagram.pdf (revision 5)
+++ trunk/doc/arbiter_diagram.pdf (nonexistent)
trunk/doc/arbiter_diagram.pdf
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: scalable_arbiter/trunk/rtl/verilog/demo_filters.v
===================================================================
--- scalable_arbiter/trunk/rtl/verilog/demo_filters.v (nonexistent)
+++ scalable_arbiter/trunk/rtl/verilog/demo_filters.v (revision 6)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+`timescale 1ns / 1ps
+
+`define CLOCK_MHZ 40
+`define DEBOUNCE_HIGH_COUNT 3
+`define DEBOUNCE_LOW_COUNT 2
+`define STRETCH_HIGH_COUNT 10
+`define STRETCH_LOW_COUNT 5
+
+module demo_filters (
+ input in,
+ output out,
+ output valid_in,
+ output valid_out,
+
+ input clock,
+ input reset
+);
+
+wire usec_tick, msec_tick, interconnect;
+
+pulser #(
+ .count(`CLOCK_MHZ-1)
+) usec_pulser (
+ .enable(1'b1),
+ .out(usec_tick),
+
+ .clock(clock),
+ .reset(reset)
+);
+
+pulser #(
+ .count(1000)
+) msec_pulser (
+ .enable(usec_tick),
+ .out(msec_tick),
+
+ .clock(clock),
+ .reset(reset)
+);
+
+debouncer #(
+ .high_count(`DEBOUNCE_HIGH_COUNT),
+ .low_count(`DEBOUNCE_LOW_COUNT)
+) debouncer (
+ .enable(msec_tick),
+ .in(in),
+ .out(interconnect),
+ .valid(valid_in),
+
+ .clock(clock),
+ .reset(reset)
+);
+
+stretcher #(
+ .high_count(`STRETCH_HIGH_COUNT),
+ .low_count(`STRETCH_LOW_COUNT)
+) stretcher (
+ .enable(msec_tick),
+ .in(interconnect),
+ .out(out),
+ .valid(valid_out),
+
+ .clock(clock),
+ .reset(reset)
+);
+
+endmodule
Index: scalable_arbiter/trunk/rtl/verilog/demo_arbiter.v
===================================================================
--- scalable_arbiter/trunk/rtl/verilog/demo_arbiter.v (nonexistent)
+++ scalable_arbiter/trunk/rtl/verilog/demo_arbiter.v (revision 6)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+`define PORT_WIDTH 8
+`define ARB_WIDTH 256
+`define SELECT_WIDTH 8
+
+/*
+
+These results give a rough idea of how the timing and size scale
+with the arbiter width. It is useful to look at the trends, but
+the individual values should be taken with a grain of salt.
+
+Preliminary results using XC3S1600E-4FG320:
+
+ arbiter arbiter_x2
+ /----------------------------\ /----------------------------\
+ width MHz slices LUTs registers MHz slices LUTs registers
+ 8 214.961 22 34 35 287.439 34 42 53
+ 16 191.571 47 75 68 284.252 69 87 103
+ 32 148.943 99 163 133 211.730 122 169 188
+ 64 124.285 200 346 262 202.840 245 349 370
+ 128 102.807 434 717 519 165.044 490 739 699
+ 256 100.796 923 1555 1032 163.666 986 1504 1389
+ 512 87.176 1867 3120 2057 148.854 1973 2914 2686
+ 1024 81.974 3628 5976 4106 140.213 3947 5883 5360
+ 2048 69.214 7089 11444 8203 116.050 7966 12164 10513
+ 4096 49.332* 14853 24501 16396 113.404* 15592 23858 21011
+
+* at 4096, arbiter and arbiter_x2 exceed device capacity
+
+Preliminary results using EP3C25F324C8:
+
+ arbiter arbiter_x2
+ /----------------------------\ /----------------------------\
+ width MHz slices LUTs registers MHz slices LUTs registers
+ 8 384.17 37 33 35 453.31 55 29 53
+ 16 289.60 80 73 68 452.90 108 68 103
+ 32 259.74 165 160 133 357.53 206 152 188
+ 64 187.51 337 320 262 299.94 415 319 370
+ 128 132.12 675 630 519 226.50 853 685 699
+ 256 122.37 1362 1279 1032 217.96 1694 1353 1389
+ 512 99.91 2738 2627 2057 132.29 3303 2642 2686
+ 1024 85.54 5434 5121 4106 130.28 6622 5312 5360
+ 2048 71.77 10861 10128 8203 123.47 13236 10582 10513
+ 4096 61.10 21777 20313 16396 140.86 23208 21177 21011
+
+*/
+
+module demo_arbiter (
+ input enable_in,
+ input enable_out,
+ input load,
+ input [`PORT_WIDTH-1:0] port_in,
+ output [`PORT_WIDTH-1:0] port_out,
+ output [`SELECT_WIDTH-1:0] select,
+ output valid,
+
+ input clock,
+ input reset
+);
+
+wire [`ARB_WIDTH-1:0] req, grant;
+
+shifter #(
+ .depth(`ARB_WIDTH/`PORT_WIDTH),
+ .width(`PORT_WIDTH)
+) in_shifter (
+ .enable(enable_in),
+ .load(1'b0),
+
+ .parallel_in({`ARB_WIDTH{1'bx}}),
+ .serial_in(port_in),
+ .parallel_out(req),
+ .serial_out(),
+
+ .clock(clock)
+);
+
+arbiter #(
+ .width(`ARB_WIDTH),
+ .select_width(`SELECT_WIDTH)
+) arbiter (
+ .enable(1'b1),
+ .req(req),
+ .grant(grant),
+ .select(select),
+ .valid(valid),
+
+ .clock(clock),
+ .reset(reset)
+);
+
+shifter #(
+ .depth(`ARB_WIDTH/`PORT_WIDTH),
+ .width(`PORT_WIDTH)
+) out_shifter (
+ .enable(enable_out),
+ .load(load),
+
+ .parallel_in(grant),
+ .serial_in({`PORT_WIDTH{1'bx}}),
+ .parallel_out(),
+ .serial_out(port_out),
+
+ .clock(clock)
+);
+
+endmodule
Index: scalable_arbiter/trunk/rtl/verilog/shifter.v
===================================================================
--- scalable_arbiter/trunk/rtl/verilog/shifter.v (nonexistent)
+++ scalable_arbiter/trunk/rtl/verilog/shifter.v (revision 6)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+`timescale 1ns / 1ps
+
+module shifter #(
+ parameter depth = 0,
+ parameter width = 0
+)(
+ input enable,
+ input load,
+
+ input [(depth*width)-1:0] parallel_in,
+ input [width-1:0] serial_in,
+ output [(depth*width)-1:0] parallel_out,
+ output [width-1:0] serial_out,
+
+ input clock
+);
+
+reg [(depth*width)-1:0] internal;
+
+assign parallel_out = internal;
+assign serial_out = internal[width-1:0];
+
+integer i;
+
+always @(posedge clock)
+begin
+ if(enable)
+ begin
+ internal[(depth*width)-1-:width] <= load
+ ? parallel_in[(depth*width)-1-:width]
+ : serial_in;
+
+ for(i = depth - 1; i > 0; i = i - 1)
+ internal[(i*width)-1-:width] <= load
+ ? parallel_in[(i*width)-1-:width]
+ : internal[((i+1)*width)-1-:width];
+ end
+end
+
+endmodule
Index: scalable_arbiter/trunk/rtl/verilog/stretcher.v
===================================================================
--- scalable_arbiter/trunk/rtl/verilog/stretcher.v (nonexistent)
+++ scalable_arbiter/trunk/rtl/verilog/stretcher.v (revision 6)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+`timescale 1ns / 1ps
+
+module stretcher #(
+ parameter count = 0,
+ parameter high_count = count,
+ parameter low_count = count
+)(
+ input enable,
+ input in,
+ output reg out,
+ output reg valid,
+
+ input clock,
+ input reset
+);
+
+`include "functions.v"
+
+// edge detector
+wire rising;
+wire falling;
+
+assign rising = ~out & in;
+assign falling = out & ~in;
+
+/// counter width is the maximum size of the loaded value
+parameter counter_width =
+ max(flog2(high_count - 1) + 1, flog2(low_count - 1) + 1);
+
+reg [counter_width:0] counter;
+reg [counter_width-1:0] counter_load;
+wire counter_overflow;
+
+assign counter_overflow = counter[counter_width];
+
+// select counter value for rising or falling edge
+always @(rising, falling)
+begin
+ case({rising, falling})
+ 'b10:
+ counter_load = ~(high_count - 1);
+ 'b01:
+ counter_load = ~(low_count - 1);
+ default:
+ counter_load = {counter_width{1'bx}};
+ endcase
+end
+
+// the counter is reset on a rising or falling edge
+// overflow has priority over reset, so input changes
+// will be ignored until the full count is reached
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ counter <= {counter_width{1'b0}};
+ else
+ begin
+ if(enable & ~counter_overflow)
+ counter <= counter + 1;
+ else if((rising | falling) & counter_overflow)
+ counter <= { 1'b0, counter_load };
+ end
+end
+
+// output is gated by the counter overflow
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ out <= 1'b0;
+ else if(counter_overflow)
+ out <= in;
+end
+
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ valid <= 0;
+ else
+ valid <= counter_overflow;
+end
+
+endmodule
Index: scalable_arbiter/trunk/rtl/verilog/debouncer.v
===================================================================
--- scalable_arbiter/trunk/rtl/verilog/debouncer.v (nonexistent)
+++ scalable_arbiter/trunk/rtl/verilog/debouncer.v (revision 6)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+`timescale 1ns / 1ps
+
+module debouncer #(
+ parameter count = 0,
+ parameter high_count = count,
+ parameter low_count = count
+)(
+ input enable,
+ input in,
+ output reg out,
+ output reg valid,
+
+ input clock,
+ input reset
+);
+
+`include "functions.v"
+
+// register and edge detect the input
+reg [1:0] in_reg;
+
+always @(posedge clock)
+begin
+ in_reg <= {in_reg[0], in};
+end
+
+// edge detector
+wire rising;
+wire falling;
+
+assign rising = ~in_reg[1] & in_reg[0];
+assign falling = in_reg[1] & ~in_reg[0];
+
+// counter width is the maximum size of the loaded value
+parameter counter_width =
+ max(flog2(high_count - 1) + 1, flog2(low_count - 1) + 1);
+
+reg [counter_width:0] counter;
+reg [counter_width-1:0] counter_load;
+wire counter_overflow;
+
+assign counter_overflow = counter[counter_width];
+
+// select counter value for rising or falling edge
+always @(rising, falling)
+begin
+ case({rising, falling})
+ 'b10:
+ counter_load = ~(high_count - 1);
+ 'b01:
+ counter_load = ~(low_count - 1);
+ default:
+ counter_load = {counter_width{1'bx}};
+ endcase
+end
+
+// the counter is reset on a rising or falling edge
+// reset has priority over overflow, so the counter
+// will not overflow until the input has been stable
+// for a full count
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ counter <= {counter_width{1'b0}};
+ else
+ begin
+ if(rising | falling)
+ counter <= { 1'b0, counter_load };
+ else if(enable & ~counter_overflow)
+ counter <= counter + 1;
+ end
+end
+
+// output is gated by the counter overflow
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ out <= 1'b0;
+ else
+ begin
+ if(counter_overflow)
+ out <= in_reg[1];
+ end
+end
+
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ valid <= 1'b0;
+ else
+ valid <= counter_overflow;
+end
+
+endmodule
Index: scalable_arbiter/trunk/rtl/verilog/functions.v
===================================================================
--- scalable_arbiter/trunk/rtl/verilog/functions.v (nonexistent)
+++ scalable_arbiter/trunk/rtl/verilog/functions.v (revision 6)
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+function integer min (
+ input integer a, b
+);
+begin
+ min = a < b ? a : b;
+end
+endfunction
+
+function integer max (
+ input integer a, b
+);
+begin
+ max = a > b ? a : b;
+end
+endfunction
+
+// compute the log base 2 of a number, rounded down to the
+// nearest whole number
+function integer flog2 (
+ input integer number
+);
+integer i;
+integer count;
+begin
+ flog2 = 0;
+ for(i = 0; i < 32; i = i + 1)
+ begin
+ if(number&(1< 1)
+ clog2 = clog2 + 1;
+end
+endfunction
+
+// compute the size of the interconnect for the arbiter's
+// 'select' muxes
+function integer mux_sum (
+ input integer width, select_width
+);
+integer i, number;
+begin
+ mux_sum = 0;
+ number = 1;
+ for(i = select_width; i > 0 && number <= width; i = i - 1)
+ begin
+ mux_sum = mux_sum + i*(number);
+ number = number * 2;
+ end
+end
+endfunction
\ No newline at end of file
Index: scalable_arbiter/trunk/rtl/verilog/pulser.v
===================================================================
--- scalable_arbiter/trunk/rtl/verilog/pulser.v (nonexistent)
+++ scalable_arbiter/trunk/rtl/verilog/pulser.v (revision 6)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+`timescale 1ns / 1ps
+
+module pulser #(
+ parameter count = 0,
+ parameter toggle = 0
+) (
+ input enable,
+ output reg out,
+
+ input clock,
+ input reset
+);
+
+`include "functions.v"
+
+// counter width is the size of the loaded value
+parameter counter_width = flog2(count - 1) + 1;
+parameter [counter_width-1:0] counter_load = ~(count - 1);
+
+reg [counter_width:0] counter;
+wire counter_overflow;
+
+assign counter_overflow = counter[counter_width];
+
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ out <= 1'b0;
+ else
+ begin
+ if(toggle)
+ out <= out ^ counter_overflow;
+ else
+ out <= counter_overflow;
+ end
+end
+
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ counter <= {counter_width{1'b1}};
+ else
+ begin
+ if(counter_overflow)
+ counter <= { 1'b0, counter_load };
+ else if(enable)
+ counter <= counter + 1;
+ end
+end
+
+endmodule
Index: scalable_arbiter/trunk/rtl/verilog/arbiter.v
===================================================================
--- scalable_arbiter/trunk/rtl/verilog/arbiter.v (nonexistent)
+++ scalable_arbiter/trunk/rtl/verilog/arbiter.v (revision 6)
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+`timescale 1ns / 1ps
+
+// Two synchronous arbiter implementations are provided:
+// 'arbiter' and 'arbiter_x2'. Both are round-robin arbiters
+// with a configurable number of inputs. The algorithm used is
+// recursive in that you can build a larger arbiter from a
+// tree of smaller arbiters. 'arbiter_x2' is a tree of
+// 'arbiter' modules, 'arbiter' is a tree of 'arbiter_node'
+// modules, and 'arbiter_node' is the primitive of the
+// algorithm, a two input round-robin arbiter.
+//
+// Both 'arbiter' and 'arbiter_x2' can take multiple clocks
+// to grant a request. (Of course, neither arbiter should
+// assert an invalid grant while changing state.) 'arbiter'
+// can take up to three clocks to grant a req, and 'arbiter_x2'
+// can take up to five clocks. 'arbiter_x2' is probably only
+// necessary for configurations over a thousand inputs.
+// Presently, the width of both 'arbiter' and 'arbiter_x2'
+// must be power of two due to the way they instantiate a tree
+// of sub-arbiters. Extra inputs can be assigned to zero, and
+// extra outputs can be left disconnected.
+//
+// Parameters for 'arbiter' and 'arbiter_x2':
+// 'width' is width of the 'req' and 'grant' ports, which
+// must be a power of two.
+// 'select_width' is the width of the 'select' port, which
+// should be the log base two of 'width'.
+//
+// Ports for 'arbiter' and 'arbiter_x2':
+// 'enable' masks the 'grant' outputs. It is used to chain
+// arbiters together, but it might be useful otherwise.
+// It can be left disconnected if not needed.
+// 'req' are the input lines asserted to request access to
+// the arbitrated resource.
+// 'grant' are the output lines asserted to grant each
+// requestor access to the arbitrated resource.
+// 'select' is a binary encoding of the bitwise 'grant'
+// output. It is useful to control a mux that connects
+// requestor outputs to the arbitrated resource. It can
+// be left disconnected if not needed.
+// 'valid' is asserted when any 'req' is asserted. It is
+// used to chain arbiters together, but it might be
+// otherwise useful. It can be left disconnected if not
+// needed.
+
+// 'arbiter_x2' is a two-level tree of arbiters made from
+// registered 'arbiter' modules. It allows a faster clock in
+// large configurations by breaking the arbiter into two
+// registered stages. For most uses, the standard 'arbiter'
+// module is plenty fast. See the 'demo_arbiter' module for
+// some implemntation results.
+
+module arbiter_x2 #(
+ parameter width = 0,
+ parameter select_width = 1
+)(
+ input enable,
+ input [width-1:0] req,
+ output reg [width-1:0] grant,
+ output reg [select_width-1:0] select,
+ output reg valid,
+
+ input clock,
+ input reset
+);
+
+`include "functions.v"
+
+// 'width1' is the width of the first stage arbiters, which
+// is the square root of 'width' rounded up to the nearest
+// power of 2, calculated as: exp2(ceiling(log2(width)/2))
+parameter width1 = 1 << ((clog2(width)/2) + (clog2(width)%2));
+parameter select_width1 = clog2(width1);
+
+// 'width0' is the the width of the second stage arbiter,
+// which is the number of arbiters in the first stage.
+parameter width0 = width/width1;
+parameter select_width0 = clog2(width0);
+
+genvar g;
+
+wire [width-1:0] grant1;
+wire [(width0*select_width1)-1:0] select1;
+wire [width0-1:0] enable1;
+wire [width0-1:0] req0;
+wire [width0-1:0] grant0;
+wire [select_width0-1:0] select0;
+wire valid0;
+wire [select_width1-1:0] select_mux[width0-1:0];
+
+assign enable1 = grant0 & req0;
+
+// Register the outputs.
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ begin
+ valid <= 0;
+ grant <= 0;
+ select <= 0;
+ end
+ else
+ begin
+ valid <= valid0;
+ grant <= grant1;
+ select <= { select0, select_mux[select0] };
+ end
+end
+
+// Instantiate the first stage of the arbiter tree.
+arbiter #(
+ .width(width1),
+ .select_width(select_width1)
+) stage1_arbs[width0-1:0] (
+ .enable(enable1),
+ .req(req),
+ .grant(grant1),
+ .select(select1),
+ .valid(req0),
+
+ .clock(clock),
+ .reset(reset)
+);
+
+// Instantiate the second stage of the arbiter tree.
+arbiter #(
+ .width(width0),
+ .select_width(select_width0)
+) stage0_narb (
+ .enable(enable),
+ .req(req0),
+ .grant(grant0),
+ .select(select0),
+ .valid(valid0),
+
+ .clock(clock),
+ .reset(reset)
+);
+
+// Generate muxes for the select outputs.
+generate
+for(g = 0; g < width0; g = g + 1)
+begin: gen_mux
+ assign select_mux[g] = select1[((g+1)*select_width1)-1-:select_width1];
+end
+endgenerate
+
+endmodule
+
+// 'arbiter' is a tree made from unregistered 'arbiter_node'
+// modules. Unregistered carries between nodes allows
+// the tree to change state on the same clock. The tree
+// contains (width - 1) nodes, so resource usage of the
+// arbiter grows linearly. The number of levels and thus the
+// propogation delay down the tree grows with log2(width).
+// The logarithmic delay scaling makes this arbiter suitable
+// for large configuations. This module can take up to three
+// clocks to grant the next requestor after its inputs change
+// (two clocks for the 'arbiter_node' modules and one clock
+// for the output registers).
+
+module arbiter #(
+ parameter width = 0,
+ parameter select_width = 1
+)(
+ input enable,
+ input [width-1:0] req,
+ output reg [width-1:0] grant,
+ output reg [select_width-1:0] select,
+ output reg valid,
+
+ input clock,
+ input reset
+);
+
+`include "functions.v"
+
+genvar g;
+
+// These wires interconnect arbiter nodes.
+wire [2*width-2:0] interconnect_req;
+wire [2*width-2:0] interconnect_grant;
+wire [width-2:0] interconnect_select;
+wire [mux_sum(width,clog2(width))-1:0] interconnect_mux;
+
+// Assign inputs to some interconnects.
+assign interconnect_req[2*width-2-:width] = req;
+assign interconnect_grant[0] = enable;
+
+// Assign the select outputs of the first arbiter stage to
+// the first mux stage.
+assign interconnect_mux[mux_sum(width,clog2(width))-1-:width/2] = interconnect_select[width-2-:width/2];
+
+// Register some interconnects as outputs.
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ begin
+ valid <= 0;
+ grant <= 0;
+ select <= 0;
+ end
+ else
+ begin
+ valid <= interconnect_req[0];
+ grant <= interconnect_grant[2*width-2-:width];
+ select <= interconnect_mux[clog2(width)-1:0];
+ end
+end
+
+// Generate the stages of the arbiter tree. Each stage is
+// instantiated as an array of 'abiter_node' modules and
+// is half the width of the previous stage. Some simple
+// arithmetic part-selects the interconnects for each stage.
+// See the "Request/Grant Interconnections" diagram of an
+// arbiter in the documentation.
+generate
+for(g = width; g >= 2; g = g / 2)
+begin: gen_arb
+ arbiter_node nodes[(g/2)-1:0] (
+ .enable(interconnect_grant[g-2-:g/2]),
+ .req(interconnect_req[2*g-2-:g]),
+ .grant(interconnect_grant[2*g-2-:g]),
+ .select(interconnect_select[g-2-:g/2]),
+ .valid(interconnect_req[g-2-:g/2]),
+
+ .clock(clock),
+ .reset(reset)
+ );
+end
+endgenerate
+
+// Generate the select muxes for each stage of the arbiter
+// tree. The generate begins on the second stage because
+// there are no muxes in the first stage. Each stage is
+// a two dimensional array of muxes, where the dimensions
+// are number of arbiter nodes in the stage times the
+// number of preceeding stages. It takes some tricky
+// arithmetic to part-select the interconnects for each
+// stage. See the "Select Interconnections" diagram of an
+// arbiter in the documentation.
+generate
+for(g = width/2; g >= 2; g = g / 2)
+begin: gen_mux
+ mux_array #(
+ .width(g/2)
+ ) mux_array[clog2(width/g)-1:0] (
+ .in(interconnect_mux[mux_sum(g,clog2(width))-1-:clog2(width/g)*g]),
+ .select(interconnect_select[g-2-:g/2]),
+ .out(interconnect_mux[mux_sum(g/2,clog2(width))-(g/2)-1-:clog2(width/g)*g/2])
+ );
+ assign interconnect_mux[mux_sum(g/2,clog2(width))-1-:g/2] = interconnect_select[g-2-:g/2];
+end
+endgenerate
+
+endmodule
+
+module mux_array #(
+ parameter width = 0
+)(
+ input [(2*width)-1:0] in,
+ input [width-1:0] select,
+ output [width-1:0] out
+);
+
+mux_node nodes[width-1:0] (
+ .in(in),
+ .select(select),
+ .out(out)
+ );
+
+endmodule
+
+module mux_node (
+ input [1:0] in,
+ input select,
+ output out
+);
+
+assign out = select ? in[1] : in[0];
+
+endmodule
+
+// This is a two input round-robin arbiter with the
+// addition of the 'valid' and 'enable' signals
+// that allow multiple nodes to be connected to form a
+// larger arbiter. Outputs are not registered to allow
+// interconnected nodes to change state on the same clock.
+
+module arbiter_node (
+ input enable,
+ input [1:0] req,
+ output [1:0] grant,
+ output select,
+ output valid,
+
+ input clock,
+ input reset
+);
+
+// The state determines which 'req' is granted. State '0'
+// grants 'req[0]', state '1' grants 'req[1]'.
+reg grant_state;
+wire next_state;
+
+// The 'grant' of this stage is masked by 'enable', which
+// carries the grants of the subsequent stages back to this
+// stage. The 'grant' is also masked by 'req' to ensure that
+// 'grant' is dropped as soon 'req' goes away.
+assign grant[0] = req[0] & ~grant_state & enable;
+assign grant[1] = req[1] & grant_state & enable;
+
+// Select is a binary value that tracks grant. It could
+// be used to control a mux on the arbitrated resource.
+assign select = grant_state;
+
+// The 'valid' carries reqs to subsequent stages. It is
+// high when the 'req's are high, except during 1-to-0 state
+// transistions when it's dropped for a cycle to allow
+// subsequent arbiter stages to make progress. This causes a
+// two cycle turnaround for 1-to-0 state transistions.
+/*
+always @(grant_state, next_state, req)
+begin
+ if(grant_state & ~next_state)
+ valid <= 0;
+ else if(req[0] | req[1])
+ valid <= 1;
+ else
+ valid <= 0;
+end
+*/
+// reduced 'valid' logic
+assign valid = (req[0] & ~grant_state) | req[1];
+
+// The 'next_state' logic implements round-robin fairness
+// for two inputs. When both reqs are asserted, 'req[0]' is
+// granted first. This state machine along with some output
+// logic can be cascaded to implement round-robin fairness
+// for many inputs.
+/*
+always @(grant_state, req)
+begin
+ case(grant_state)
+ 0:
+ if(req[0])
+ next_state <= 0;
+ else if(req[1])
+ next_state <= 1;
+ else
+ next_state <= 0;
+ 1:
+ if(req[1])
+ next_state <= 1;
+ else
+ next_state <= 0;
+ endcase
+end
+*/
+// reduced next state logic
+assign next_state = (req[1] & ~req[0]) | (req[1] & grant_state);
+
+// state register
+always @(posedge clock, posedge reset)
+begin
+ if(reset)
+ grant_state <= 0;
+ else
+ grant_state <= next_state;
+end
+
+endmodule
Index: scalable_arbiter/trunk/bench/verilog/tb_arbiter.v
===================================================================
--- scalable_arbiter/trunk/bench/verilog/tb_arbiter.v (nonexistent)
+++ scalable_arbiter/trunk/bench/verilog/tb_arbiter.v (revision 6)
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+`timescale 1ns / 1ps
+
+// This bench simply applies the vectors in the pattern file,
+// and tests that the output matches the expected values. This
+// test is usful to verify basic behavior, but it is difficult
+// to generate vectors for large configurations.
+
+`define WIDTH 8
+`define SELECT_WIDTH 8
+`define TURNAROUND 3
+//`define TURNAROUND 6 for arbiter x2
+`define TICK 10
+`define HALF_TICK 5
+`define TEST_VEC_COUNT 241
+`define TEST_VEC_MULT 2
+`define PATTERN_FILE "tb_arbiter.txt"
+
+module tb_arbiter;
+
+reg reset;
+reg clock;
+
+reg [`WIDTH-1:0] req;
+wire [`WIDTH-1:0] grant;
+wire [`SELECT_WIDTH-1:0] select;
+wire valid;
+
+reg [`WIDTH-1:0] pattern[(`TEST_VEC_MULT*`TEST_VEC_COUNT)-1:0];
+reg [`WIDTH-1:0] grant_expected;
+
+integer test_i;
+integer grant_i;
+integer grant_count;
+integer failures;
+integer monitor_exceptions;
+
+//
+// UUT
+//
+
+arbiter #(
+ .width(`WIDTH),
+ .select_width(`SELECT_WIDTH)
+) arbiter (
+ .enable(1'b1),
+ .req(req),
+ .grant(grant),
+ .select(select),
+ .valid(valid),
+
+ .clock(clock),
+ .reset(reset)
+);
+
+//
+// clock
+//
+
+always @(clock)
+ #`HALF_TICK clock <= !clock;
+
+//
+// test monitors
+//
+
+always @(grant)
+begin
+ grant_count = 0;
+ for(grant_i = 0; grant_i < `WIDTH; grant_i = grant_i + 1)
+ begin
+ if(grant[grant_i])
+ begin
+ grant_count = grant_count + 1;
+
+ if(!req[grant_i])
+ begin
+ monitor_exceptions = monitor_exceptions + 1;
+
+ $display("EXCEPTION @%e: grant line %d with no req",
+ $realtime, grant_i);
+ end
+
+ if(select != grant_i)
+ begin
+ monitor_exceptions = monitor_exceptions + 1;
+
+ $display("EXCEPTION @%e: select of %d does not match grant of line %d",
+ $realtime, select, grant_i);
+ end
+ end
+ end
+
+ if(grant_count > 1)
+ begin
+ monitor_exceptions = monitor_exceptions + 1;
+
+ $display("EXCEPTION @%e: grant %h asserts multiple lines",
+ $realtime, grant);
+ end
+end
+
+//
+// test sequence
+//
+
+initial
+begin
+ $readmemb(`PATTERN_FILE, pattern);
+ failures = 0;
+ monitor_exceptions = 0;
+
+ clock = 1;
+ req = 0;
+ reset = 1;
+ #`TICK @(negedge clock) reset = 0;
+
+ // apply reqs, and test grants against exepcted values
+ for(test_i = 0; test_i < `TEST_VEC_COUNT; test_i = test_i + 1)
+ begin
+ #`TICK;
+
+ req = pattern[test_i*`TEST_VEC_MULT];
+ grant_expected = pattern[test_i*`TEST_VEC_MULT + 1];
+
+ #(`TURNAROUND*`TICK);
+
+ if(grant != grant_expected)
+ begin
+ failures = failures + 1;
+
+ $display("FAILED %d: req %h, grant %h (expected %h)",
+ test_i, req, grant, grant_expected);
+ end
+ else
+ begin
+ $display("ok %d: req %h, grant %h (expected %h)",
+ test_i, req, grant, grant_expected);
+ end
+ end
+
+ $display("%d failures", failures);
+ $display("%d monitor exceptions", monitor_exceptions);
+
+ if(failures == 0 && monitor_exceptions == 0)
+ $display("PASS");
+ else
+ $display("FAIL");
+end
+
+endmodule
Index: scalable_arbiter/trunk/bench/verilog/tb_abrbiter2.v
===================================================================
--- scalable_arbiter/trunk/bench/verilog/tb_abrbiter2.v (nonexistent)
+++ scalable_arbiter/trunk/bench/verilog/tb_abrbiter2.v (revision 6)
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2008, Kendall Correll
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+`timescale 1ns / 1ps
+
+// This bench applies req vectors, deasserts req lines as
+// they are granted, and tests that each req is granted
+// only once for each vector. It seems to be a pretty good
+// test because it is similar to the arbiter's intended
+// application, and it focuses on fairness, the most
+// important aspect of the arbiter's behavior. This test
+// also makes it easy to use large arbiter configurations,
+// which tend to find more problems.
+
+`define WIDTH 128
+`define SELECT_WIDTH 7
+`define TURNAROUND 3
+//`define TURNAROUND 6 for arbiter x2
+`define TICK 10
+`define HALF_TICK 5
+`define TEST_VEC_COUNT 8
+`define PATTERN_FILE "tb_arbiter2.txt"
+`define ROUND_COUNT 3
+
+module tb_arbiter2;
+
+reg reset;
+reg clock;
+
+reg [`WIDTH-1:0] req;
+wire [`WIDTH-1:0] grant;
+wire [`SELECT_WIDTH-1:0] select;
+wire valid;
+
+reg [`WIDTH-1:0] pattern[`TEST_VEC_COUNT-1:0];
+
+integer test_i;
+integer grant_i;
+integer grant_count;
+integer req_i;
+integer req_count[`TEST_VEC_COUNT-1:0];
+integer failures;
+integer monitor_exceptions;
+integer fill_i;
+integer round;
+integer reqs[`WIDTH-1:0];
+integer grants[`ROUND_COUNT-1:0][`WIDTH-1:0];
+
+//
+// UUT
+//
+
+arbiter #(
+ .width(`WIDTH),
+ .select_width(`SELECT_WIDTH)
+) arbiter (
+ .enable(1'b1),
+ .req(req),
+ .grant(grant),
+ .select(select),
+ .valid(valid),
+
+ .clock(clock),
+ .reset(reset)
+);
+
+//
+// clock
+//
+
+always @(clock)
+ #`HALF_TICK clock <= !clock;
+
+//
+// test monitors
+//
+
+always @(grant)
+begin
+ grant_count = 0;
+ for(grant_i = 0; grant_i < `WIDTH; grant_i = grant_i + 1)
+ begin
+ if(grant[grant_i])
+ begin
+ grant_count = grant_count + 1;
+ grants[round][grant_i] = grants[round][grant_i] + 1;
+
+ if(!req[grant_i])
+ begin
+ monitor_exceptions = monitor_exceptions + 1;
+
+ $display("EXCEPTION @%e: grant line %d with no req",
+ $realtime, grant_i);
+ end
+
+ if(select != grant_i)
+ begin
+ monitor_exceptions = monitor_exceptions + 1;
+
+ $display("EXCEPTION @%e: select of %d does not match grant of line %d",
+ $realtime, select, grant_i);
+ end
+ end
+ end
+
+ if(grant_count > 1)
+ begin
+ monitor_exceptions = monitor_exceptions + 1;
+
+ $display("EXCEPTION @%e: grant %h asserts multiple lines",
+ $realtime, grant);
+ end
+end
+
+//
+// test sequence
+//
+
+initial
+begin
+ $readmemh(`PATTERN_FILE, pattern);
+ failures = 0;
+ monitor_exceptions = 0;
+ fill_i = 0;
+ round = 0;
+ for(req_i = 0; req_i < `WIDTH; req_i = req_i + 1)
+ begin
+ reqs[req_i] = 0;
+
+ grants[0][req_i] = 0;
+ grants[1][req_i] = 0;
+ grants[2][req_i] = 0;
+ end
+ // pre-calculate some values used in the test
+ for(test_i = 0; test_i < `TEST_VEC_COUNT; test_i = test_i + 1)
+ begin
+ req_count[test_i] = 0;
+ for(req_i = 0; req_i < `WIDTH; req_i = req_i + 1)
+ begin
+ if(pattern[test_i][req_i])
+ begin
+ req_count[test_i] = req_count[test_i] + 1;
+ reqs[req_i] = reqs[req_i] + 1;
+ end
+ end
+ end
+
+ clock = 1;
+ req = 0;
+ reset = 1;
+ #`TICK @(negedge clock) reset = 0;
+
+ // apply reqs, and turn off granted reqs permanently
+ for(test_i = 0; test_i < `TEST_VEC_COUNT; test_i = test_i + 1)
+ begin
+ req = pattern[test_i];
+
+ for(req_i = 0; req_i < req_count[test_i]; req_i = req_i + 1)
+ begin
+ #(`TURNAROUND*`TICK);
+
+ req = req & ~grant;
+ end
+
+ // one clock to deassert the last req before we apply
+ // the next req vector
+ #`TICK;
+ end
+
+ // apply reqs, but only turn off granted reqs temporarily
+ round = round + 1;
+ for(test_i = 0; test_i < `TEST_VEC_COUNT; test_i = test_i + 1)
+ begin
+ req = pattern[test_i];
+
+ for(req_i = 0; req_i < req_count[test_i]; req_i = req_i + 1)
+ begin
+ #(`TURNAROUND*`TICK);
+
+ req = pattern[test_i] & ~grant;
+ end
+
+ // one clock to deassert the reqs before we apply the
+ // next req vector
+ req = 0;
+ #`TICK;
+ end
+
+ // apply reqs, and fill behind with the next vector as reqs
+ // are granted
+ round = round + 1;
+ req = pattern[0];
+ fill_i = `WIDTH;
+ for(test_i = 0; test_i < `TEST_VEC_COUNT; test_i = test_i + 1)
+ begin
+ for(req_i = 0; req_i < req_count[test_i]; req_i = req_i + 1)
+ begin
+ #(`TURNAROUND*`TICK);
+
+ req = req & ~grant;
+
+ for(fill_i = fill_i; ~grant[fill_i%`WIDTH]; fill_i = fill_i + 1)
+ begin
+ req[fill_i%`WIDTH] = (fill_i/`WIDTH < `TEST_VEC_COUNT)
+ ? pattern[fill_i/`WIDTH][fill_i%`WIDTH]
+ : 1'b0;
+ end
+ end
+ end
+
+ // check the results
+ for(req_i = 0; req_i < `WIDTH; req_i = req_i + 1)
+ begin
+ if(reqs[req_i] != grants[0][req_i]
+ || reqs[req_i] != grants[1][req_i]
+ || reqs[req_i] != grants[2][req_i])
+ begin
+ failures = failures + 1;
+
+ $display("FAILED %d: %d reqs, %d %d %d grants",
+ req_i, reqs[req_i], grants[0][req_i],
+ grants[1][req_i], grants[2][req_i]);
+ end
+ else
+ begin
+ $display("ok %d: %d reqs, %d %d %d grants",
+ req_i, reqs[req_i], grants[0][req_i],
+ grants[1][req_i], grants[2][req_i]);
+ end
+ end
+
+ $display("%d failures", failures);
+ $display("%d monitor exceptions", monitor_exceptions);
+
+ if(failures == 0 && monitor_exceptions == 0)
+ $display("PASS");
+ else
+ $display("FAIL");
+end
+
+endmodule
Index: scalable_arbiter/trunk/bench/verilog/tb_arbiter.txt
===================================================================
--- scalable_arbiter/trunk/bench/verilog/tb_arbiter.txt (nonexistent)
+++ scalable_arbiter/trunk/bench/verilog/tb_arbiter.txt (revision 6)
@@ -0,0 +1,241 @@
+0 0
+11111111 00000001
+11111110 00000010
+11111100 00000100
+11111000 00001000
+11110000 00010000
+11100000 00100000
+11000000 01000000
+10000000 10000000
+0 0
+11111111 00000001
+11111110 00000010
+11111100 00000100
+11111000 00001000
+11110000 00010000
+11100000 00100000
+11000000 01000000
+10000000 10000000
+0 0
+11111111 00000001
+01111111 00000001
+00111111 00000001
+00011111 00000001
+00001111 00000001
+00000111 00000001
+00000011 00000001
+00000001 00000001
+0 0
+00000001 00000001
+00000010 00000010
+00000100 00000100
+00001000 00001000
+00010000 00010000
+00100000 00100000
+01000000 01000000
+10000000 10000000
+0 0
+10000000 10000000
+01000000 01000000
+00100000 00100000
+00010000 00010000
+00001000 00001000
+00000100 00000100
+00000010 00000010
+00000001 00000001
+0 0
+11111110 00000010
+11111101 00000100
+11111011 00001000
+11110111 00010000
+11101111 00100000
+11011111 01000000
+10111111 10000000
+01111111 00000001
+0 0
+01111111 00000001
+10111111 00000001
+11011111 00000001
+11101111 00000001
+11110111 00000001
+11111011 00000001
+11111101 00000001
+11111110 00000010
+0 0
+00000001 00000001
+00000000 00000000
+00000010 00000010
+00000000 00000000
+00000100 00000100
+00000000 00000000
+00001000 00001000
+00000000 00000000
+00010000 00010000
+00000000 00000000
+00100000 00100000
+00000000 00000000
+01000000 01000000
+00000000 00000000
+10000000 10000000
+0 0
+10000000 10000000
+00000000 00000000
+01000000 01000000
+00000000 00000000
+00100000 00100000
+00000000 00000000
+00010000 00010000
+00000000 00000000
+00001000 00001000
+00000000 00000000
+00000100 00000100
+00000000 00000000
+00000010 00000010
+00000000 00000000
+00000001 00000001
+0 0
+11111111 00000001
+11111110 00000010
+11111111 00000010
+11111101 00000100
+11111111 00000100
+11111011 00001000
+11111111 00001000
+11110111 00010000
+11111111 00010000
+11101111 00100000
+11111111 00100000
+11011111 01000000
+11111111 01000000
+10111111 10000000
+11111111 10000000
+01111111 00000001
+11111111 00000001
+0 0
+11111111 00000001
+01111111 00000001
+11111111 00000001
+10111111 00000001
+11111111 00000001
+11011111 00000001
+11111111 00000001
+11101111 00000001
+11111111 00000001
+11110111 00000001
+11111111 00000001
+11111011 00000001
+11111111 00000001
+11111101 00000001
+11111111 00000001
+11111110 00000010
+11111111 00000010
+0 0
+01010101 00000001
+10000000 10000000
+01010101 00000001
+00100000 00100000
+01010101 01000000
+00001000 00001000
+01010101 00010000
+00000010 00000010
+01010101 00000100
+0 0
+10101010 00000010
+01000000 01000000
+10101010 10000000
+00010000 00010000
+10101010 00100000
+00000100 00000100
+10101010 00001000
+00000001 00000001
+10101010 00000010
+0 0
+00010000 00010000
+00100001 00100000
+01000001 01000000
+10000001 10000000
+00010001 00000001
+00010010 00000010
+00010100 00000100
+00011000 00001000
+00010001 00010000
+00100001 00100000
+01000001 01000000
+10000001 10000000
+00010001 00000001
+00010010 00000010
+00010100 00000100
+00011000 00001000
+0 0
+01010101 00000001
+01010110 00000010
+01010101 00000100
+01011001 00001000
+01010101 00010000
+01100101 00100000
+01010101 01000000
+10010101 10000000
+01010101 00000001
+0 0
+10101010 00000010
+10101101 00001000
+11110111 00100000
+11011111 10000000
+01111111 00000001
+11111110 00000010
+11111100 00000100
+11111010 00001000
+11110010 00010000
+11101010 00100000
+11001010 01000000
+10101010 10000000
+0 0
+11001110 00000010
+01010101 00000100
+00100001 00000001
+00101100 00000100
+01000000 01000000
+10110110 10000000
+11100111 10000000
+01011101 00000100
+10010110 00000100
+01010010 00010000
+00000111 00000010
+01110110 00000010
+00010100 00000100
+10110110 00000100
+00011110 00000100
+00110111 00000100
+10101001 00001000
+11000100 10000000
+01001011 00001000
+11110001 01000000
+01101110 01000000
+10011110 10000000
+01001100 00000100
+11110111 00000100
+11010011 01000000
+01111110 01000000
+00000011 00000010
+01001110 00000010
+10011101 00000100
+00110000 00010000
+00110110 00010000
+01000110 01000000
+10001101 10000000
+01110000 00010000
+00001011 00000001
+01111100 00001000
+11010100 00010000
+01001111 01000000
+00010001 00000001
+11101010 00000010
+01000111 00000010
+01100001 01000000
+11111011 01000000
+00011001 00000001
+10011111 00000001
+10010000 00010000
+00001100 00000100
+11110011 00010000
+0 0
\ No newline at end of file
Index: scalable_arbiter/trunk/bench/verilog/tb_arbiter2.txt
===================================================================
--- scalable_arbiter/trunk/bench/verilog/tb_arbiter2.txt (nonexistent)
+++ scalable_arbiter/trunk/bench/verilog/tb_arbiter2.txt (revision 6)
@@ -0,0 +1,8 @@
+8176255410b7cb44a074ee702a9a86db
+8176255410b7cb44a074ee702a9a86db
+49539737fd0c739c556513c608c1228b
+10a60347121e743967d73eb4a2dc629b
+ee6064c875d6fdbda8a95e35102c551e
+0d1361fd41adf235fdafff491b1963e4
+0d1361fd41adf235fdafff491b1963e4
+e89c064542709e292edd0abf77b1e89c
\ No newline at end of file
Index: scalable_arbiter/trunk/doc/arbiter_diagram.odg
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: scalable_arbiter/trunk/doc/arbiter_diagram.odg
===================================================================
--- scalable_arbiter/trunk/doc/arbiter_diagram.odg (nonexistent)
+++ scalable_arbiter/trunk/doc/arbiter_diagram.odg (revision 6)
scalable_arbiter/trunk/doc/arbiter_diagram.odg
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: scalable_arbiter/trunk/doc/arbiter_diagram.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: scalable_arbiter/trunk/doc/arbiter_diagram.pdf
===================================================================
--- scalable_arbiter/trunk/doc/arbiter_diagram.pdf (nonexistent)
+++ scalable_arbiter/trunk/doc/arbiter_diagram.pdf (revision 6)
scalable_arbiter/trunk/doc/arbiter_diagram.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: scalable_arbiter/trunk
===================================================================
--- scalable_arbiter/trunk (nonexistent)
+++ scalable_arbiter/trunk (revision 6)
scalable_arbiter/trunk
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: scalable_arbiter/web_uploads
===================================================================
--- scalable_arbiter/web_uploads (nonexistent)
+++ scalable_arbiter/web_uploads (revision 6)
scalable_arbiter/web_uploads
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: scalable_arbiter/branches
===================================================================
--- scalable_arbiter/branches (nonexistent)
+++ scalable_arbiter/branches (revision 6)
scalable_arbiter/branches
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: scalable_arbiter/tags
===================================================================
--- scalable_arbiter/tags (nonexistent)
+++ scalable_arbiter/tags (revision 6)
scalable_arbiter/tags
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##