FSM (Elevator)

Seungyun Lee·2025년 11월 18일
post-thumbnail

2층 엘리베이터

요구사항

  1. 엘리베이터는 1층 또는 2층 중 하나에 위치
  2. 버튼은 2개
    1층 버튼(call_1)
    2층 버튼(call_2)
    3.엘리베이터 동작
    1층에서 2층 요청 -> 올라감
    2층에서 1층 요청 -> 내려감
  3. 각 층 도착하면 문을 잠시 열었다 닫고 정지
  4. 동작 상태
    STOP
    UP
    DOWN
    DOOR_OPEN

FSM 상태 설계

S_IDLE_1 : 1층에서 정지
S_IDLE_2 : 2층에서 정지
S_UP : 1층 → 2층 이동
S_DOWN : 2층 → 1층 이동
S_DOOR_OPEN : 문 열림 상태 (타이머 3초)

State Diagram

 call_2
 S_IDLE_1 ─────→ S_UP ─────→ S_DOOR_OPEN ─────→ S_IDLE_2
                     
 call_1
 S_IDLE_2 ←──── S_DOWN ←──── S_DOOR_OPEN

Verilog code

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

TestBench

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

Result


profile
RTL, FPGA Engineer

0개의 댓글