이번에는 베릴로그를 활용하여 간단한 FSM을 설계해보려고 합니다.
사진에 나온 FSM을 먼저 설계해보도록 하겠습니다. 아래 상태도는 STOP와 RUN 이라는 2가지 state(상태)를 가지고 있습니다. Switch로 입력을 받고 출력으로 LED를 On/Off 하는 로직입니다. LED[0]이 On 되어 있는 상태를 STOP 상태로 정의하고 LED[1]이 On 되어 있는 상태를 RUN 상태라고 할 수 있습니다.
아래 코드는 두 개의 상태(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_state
와 n_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