How can I simulate a simple elevator FSM in Verilog where it can detect over weigth?

Thread Starter

GRVEN21

Joined Jul 21, 2025
9
I'm doing a Finite state machine of a elevator using verilog. The elevator contain four states: IDLE, MOVING, ERROR, ALERT

* IDLE: When the elevator is stopped.
* ERROR: When the elevator's weigth limit is exceeded.
* MOVING: When the elevador leaves the current floor and start moving across the floors.
* ALERT: When the elevator's time of activation runs out.

This is the design that I came up with:


Code:
module Elevator_FSM2;
   
        // Input signals
        reg clk;
        reg reset;
        reg [3:0] request_floor;
        reg over_time;
        reg over_weight;
   
        // Output signals
        wire [3:0] current_floor;
        wire door_alert;
        wire weight_alert;
   
     
        Elevator_FSM_inst uut (
            .clk(clk),
            .reset(reset),
            .request_floor(request_floor),
            .over_time(over_time),
            .over_weight(over_weight),
            .current_floor(current_floor),
            .door_alert(door_alert),
            .weight_alert(weight_alert)
        );
   
       
        initial clk = 0;
        always #5 clk = ~clk;
   
   
        initial begin
            // Monitor the signals
            $monitor("Time=%0t | State=%b | Floor=%d | Request=%d | Door=%b | Weight=%b",
                      $time, uut.current_state, current_floor, request_floor, door_alert, weight_alert);
   
            // Initialize inputs
            reset = 1; request_floor = 4'd0; over_time = 0; over_weight = 0;
            #0 reset = 0;
   
            // Request to go to floor 3
            #10 request_floor = 4'd3;
   
            // Wait to observe movement
            #50;
   
            // End simulation
            $finish;
        end
   
       
        always @(posedge clk) begin
            if (uut.current_floor != current_floor)  // Print only if floor changes
                $display("Current Floor: %d at Time=%0t", current_floor, $time);
        end
   
    endmodule
   
   
    module Elevator_FSM_inst (
        input        clk,
        input        reset,
        input  [3:0] request_floor,
        input        over_time,
        input        over_weight,
        output reg [3:0] current_floor,
        output reg       door_alert,
        output reg       weight_alert
    );
        localparam IDLE   = 2'b00,
                   MOVING = 2'b01,
                   ALERT  = 2'b10,
                   ERROR  = 2'b11;
   
        reg [1:0] current_state, next_state;
   
        always @(posedge clk or posedge reset) begin
            if (reset)
                current_state <= IDLE;
            else
                current_state <= next_state;
        end
   
        always @(*) begin
            next_state = current_state;
            door_alert = 0;
            weight_alert = 0;
   
            case (current_state)
                IDLE: begin
                    if (request_floor != 4'b0000)
                        next_state = MOVING;
                end
   
                MOVING: begin
                    if (over_time) begin
                        door_alert = 1;
                        next_state = ALERT;
                    end else if (over_weight) begin
                        weight_alert = 1;
                        next_state = ERROR;
                    end else if (current_floor == request_floor) begin
                        next_state = IDLE;
                    end
                end
   
                ALERT: begin
                    if (!over_time)
                        next_state = MOVING;
                end
   
                ERROR: begin
                    if (!over_weight)
                        next_state = MOVING;
                end
            endcase
        end
   
        always @(posedge clk or posedge reset) begin
            if (reset)
                current_floor <= 0;
            else if (current_state == MOVING) begin
                if (current_floor < request_floor)
                    current_floor <= current_floor + 1;
                else if (current_floor > request_floor)
                    current_floor <= current_floor - 1;
            end
        end
    endmodule
This is the log I got from the simulation, and the output waves were as expected:


Code:
 Time=0 | State=00 | Floor= 0 | Request= 0 | Door=0 | Weight=0
    Time=10 | State=00 | Floor= 0 | Request= 3 | Door=0 | Weight=0
    Time=15 | State=01 | Floor= 0 | Request= 3 | Door=0 | Weight=0
    Time=25 | State=01 | Floor= 1 | Request= 3 | Door=0 | Weight=0
    Time=35 | State=01 | Floor= 2 | Request= 3 | Door=0 | Weight=0
    Time=45 | State=01 | Floor= 3 | Request= 3 | Door=0 | Weight=0
    Time=55 | State=00 | Floor= 3 | Request= 3 | Door=0 | Weight=0
    design.sv:48: $finish called at 60 (1s)
In the testbench, the elevator moves from floor 1 to floor 3. While the elevator is moving, the FSM is in state 01 (MOVING). When the elevator reaches the requested floor, it transitions to state 00 (IDLE).All good so far.

Now, when I tested the state that stop (IDLE) the elevator when the weigth is overloaded (ERROR):


Code:
   initial clk = 0;
        always #5 clk = ~clk;
   
     
        initial begin

            $monitor("Time=%0t | State=%b | Current Floor=%d | Request Floor=%d | Door Alert=%b | Weight Alert=%b",
                      $time, uut.current_state, current_floor, request_floor, door_alert, weight_alert);
           
           
            reset = 1;
            request_floor = 4'd1;
            over_time = 0;
            over_weight = 0;
   
            #10 reset = 0;
   
            #10 request_floor = 4'd3;
   
            #40;
            $display("Elevator reached Floor 2. Activating over_weight signal.");
           
            over_weight = 1;
            #20;
   
            $display("Elevator in ERROR state due to over_weight.");
            over_weight = 0;
   
            #40;
         
            #100 $finish;
        end
Here's what I've tried is when the elevator goes to floor 3, stop in floor 2 and trigger the ERROR state when over weigth is 1, and later resume his usual move to the requested floor which is 3. However this is what I've got:

Code:
 Time=0 | State=00 | Current Floor= 0 | Request Floor= 1 | Door Alert=0 | Weight Alert=0
Time=15 | State=01 | Current Floor= 0 | Request Floor= 1 | Door Alert=0 | Weight Alert=0
Time=20 | State=01 | Current Floor= 0 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=25 | State=01 | Current Floor= 1 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=35 | State=01 | Current Floor= 2 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=45 | State=01 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0 Time=55 | State=00 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0 Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=1
Time=75 | State=11 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0 
Time=85 | State=01 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=95 | State=00 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=105 | State=01 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=115 | State=00 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=125 | State=01 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=135 | State=00 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=145 | State=01 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=155 | State=00 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=165 | State=01 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=175 | State=00 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=185 | State=01 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=195 | State=00 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=205 | State=01 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0
Time=215 | State=00 | Current Floor= 3 | Request Floor= 3 | Door Alert=0 | Weight Alert=0.
As you can see in the log, the FSM doesn't detect when and where the ALERT state should be triggered. The over_weigth is activated in floor 3 rather than floor 2.

I suspect the error had to do with clock generation. I dont know much how to configure the clock of the FSM.

So my question is: How can I succesfully detect the over weigth with is asociate state (ERROR) and make a transtion of state?
 
Top