zl程序教程

您现在的位置是:首页 >  硬件

当前栏目

【数字IC/FPGA】总线仲裁器

IC 数字 FPGA 总线 仲裁
2023-09-14 09:10:02 时间

轮询仲裁

所谓轮询仲裁,就是指每次访问结束后都会更新优先级,举个栗子:假设有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

仿真测试文件和轮询仲裁所给出的一致,只需修改例化时模块的名字即可,以下时仿真波形:
在这里插入图片描述