Skip to content

Final project - Arbiter module

Code

`timescale 1ns/1ps

module arbiter (
    input  wire       clk,       // Clock
    input  wire       rst_n,     // Reset (active low)
    input  wire       data_in1,  // 1-bit input, player 1
    input  wire       data_in2,  // 1-bit input, player 2
    output reg        data_out,  // 1-bit output, HIGH when first player wins, LOW otherwise
    output reg        finish     // 1 bit output, HIGH when at least one players cross the finish line
);

    // State encoding
    parameter IDLE = 2'b00;
    parameter L1_WIN = 2'b01;
    parameter L2_WIN = 2'b10;

    reg [1:0] state, next_state;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin 
            state <= IDLE;
        end
        else begin
            state <= next_state;
        end
    end

    always @(*) begin
        next_state = state;
        data_out = 0;
        finish = 0; 
        case (state)
            IDLE: begin
                if (data_in1 == 1 && data_in2 == 1)
                    next_state = L1_WIN; // Tie-breaker: Lane 1 wins
                else if (data_in1 == 1)
                    next_state = L1_WIN;
                else if (data_in2 == 1)
                    next_state = L2_WIN;
                else begin
                    data_out = 0;
                    finish = 0;
                    next_state = IDLE;
                end
            end
            L1_WIN: begin
                data_out = 1;
                finish = 1;
                // Stay in this state until reset
            end
            L2_WIN: begin
                data_out = 0;
                finish = 1;
                // Stay in this state until reset
            end
            default: next_state = IDLE;
        endcase
    end

endmodule

Lint

verilator --lint-only -Wall -Ilib puf/arbiter.v
- V e r i l a t i o n   R e p o r t: Verilator 5.044 2026-01-01 rev v5.044
- Verilator: Built from 0.032 MB sources in 2 modules, into 0.018 MB in 3 C++ files needing 0.000 MB
- Verilator: Walltime 0.007 s (elab=0.000, cvt=0.003, bld=0.000); cpu 0.007 s on 1 threads; alloced 30.352 MB

Test harness

`timescale 1ns/1ps

module test_arbiter;
    // Inputs are reg (we drive them)
    reg clk, rst_n, data_in1, data_in2;

    // Outputs are wire (DUT drives them)
    wire data_out, finish;

    // Instantiate Device Under Test
    arbiter arbiter (
        .clk(clk),
        .rst_n(rst_n),
        .data_in1(data_in1),
        .data_in2(data_in2),
        .data_out(data_out),
        .finish(finish)
    );

    // Clock generation
    always #10 clk = ~clk;  // 50 MHz (20ns period)

    // Test stimulus
    initial begin
        $dumpfile("waves.vcd");
        $dumpvars(0, test_arbiter);

        // Initialize
        $display("Initialize");
        #10 
        clk = 0;        
        display;

        // Reset
        $display("----------- Reset --------------");
        rst_n = 0;
        data_in1 = 0;
        data_in2 = 0;
        #20 
        rst_n = 1;    
        #20    
        $display("----------------- --------------");

        // Test case 1
        $display("==> Test case 1: first player wins");       
        data_in1 = 1;           
        #20  
        $display("Second player follows");       
        data_in2 = 1; 
        #20       
        display;

         // Reset
        $display(" --------- Reset --------------");
        rst_n = 0;       
        data_in1 = 0;
        data_in2 = 0;
        #20 
        rst_n = 1;
        #20         
        $display("----------------- --------------");

        // Test case 2
        $display("==> Test case 2: second player wins");      
        data_in2 = 1;
        #20
        $display("First player follows");
        data_in1 = 1; 
        #20       
        display;        

        // Reset
        $display(" --------- Reset --------------");
        rst_n = 0;       
        data_in1 = 0;
        data_in2 = 0;
        #20 
        rst_n = 1;    
        #20    
        $display("----------------- --------------");

        // Test case 2
        $display("==> Test case 3: both wins... player 1 is picked");      
        data_in2 = 1;
        data_in1 = 1; 
        #20      
        display;   

        // Reset
        $display(" --------- Reset --------------");
        rst_n = 0;       
        data_in1 = 0;
        data_in2 = 0;
        #20 
        rst_n = 1;    
        #20    
        $display("----------------- --------------");  

        #100 
        $finish;
    end
    task display;
    #1 $display("data_in1:%0h, data_in2:%0h, data_out:%0h, finish:%0h, reset:%0h",
      data_in1, data_in2, data_out, finish, rst_n);
  endtask

endmodule

Test run in simulation

Initialize
data_in1:x, data_in2:x, data_out:x, finish:x, reset:x
----------- Reset --------------
----------------- --------------
==> Test case 1: first player wins
Second player follows
data_in1:1, data_in2:1, data_out:1, finish:1, reset:1
 --------- Reset --------------
----------------- --------------
==> Test case 2: second player wins
First player follows
data_in1:1, data_in2:1, data_out:0, finish:1, reset:1
 --------- Reset --------------
----------------- --------------
==> Test case 3: both wins... player 1 is picked
data_in1:1, data_in2:1, data_out:1, finish:1, reset:1
 --------- Reset --------------
----------------- --------------
puf/test_arbiter.v:100: $finish called at 374000 (1ps)