用有限状态机设计一个电梯控制电路。共有两层楼,每层安置一个叫电梯按钮。一楼按钮信号为req1,二楼按钮信号为req2。电梯内有两个按钮,信号分别为go1和go2。当所有按钮都没有按时,电梯根据目前的位置自动转换到一楼开门状态。如果电梯不在的楼层有req信号,电梯先到关门状态,然后改变楼层,最后在该楼层开门。如果电梯所在楼层有req信号,无论电梯是开门或关门都要保持开门,直到req信号消失。电梯处于开门状态时,如果收到去不同楼层的go信号,则电梯应先关门,然后到目的楼层,再开门。当电梯处于二楼开门状态时,如果没有任何按钮输入,一个时钟周期后,电梯应关门然后到一楼,并开门等在一楼。电路输入信号除以上按钮信号外,还有时钟clock及置零reset。 电路输出信号为up,down,open,close.
/**************************************************************
* File: elevator.v
* Description: This is a state machine design for 2-level
* elevator control circuit
**************************************************************/
module elevator (clock, reset, req1, req2, go1, go2,
up, down, open, close);
input clock, // clock input
reset, // active-high reset
req1, // level 1 request button
req2, // level 2 request button
go1, // Go level 1 button
go2; // Go level 2 button
output up, // up control output
down, // down control output
open, // open door control output
close; // close door control output
reg[3:0] state; // state of elevator
parameter[3:0]
OP1 = 0, // level 1 open door state
GUP = 1, // Go up state
CL2 = 3, // level 2 close door state
OP2 = 2, // level 2 open door state
GDN = 6, // Go down state
CL1 = 4; // level 1 close door state
reg up,down,open,close; // registered output
always @(posedge clock or posedge reset) begin
if(reset) begin
state <= OP1;
open <= 0;
close <= 0;
up <= 0;
down <= 0;
end
else begin
open <= 0; // default value, may be overwritten below
close <= 0;
up <= 0;
down <= 0; // end of defaut settings
case (state)
OP1: begin // from level 1 open door state
if(!req1 && (req2 || go2)) begin
close <= 1;
state <= GUP;
end
else open <= 1;
end
GUP: begin // from Go down state
up <= 1;
state <= CL2;
end
CL2: begin // from level 2 close door state
open <= 1;
state <= OP2;
end
OP2: begin // from level 2 open door state
if(req2) open <= 1;
else begin
close <= 1;
state <= GDN;
end
end
GDN: begin // from Go down state
down <= 1;
state <= CL1;
end
CL1: begin // from level 1 close state
open <= 1;
state <= OP1;
end
default: begin // any other unexpected states
state <= OP1;
open <= 0;
close <= 0;
up <= 0;
down <= 0;
end
endcase
end
end
endmodule
/*********************************************************
* File: testelevator.v
* Description: This module is a test bench to run
* the elevator state machine design
*********************************************************/
`timescale 1s / 1s
module testelevator;
reg clock, // clock generated in test bench
reset, // active-high reset
req1, // level 1 request button signal
req2, // level 2 request button signal
go1, // Go level 1 button signal
go2, // Go level 2 button signal
hold; // hold request
wire up, // up control
down, // down control
open, // open door control
close; // close door control
parameter[3:0]
OP1 = 0,
GUP = 1,
CL2 = 3,
OP2 = 2,
GDN = 6,
CL1 = 4;
elevator machine(.clock(clock), .reset(reset), .req1(req1),
.req2(req2), .go1(go1), .go2(go2),
.up(up), .down(down), .open(open), .close(close));
always #5 clock = !clock;
initial begin
$vcdpluson;
clock = 0;
reset = 1; // enable reset at start up
req1 = 0; // assign initial values to button signals
req2 = 0;
go1 = 0;
go2 = 0;
hold = 0;
#40 reset = 0; // release reset
repeat(2) @(posedge clock);
req2 = 1; // first request from level 2
repeat(1) @(posedge clock);
req1 = 1; // then there is a request from level 1
wait(machine.state==OP2) go1 = 1; // go 1 when arrives at L2
wait(machine.state==OP1) go2 = 1; // go 2 when arrives at L1
wait(machine.state==OP2) repeat(5) begin
req2 = 1; // hold the door open for 5 clocks
hold = 1;
@(posedge clock);
req1 = 1; // in the mean time req1 is pushed
end
hold = 0;
go1 = 1; // go1 pushed at L2
repeat(2) @(posedge clock); // let the req2 be cleared
wait(machine.state==OP1);
repeat(5) @(posedge clock);
$display("Elevator test completed. Look at waveforms to check.");
$finish;
end
always @(posedge clock) begin // this always clears held button signals
// note the order of the always blocks, settings in this block can
// be overwritton by the other always block
case (machine.state)
CL1: begin
req1 = 0;
go1 = 0;
end
OP1: begin
if(!hold) req1 = 0;
go1 = 0;
end
CL2: begin
req2 = 0;
go2 = 0;
end
OP2: begin
if(!hold) req2 = 0;
go2 = 0;
end
endcase
end
initial begin
repeat(200) @(posedge clock); // time out limit is 200 clocks
$display("Error: time out stop.");
$finish;
end
endmodule