相关文章
数字IC前端学习笔记:LSFR(线性反馈移位寄存器)
数字IC前端学习笔记:跨时钟域信号同步
数字IC前端学习笔记:信号同步和边沿检测
数字IC前端学习笔记:锁存器Latch的综合
数字IC前端学习笔记:格雷码(含Verilog实现的二进制格雷码转换器)
数字IC前端学习笔记:FIFO的Verilog实现(一)
数字IC前端学习笔记:FIFO的Verilog实现(二)
目录
1.关于仲裁
2.常规仲裁方案
3.严格优先级轮询
1.关于仲裁
当多个源或用户需要共享同一资源时,需要某种仲裁形式,使得所有用户基于一定的规则或算法得到获取或访问共享资源的机会。例如,共享总线上,可以连接多个总线用户。另一个例子是交换机中的端口仲裁,当多个入口希望通过某一个出口输出数据时,需要使用一定的端口仲裁机制来选择某一时刻允许哪一个入口发送数据。最简单的仲裁方案是公平轮询(round-robin)方案,此时,仲裁器公平的对待所有用户的请求,不同用户具有均等的机会。然而,如果某些设备的速度快于其他设备,它需要更多的对共享资源的访问机会,或者某些用户具有更高的处理优先级,那么简单的循环方案是不够的。
在此情形下,使用严格优先级轮询或者权重轮询方案更为合适。也有一些方案将多种轮询方案结合起来使用。无论采用哪一种方案,都应该保证让某些用户始终得到资源,下面将讨论通常使用的仲裁方案。
2.常规仲裁方案
根据需要,设计者可以选择和设计自己所需要的仲裁(轮询)方案。接下来要讨论的是工业上经常使用的的经典方案。
- 严格优先级轮
- 根据优先级的差异,用户访问共享资源的机会也不同。
- 低优先级的用户可能始终无法得到资源。
- 公平轮询
- 公平地对待所有请求。
- 所有用户获得均等的访问机会,不会有用户始终无法得到资源。
- 权重轮询
- 兼顾了公平性和差异性。
- 在一个轮询周期中,不同权重的用户会得到不同的访问次数。
- 在一个轮询周期中,不同权重的用户会得到不用的访问时间片。
- 混合优先级(高优先级组合低优先级组)
- 组间采用优先级轮询,组内采用公平轮询。
3.严格优先级轮询
在严格优先级轮询方案中,发出请求的用户有固定的优先级。我们假设有8个用户(agent),agent0具有最高的优先级,agent7具有最低的优先级。在本方案中,优先级高的用户只要保持请求,就会持续得到授权。随着优先级不断降低,用户得到授权的机会也随之下降。该方案可以根据用户的重要性提供不同的服务,但低优先级用户可能长时间得不到服务。此时可以通过对高优先级用户增加一些请求约束的方法来避免低优先级用户被“饿死”。如下图为严格优先级轮询的波形。
严格优先级轮询代码及仿真结果如下。
module arbiter_strict_priority(clk,resetb,
req_vector,
end_access_vector,
gnt_vector);
input clk;
input resetb;
input [3:0] req_vector;
input [3:0] end_access_vector;
output reg [3:0] gnt_vector;
reg [1:0] arbiter_state,arbiter_state_nxt;
reg [3:0] gnt_vector_nxt;
wire any_request;
parameter IDLE = 2'b01;
parameter END_ACCESS = 2'b10;
assign any_request = (req_vector != 0);
always@(*) begin
arbiter_state_nxt = arbiter_state;
gnt_vector_nxt = gnt_vector;
case(arbiter_state)
IDLE:begin
if(any_request)
arbiter_state_nxt = END_ACCESS;
if(req_vector[0])
gnt_vector_nxt = 4'b0001;
else if(req_vector[1])
gnt_vector_nxt = 4'b0010;
else if(req_vector[2])
gnt_vector_nxt = 4'b0100;
else if(req_vector[3])
gnt_vector_nxt = 4'b1000;
end
END_ACCESS:begin
if((end_access_vector[0] & gnt_vector[0]) ||
(end_access_vector[1] & gnt_vector[1]) ||
(end_access_vector[2] & gnt_vector[2]) ||
(end_access_vector[3] & gnt_vector[3])) begin
if(any_request) begin
arbiter_state_nxt = END_ACCESS;
if(req_vector[0])
gnt_vector_nxt = 4'b0001;
else if(req_vector[1])
gnt_vector_nxt = 4'b0010;
else if(req_vector[2])
gnt_vector_nxt = 4'b0100;
else if(req_vector[3])
gnt_vector_nxt = 4'b1000;
end
else begin
arbiter_state_nxt = IDLE;
gnt_vector_nxt = 4'b0000;
end
end
end
endcase
end
always@(posedge clk or negedge resetb) begin
if(!resetb) begin
arbiter_state <= IDLE;
gnt_vector <=0;
end
else begin
arbiter_state <= arbiter_state_nxt;
gnt_vector <= gnt_vector_nxt;
end
end
endmodule