0
0
VerilogHow-ToBeginner · 3 min read

Verilog Code for Arbiter: Syntax, Example, and Tips

An arbiter in Verilog controls access to a shared resource by granting requests one at a time. Use always blocks with priority logic or round-robin schemes to decide which request gets granted. The arbiter outputs grant signals based on input requests and a clock or enable signal.
📐

Syntax

An arbiter module typically has input request signals, output grant signals, and a clock or enable input. Inside, always blocks with if-else or case statements decide which request to grant based on priority or fairness.

  • input req: Request signals from clients.
  • output grant: Grant signals to clients.
  • clk: Clock signal for synchronous operation.
  • reset: Optional reset to clear grants.
verilog
module arbiter(
    input wire clk,
    input wire reset,
    input wire [3:0] req,
    output reg [3:0] grant
);

always @(posedge clk or posedge reset) begin
    if (reset) begin
        grant <= 4'b0000;
    end else begin
        casez (req)
            4'b???1: grant <= 4'b0001; // Grant to req[0]
            4'b??10: grant <= 4'b0010; // Grant to req[1]
            4'b?100: grant <= 4'b0100; // Grant to req[2]
            4'b1000: grant <= 4'b1000; // Grant to req[3]
            default: grant <= 4'b0000;  // No request
        endcase
    end
end

endmodule
💻

Example

This example shows a simple 4-client priority arbiter. It grants the lowest numbered request first if multiple requests come at once. The grant output signals which client is allowed access.

verilog
module arbiter(
    input wire clk,
    input wire reset,
    input wire [3:0] req,
    output reg [3:0] grant
);

always @(posedge clk or posedge reset) begin
    if (reset) begin
        grant <= 4'b0000;
    end else begin
        casez (req)
            4'b???1: grant <= 4'b0001;
            4'b??10: grant <= 4'b0010;
            4'b?100: grant <= 4'b0100;
            4'b1000: grant <= 4'b1000;
            default: grant <= 4'b0000;
        endcase
    end
end

endmodule

// Testbench
module tb_arbiter();
    reg clk = 0;
    reg reset;
    reg [3:0] req;
    wire [3:0] grant;

    arbiter uut(.clk(clk), .reset(reset), .req(req), .grant(grant));

    always #5 clk = ~clk; // 10 time units clock period

    initial begin
        reset = 1; req = 4'b0000;
        #10 reset = 0;

        req = 4'b0001; #10;
        $display("req=0001 grant=%b", grant);

        req = 4'b0101; #10;
        $display("req=0101 grant=%b", grant);

        req = 4'b1000; #10;
        $display("req=1000 grant=%b", grant);

        req = 4'b0000; #10;
        $display("req=0000 grant=%b", grant);

        $finish;
    end
endmodule
Output
req=0001 grant=0001 req=0101 grant=0001 req=1000 grant=1000 req=0000 grant=0000
⚠️

Common Pitfalls

Common mistakes when writing arbiters include:

  • Not handling multiple simultaneous requests properly, causing multiple grants.
  • Forgetting to reset the grant signals, leading to stale grants.
  • Using combinational logic without clock, which can cause glitches.
  • Not prioritizing requests clearly, causing unpredictable grants.

Always use synchronous logic and clear priority or fairness rules.

verilog
/* Wrong: combinational grant without reset and priority */
module wrong_arbiter(
    input wire [3:0] req,
    output reg [3:0] grant
);
    always @(*) begin
        grant = req; // Grants all requests at once - wrong
    end
endmodule

/* Right: synchronous with priority and reset */
module right_arbiter(
    input wire clk,
    input wire reset,
    input wire [3:0] req,
    output reg [3:0] grant
);
    always @(posedge clk or posedge reset) begin
        if (reset) grant <= 4'b0000;
        else if (req[0]) grant <= 4'b0001;
        else if (req[1]) grant <= 4'b0010;
        else if (req[2]) grant <= 4'b0100;
        else if (req[3]) grant <= 4'b1000;
        else grant <= 4'b0000;
    end
endmodule
📊

Quick Reference

  • Use synchronous always @(posedge clk) blocks for stable grants.
  • Implement clear priority or round-robin logic to avoid conflicts.
  • Reset grant signals to avoid stale outputs.
  • Use casez or if-else to check requests in priority order.
  • Test with multiple simultaneous requests to verify correct arbitration.

Key Takeaways

Always use synchronous logic with clock and reset for arbiter grants.
Implement clear priority or fairness rules to decide which request to grant.
Reset grant outputs to avoid stale or multiple grants.
Test arbiter behavior with multiple simultaneous requests.
Avoid combinational grants that can cause glitches or multiple grants.