
2층 엘리베이터
S_IDLE_1 : 1층에서 정지
S_IDLE_2 : 2층에서 정지
S_UP : 1층 → 2층 이동
S_DOWN : 2층 → 1층 이동
S_DOOR_OPEN : 문 열림 상태 (타이머 3초)
call_2
S_IDLE_1 ─────→ S_UP ─────→ S_DOOR_OPEN ─────→ S_IDLE_2
call_1
S_IDLE_2 ←──── S_DOWN ←──── S_DOOR_OPEN
module elevator(
input logic clk,
input logic reset,
input logic call_1,
input logic call_2,
output logic [1:0] state
);
// 상태 정의 (SystemVerilog enum)
typedef enum logic [1:0] {
S_IDLE_1 = 2'b00,
S_UP = 2'b01,
S_IDLE_2 = 2'b10,
S_DOWN = 2'b11
} state_t;
state_t curr, next;
// 상태 레지스터 (always_ff)
always_ff @(posedge clk or posedge reset) begin
if (reset)
curr <= S_IDLE_1;
else
curr <= next;
end
// 상태 전이 (조합논리 always_comb)
always_comb begin
next = curr;
unique case (curr)
S_IDLE_1: begin
if (call_2)
next = S_UP;
end
S_UP: begin
next = S_IDLE_2; // 클럭 1개 만에 도착하는 모델
end
S_IDLE_2: begin
if (call_1)
next = S_DOWN;
end
S_DOWN: begin
next = S_IDLE_1;
end
endcase
end
// 출력 (조합 논리)
always_comb begin
state = curr;
end
endmodule
module elevator_tb;
// Testbench signals
logic clk;
logic reset;
logic call_1, call_2;
logic [1:0] state;
// DUT
elevator dut (
.clk(clk),
.reset(reset),
.call_1(call_1),
.call_2(call_2),
.state(state)
);
// Clock generation (10ns period → 100MHz)
always #5 clk = ~clk;
// Stimulus
initial begin
// 초기화
clk = 0;
reset = 1;
call_1 = 0;
call_2 = 0;
#20;
reset = 0;
// 1층 → 2층 요청
#10 call_2 = 1;
#10 call_2 = 0;
// 도착 기다림
#50;
// 2층 → 1층 요청
#10 call_1 = 1;
#10 call_1 = 0;
#50;
$finish;
end
// 상태 모니터
initial begin
$display("===== Elevator SystemVerilog Testbench =====");
$monitor("T=%0t | call1=%b call2=%b | state=%b",
$time, call_1, call_2, state);
end
endmodule

