//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
// Srdy/drdy round-robin arbiter
|
// Srdy/drdy round-robin arbiter
|
//
|
//
|
// Asserts drdy for an input and then moves to the next input.
|
// Asserts drdy for an input and then moves to the next input.
|
//
|
//
|
// This component supports multiple round-robin modes:
|
// This component supports multiple round-robin modes:
|
//
|
//
|
// Mode 0 : Each input gets a single cycle, regardless of data
|
// Mode 0 : Each input gets a single cycle, regardless of data
|
// availability. This mode functions like a TDM
|
// availability. This mode functions like a TDM
|
// demultiplexer. Output flow control will cause the
|
// demultiplexer. Output flow control will cause the
|
// component to stall, so that inputs do not miss their
|
// component to stall, so that inputs do not miss their
|
// turn due to flow control.
|
// turn due to flow control.
|
|
// Mode 0 fast arb : Each input gets a single grant. If the
|
|
// output is not ready (p_drdy deasserted), then the
|
|
// machine will hold on that particular input until it
|
|
// receives a grant. Once a single token has been
|
|
// accepted the machine will round-robin arbitrate.
|
|
// When there are no requests the machine returns to
|
|
// its default state.
|
// Mode 1 : Each input can transmit for as long as it has data.
|
// Mode 1 : Each input can transmit for as long as it has data.
|
// When input deasserts, device will begin to hunt for a
|
// When input deasserts, device will begin to hunt for a
|
// new input with data.
|
// new input with data.
|
// Mode 2 : Continue to accept input until the incoming data
|
// Mode 2 : Continue to accept input until the incoming data
|
// matches a particular "end pattern". The end pattern
|
// matches a particular "end pattern". The end pattern
|
// is provided on the c_rearb (re-arbitrate) input. When
|
// is provided on the c_rearb (re-arbitrate) input. When
|
// c_rearb is high, will hunt for new inputs on next clock.
|
// c_rearb is high, will hunt for new inputs on next clock.
|
//
|
//
|
// This component also supports two arbitration modes: slow and fast.
|
// This component also supports two arbitration modes: slow and fast.
|
// slow rotates the grant from requestor to requestor cycle by cycle,
|
// slow rotates the grant from requestor to requestor cycle by cycle,
|
// so each requestor gets serviced at most once every #inputs cycles.
|
// so each requestor gets serviced at most once every #inputs cycles.
|
// This can be useful for producing a TDM-type interface, however
|
// This can be useful for producing a TDM-type interface, however
|
// requestors may be delayed waiting for the grant to come around even
|
// requestors may be delayed waiting for the grant to come around even
|
// if there are no other requestors.
|
// if there are no other requestors.
|
//
|
//
|
// Fast mode immediately grants the highest-priority requestor, however
|
// Fast mode immediately grants the highest-priority requestor, however
|
// it is drdy-noncompliant (drdy will not be asserted until srdy is
|
// it is drdy-noncompliant (drdy will not be asserted until srdy is
|
// asserted).
|
// asserted).
|
//
|
//
|
// Naming convention: c = consumer, p = producer, i = internal interface
|
// Naming convention: c = consumer, p = producer, i = internal interface
|
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
// Author: Guy Hutchison
|
// Author: Guy Hutchison
|
//
|
//
|
// This block is uncopyrighted and released into the public domain.
|
// This block is uncopyrighted and released into the public domain.
|
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
|
|
// Clocking statement for synchronous blocks. Default is for
|
// Clocking statement for synchronous blocks. Default is for
|
// posedge clocking and positive async reset
|
// posedge clocking and positive async reset
|
`ifndef SDLIB_CLOCKING
|
`ifndef SDLIB_CLOCKING
|
`define SDLIB_CLOCKING posedge clk or posedge reset
|
`define SDLIB_CLOCKING posedge clk or posedge reset
|
`endif
|
`endif
|
|
|
// delay unit for nonblocking assigns, default is to #1
|
// delay unit for nonblocking assigns, default is to #1
|
`ifndef SDLIB_DELAY
|
`ifndef SDLIB_DELAY
|
`define SDLIB_DELAY #1
|
`define SDLIB_DELAY #1
|
`endif
|
`endif
|
|
|
module sd_rrmux
|
module sd_rrmux
|
#(parameter width=8,
|
#(parameter width=8,
|
parameter inputs=2,
|
parameter inputs=2,
|
parameter inputs_asz=1, // log2(inputs)
|
parameter inputs_asz=1, // log2(inputs)
|
parameter mode=0,
|
parameter mode=0,
|
parameter fast_arb=0)
|
parameter fast_arb=0)
|
(
|
(
|
input clk,
|
input clk,
|
input reset,
|
input reset,
|
|
|
input [(width*inputs)-1:0] c_data,
|
input [(width*inputs)-1:0] c_data,
|
input [inputs-1:0] c_srdy,
|
input [inputs-1:0] c_srdy,
|
output [inputs-1:0] c_drdy,
|
output [inputs-1:0] c_drdy,
|
input c_rearb, // for use with mode 2 only
|
input c_rearb, // for use with mode 2 only
|
|
|
output reg [width-1:0] p_data,
|
output [width-1:0] p_data,
|
output [inputs-1:0] p_grant,
|
output [inputs-1:0] p_grant,
|
output reg p_srdy,
|
output p_srdy,
|
input p_drdy
|
input p_drdy
|
);
|
);
|
|
|
reg [inputs-1:0] rr_state;
|
reg [inputs-1:0] rr_state;
|
reg [inputs-1:0] nxt_rr_state;
|
reg [inputs-1:0] nxt_rr_state;
|
|
|
wire [width-1:0] rr_mux_grid [0:inputs-1];
|
//wire [width-1:0] rr_mux_grid [0:inputs-1];
|
reg rr_locked;
|
reg rr_locked;
|
genvar i;
|
//genvar i;
|
integer j;
|
integer j;
|
|
|
assign c_drdy = rr_state & {inputs{p_drdy}};
|
assign c_drdy = rr_state & {inputs{p_drdy}};
|
assign p_grant = rr_state;
|
assign p_grant = rr_state;
|
|
|
function [inputs-1:0] nxt_grant;
|
function [inputs-1:0] nxt_grant;
|
input [inputs-1:0] cur_grant;
|
input [inputs-1:0] cur_grant;
|
input [inputs-1:0] cur_req;
|
input [inputs-1:0] cur_req;
|
reg [inputs-1:0] msk_req;
|
reg [inputs-1:0] msk_req;
|
reg [inputs-1:0] tmp_grant;
|
reg [inputs-1:0] tmp_grant;
|
begin
|
begin
|
msk_req = cur_req & ~((cur_grant - 1) | cur_grant);
|
msk_req = cur_req & ~((cur_grant - 1) | cur_grant);
|
tmp_grant = msk_req & (~msk_req + 1);
|
tmp_grant = msk_req & (~msk_req + 1);
|
|
|
if (msk_req != 0)
|
if (msk_req != 0)
|
nxt_grant = tmp_grant;
|
nxt_grant = tmp_grant;
|
else
|
else
|
nxt_grant = cur_req & (~cur_req + 1);
|
nxt_grant = cur_req & (~cur_req + 1);
|
end
|
end
|
endfunction
|
endfunction
|
|
|
generate
|
always @*
|
for (i=0; i<inputs; i=i+1)
|
begin
|
begin : grid_assign
|
data_ind = 0;
|
assign rr_mux_grid[i] = c_data >> (i*width);
|
for (j=0; j<inputs; j=j+1)
|
|
if (rr_state[j])
|
|
data_ind = j;
|
end
|
end
|
|
|
|
generate
|
|
/* -----\/----- EXCLUDED -----\/-----
|
|
for (i=0; i<inputs; i=i+1)
|
|
begin : grid_assign
|
|
wire [width-1:0] temp;
|
|
assign temp = c_data >> (i*width);
|
|
assign rr_mux_grid[i] = c_data >> (i*width);
|
|
end
|
|
-----/\----- EXCLUDED -----/\----- */
|
|
|
if (mode == 2)
|
if (mode == 2)
|
begin : tp_gen
|
begin : tp_gen
|
reg nxt_rr_locked;
|
reg nxt_rr_locked;
|
reg selected_srdy;
|
reg selected_srdy;
|
|
|
always @*
|
always @*
|
begin
|
begin
|
if (c_rearb)
|
/* -----\/----- EXCLUDED -----\/-----
|
|
data_ind = 0;
|
|
for (j=0; j<inputs; j=j+1)
|
|
if (rr_state[j])
|
|
data_ind = j;
|
|
-----/\----- EXCLUDED -----/\----- */
|
|
|
|
nxt_rr_locked = rr_locked;
|
|
|
|
if ((c_srdy & rr_state) & (!rr_locked))
|
|
nxt_rr_locked = 1;
|
|
else if ((c_srdy & rr_state & c_rearb) & p_drdy )
|
nxt_rr_locked = 0;
|
nxt_rr_locked = 0;
|
else if ((nxt_rr_state != rr_state) && (nxt_rr_state != 0))
|
else if ((nxt_rr_state != rr_state) && (nxt_rr_state != 0))
|
nxt_rr_locked = 1;
|
nxt_rr_locked = 1;
|
else
|
else
|
nxt_rr_locked = rr_locked;
|
nxt_rr_locked = rr_locked;
|
end
|
end
|
|
|
always @(`SDLIB_CLOCKING)
|
always @(`SDLIB_CLOCKING)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
rr_locked <= `SDLIB_DELAY 0;
|
rr_locked <= `SDLIB_DELAY 0;
|
else
|
else
|
rr_locked <= `SDLIB_DELAY nxt_rr_locked;
|
rr_locked <= `SDLIB_DELAY nxt_rr_locked;
|
end
|
end
|
end // block: tp_gen
|
end // block: tp_gen
|
endgenerate
|
endgenerate
|
|
|
always @*
|
assign p_srdy = |(rr_state & c_srdy);
|
begin
|
assign p_data = c_data[data_ind*width +: width];
|
p_data = 0;
|
|
p_srdy = 0;
|
|
for (j=0; j<inputs; j=j+1)
|
|
if (rr_state[j])
|
|
begin
|
|
p_data = rr_mux_grid[j];
|
|
p_srdy = c_srdy[j];
|
|
end
|
|
end
|
|
|
|
always @*
|
always @*
|
begin
|
begin
|
if ((mode == 1) & (c_srdy & rr_state))
|
if ((mode == 1) & (c_srdy & rr_state))
|
nxt_rr_state = rr_state;
|
nxt_rr_state = rr_state;
|
else if ((mode == 0) & !p_drdy)
|
else if ((mode == 0) && !p_drdy && !fast_arb)
|
|
nxt_rr_state = rr_state;
|
|
else if ((mode == 0) && |(rr_state & c_srdy) && !p_drdy && fast_arb)
|
nxt_rr_state = rr_state;
|
nxt_rr_state = rr_state;
|
else if ((mode == 2) & (rr_locked | (c_srdy & rr_state)))
|
else if ((mode == 2) & (rr_locked | (c_srdy & rr_state)))
|
nxt_rr_state = rr_state;
|
nxt_rr_state = rr_state;
|
else if (fast_arb)
|
else if (fast_arb)
|
nxt_rr_state = nxt_grant (rr_state, c_srdy);
|
nxt_rr_state = nxt_grant (rr_state, c_srdy);
|
else
|
else
|
nxt_rr_state = { rr_state[0], rr_state[inputs-1:1] };
|
nxt_rr_state = { rr_state[0], rr_state[inputs-1:1] };
|
end
|
end
|
|
|
always @(`SDLIB_CLOCKING)
|
always @(`SDLIB_CLOCKING)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
rr_state <= `SDLIB_DELAY 1;
|
rr_state <= `SDLIB_DELAY (fast_arb)? 0 : 1;
|
else
|
else
|
rr_state <= `SDLIB_DELAY nxt_rr_state;
|
rr_state <= `SDLIB_DELAY nxt_rr_state;
|
end
|
end
|
|
|
endmodule // sd_rrmux
|
endmodule // sd_rrmux
|
|
|