FPGA를 활용한 디지털 시스템 설계에서 7세그먼트 디스플레이(FND)는 숫자나 간단한 정보를 시각적으로 출력할 때 자주 사용됩니다. 이번 글에서는 Verilog로 작성된 4자리 7세그먼트 제어 회로를 소개하고, 각 모듈의 역할과 동작 흐름을 자세히 분석해보겠습니다.

먼저 4비트 숫자를 받아 7-Segment FND에 출력할 수 있게 변환하는 bcd 모듈을 설계해보겠습니다.

Basys3 보드의 FND는 Common anode 방식이고, 각 세그먼트에 0을 출력하면 켜지게 됩니다.

image.png

ℹ️ Verilog Code

bcd 모듈의 소스 코드를 보면 아래와 같습니다. 우선 0~9까지의 10진수를 표현하기 위해 input은 4bit이고 output은 FND의 a~dp까지 총 8bit입니다. 예를 들면 숫자 0을 LED로 나타내려면 dp와 g를 off하고 나머지를 on하여 11000000가 됩니다.

fnd_data는 출력 포트이기 때문에 직접 대입할 수 없습니다. 따라서 내부에 reg형 변수 r_fnd_data를 만들고 always 블록 안에서 reg에 값을 저장한 후, assign으로 그 값을 fnd_data에 연결합니다.

module bcd (
    input  [3:0] bcd,
    output [7:0] fnd_data
);

    reg [7:0] r_fnd_data;

    assign fnd_data = r_fnd_data;

    // 조합논리 combinational , 행위수준 모델링.

    always @(bcd) begin
        case (bcd)
            4'h00:   r_fnd_data = 8'hc0;
            4'h01:   r_fnd_data = 8'hf9;
            4'h02:   r_fnd_data = 8'ha4;
            4'h03:   r_fnd_data = 8'hb0;
            4'h04:   r_fnd_data = 8'h99;
            4'h05:   r_fnd_data = 8'h92;
            4'h06:   r_fnd_data = 8'h82;
            4'h07:   r_fnd_data = 8'hf8;
            4'h08:   r_fnd_data = 8'h80;
            4'h09:   r_fnd_data = 8'h90;
            default: r_fnd_data = 8'hff;
        endcase
    end

endmodule

🔄 Latch 피하기

위 bcd 모듈에서 default 문이 없다면 어떻게 되는지 알아보겠습니다. default문을 삭제하고 Schematic를 확인하면 아래와 같이 나오게 됩니다.

image.png

r_fnd_data_reg으로 표시된 RTL_LATCH는 Verilog에서 latch 추론에 의해 생성된 구조입니다. 이는 사용자가 작성한 always 구문에서 모든 경우에 대해 r_fnd_data가 할당되지 않았기 때문입니다. case 문에서 bcd = 4'b1010 ~ 4'b1111 구간에 대한 처리가 없고 default도 없으므로, Verilog는 “값을 유지해야겠다” 라고 판단합니다. 이때 “이전 값을 유지”하기 위해 latch를 생성합니다.

그렇다면 Latch를 피하기 위해서 어떻게 코드를 작성해야 할까요?

위 코드에서는 모든 case에 대응하도록 default 문을 추가하여 Latch가 발생하는 것을 방지하였습니다.