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
/scalable_arbiter
- from Rev 8 to Rev 9
- ↔ Reverse comparison
Rev 8 → Rev 9
/trunk/bench/verilog/tb_arbiter3.v
0,0 → 1,93
/* |
* Copyright (c) 2009, 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 walks the demo through its sequence, but it does not verify outputs. |
|
`define WIDTH 16 |
`define SELECT_WIDTH 4 |
`define TURNAROUND 3 |
`define TICK 10 |
`define HALF_TICK 5 |
|
module tb_arbiter3; |
|
reg clock; |
reg reset; |
|
reg next_test; |
reg next_step; |
|
wire [`SELECT_WIDTH-1:0] select; |
wire valid; |
|
integer test_i; |
|
`include "functions.v" |
|
// |
// UUT |
// |
|
demo #( |
.width(`WIDTH), |
.select_width(`SELECT_WIDTH) |
) demo ( |
.next_test(next_test), |
.next_step(next_step), |
.select(select), |
.valid(valid), |
.clock(clock), |
.reset(reset) |
); |
|
// |
// clock |
// |
|
always @(clock) |
begin |
#`HALF_TICK clock <= !clock; |
end |
|
// |
// test sequence |
// |
|
initial begin |
clock = 1; |
next_test = 0; |
next_step = 0; |
reset = 1; |
#`TICK @(negedge clock) reset = 0; |
|
// step through the stimulus sequence, 'req_enable' is always high, so |
// reqs will be deasserted as soon as they are granted |
while(1'b1) |
begin |
#`TICK next_test = 1; |
#`TICK next_test = 0; |
|
for(test_i = 0; test_i < `WIDTH; test_i = test_i + 1) |
begin |
#(`TURNAROUND*`TICK) next_step = 1; |
#`TICK next_step = 0; |
end |
end |
end |
|
endmodule |
/trunk/rtl/verilog/demo_arbiter.v
File deleted
/trunk/rtl/verilog/demo_filters.v
File deleted
/trunk/rtl/verilog/stretcher.v
1,5 → 1,5
/* |
* Copyright (c) 2008, Kendall Correll |
* Copyright (c) 2008-2009, 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 |
17,13 → 17,15
`timescale 1ns / 1ps |
|
module stretcher #( |
parameter count = 0, |
parameter count = 1, |
parameter high_count = count, |
parameter low_count = count |
parameter low_count = count, |
parameter width = 1, |
parameter reset_value = {width{1'b0}} |
)( |
input enable, |
input in, |
output reg out, |
input [width-1:0] in, |
output reg [width-1:0] out, |
output reg valid, |
|
input clock, |
36,12 → 38,12
wire rising; |
wire falling; |
|
assign rising = ~out & in; |
assign falling = out & ~in; |
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); |
parameter counter_width = max(flog2(count - 1) + 1, |
max(flog2(high_count - 1) + 1, flog2(low_count - 1) + 1)); |
|
reg [counter_width:0] counter; |
reg [counter_width-1:0] counter_load; |
53,10 → 55,12
always @(rising, falling) |
begin |
case({rising, falling}) |
'b11: |
counter_load = -count; |
'b10: |
counter_load = ~(high_count - 1); |
counter_load = -high_count; |
'b01: |
counter_load = ~(low_count - 1); |
counter_load = -low_count; |
default: |
counter_load = {counter_width{1'bx}}; |
endcase |
82,9 → 86,12
always @(posedge clock, posedge reset) |
begin |
if(reset) |
out <= 1'b0; |
else if(counter_overflow) |
out <= in; |
out <= reset_value; |
else |
begin |
if(counter_overflow) |
out <= in; |
end |
end |
|
always @(posedge clock, posedge reset) |
/trunk/rtl/verilog/shifter.v
1,5 → 1,5
/* |
* Copyright (c) 2008, Kendall Correll |
* Copyright (c) 2008-2009, 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 |
46,10 → 46,12
? parallel_in[(depth*width)-1-:width] |
: serial_in; |
|
for(i = depth - 1; i > 0; i = i - 1) |
for(i = depth - 1; i > 0; i = i - 1) |
begin |
internal[(i*width)-1-:width] <= load |
? parallel_in[(i*width)-1-:width] |
: internal[((i+1)*width)-1-:width]; |
: internal[((i+1)*width)-1-:width]; |
end |
end |
end |
|
/trunk/rtl/verilog/demo.v
0,0 → 1,115
/* |
* Copyright (c) 2008-2009, 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. |
*/ |
|
/* |
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 XC6SLX45-2FGG484: |
|
arbiter arbiter_x2 |
/----------------------------\ /----------------------------\ |
width MHz LEs LUTs FFs MHz LEs LUTs FFs |
8 289.855 42 34 35 399.672 56 36 53 |
16 273.000 83 67 68 397.377 109 70 103 |
32 230.240 188 156 133 289.855 214 143 188 |
64 189.593 391 320 262 289.855 428 288 370 |
128 166.073 796 650 519 261.852 886 618 699 |
256 161.496 1582 1267 1032 261.852 1779 1245 1389 |
512 136.753 3164 2493 2057 196.883 3489 2443 2686 |
1024 122.155 6755 5348 4106 197.280 7015 4928 5360 |
2048 102.198 12538 9485 8203 193.289 13956 9767 10513 |
4096 103.433 27182 20683 16396 190.964 27813 19450 21011 |
|
note: width 4096 arbiter_x2 exceeds device capacity |
|
Preliminary results using EP3C40F484C8: |
|
arbiter arbiter_x2 |
/---------------------------\ /---------------------------\ |
width MHz LEs LUTs FFs MHz LEs LUTs FFs |
8 444.25 50 42 35 457.67 65 46 53 |
16 313.77 92 91 68 396.67 114 92 103 |
32 239.52 195 194 133 338.18 232 194 188 |
64 185.08 388 387 262 311.04 465 393 370 |
128 161.47 769 768 519 283.37 959 822 699 |
256 138.26 1551 1550 1032 249.25 1889 1619 1389 |
512 103.90 3132 3131 2057 155.88 3657 3132 2686 |
1024 88.39 6150 6149 4106 132.93 7328 6282 5360 |
2048 76.24 12283 12282 8203 138.12 14549 12479 10513 |
4096 57.02 24533 24532 16396 128.07 29099 24964 21011 |
*/ |
|
`timescale 1ns / 1ps |
|
module demo #( |
parameter width = 128, |
parameter select_width = 7 |
)( |
input next_test, |
input next_step, |
output [select_width-1:0] select, |
output valid, |
|
input clock, |
input reset |
); |
|
reg [width-1:0] req; |
wire [width-1:0] seq; |
wire [width-1:0] grant; |
|
lfsr #( |
.width(width) |
) lfsr ( |
.enable(next_test), |
.load(1'b0), |
.in(1'bx), |
.out(seq), |
|
.clock(clock), |
.reset(reset) |
); |
|
arbiter #( |
.width(width), |
.select_width(select_width) |
) arbiter ( |
.enable(1'b1), |
.req(req), |
.grant(grant), |
.select(select), |
.valid(valid), |
|
.clock(clock), |
.reset(reset) |
); |
|
always @(posedge clock) |
begin |
if(reset) |
req <= 0; |
else |
begin |
if(next_test) |
req <= seq; |
else if(next_step) |
req <= req & ~grant; |
end |
end |
|
endmodule |
/trunk/rtl/verilog/debouncer.v
1,5 → 1,5
/* |
* Copyright (c) 2008, Kendall Correll |
* Copyright (c) 2008-2009, 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 |
16,14 → 16,18
|
`timescale 1ns / 1ps |
|
module debouncer #( |
parameter count = 0, |
module debouncer #( |
parameter count = 1, |
parameter high_count = count, |
parameter low_count = count |
parameter low_count = count, |
parameter width = 1, |
parameter reset_value = {width{1'b0}} |
)( |
input enable, |
input in, |
output reg out, |
input [width-1:0] in, |
output [width-1:0] out, |
output reg rising_pulse, |
output reg falling_pulse, |
output reg valid, |
|
input clock, |
33,11 → 37,12
`include "functions.v" |
|
// register and edge detect the input |
reg [1:0] in_reg; |
reg [width-1:0] in_reg; |
reg [width-1:0] out_reg; |
|
always @(posedge clock) |
begin |
in_reg <= {in_reg[0], in}; |
in_reg <= in; |
end |
|
// edge detector |
44,12 → 49,12
wire rising; |
wire falling; |
|
assign rising = ~in_reg[1] & in_reg[0]; |
assign falling = in_reg[1] & ~in_reg[0]; |
assign rising = |(~in_reg & in); |
assign falling = |(in_reg & ~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); |
parameter counter_width = max(flog2(count - 1) + 1, |
max(flog2(high_count - 1) + 1, flog2(low_count - 1) + 1)); |
|
reg [counter_width:0] counter; |
reg [counter_width-1:0] counter_load; |
61,10 → 66,12
always @(rising, falling) |
begin |
case({rising, falling}) |
'b11: |
counter_load = -count; |
'b10: |
counter_load = ~(high_count - 1); |
counter_load = -high_count; |
'b01: |
counter_load = ~(low_count - 1); |
counter_load = -low_count; |
default: |
counter_load = {counter_width{1'bx}}; |
endcase |
87,16 → 94,32
end |
end |
|
// output is gated by the counter overflow |
// output is gated by the counter overflow |
assign out = out_reg; |
|
always @(posedge clock, posedge reset) |
begin |
if(reset) |
out <= 1'b0; |
out_reg <= reset_value; |
else |
begin |
if(counter_overflow) |
out <= in_reg[1]; |
out_reg <= in_reg; |
end |
end |
|
always @(posedge clock, posedge reset) |
begin |
if(reset) |
begin |
rising_pulse <= 1'b0; |
falling_pulse <= 1'b0; |
end |
else |
begin |
rising_pulse <= counter_overflow & ~out_reg & in_reg; |
falling_pulse <= counter_overflow & out_reg & ~in_reg; |
end |
end |
|
always @(posedge clock, posedge reset) |
/trunk/rtl/verilog/demo_top.v
0,0 → 1,162
/* |
* Copyright (c) 2009, 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 MHZ 100 |
`define WIDTH 8 |
`define SELECT_WIDTH 3 |
`define DEBOUNCE_MSEC 250 |
`define STRETCH_MSEC 250 |
|
module demo_top ( |
input [1:0] buttons, |
output [`SELECT_WIDTH:0] indicators, |
|
input refclock |
); |
|
wire reset; |
wire clock; |
wire locked; |
wire usec_tick; |
wire msec_tick; |
wire next_test; |
wire next_step; |
wire [`SELECT_WIDTH-1:0] select; |
wire valid; |
|
reg [1:0] buttons_reg; |
|
// replace the clock generator with the appropriate module for your part |
assign reset = ~locked; |
|
/*clockgen clockgen ( |
.inclk0(refclock), |
.c0(clock), |
.locked(locked) |
);*/ |
clockgen clockgen ( |
.CLKIN_IN(refclock), |
.CLKFX_OUT(clock), |
.CLKIN_IBUFG_OUT(), |
.LOCKED_OUT(locked) |
); |
|
// register inputs |
always @(posedge clock) |
begin |
buttons_reg <= buttons; |
end |
|
// this counter is always enabled, so subtract 1 from the count to account for |
// the extra clock that it takes to reload the counter |
pulser #( |
.count(`MHZ-1) |
) usec_pulser ( |
.enable(1'b1), |
.out(usec_tick), |
|
.clock(clock), |
.reset(1'b0) |
); |
|
// this counter is only enabled every few clocks, so use the full count because |
// the clock that it takes to reload the counter will happen between enables |
pulser #( |
.count(1000) |
) msec_pulser ( |
.enable(usec_tick), |
.out(msec_tick), |
|
.clock(clock), |
.reset(1'b0) |
); |
|
// this assumes that the buttons are normally low, it fires a pulse on the |
// rising edge of a button event, and only accepts one event per DEBOUNCE_MSEC |
debouncer #( |
.low_count(`DEBOUNCE_MSEC) |
) next_test_debouncer ( |
.enable(msec_tick), |
.in(buttons_reg[1]), |
.out(), |
.rising_pulse(next_test), |
.falling_pulse(), |
.valid(), |
|
.clock(clock), |
.reset(1'b0) |
); |
|
debouncer #( |
.low_count(`DEBOUNCE_MSEC) |
) next_step_debouncer ( |
.enable(msec_tick), |
.in(buttons_reg[0]), |
.out(), |
.rising_pulse(next_step), |
.falling_pulse(), |
.valid(), |
|
.clock(clock), |
.reset(1'b0) |
); |
|
// the arbiter demo module |
demo #( |
.width(`WIDTH), |
.select_width(`SELECT_WIDTH) |
) demo ( |
.next_test(next_test), |
.next_step(next_step), |
.select(select), |
.valid(valid), |
|
.clock(clock), |
.reset(reset) |
); |
|
// this stretches brief changes long enough to be visible, specifically, to see |
// select blip when the arbiter wraps around (a wrap around is the transition |
// from granting a higher number req to a lower number, and while select blips, |
// all grants are deasserted) |
stretcher #( |
.count(`STRETCH_MSEC), |
.width(`SELECT_WIDTH) |
) select_stretcher ( |
.enable(msec_tick), |
.in(select), |
.out(indicators[`SELECT_WIDTH:1]), |
.valid(), |
|
.clock(clock), |
.reset(1'b0) |
); |
|
stretcher #( |
.count(`STRETCH_MSEC) |
) valid_stretcher ( |
.enable(msec_tick), |
.in(valid), |
.out(indicators[0]), |
.valid(), |
|
.clock(clock), |
.reset(1'b0) |
); |
|
endmodule |
/trunk/rtl/verilog/lfsr.v
0,0 → 1,88
/* |
* Copyright (c) 2009, 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 lfsr #( |
parameter width = 0, |
parameter reset_value = {width{1'b1}} |
)( |
input enable, |
input load, |
input in, |
output reg [width-1:0] out, |
|
input clock, |
input reset |
); |
|
// it's assumed that the msb is a tap so it need not be in this table, |
// indexes are 0-based, you can add cases for any other widths |
function is_tap ( |
input integer width, index |
); |
begin |
case(width) |
3: is_tap = index == 1; |
4: is_tap = index == 2; |
5: is_tap = index == 2; |
6: is_tap = index == 4; |
7: is_tap = index == 5; |
8: is_tap = index == 5 || index == 4 || index == 3; |
15: is_tap = index == 13; |
16: is_tap = index == 14 || index == 12 || index == 3; |
31: is_tap = index == 27; |
32: is_tap = index == 21 || index == 1 || index == 0; |
63: is_tap = index == 61; |
64: is_tap = index == 62 || index == 60 || index == 59; |
127: is_tap = index == 125; |
128: is_tap = index == 125 || index == 100 || index == 98; |
default: is_tap = 0; |
endcase |
end |
endfunction |
|
// combine the taps to compute the next lsb |
function [0:0] feedback ( |
input [width-1:0] value |
); |
integer i; |
begin |
// always include the msb |
feedback = value[width-1]; |
|
// include the other taps specified by the table |
for(i = 0; i < width - 1; i = i + 1) |
begin |
if(is_tap(width, i)) |
feedback = feedback ^ value[i]; |
end |
end |
endfunction |
|
// the shift register |
always @(posedge clock, posedge reset) |
begin |
if(reset) |
out <= reset_value; |
else |
begin |
if(enable) |
out <= {out[width-2:0], load ? in : feedback(out)}; |
end |
end |
|
endmodule |
/trunk/rtl/verilog/arbiter.v
1,5 → 1,5
/* |
* Copyright (c) 2008, Kendall Correll |
* Copyright (c) 2008-2009, 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 |
142,7 → 142,7
arbiter #( |
.width(width0), |
.select_width(select_width0) |
) stage0_narb ( |
) stage0_arb ( |
.enable(enable), |
.req(req0), |
.grant(grant0), |
/trunk/rtl/verilog/pulser.v
17,9 → 17,9
`timescale 1ns / 1ps |
|
module pulser #( |
parameter count = 0, |
parameter count = 1, |
parameter toggle = 0 |
) ( |
)( |
input enable, |
output reg out, |
|
31,12 → 31,13
|
// 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; |
reg [counter_width:0] counter; |
wire [counter_width-1:0] counter_load; |
wire counter_overflow; |
|
assign counter_overflow = counter[counter_width]; |
assign counter_overflow = counter[counter_width]; |
assign counter_load = -count; |
|
always @(posedge clock, posedge reset) |
begin |