/*!
* Module:round_robin
* @file round_robin.v
* @date 2015-07-10
* @author Andrey Filippov
*
* @brief Round-robin arbiter
*
* @copyright Copyright (c) 2015 Elphel, Inc .
*
* License:
*
* round_robin.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* round_robin.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*/
`timescale 1ns/1ps
module round_robin #(
parameter FIXED_PRIORITY = 0, // 0 - round-robin, 1 - fixed channel priority (0 - highest)
parameter BITS = 2 // number of bits to encode channel number (1 << BITS) - number of inputs
)(
input clk,
input srst, // sync. reset - needed to reset current channel
input [(1 << BITS) -1:0] rq, // request vector
input en, // enable to grant highest priority request (should be reset by grant)
output reg grant, // changed to 1-cycle long (was: stays on until reset by !en)
output [BITS-1:0] chn,
output reg [(1 << BITS) -1:0] grant_chn); // 1-hot grant output per-channel, single-clock pulse
reg [BITS-1:0] last_chn;
wire valid;
wire [BITS-1:0] next_chn;
wire pre_grant_w;
reg grant_r;
assign pre_grant_w = en && valid &&!grant_r;
// assign grant = grant_r;
assign chn = last_chn;
assign {valid, next_chn}= func_selrr (rq, FIXED_PRIORITY?((1 << BITS) -1):last_chn);
always @ (posedge clk) begin
if (srst) last_chn <= (1 << BITS) -1;
else if (pre_grant_w) last_chn <= next_chn;
if (srst || !en) grant_r <= 0;
else if (valid) grant_r <= 1; // grant will stay on until reset by !en
grant_chn <= func_demux (!srst && pre_grant_w, next_chn);
grant <= !srst && pre_grant_w;
end
// round-robin priority encode
function [BITS : 0] func_selrr; // returns {valid, chn}
input [(1 << BITS) -1:0] rq; // request vector
input [BITS-1:0] cur_chn; // current (last served) channel - lowest priority
reg valid; // at least one request
reg [BITS - 1:0] chn, sample_chn;
integer i;
begin
valid = 0;
chn = 0;
for (i = 0; i < (1 << BITS); i = i+1) begin
sample_chn = (cur_chn - i) % (1 << BITS);
if (rq[sample_chn]) begin
valid = 1;
chn = sample_chn;
end
end
func_selrr = {valid,chn};
end
endfunction
function [(1 << BITS) -1:0] func_demux;
input en;
input [BITS - 1:0] sel;
integer i;
begin
for (i=0; i < (1 << BITS); i = i + 1) begin
func_demux[i] = en && (sel == i);
end
end
endfunction
endmodule