I'm working on a Verilog project using ModelSim, and I've created a testbench to simulate the behavior of a module called Elevator_FSM, which models an elevator's operation.
My goal is to assign values to the request_floor signal from the testbench and, based on that signal, have the output signals, such as output_floor, and the internal states of the Finite State Machine (FSM) update accordingly.
The problem: I want my testbench to assign values to request_floor
and have those values correctly update the output signals and internal states of the Elevator_FSM
module. However, I'm not seeing the expected changes reflected in the simulation.
Debugging details are as follows:
This module simulates the behavior of an elevator using a Finite State Machine (FSM). The system's inputs include signals like request_floor
, over_time
, and over_weight
, which determine the elevator's behavior. The outputs include current_floor
(the current floor) and alert signals such as door_alert
and weight_alert
.
Inputs:
clk
: Clock signal.reset
: Signal to reset the system, restoring initial values.request_floor
: The floor to which the user requests the elevator to move (4-bit value).over_time
: Indicates if the elevator door has been open for an excessive amount of time (more than 3 minutes).over_weight
: Indicates if the weight inside the elevator exceeds the allowed limit.
Outputs:
current_floor
: The current floor of the elevator.door_alert
: Alert activated when the door has been open for more than 3 minutes.weight_alert
: Alert activated when the weight exceeds the allowed limit.
FSM States:
The FSM has four possible states, represented by current_state
and next_state
:
IDLE
(00): The elevator is inactive, waiting for a request.MOVING
(01): The elevator is moving towards the requested floor.ALERT
(10): The elevator has detected an issue (door open for too long or over weight).ERROR
(11): The elevator is in an error state, such as over weight or sensor error.
Combinational Logic:
The elevator's behavior is based on the comparison between current_floor
and request_floor
, as well as the signals over_time
and over_weight
.
IDLE
State:- The elevator is inactive, waiting for a
request_floor
. - If
request_floor
is not equal to 0 (i.e., there is a floor request), the system transitions to theMOVING
state. current_floor
remains constant in theIDLE
state.
- The elevator is inactive, waiting for a
MOVING
State:- The elevator is moving.
- If
request_floor
is greater thancurrent_floor
, the elevator moves up. - If
request_floor
is less thancurrent_floor
, the elevator moves down. - If
current_floor == request_floor
, the elevator has reached the destination and returns to theIDLE
state. - During movement, if
over_time
is active (door open for more than 3 minutes), the elevator enters theALERT
state. - If
over_weight
is active (weight exceeded), the system enters theERROR
state.
ALERT
State:- In this state, the system waits for the door time issue to resolve.
- If
over_time
returns to 0 (door no longer open for too long), the elevator can return to theMOVING
state to continue movement.
ERROR
State:- If
over_weight
is active (indicating over weight), the elevator enters theERROR
state. - If
over_weight
returns to 0 (weight no longer exceeds limit), the elevator can return toMOVING
orIDLE
if no more requests.
- If
Elevator_FSM Module Code:
module Elevator_FSM(
input clk, // Clock signal
input reset, // Asynchronous reset signal
input [3:0] request_floor, // Requested floor
input over_time, // Door open time signal
input over_weight, // Over weight signal
output reg [3:0] current_floor, // Current floor
output reg door_alert, // Door alert
output reg weight_alert // Weight alert
);
// State definitions
localparam IDLE = 2'b00,
MOVING = 2'b01,
ALERT = 2'b10,
ERROR = 2'b11;
// Registers for current and next state
reg [1:0] current_state, next_state;
// Asynchronous reset for current state
always @(posedge clk or posedge reset) begin
if (reset)
current_state <= IDLE;
else
current_state <= next_state;
end
// Combinational logic: next state + alert generation
always @(*) begin
next_state = current_state;
door_alert = 1'b0;
weight_alert = 1'b0;
case (current_state)
IDLE: begin
if (request_floor != 4'b0000)
next_state = MOVING;
end
MOVING: begin
if (over_time) begin
door_alert = 1'b1;
next_state = ALERT;
end
else if (over_weight) begin
weight_alert = 1'b1;
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
default: next_state = IDLE;
endcase
end
// Asynchronous reset for current floor
always @(posedge clk or posedge reset) begin
if (reset)
current_floor <= 4'b0000; // Initialize to floor 0
else if (current_state == MOVING) begin
if (current_floor < request_floor && current_floor < 4'b1111)
current_floor <= current_floor + 1;
else if (current_floor > request_floor && current_floor > 4'b0000)
current_floor <= current_floor - 1;
end
end
endmodule
And this is the testbench that I've made:
module Elevator_FSM_tb;
reg clk;
reg reset;
reg [3:0] request_floor;
reg [3:0] current_floor;
reg over_time;
reg over_weight;
wire [3:0] current_floor_out;
wire door_alert;
wire weight_alert;
Elevator_FSM uut (
.clk(clk),
.reset(reset),
.request_floor(request_floor),
.over_time(over_time),
.over_weight(over_weight),
.current_floor(current_floor_out),
.door_alert(door_alert),
.weight_alert(weight_alert)
);
always begin
#5 clk = ~clk;
end
initial begin
clk = 0;
reset = 1;
request_floor = 4'b0000;
current_floor = 4'b0000;
over_time = 0;
over_weight = 0;
#10 reset = 0;
#10 request_floor = 4'b0001; // Solicitar piso 1
#10 request_floor = 4'b0010; // Solicitar piso 2
#10 request_floor = 4'b0011; // Solicitar piso 3
#10 request_floor = 4'b0100; // Solicitar piso 4
#10 request_floor = 4'b0101; // Solicitar piso 5
#10 request_floor = 4'b0110; // Solicitar piso 6
#10 request_floor = 4'b0111; // Solicitar piso 7
// Simulamos un error de tiempo en la puerta
#10 over_time = 1;
#10 over_time = 0;
// Simulamos un error de sobrepeso
#10 over_weight = 1;
#10 over_weight = 0;
#10 $finish;
end
endmodule
PD: I set four request_floor
expecting the fsm automatically detect the current_floor
and update the current_floor
value with the former value of request_floor
. I know the external state such as IDLE, ERROR, MOVING, ALERT
doesn't seem reflected on the testbench because I didnt assign the values for them. Also, I dont know much about setting testbench.
But when I simulate from the Intel quartus idle to ModelSim simulator, this what I got:
What should I do to ensure the signals update and reflect the signals correctly during simulation?
-
\$\begingroup\$ What should I do when someone answers my question? \$\endgroup\$toolic– toolic2025年08月18日 21:45:53 +00:00Commented Aug 18 at 21:45
1 Answer 1
The problem is with your simulator, or how you are running your simulation software. If all you see is x
and z
in waves, that means the simulation has not run properly.
The Verilog code simulates fine for me on other simulators. You can run it on EDA Playground to see waveforms toggling like this:
Explore related questions
See similar questions with these tags.