이번에는 베릴로그를 활용하여 간단한 FSM을 설계해보려고 합니다.

사진에 나온 FSM을 먼저 설계해보도록 하겠습니다. 아래 상태도는 STOP와 RUN 이라는 2가지 state(상태)를 가지고 있습니다. Switch로 입력을 받고 출력으로 LED를 On/Off 하는 로직입니다. LED[0]이 On 되어 있는 상태를 STOP 상태로 정의하고 LED[1]이 On 되어 있는 상태를 RUN 상태라고 할 수 있습니다.

image.png

ℹ️ Verilog Code(fsm1)

아래 코드는 두 개의 상태(STOP, RUN)를 가진 Finite State Machine(FSM, 유한 상태 기계)를 구현한 예제입니다. 입력 신호 sw에 따라 상태를 전이시키고, 각 상태에 따라 출력 led 값을 변경합니다.

이 FSM은 clk 상승 엣지에서 동작하고, reset 신호가 들어오면 초기 상태로 복귀합니다. led는 현재 상태를 사용자에게 표시합니다.

module fsm (
    input clk,
    input reset,
    input sw,
    output reg [1:0] led
);

STOP 상태와 RUN 상태는 각각 1비트로 정의됩니다. c_staten_state는 각각 현재 상태와 다음 상태를 나타냅니다.

parameter STOP = 1'b0, RUN = 1'b1;
reg c_state, n_state;

아래 always 블록은 상태 레지스터로 클럭의 상승 엣지마다 상태를 업데이트합니다. reset이 1이면 무조건 STOP 상태로 초기화되고 그렇지 않으면 다음 상태 n_state를 현재 상태에 반영합니다.

    // state register
    always @(posedge clk, posedge reset) begin
        if (reset) begin
            c_state <= 1'b0; // reset이 걸려있으면 항상 stop(current state)
        end else begin
            c_state <= n_state;
        end
    end

아래 always 블록은 다음 상태를 결정하는 Combinational Logic입니다. STOP 상태일 때 스위치가 눌리면 RUN 상태로 전환하고 RUN 상태일 때 스위치를 놓으면 다시 STOP 상태로 전환합니다.

    // next state Combinational Logic
    always @(*) begin
        n_state = c_state; // 초기화
        case (c_state)
            STOP: begin
                // 입력 조건에 따라 next state를 처리한다.
                if (sw == 1'b1) begin
                    n_state = RUN;
                end
            end
            RUN: begin
                if (sw == 1'b0) begin
                    n_state = STOP;
                end
            end
            default: n_state = STOP;
        endcase
    end

아래는 현재 상태에 따라 출력 값을 조합 논리로 결정하는 코드입니다. STOP 상태는 led = 2'b10 이고 RUN 상태는 led = 2'b01 입니다. 즉, STOP 상태일때 led[1] 이 ON되고 RUN 상태일때 led[0] 이 ON됩니다.

always @(*) begin
    led = 2'b10; // 기본 출력은 STOP
    case (c_state)
        STOP: led = 2'b10;
        RUN:  led = 2'b01;
    endcase
end

전체 fsm 코드를 확인하면 다음과 같이 나오게 됩니다.

// fsm
`timescale 1ns / 1ps

module fsm (
    input clk,
    input reset,
    input sw,
    output reg [1:0] led
);

    // 상태 정의.
    parameter STOP = 1'b0, RUN = 1'b1;  // 상태는 2개의므로 1bit
    reg c_state, n_state;  // c_state : current state, n_state : next state

    // state register
    always @(posedge clk, posedge reset) begin
        if (reset) begin
            c_state <= 1'b0; // reset이 걸려있으면 항상 stop(current state)
        end else begin
            c_state <= n_state;
        end
    end

    // next state Combinational Logic
    always @(*) begin
        n_state = c_state; // 초기화
        case (c_state)
            STOP: begin
                // 입력 조건에 따라 next state를 처리한다.
                if (sw == 1'b1) begin
                    n_state = RUN;
                end
            end
            RUN: begin
                if (sw == 1'b0) begin
                    n_state = STOP;
                end
            end
            default: n_state = STOP;
        endcase
    end

    // Output Combinational Logic
    always @(*) begin
        led = 2'b10; // 초기화
        case (c_state)
            STOP: begin
                led = 2'b10;
            end
            RUN: begin
                led = 2'b01;
            end
        endcase
    end

endmodule