Fixed priority arbiter design

foreword

The arbiter Arbiter is a very common module in digital design and has a wide range of applications. The definition is that when two or more modules need to occupy the same resource , we need the arbiter to decide which module will occupy the resource. Generally speaking, the module that proposes to occupy resources needs to generate a request, and after all the requests are sent to the arbitrator, the arbitrator must return a grant.

Fixed priority arbiter (fixed priority)

Fixed priority. The priority of each module is fixed and assigned in advance. If two modules generate requests at the same time, the module with higher priority can get the grant. Assume that there are three modules as CBA, and use 3-bit request to represent their requests, so that the lower the bit priority, the higher the priority, that is, when request = 3'b011, A has the highest priority, so grant=3'b001, the bus control is given to module A.

1. Fixed priority arbitration for casex statements

You can use the casex statement to perform fixed-priority arbitration. The verilog code is as follows:

1.1 Code

module fixed_arbiter(
    input              rstn    ,
    input              clk     ,
    input      [2:0]   request ,
    
    output reg [2:0]   grant
);

always @(posedge clk)begin
    if(!rstn)begin
        grant <= 3'b000;
    end 
    else begin
        casex(request)
            3'b??1: grant <= 3'b001;
            3'b?10: grant <= 3'b010;
            3'b100: grant <= 3'b100;
            default: grant <= 3'b000;
        endcase
    end
end

endmodule

The use of the casez statement and the case statement is very similar, the only difference is that the state z will not be regarded as a normal z state in the casez statement, but the bit (or those) marked as z in the expression is regarded as don't care (dont care). The use of the casex statement and the casez statement are very similar, the only difference is that casex can treat both state x and state z as don't care (dont care).

Just like the above code, when the lowest bit is 1, it doesn't care what the first 2 bits are, as long as the lowest bit is 1, then assign 3'b001 to grant.

1.2testbench

module fixed_arbiter_tb();

reg clk, rstn;
wire [2:0] grant;

reg [2:0] request;
initial begin
    forever #5 clk <= ~clk;
end
initial begin
    clk  <= 1'b0;
    rstn <= 1'b0;
    #15
    rstn <= 1'b1;
    request <= 3'b110;
    #10
    request <= #1 3'b011;
    #10
    request <= #1 3'b111;
    #10
    request <= #1 3'b010;
    #50
    $finish();
end

fixed_arbiter u_fixed_arbiter(
    .clk        (clk)       ,
    .rstn       (rstn)      ,
    .request    (request)   ,
    .grant      (grant)
);

initial begin
    $fsdbDumpfile("fixed_arbiter.fsdb");
    $fsdbDumpvars(0);
end 

endmodule

waveform

2. Utilize the characteristics of complementary codes to judge the priority.

The result of ANDing a number with its complement is a one-hot code, and the bit whose one-hot code is 1 is the lowest 1 of the number .

For example, a=4'b1011, the complement of a is: ~(a-1)=4'b0101. The AND of a and its complement gives: 4'b0001.

For example, a=4'b1010, the complement of a is: ~(a-1)=4'b0110. The AND of a and its complement gives: 4'b0010.

Using this feature, we can get a very simple fixed-priority arbiter (using bitwise operators):

2.1 Code

module fixed_arbiter(
    input              rstn    ,
    input              clk     ,
    input      [2:0]   request ,
    
    output reg [2:0]   grant
);

always @(posedge clk)begin
    if(!rstn)begin
        grant <= 3'b000;
    end 
    else begin
        grant <= request & (~(request-1));
    end
end

endmodule

In fact, it uses a feature: a number and its complement, the result is a one-hot code, and the bit with the one-hot code being 1 is the lowest 1 of the number .

Guess you like

Origin blog.csdn.net/qq_57502075/article/details/129767386