Digital IC front-end study notes: arbitration polling (3)

related articles

Digital IC front-end study notes: LSFR (Linear Feedback Shift Register)

Digital IC front-end study notes: cross-clock domain signal synchronization

Digital IC front-end study notes: signal synchronization and edge detection

Digital IC front-end study notes: synthesis of latch Latch

Digital IC front-end study notes: Gray code (including binary Gray code converter implemented by Verilog)

Digital IC front-end study notes: Verilog implementation of FIFO (1)

Digital IC front-end study notes: Verilog implementation of FIFO (2)

Digital IC front-end study notes: arbitration polling (1)

Digital IC front-end study notes: arbitration polling (2)

Digital IC front-end study notes: arbitration polling (4)

Digital IC front-end study notes: arbitration polling (5)

Digital IC front-end study notes: arbitration polling (6)

Digital IC front-end study notes: least recently used (LRU) algorithm


5. Fair polling without dead cycle

        In the previous Verilog RTL code of the fair polling arbitrator, each user has three signals: request (request), grant (authorization), and end_access (end access). When the bus is used, we can observe that there are dead cycles on the bus where data transmission cannot be performed. When the transmitted data packets are long or each burst is long, it has little influence on the transmission efficiency. However, when the data packets are short, the dead cycle will affect the efficiency of bus usage. The following figure shows the fair polling arbitration waveform without interval. Some methods are given below to reduce or even eliminate dead cycles.

  • The first solution is that when the grant signal is valid, the user's first data has been prepared and output effectively. In the original scheme, after the user's grant is valid, it outputs data in the next cycle. Now, when the grant sample is high, it starts to output data in the same cycle. At this time, the user needs to read the first data from the internal circuit in advance. When using this scheme, the design of the arbiter remains unchanged, and the user part needs to be modified.
  • The second way is to add an additional signal start_access, which is used together with end_access. After a user obtains the right to use the bus and starts to operate, the arbiter starts a new arbitration process by setting start_access to be effective, instead of waiting for the end_access signal to go high to start a new arbitration process, thus reducing the dead cycle during conversion. When the next user is authorized, the current user is still using the bus, and the new user cannot use the bus immediately. The arbiter will give an end_access_out signal when the current user completes the operation, and the new authorized user can start the operation thereafter. The arbiter sets resource_idle to 1 when no user uses the public resource. When resource_idle is 1, authorized users can start data operations without checking the end_access_out signal.

        The fair polling code and simulation results without dead cycle are as follows.

module arbiter_roundrobin(
            clk,resetb,
            req_vec,
            end_access_vec,
            gnt_vec,
            end_access_out);
    
    input clk, resetb;
    input [2:0] req_vec, end_access_vec;
    output [2:0] gnt_vec;
    output end_access_out;
    reg [1:0] arbiter_state, arbiter_state_nxt;
    reg [2:0] gnt_vec, gnt_vec_nxt;
    reg [2:0] relative_req_vec;
    wire any_req_asserted;
    reg [1:0] grant_posn, grant_posn_nxt;
    reg resource_idle_nxt, resource_idle;
    reg [2:0] start_access_vec, start_access_vec_nxt;
    parameter IDLE = 2'b00;
    parameter END_ACCESS = 2'b01;
    
    assign any_req_asserted = (req_vec != 0);
    assign end_access_out = |end_access_vec;
 
    always@(*) begin
        relative_req_vec = req_vec;
        case(grant_posn)
            2'd0: relative_req_vec = {req_vec[0], req_vec[2:1]};
            2'd1: relative_req_vec = {req_vec[1:0], req_vec[2]};
            2'd2: relative_req_vec = {req_vec[2:0]};
        endcase
    end
    always@(*) begin
        arbiter_state_nxt = arbiter_state;
        grant_posn_nxt = grant_posn;
        gnt_vec_nxt = gnt_vec;
        resource_idle_nxt = 1'b0;
        start_access_vec_nxt = 3'b0;
        case(arbiter_state)
            IDLE:begin
                    if(any_req_asserted)
                        arbiter_state_nxt = END_ACCESS;
                        resource_idle_nxt = 1'b1;
                    if(relative_req_vec[0])
                        case(grant_posn)
                            2'd0: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
                            2'd1: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
                            2'd2: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
                        endcase
                    else if(relative_req_vec[1])
                        case(grant_posn)
                            2'd0: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
                            2'd1: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
                            2'd2: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
                        endcase
                    else if(relative_req_vec[2])
                        case(grant_posn)
                            2'd0: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
                            2'd1: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
                            2'd2: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
                        endcase
                    else
                        gnt_vec_nxt = 3'b000;
            end
            END_ACCESS:begin  
                if((resource_idle == 1'b1) || (end_access_out == 1'b1))
                    start_access_vec_nxt = gnt_vec;
                if(start_access_vec != 0)begin
                    if(relative_req_vec[0])
                        case(grant_posn)
                            2'd0: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
                            2'd1: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
                            2'd2: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
                        endcase
                    else if(relative_req_vec[1])
                        case(grant_posn)
                            2'd0: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
                            2'd1: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
                            2'd2: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
                        endcase
                    else if(relative_req_vec[2])
                        case(grant_posn)
                            2'd0: begin gnt_vec_nxt = 3'b001; grant_posn_nxt = 3'd0; end
                            2'd1: begin gnt_vec_nxt = 3'b010; grant_posn_nxt = 3'd1; end
                            2'd2: begin gnt_vec_nxt = 3'b100; grant_posn_nxt = 3'd2; end
                        endcase
                    else begin
                        gnt_vec_nxt = 3'b000;   
                        arbiter_state_nxt = IDLE;
                    end         
                end
            end
        endcase
    end
    
    always@(posedge clk or negedge resetb)begin
        if(!resetb) begin
            arbiter_state <= IDLE;
            gnt_vec <= 0;
            grant_posn <= 0;
            resource_idle <= 0;
            start_access_vec <= 0;
        end  
        else begin
            arbiter_state <= arbiter_state_nxt;
            gnt_vec <= gnt_vec_nxt;
            grant_posn <= grant_posn_nxt;
            resource_idle <= resource_idle_nxt;
            start_access_vec <= start_access_vec_nxt;
        end
    end
endmodule

        In the Verilog implementation process, two states IDLE and END_ACCESS are used, respectively indicating that the arbitrator is in the state of no request and arbiter authorization. In the IDLE state, any request signal can make the state transfer to the END_ACCESS state, and set the resource_idle signal to 1 (this is a signal designed for the start_access setting in the IDLE state), and give corresponding authorization according to the request signal. In the END_ACCESS state, gnt_vec is used to set start_access according to the resource_idle or end_access_out signal. When the start_access signal is valid, the next authorization is performed according to the request signal. If there is no request signal at this time, the state returns to IDLE and waits.

The above content comes from "Verilog Advanced Digital System Design Technology and Example Analysis", with deletions and modifications

Guess you like

Origin blog.csdn.net/weixin_45791458/article/details/131339436