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 11 to Rev 12
    Reverse comparison

Rev 11 → Rev 12

/trunk/bench/verilog/tb_arbiter.v
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
/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/bench/verilog/tb_abrbiter2.v
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
/trunk/bench/verilog/tb_arbiter.txt
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
/trunk/bench/verilog/tb_arbiter2.txt
0,0 → 1,8
8176255410b7cb44a074ee702a9a86db
8176255410b7cb44a074ee702a9a86db
49539737fd0c739c556513c608c1228b
10a60347121e743967d73eb4a2dc629b
ee6064c875d6fdbda8a95e35102c551e
0d1361fd41adf235fdafff491b1963e4
0d1361fd41adf235fdafff491b1963e4
e89c064542709e292edd0abf77b1e89c
/trunk/rtl/verilog/stretcher.v
0,0 → 1,105
/*
* 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.
*/
 
`timescale 1ns / 1ps
 
module stretcher #(
parameter count = 1,
parameter high_count = count,
parameter low_count = count,
parameter width = 1,
parameter reset_value = {width{1'b0}}
)(
input enable,
input [width-1:0] in,
output reg [width-1:0] 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(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;
wire counter_overflow;
 
assign counter_overflow = counter[counter_width];
 
// select counter value for rising or falling edge
always @(rising, falling)
begin
case({rising, falling})
'b11:
counter_load = -count;
'b10:
counter_load = -high_count;
'b01:
counter_load = -low_count;
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 <= reset_value;
else
begin
if(counter_overflow)
out <= in;
end
end
 
always @(posedge clock, posedge reset)
begin
if(reset)
valid <= 0;
else
valid <= counter_overflow;
end
 
endmodule
/trunk/rtl/verilog/shifter.v
0,0 → 1,58
/*
* 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.
*/
 
`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)
begin
internal[(i*width)-1-:width] <= load
? parallel_in[(i*width)-1-:width]
: internal[((i+1)*width)-1-:width];
end
end
end
 
endmodule
/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/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/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/debouncer.v
0,0 → 1,132
/*
* 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.
*/
 
`timescale 1ns / 1ps
 
module debouncer #(
parameter count = 1,
parameter high_count = count,
parameter low_count = count,
parameter width = 1,
parameter reset_value = {width{1'b0}}
)(
input enable,
input [width-1:0] in,
output [width-1:0] out,
output reg rising_pulse,
output reg falling_pulse,
output reg valid,
input clock,
input reset
);
 
`include "functions.v"
 
reg [width-1:0] in_reg;
reg [width-1:0] out_reg;
 
always @(posedge clock)
begin
in_reg <= in;
end
 
// edge detector
wire rising;
wire falling;
 
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(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;
wire counter_overflow;
 
assign counter_overflow = counter[counter_width];
 
// select counter value for rising or falling edge
always @(rising, falling)
begin
case({rising, falling})
'b11:
counter_load = -count;
'b10:
counter_load = -high_count;
'b01:
counter_load = -low_count;
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
assign out = out_reg;
 
always @(posedge clock, posedge reset)
begin
if(reset)
out_reg <= reset_value;
else
begin
if(counter_overflow)
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)
begin
if(reset)
valid <= 1'b0;
else
valid <= counter_overflow;
end
 
endmodule
/trunk/rtl/verilog/functions.v
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<<i))
flog2 = i;
end
end
endfunction
 
// compute the log base 2 of a number, rounded up to the
// nearest whole number
function integer clog2 (
input integer number
);
integer i;
integer count;
begin
clog2 = 0;
count = 0;
for(i = 0; i < 32; i = i + 1)
begin
if(number&(1<<i))
begin
clog2 = i;
count = count + 1;
end
end
// clog2 holds the largest set bit position and count
// holds the number of bits set. More than one bit set
// indicates that the input was not an even power of 2,
// so round the result up.
if(count > 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
/trunk/rtl/verilog/arbiter.v
0,0 → 1,388
/*
* 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.
*/
 
`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_arb (
.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
/trunk/rtl/verilog/pulser.v
0,0 → 1,68
/*
* 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 = 1,
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;
 
reg [counter_width:0] counter;
wire [counter_width-1:0] counter_load;
wire counter_overflow;
 
assign counter_overflow = counter[counter_width];
assign counter_load = -count;
 
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
/trunk/doc/arbiter_diagram.pdf
0,0 → 1,372
%PDF-1.4
%äüöß
2 0 obj
<</Length 3 0 R/Filter/FlateDecode>>
stream
+Hcfu΂l#2ٚdYi0zĒ΂GdwfiLE1Bܷdr=Fdr/&3<$ơӄir\~,&>"dU=.x*bmB,ٱ\7r&6 [_l]E_lyEt]J^t6IU$9Zx|qW- dHr!*b(a=ad5hGAPh4́:u *ءS4;z yDdGuR툸.$q]U;Ā.΢ԕΡ$AHp5vx\q]\u!Bq%F4KPt+ vyJAa;єA Iv\B+1 pT9$(vÕxddǃ5s<q)Kt aY>X06.2Nk+nZe#6yyrPSHc_y)$(Ӯ824ʠ̿>\ i`W;mE{$VFWөˤcjX⋎T>9ޯkeo`rs=Gɦϗ;uWd>^Oe=߿þeyFϧ3uva{;UpuÒ +TÕm:]S8ݻ"{ցTn`Va_wvmt6sbgn;='w9Ɲo;='ӓo:='S[˓z\ +9^7*9]cRrrLܨ4Mɛ@tcݣڱugTq^w9LfOP۠<'%٦;to̲3;&)7Pэաt+ƈo3_WPeYn1!"t&]i:WPe=ѷYL_* +*6 +b| +BOsHj쾡&) Dr + %% +.AtGt`QQC`J2sh|N*Pe5#NMggե zv<ߨt}&™+=,n2[⌘:_{7T +S1!َh6*,VN2!L`q̓AMAgW΀J'|CjwK'9hlϞhyc'/ ǖdtH/fOҝ' ry1IbOQC^̶Ч(j]|G)t} +} +endstream +endobj + +3 0 obj +3035 +endobj + +5 0 obj +<> +stream +xZKo7 ϯsoE1#`ai5C[@-\Kz7gûlc(R`:7я ^\^1fwr y|ׄ;c>,i + `4=frsjWy 0w闪|oaN y̰Ώ~<:C]Gѥ{zO?OYpbjr +MӌDXcyIoRC8lm}uCjifrHE Q2I#kGkȁ$֎1fѺف!}C(8zAʓ@j٠`v,cH!ǵi@]ɱ!֫@=ŗf#6|ʠD.#CDGa0Q:}Op= &Ar +Mj*5kTqR=cQq9EXƩm}v~E`A7?j3$s-A䁠b?XPVcՔňz~aN%P=tHF߬RcFU8/=zƄJ&Ŋ(F6=y +,Y˃9WHS!Eh@Pc( 1Tj@c@RIuHF߬RcFUc煸GϘ0uTy0*/VF4qy8<mX"]`zt6TpfzaPFK,rRYb"BܣgL:`YHimkbʴ/(2r绚ed%@q(6rR5lbELܫL+mK"ސi͛-m-֨j%Ek |mE:/}a/J %OBvf2+3%g!Hu"tf1;EBܫ&Ȩ&v,;)ʝ#PEsԳ04M@*uK}J8L +%nLJvM%9]U(rf%ldՔ<^V$H`Cv&HF߬Rحvr .?~?Ɣ b掳"׊:DpCUP4bFBܫ&H.5Vo%PvHF6bꨆ0ś@΋"0+3 F߬g&u&q!!r⿖a-0L $~G֡A-AI"OB> +stream +xy|8~ΙνwflFr"*A"$Fe3V\`U ڪTZu+mZJ[1sfn} 3̙3gy<9C"ڌ8m +D(Dw +jTCq)B҄%uREQ8zs, +$!/CS?=WlWPDF2xӂ N)iDaKh$Z} &E~r +dA~>\gdi!?ڐj Gj|Q"׸5)3 3P$ 2n77d"YJ~@}F^_Э'؆9\7|/>OO2"_pj9 +|*ga~ +,,^>4M^_㵳s۵Goj;<>m*#6R{ɯȯ:nN%N a2rYyh%qí矅 + aDʠΟsE|{ÝZA.onOf<Ǐ4~oDGH%h싺]3Q\qd&ptZEB ;ݸ_nCx= +R1Bhj"v܃zW30'8V\ݧ:k{Zyzh;Z؂  Q&nMUN; +q@Ư-+ԣOz +A Ŀ'E&Vĝ((qݎmQ+ +O&ׄɉ|E&ȞK OxC]w瀆-CWϡ+>TI&&shND*6D#E? +>r:6d1DAj#U&Y5|V+s( + a 52$M4O\òɗ@QrFsbI.GyreH>9)$s|P `ii\驟$w{ʚIPAabhb̐vZbxw  M&tsѺsUNUu㉵e(tE%̲nn-FnAvJhYMX E,Ukg +bIJShAbڢT`nV, +AKl, +Wu@nĚ.iMw RHҔɔ(Hd}ss)h'Msi~ޚ^ +GDQ@/ҫRBWvr_ +/jsQ'T=[7vKjYϋ7s0 <^NՊB5(H֊xE89i'Ap^#iAc#2ip=syb1EnE,Yi&f-~pV>vUTT[ڐ捀+T݆ѣGYtVn{h|C5׎ˮuW_9)5mo'|*R Z2RR*RSIj*`/pE5uwfUUY]VMfW/m;?3T,Z +[ǀ̇p +PY%T< +[=AϗKrI*92ZdLy`KctHYVُ-0sG l.r]NkZEiP{5Ζ =lϺ@eQ w:,I @EUG{RXS^ش8EsnJBӠӕHl\JimҳDX+U۪]s=MBNj5"̒"^\N;iT*3h‘DF/cdf]b@6G:D9jaF ˄ezWW!.!14:Oz柿]cvl?txێCĎo[nAlzWW^MN| +\M:V:!uR~kC?y?d+55F4д$TGJMHicjjB +feD/ɶ)TSS[{>:lσpZI][W.=\?0DJHgI!kR0T$KlT`+aNlm7nSxx@~s͏]?u05g15^}/ *uo$ב4ьmSRyD[cW-f2SD +y)ny<Y2߯ +>P`La_7bRu(W^e*L+D{e~\sH  ŹEnrM>;J?7TJXzgwS}׃=n:1 ?3 A0 +;)wZ\LĘd +ӛc*Ӻs hv !6a0 cIU..1p#~ 5=zqmn]%>&e0*sh1%pQF*;0p[YƐ}'?v:+QR=;x"h ylaJWx +;("3B6?T&D\6܎nNk 6w#egjyTsR?O +',CD3ԩ.`59%ʐ O"&2LQL X"oCLH5 a@rZ +Ny9OЧ )(Gϲbk/=@ LDCu6u &FD +M`e'(~Patd Pfe36e¬.!-)ci*ә5W +Fۨ34 4T&`ZؓzתMX/fwhV% ~Cg6(V,UZp*^9 FLd/&CLMPIAĬĉs7NJ?ORzhx6$/͗Wqu:J[ܡ lm{elM"l2&ed!9V6h>fFlHf)a$B/=M-iwR." +Yt?Y@[ ƣ׬r1)qtZc4AG2: j/P864fOm9כuW3t<@/pPA +,:09A)gQe^Dآ":`/-JKٗp𰓕d.uEOڪAeҐ3$uZ?MsNiK'SgNӡ%+pڀI%hL pMuMHHh#wVNu[Pom1nnuj}nKI9}&˅/gQ E tz%+"RAv,Y$ ;ws2ڝ.3$#] ׯuN]HZ2N*K)$QZԊ:R6)}Oq=LٔXͶkJ +\9y߾(pYȇZ)3rŦ1jE6FDXa{>IW7ÖI@Yc倁"09E%hEeزbi8Tjj̱دtU٪U[^ƴz:6Sumf=}gg>v4 ӑmjle7eexl1Kcf3 3m@pqc-b#Kmۈ_qԂQ@_1lEdH%rńHDq!=~yrO7@ 䡋 +ц)8NC=#6.q3`q)&OTNPЇ2M= :{ +g|⭱UpB_"n4tMN2K%z +$T.Ib9>-/G]4F[.QGeG2\ +FCЋOG45mLe> p9պ:;Ta+}(zpgSҖVZ5e,`ОPp2\5c{̞2#S)eb>J+؜ #A%Z6pnU1n"c +q؂}@^θ$9qqWx5kIcO`g$۹.)2&g㪴KRιn[LYI ; 0dV$5;B9 eg&eV.d6WV;bLY6J۹.ͦ.˭Ҷ24qUO˲|8 >?jdKo_O.S~0;g +.Z/c0ժ.+W$?3l2 +m>{Hu|auP4P67سVUZC4x1AR쓣jXx7w*#kӦK.7iXq×ۅ'w?X6hu/_ſoI+Bhxñ5|m[U\*#k:_kT4Yx/Q5z>9*Oy+2h*g? +IpN^BJ8oД&໛஧w ~6ߞx_8OYB8}j 8pΣPrVBizm`gzߣy-/Dȉ>Md y1J-+׍-̽6R@`l:GBW oo?3M) +pT E=?er*֊XJ\&CMf*48*Ǿ2c +sZRap +ߨZLڪ:d>Ra=Wa#i`T-vp*lFjh )E- (Ew3Xcf?c +Uaw +sThmPaw +|0UaO* 4J}RFEFr +"Cʃ +Au*QLɪ&qV^R梅54grתH \DQ0壌V +w jYV&{ +5l)zqMi{;1jX uf $f;Րr2u :BuvE;THSeCSy(EױVrk!NSjcjeR~ɺΤ mjT,v-Nxd +ؘXZңa vjLjQ(ƞR + s߭a-%olX-3Aχ~2(< R0Yz%̃+)0T1G&JڿtEN8(6DFNy{wY;~kKEs QE~Tٮ +1] @gaeM- +(KAw0*Hպ^VWХ1|L]>9VwY5jcmjv-u Ckbku|@h!7GhSC4^Ų&~ʽZG3,7%cFcF/*)*LĢ#KJ:xOH?!OH?!ڹޘ6;%6^ +KٯRC,G [h PI% *Y/Q?v}\V=>$ >~"MB6 +L 5`p?>{{C4.˿,,cz;8w`|=<+PkQexkEjԫ=:ήDza4osU:+ =2{;nZ^ZG[RI~#MTB"U٫b5lӣ¶Q'[`MT/'22O>3LӸ;Ã֦uf"7qѿs73џ:}`7zO?<"{;HT$fi4Y$6wrB3vlQ9jN|c> +endobj + +11 0 obj +<> +stream +x]N0E +/ayP)TZ*uC> M%u"7]5 hulߙXt]o0~v4zO;R{:.FC7ǕwvJPg:ma$} g_Ͳt/'?Xzw/:U4Uw4W +45 +endstream +endobj + +12 0 obj +<> +endobj + +13 0 obj +<> +endobj + +14 0 obj +<> +endobj + +1 0 obj +<>/Contents 2 0 R>> +endobj + +4 0 obj +<>/Contents 5 0 R>> +endobj + +15 0 obj +<> +endobj + +16 0 obj +< +/Dest[1 0 R/XYZ 0 792 0]/Parent 15 0 R/Next 17 0 R>> +endobj + +17 0 obj +< +/Dest[4 0 R/XYZ 0 792 0]/Parent 15 0 R/Prev 16 0 R>> +endobj + +7 0 obj +<> +endobj + +18 0 obj +<> +endobj + +19 0 obj +< +/Producer +/CreationDate(D:20080805213703-07'00')>> +endobj + +xref +0 20 +0000000000 65535 f +0000027692 00000 n +0000000019 00000 n +0000003125 00000 n +0000027835 00000 n +0000003146 00000 n +0000005299 00000 n +0000028276 00000 n +0000005320 00000 n +0000026555 00000 n +0000026577 00000 n +0000026765 00000 n +0000027261 00000 n +0000027604 00000 n +0000027637 00000 n +0000027978 00000 n +0000028034 00000 n +0000028155 00000 n +0000028381 00000 n +0000028482 00000 n +trailer +< +<586296B84E8AF08F010ED6036E89DC9F> ] +/DocChecksum /9DC167ACCAD43A8345B1B0E639C4D500 +>> +startxref +28661 +%%EOF
/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 : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property

powered by: WebSVN 2.1.0

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