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:
This is the log I got from the simulation, and the output waves were as expected:
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):
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:
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?
* 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
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)
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
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.
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?