`define WB_IDLE 4'h0
`define WB_DEV3_GNT 4'h8
`define WB_DEV2_GNT 4'h4
`define WB_DEV1_GNT 4'h2
`define WB_DEV0_GNT 4'h1
module wb_arbiter(wb_clk, wb_rst, wb_req, wb_gnt);
input wb_clk;
input wb_rst;
input [3:0] wb_req; /* запрос ведущего wb_устройства на обмен по wishbone шине */
output [3:0] wb_gnt; /* разрешение ведущему wb_устройству на обмен по wishbone шине */
/*================================================================================================*/
reg [3:0] arbiter_state; /* код ведущего, которому отдана шина */
wire arbiter_idle; /* шина свободна */
wire wb_release; /* ведущее wb_устройство освободило wb шину */
reg arbiter_idle_o; /* состояние arbiter_idle защелкнутое на предыдущем фронте wb_clk */
reg [3:0] wb_nice3, wb_nice2, wb_nice1, wb_nice0; /* сдвиговые регистры (маска приоритета) */
wire wb_req_nice3, wb_req_nice2, wb_req_nice1, wb_req_nice0; /* существует запрос этого приоритета */
assign arbiter_idle=!(|arbiter_state);
assign wb_req_nice3= |(wb_req & wb_nice3);
assign wb_req_nice2= |(wb_req & wb_nice2);
assign wb_req_nice1= |(wb_req & wb_nice1);
assign wb_req_nice0= |(wb_req & wb_nice0);
assign wb_release= !(|(wb_req & arbiter_state));
assign wb_gnt= arbiter_state;
/*================================================================================================*/
always @(posedge wb_clk or posedge wb_rst) /* изменение приоритетов ведущих wb_устройств */
begin
if(wb_rst)
begin
wb_nice3<= `WB_DEV3_GNT;
wb_nice2<= `WB_DEV2_GNT;
wb_nice1<= `WB_DEV1_GNT;
wb_nice0<= `WB_DEV0_GNT;
arbiter_idle_o<= 1'h0;
end
else
begin
arbiter_idle_o<= arbiter_idle;
if(arbiter_idle & ~arbiter_idle_o)
begin
wb_nice3<= wb_nice2;
wb_nice2<= wb_nice1;
wb_nice1<= wb_nice0;
wb_nice0<= wb_nice3;
end
end
end
/*================================================================================================*/
always @(posedge wb_clk or posedge wb_rst) /* арбитраж */
begin
if(wb_rst)
arbiter_state <= `WB_IDLE;
else
begin
if(arbiter_state == `WB_IDLE)
begin
if(wb_req_nice3) arbiter_state<= wb_nice3;
else
if(wb_req_nice2) arbiter_state<= wb_nice2;
else
if(wb_req_nice1) arbiter_state<= wb_nice1;
else
if(wb_req_nice0) arbiter_state<= wb_nice0;
end
else
if(wb_release) arbiter_state<= `WB_IDLE;
end
end
/*================================================================================================*/
endmodule