OpenCores
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/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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.