在多模块共享同一资源时,需要仲裁器来决定谁可以使用共享资源(如memory access).所以输入是各模块的请求(req),输出是grant。
仲裁器(arbiter) 在FPGA主要用于多个source源同时发出请求时,根据相应的优先级来响应哪一个source。FPGA的仲裁器分为轮询仲裁器(Round-Robiin)和固定优先级仲裁器(Fixed-Priority)。
轮询仲裁器规则
轮询仲裁的规则是当0、1、2、、、N-1个source信号源同时向仲裁器发出请求时,初始情况下source 0的优先级最高,当仲裁器响应了source0后,source1的优先级最高,依次类推。
轮询仲裁器实现
轮询仲裁器的实现分为检测仲裁器输入口source信号源的request,根据当前仲裁器的优先级响应相应的request,仲裁器grant输出source端的请求,更新仲裁器的优先级。
固定优先级仲裁器规则
Fixed-priority Arbiter顾名思义当0、1、2、、、N-1个source同时发起request,Source 0的优先级最高,即便source0被响应完后,仍为最高优先级,其中优先级按照序号逐渐降低。
固定优先级仲裁实现
固定优先级仲裁器在FPGA实现与轮询仲裁器类似,唯一不同的是轮询仲裁在每次响应完request后会对优先级进行更新,而固定优先级则不需要此步骤。
SoC 设计广泛采用共享总线式的片上通信,其中的仲裁器是共享总线的关键技术之一。AMBA AXI 总线协议以高性能、高频率的系统设计为目标,适合高带宽、低延迟的系统设计,可以达到高频率的操作而不需要复杂的总线桥,满足众多部件的接口要求,具备高度灵活的互联结构,并且向后兼容 AHB 和 APB 接口。
共享总线是一种常见的总线结构,多个总线上的设备拥有共同的地址线和数据线。
当一个总线设备希望占据总线进行数据收发操作时,需要通过属于自己的arequest信号向仲裁器发出申请,只有得到仲裁器的许可(对应的agrant置1 )时才能进行数据收发操作,没有得到许可的总线设备不能发起数据操作,否则将会出现多个设备同时驱动总线的错误。
下图是有两个总线设备的总线仲裁器电路,areq0和areq1以及agnt0和agnt1分别是master1和master2的请求和确认信号,rid是仲裁方式选择信号。当多个总线设备同时发出请求时,仲裁器根据内部控制寄存器的值按照固定优先级( rid=1, master2拥有高优先级)或者循环判断( rid=0,从master1->master2->master1循环判断)两种机制给相应的总线设备发出确认信号。
设计代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Design Name:
// Module Name: Arbiter
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
//
module Arbiter(clk,reset,areq0,areq1,agnt0,agnt1,rid);
input clk,reset;
input areq0,areq1;
input rid;
output agnt0,agnt1;
reg [1:0] current_state,nx_state;
parameter idle=2'b00,master1=2'b01,master2=2'b10;
/
always @(posedge clk or posedge reset)
if(reset)
current_state<=idle;
else
current_state<=nx_state;
/
always @(current_state or areq0 or areq1 or rid)
begin
case(current_state)
idle:if(areq1==1 && areq0==0)
nx_state=master2;
else if(areq1==0 && areq0==1)
nx_state=master1;
else if(areq1==1 && areq0==1 && !rid)
nx_state=master1;
else if(areq1==1 && areq0==1 && rid)
nx_state=master2;
else nx_state=idle;
master1:if(areq1==1)
nx_state=master2;
else if(areq1==0 && areq0==0)
nx_state=idle;
else nx_state=master1;
master2:if(areq0==1)
nx_state=master1;
else if(areq1==0 && areq0==0)
nx_state=idle;
else nx_state=master2;
default:nx_state=idle;
endcase
end
assign agnt0=(current_state==master1)?1:0;
assign agnt1=(current_state==master2)?1:0;
endmodule
测试代码
`timescale 1ns / 1ps
module Arbiter_tb;
reg clk;
reg reset;
reg areq0,areq1;
reg rid;
wire agnt0,agnt1;
always begin
#10 clk=1;
#10 clk=0;
end
/
initial begin
clk=0;
reset=1;
areq0=0;
areq1=0;
rid=0;
#100;
reset=0;
//rid=0,路径1->2
repeat(1)@(posedge clk);
#2; areq0=1;areq1=1;
repeat(1)@(posedge clk);
#2; areq0=0;areq1=0;
repeat(1)@(posedge clk);
#2; areq0=1;areq1=1;
repeat(1)@(posedge clk);
#2; areq0=0;areq1=0;
//rid=0,路径4->3
repeat(1)@(posedge clk);
#2; areq0=0;areq1=1;rid=1;
repeat(1)@(posedge clk);
#2; areq0=0;areq1=0;
repeat(1)@(posedge clk);
#2; areq0=1;areq1=1;
repeat(1)@(posedge clk);
#2; areq0=0;areq1=0;
//路径1->5->6->2
repeat(4)@(posedge clk);
#2; areq0=1;areq1=0;
repeat(1)@(posedge clk);
#2; areq0=0;areq1=1;
repeat(1)@(posedge clk);
#2; areq0=1;areq1=0;
repeat(1)@(posedge clk);
#2; areq0=0;areq1=0;
end
Arbiter U1(
.clk (clk ),
.reset (reset ),
.areq0 (areq0 ),
.areq1 (areq1 ),
.agnt0 (agnt0 ),
.agnt1 (agnt1 ),
.rid (rid ));
endmodule
参考链接:https://blog.csdn.net/Hennys/article/details/107662757