轮询仲裁
所谓轮询仲裁,就是指每次访问结束后都会更新优先级,举个栗子:假设有N个请求,分别编号为0,1,2,…,N-1,初始时刻,这N个请求的优先级为0>1>2>…>N-1,某个时刻,仲裁器将总线的控制权交给了请求i(0<=i<=N-1),则这之后这N个请求的优先级修改为i+1>i+2>…>N-1>0>1>…>i。
在本文中,我们设计了一个3请求的总线仲裁器,代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/03/08 20:05:47
// Design Name:
// Module Name: arbitor
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
`timescale 1ns/10ps
module bus_arbitor(
input logic clk,
input logic rst_n,
input logic signal_a, //三个主机,轮询仲裁
input logic signal_b,
input logic signal_c,
output logic [1:0] grant);
logic [1:0] last_grant; //记录上一次总线仲裁结果
parameter A = 2'b00; //将总线控制权交给A
parameter B = 2'b01; //总线控制权交给B
parameter C= 2'b10; //总线控制权交给C
parameter NULL = 2'b11; //
always@(posedge clk,negedge rst_n)
if(~rst_n)
begin
grant<=NULL;
last_grant<=NULL;
end
else
begin
case({signal_a,signal_b,signal_c})
3'b000:begin
grant<=NULL;
last_grant<=last_grant;
end
3'b001:begin
grant<=C;
last_grant<=C;
end
3'b010:begin
grant<=B;
last_grant<=B;
end
3'b100:begin
grant<=A;
last_grant<=A;
end
3'b110:begin //A,B同时请求总线,需要进行仲裁
case(last_grant)
A:begin grant<=B;last_grant<=B;end
B:begin grant<=A;last_grant<=A;end
C:begin grant<=A;last_grant<=A;end
NULL:begin grant<=A;last_grant<=A;end
endcase
end
3'b101:begin //A,C同时请求总线
case(last_grant)
A:begin grant<=C;last_grant<=C;end
B:begin grant<=C;last_grant<=C;end
C:begin grant<=A;last_grant<=A;end
NULL:begin grant<=A;last_grant<=A;end
endcase
end
3'b011:begin //B,C同时请求总线
case(last_grant)
A:begin grant<=B;last_grant<=B;end
B:begin grant<=C;last_grant<=C;end
C:begin grant<=B;last_grant<=B;end
NULL:begin grant<=B;last_grant<=B;end
endcase
end
3'b111:begin //三个总线同时请求
case(last_grant)
A:begin grant<=B;last_grant<=B;end
B:begin grant<=C;last_grant<=C;end
C:begin grant<=A;last_grant<=A;end
NULL:begin grant<=A;last_grant<=A;end
endcase
end
default:begin grant<=NULL;last_grant<=last_grant;end
endcase
end
endmodule
测试平台:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/03/08 20:37:45
// Design Name:
// Module Name: sim_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module sim_tb;
logic clk;
logic rst_n;
logic signal_a;
logic signal_b;
logic signal_c;
logic [1:0] grant;
initial begin
clk=0;
forever begin
#5 clk=~clk;
end
end
//rst_n
initial
begin
rst_n=0;
#100
rst_n=1;
end
//signal_a,b,c
always@(posedge clk,negedge rst_n)
if(~rst_n)
{signal_a,signal_b,signal_c}<=0;
else if($urandom%2==1)
{signal_a,signal_b,signal_c}<=$urandom%8;
else
{signal_a,signal_b,signal_c}<=0;
//inst
bus_arbitor U(.*);
// input logic clk,
// input logic rst_n,
// input logic signal_a, //三个主机,轮询仲裁
// input logic signal_b,
// input logic signal_c,
// output logic [1:0] grant);
endmodule
仿真波形:
可以看到,当A获得请求后,优先级顺序变为BCA,B获得请求后,优先级顺序变为CAB,C获得请求后,优先级顺序变为ABC,若当前无请求,则last_grant信号保持不变(last_grant信号用于保存上一次仲裁器给出的结果,都无请求时仲裁结果不保存)。
固定优先级仲裁
优先级固定不变,比如优先级永远都是0>1>2>…>N-1。
代码实现:
`timescale 1ns / 1ps
`timescale 1ns/10ps
module fixed_bus_arbitor(
input logic clk,
input logic rst_n,
input logic signal_a, //三个主机,轮询仲裁
input logic signal_b,
input logic signal_c,
output logic [1:0] grant);
parameter A = 2'b00;
parameter B = 2'b01;
parameter C = 2'b10;
parameter NULL =2'b11;
//
always_ff@(posedge clk,negedge rst_n)
if(~rst_n)
grant<=NULL;
else
begin
casez({signal_a,signal_b,signal_c}) //优先级A>B>C
3'b1zz:grant<=A;
3'bz1z:grant<=B;
3'bzz1:grant<=C;
default:grant<=NULL;
endcase
end
endmodule
仿真测试文件和轮询仲裁所给出的一致,只需修改例化时模块的名字即可,以下时仿真波形: