blob: 66407aed201e28373d3733e893453391ed13e036 [file] [log] [blame] [edit]
module arbiter(clock, reset, roundORpriority, request, tpriority, grant);
integer i,j,k,p,q,r,s,t,u,v; //index for "for" loops
//------------------------------------------------------------------------
// parameters
//------------------------------------------------------------------------
parameter NUMUNITS = 8;
parameter ADDRESSWIDTH = 3; //number of bits needed to address NUMUNITS
//------------------------------------------------------------------------
// input and output declarations
//------------------------------------------------------------------------
input clock;
input reset;
input roundORpriority;
input [NUMUNITS-1 : 0] request;
input [ADDRESSWIDTH*NUMUNITS-1 : 0] tpriority;
output [NUMUNITS-1 : 0] grant;
//hack for 2-D input
reg [ADDRESSWIDTH-1 : 0] prio [NUMUNITS-1 : 0];
reg [ADDRESSWIDTH-1 : 0] tmp_prio;
always@(tpriority)
begin
for (i=0; i<NUMUNITS; i=i+1)
begin
for (j=0; j<ADDRESSWIDTH; j=j+1)
tmp_prio[j] = tpriority[i*ADDRESSWIDTH + j];
prio[i] = tmp_prio;
end
end
reg [NUMUNITS-1 : 0] grant; //registered output
reg [NUMUNITS-1 : 0] grantD; //input to "grant" flip-flop
reg [ADDRESSWIDTH-1 : 0] next; //index of next unit in round-robin
reg [ADDRESSWIDTH-1 : 0] nextNext; //input to "next" flip-flop
reg [ADDRESSWIDTH-1 : 0] scan [NUMUNITS-1 : 0];
//stores info on the order in which to scan units for round-robin
reg [NUMUNITS-2 : 0] found;
//in round-robin search, stores info on where assignment is made
reg [ADDRESSWIDTH-1 : 0] selectPrio[NUMUNITS-1 : 0];
//holds the priorities of only those units requesting the bus
reg [ADDRESSWIDTH-1 : 0] min;
//holds the minimum priority of all units currently requesting the bus
reg [NUMUNITS-1 : 0] minPrio;
//units that have the minimum priority
wire [NUMUNITS-1 : 0] prioRequest;
//request signals for only those units with minimum priority
reg [NUMUNITS-1 : 0] finalRequest;
//requests actually examined depending on "roundORpriority"
// flip-flop for "grant" signals
always@(posedge clock)
begin
if(!reset) grant <= 0;
else grant <= grantD;
end
// flip-flop for "next" register
always@(posedge clock)
begin
if(!reset) next <= 0;
else next <= nextNext;
end
//selects the priorities of units sending requests
always@(request or prio[7] or prio[6] or prio[5] or prio[4] or
prio[3] or prio[2] or prio[1] or prio[0])
begin
for(k=0; k<NUMUNITS; k=k+1)
selectPrio[k] = request[k] ? prio[k] : NUMUNITS-1;
end
//selects priority or round robin operation
always@(prioRequest or request or roundORpriority)
begin
for(r=0; r<NUMUNITS; r=r+1)
finalRequest[r] = roundORpriority ? prioRequest[r] :
request[r];
end
//this logic finds the minimum priority out of all units sending a
//request
always@(selectPrio[7] or selectPrio[6] or selectPrio[5] or
selectPrio[4] or selectPrio[3] or selectPrio[2] or
selectPrio[1] or selectPrio[0])
begin
min = selectPrio[0];
for (p=1; p<NUMUNITS; p=p+1)
if (selectPrio[p] < min) min = selectPrio[p];
end
//this logic decides if the units have minimum priority
always@(min or minPrio or prio[7] or prio[6] or prio[5] or prio[4]
or prio[3] or prio[2] or prio[1] or prio[0])
begin
for(q=0; q<NUMUNITS; q=q+1)
minPrio[q] = (prio[q]==min) ? 1:0;
end
//produces request signals for units that have minimum priority
assign prioRequest = minPrio & request;
//produces the "scan" array
always@(next)
begin
for(s=0; s<NUMUNITS; s=s+1)
scan[s] = (next+s < NUMUNITS) ? next+s : next+s-NUMUNITS;
end
//produces the "found" array
always@(finalRequest or scan[7] or scan[6] or scan[5] or scan[4] or
scan[3] or scan[2] or scan[1] or scan[0])
begin
found[0] = finalRequest[scan[0]];
for(t=1; t<NUMUNITS-1; t=t+1)
found[t] = found[t-1] || finalRequest[scan[t]];
end
//produces inputs to "grant" flip-flops
always@(finalRequest or found or scan[7] or scan[6] or scan[5] or
scan[4] or scan[3] or scan[2] or scan[1] or scan[0])
begin
grantD[scan[0]] = finalRequest[scan[0]];
for(u=1; u<NUMUNITS; u=u+1)
grantD[scan[u]] = finalRequest[scan[u]] && ~found[u-1];
end
always@(grantD)
begin
nextNext = 0;
for(v=0; v<NUMUNITS-1; v=v+1)
if(grantD[v]) nextNext = v+1;
end
endmodule //arbiter