호타리 2025. 7. 9. 16:50

2025.07.09

 

shift_register & FSM

 

btnU 를 누르면 1이 btnD를 누르면 0이 입력 되도록 구현
입력 되는 상황은 led6~led0로 left shift표시 되도록 하고 동일한 입력 2개(00 또는 11) 발견 시00이면 led15 on 11이면 led14를 on
그렇지 않은 경우는 led15 led14를 off로 처리

 

 

 

top.v

`timescale 1ns / 1ps

module pattern_detector_top (
    input  wire clk,
    input  wire rst,      // 동기 리셋
    input  wire btnU,     // 1 입력 버튼
    input  wire btnD,     // 0 입력 버튼
    output wire [15:0] led // led[6:0] = 입력 표시, led[7] = 패턴 감지
);

    wire clean_btnU, clean_btnD;
    wire pulse_btnU, pulse_btnD;

    // 디바운싱
    button_debouncer db_u (
        .clk(clk),
        .btn(btnU),
        .debounced(clean_btnU)
    );

    button_debouncer db_d (
        .clk(clk),
        .btn(btnD),
        .debounced(clean_btnD)
    );

    // 원샷
    one_pulse op_u (
        .clk(clk),
        .btn_in(clean_btnU),
        .pulse_out(pulse_btnU)
    );

    one_pulse op_d (
        .clk(clk),
        .btn_in(clean_btnD),
        .pulse_out(pulse_btnD)
    );

    // FSM 동작
    pattern_detector_fsm fsm (
        .clk(clk),
        .rst(rst),
        .in1(pulse_btnU),
        .in0(pulse_btnD),
        .led(led)
    );

endmodule

 

pattern_detector_fsm.v

`timescale 1ns / 1ps


module pattern_detector_fsm (
    input wire clk,
    input wire rst,
    input wire in1,             // btnU → 1
    input wire in0,             // btnD → 0
    output reg [15:0] led       // led[6:0]: 입력 표시, led[14]: 11 감지, led[15]: 00 감지
);

    // 상태 정의
    parameter S_IDLE = 2'b00;
    parameter S_1ST  = 2'b01;

    reg [1:0] current_state, next_state;

    reg prev_bit;
    reg din_bit;
    reg input_valid;

    // 입력 디코딩
    always @(*) begin
        if (in1) begin
            din_bit = 1'b1;
            input_valid = 1'b1;
        end else if (in0) begin
            din_bit = 1'b0;
            input_valid = 1'b1;
        end else begin
            input_valid = 1'b0;
        end
    end

    // 입력 시프트 저장 레지스터 (입력값 자체 shift)
    reg [6:0] input_shift;

    // 상태 전이 및 출력 동작
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            current_state <= S_IDLE;
            prev_bit <= 1'b0;
            input_shift <= 7'b0000000;
            led[15:14] <= 2'b00;
        end else begin
            current_state <= next_state;

            if (input_valid) begin
                // ⬅ 왼쪽으로 입력값 shift (0 또는 1 입력 반영)
                input_shift <= {input_shift[5:0], din_bit};

                // 이전 입력과 비교하여 패턴 감지
                if (din_bit == 1'b0 && prev_bit == 1'b0) begin
                    led[15] <= 1'b1;  // 00
                    led[14] <= 1'b0;
                end else if (din_bit == 1'b1 && prev_bit == 1'b1) begin
                    led[15] <= 1'b0;
                    led[14] <= 1'b1;  // 11
                end else begin
                    led[15] <= 1'b0;
                    led[14] <= 1'b0;  // 01 or 10
                end

                prev_bit <= din_bit;
            end
        end
    end

    // 상태 천이 및 출력 결합
    always @(*) begin
        next_state = current_state;

        case (current_state)
            S_IDLE: begin
                if (input_valid)
                    next_state = S_1ST;
            end

            S_1ST: begin
                next_state = S_1ST;
            end
        endcase

        // 입력 시프트값 출력 연결
        led[6:0] = input_shift;
        // 나머지 led[13:7]는 0으로 유지
    end

endmodule

 

one_pulse.v

`timescale 1ns / 1ps

module one_pulse (
    input  wire clk,
    input  wire btn_in,
    output reg  pulse_out
);

    reg btn_delay;

    always @(posedge clk) begin
        btn_delay <= btn_in;
        pulse_out <= btn_in & ~btn_delay;
    end

endmodule

 

button_debouncer.v

`timescale 1ns / 1ps

module button_debouncer (
    input  wire clk,
    input  wire btn,
    output reg  debounced
);

    reg [15:0] cnt;
    reg btn_sync, btn_prev;

    always @(posedge clk) begin
        btn_sync <= btn;
        if (btn_sync == btn_prev)
            cnt <= cnt + 1;
        else
            cnt <= 0;

        if (cnt == 16'hFFFF)
            debounced <= btn_sync;

        btn_prev <= btn_sync;
    end

endmodule

 

결과 영상

https://youtu.be/zFXQ9qYePkk