相关文章
数字IC前端学习笔记:LSFR(线性反馈移位寄存器)
数字IC前端学习笔记:跨时钟域信号同步
数字IC前端学习笔记:信号同步和边沿检测
数字IC前端学习笔记:锁存器Latch的综合
数字IC前端学习笔记:格雷码(含Verilog实现的二进制格雷码转换器)
数字IC前端学习笔记:FIFO的Verilog实现(一)
数字IC前端学习笔记:FIFO的Verilog实现(二)
数字IC前端学习笔记:仲裁轮询(一)
数字IC前端学习笔记:仲裁轮询(二)
数字IC前端学习笔记:仲裁轮询(三)
数字IC前端学习笔记:仲裁轮询(五)
数字IC前端学习笔记:仲裁轮询(六)
数字IC前端学习笔记:近期最少使用(LRU)算法
带权重的轮询(Weighted Round Robin, WRR)方案与常规的轮询方案类似,所不同的是不同的用户得到许可的机会存在差异,也就是说,不同的用户权重不同,权重高的用户得到许可的机会更多。权重的分配存在多种方式,这里介绍两种。第一种方法是为每个用户分配一个变量,该变量决定了在一个轮询周期内该用户能够得到许可(被授权)的次数。该变量是可以通过软件编程进行修改的,因此其轮询权重也可以相应调整。例如,有三个用户,agent0的权重为3,、agent1的权重为2、agent2的权重为1。在一个轮询周期中,agent0最大可以得到3次许可,agent1可以得到2次许可,agent2可以得到1次许可。在一个轮询周期开始时,变量N_agnt0、N_agnt1和N_agnt2分别被预置为3、2和1.每次轮询过后对应的变量值减1,一个轮询周期结束后,这些变量会被重新设置为预置的初值。如果所有的用户同时请求,仲裁器将按照下面两种方式之一给予许可:
1、一个用户可以连续地获取许可,获得许可的次数由预置的权重值决定。当所有用户同时发出请求时,许可序列依次为:
(A,A,A),(B,B),C, (A,A,A),(B,B),C ......
2、在所有存在许可机会的用户之间进行公平轮询,一个循环周期内,不同用户得到的总许可机会由预置的权重值决定。当所有请求同时发生时,许可序列为:
A,B,C,A,B,A B,C,A,B,A,A ......
在第二种方案中,可软件编程的定时器被用于分配权重。一个仲裁周期开始时,定时器数值被加载。当一个用户获得许可后,定时器开始计时,直到计满,此时如果被授权的用户没有完成操作,仲裁器停止对当前用户的许可并根据优先级轮询下一个用户。
下面是采用WRR轮询方案的Verilog代码及仿真结果,它采用的是第一种方法的第一种许可方式,序列为A,A,A,B,B,C...。
module arbiter_wrr(clk,resetb,req_vec,
req_vec_wt_0,
req_vec_wt_1,
req_vec_wt_2,
req_n_valid,
end_access_vec,
gnt_vec);
input clk;
input resetb;
input [2:0] req_vec;
input [3:0] req_vec_wt_0;
input [3:0] req_vec_wt_1;
input [3:0] req_vec_wt_2;
input req_n_valid;
input [2:0] end_access_vec;
output reg [2:0] gnt_vec;
reg [2:0] arbiter_state,arbiter_state_nxt;
reg [2:0] gnt_vec_nxt;
reg [3:0] count_req_vec [2:0];
reg [3:0] count_req_vec_nxt [2:0];
wire [3:0] req_vec_wt [2:0];
reg [3:0] req_vec_wt_stored [2:0];
reg [3:0] req_vec_wt_stored_nxt [2:0];
wire [2:0] cnt_reqdone_vec;
parameter IDLE = 3'b001;
parameter ARM_VALUE = 3'b010;
parameter END_ACCESS = 3'b100;
assign req_vec_wt[0] = req_vec_wt_0;
assign req_vec_wt[1] = req_vec_wt_1;
assign req_vec_wt[2] = req_vec_wt_2;
always@(*) begin
arbiter_state_nxt = arbiter_state;
gnt_vec_nxt = gnt_vec;
count_req_vec_nxt[0] = count_req_vec[0];
count_req_vec_nxt[1] = count_req_vec[1];
count_req_vec_nxt[2] = count_req_vec[2];
req_vec_wt_stored_nxt[0] = req_vec_wt_stored[0];
req_vec_wt_stored_nxt[1] = req_vec_wt_stored[1];
req_vec_wt_stored_nxt[2] = req_vec_wt_stored[2];
case(arbiter_state)
IDLE:begin
if(req_n_valid)begin
arbiter_state_nxt = ARM_VALUE;
count_req_vec_nxt[0] = req_vec_wt[0];
count_req_vec_nxt[1] = req_vec_wt[1];
count_req_vec_nxt[2] = req_vec_wt[2];
req_vec_wt_stored_nxt[0] = req_vec_wt[0];
req_vec_wt_stored_nxt[1] = req_vec_wt[1];
req_vec_wt_stored_nxt[2] = req_vec_wt[2];
end
end
ARM_VALUE:begin
if((gnt_vec == 0) ||
(end_access_vec[0] & gnt_vec[0]) ||
(end_access_vec[1] & gnt_vec[1]) ||
(end_access_vec[2] & gnt_vec[2]))
begin
if(req_vec[0] & !cnt_reqdone_vec[0]) begin
arbiter_state_nxt = END_ACCESS;
gnt_vec_nxt = 3'b001;
count_req_vec_nxt[0] = count_req_vec[0] - 1;
end
else if(req_vec[1] & !cnt_reqdone_vec[0]) begin
arbiter_state_nxt = END_ACCESS;
gnt_vec_nxt = 3'b010;
count_req_vec_nxt[1] = count_req_vec[1] - 1;
end
else if(req_vec[2] & !cnt_reqdone_vec[1]) begin
arbiter_state_nxt = END_ACCESS;
gnt_vec_nxt = 3'b100;
count_req_vec_nxt[2] = count_req_vec[2] - 1;
end
else begin
count_req_vec_nxt[0] = req_vec_wt_stored[0];
count_req_vec_nxt[1] = req_vec_wt_stored[1];
count_req_vec_nxt[2] = req_vec_wt_stored[2];
gnt_vec_nxt = 3'b0;
end
end
end
END_ACCESS:if((end_access_vec[0] & gnt_vec[0]) ||
(end_access_vec[1] & gnt_vec[1]) ||
(end_access_vec[2] & gnt_vec[2]))
begin
arbiter_state_nxt = ARM_VALUE;
if(req_vec[0] & !cnt_reqdone_vec[0]) begin
arbiter_state_nxt = END_ACCESS;
gnt_vec_nxt = 3'b001;
count_req_vec_nxt[0] = count_req_vec[0] - 1;
end
else if(req_vec[1] & !cnt_reqdone_vec[0]) begin
arbiter_state_nxt = END_ACCESS;
gnt_vec_nxt = 3'b010;
count_req_vec_nxt[1] = count_req_vec[1] - 1;
end
else if(req_vec[2] & !cnt_reqdone_vec[1]) begin
arbiter_state_nxt = END_ACCESS;
gnt_vec_nxt = 3'b100;
count_req_vec_nxt[2] = count_req_vec[2] - 1;
end
else begin
count_req_vec_nxt[0] = req_vec_wt_stored[0];
count_req_vec_nxt[1] = req_vec_wt_stored[1];
count_req_vec_nxt[2] = req_vec_wt_stored[2];
gnt_vec_nxt = 3'b0;
end
end
endcase
end
assign cnt_reqdone_vec[0] = (count_req_vec[0] == 0);
assign cnt_reqdone_vec[1] = (count_req_vec[1] == 0);
assign cnt_reqdone_vec[2] = (count_req_vec[2] == 0);
always@(posedge clk or negedge resetb) begin
if(!resetb) begin
arbiter_state <= IDLE;
gnt_vec <= 0;
count_req_vec[0] <= 0;
count_req_vec[1] <= 0;
count_req_vec[2] <= 0;
req_vec_wt_stored[0] <= 0;
req_vec_wt_stored[1] <= 0;
req_vec_wt_stored[2] <= 0;
end
else begin
arbiter_state <= arbiter_state_nxt;
gnt_vec <= gnt_vec_nxt;
count_req_vec[0] <= count_req_vec_nxt[0];
count_req_vec[1] <= count_req_vec_nxt[1];
count_req_vec[2] <= count_req_vec_nxt[2];
req_vec_wt_stored[0] <= req_vec_wt_stored_nxt[0];
req_vec_wt_stored[1] <= req_vec_wt_stored_nxt[1];
req_vec_wt_stored[2] <= req_vec_wt_stored_nxt[2];
end
end
endmodule
代码中使用了req_vec_wt_stored信号保存各用户的权重值,使用count_req_vec保存用户的当前剩余请求次数。注意:一旦出现了空档期,则所有用户的剩余请求次数会重置。
以上内容来源于《Verilog高级数字系统设计技术和实例分析》