[Basys_3] Implementation of a 7-Segment Counter Circuit with Debouncing and Edge Detection
juniha2025. 7. 7. 20:35
목적
비동기 리셋, 버튼 디바운싱, 에지 검출, 카운터, 7세그먼트 디코더를 조합하여 FPGA에서 정확한 사용자 입력 기반의 디지털 카운터 시스템을 구현
사용 코드 _ top_module
module counter_top(
input clk, // 시스템 클럭
input reset_p, // 비동기 리셋 입력 (양의 엣지에서 작동)
input btn, // 버튼 입력 (사용자가 누름)
output [7:0] seg_7, // 7세그먼트 LED 출력 (a~g + dp)
output [3:0] com // FND의 자릿수 선택 (common)
);
reg [3:0] count; // 현재 카운트 값 (0~15, 4비트)
wire btn_nedge; // 버튼 하강 에지 검출 신호
// 버튼 하강 에지를 감지하는 서브모듈 (디바운싱 포함)
botton_cntr btn0(
.clk(clk),
.reset_p(reset_p),
.btn(btn),
.btn_nedge(btn_nedge)
);
// 버튼이 눌려졌을 때(count 증가), 또는 리셋일 때 동작
always @(posedge clk, posedge reset_p) begin
if (reset_p)
count = 0; // 리셋 시 카운터 초기화
else if (btn_nedge)
count = count + 1; // 버튼 하강 에지 시 카운트 증가
end
// 현재 count 값을 7세그먼트에 표시
fnd_4digit_cntr fnd(
.value(count),
.seg_7(seg_7),
.com(com)
);
endmodule
사용 코드_2 _하위 모듈
module botton_cntr(
input clk, // 시스템 클럭 입력
input reset_p, // 비동기 리셋 (양의 엣지에서 동작)
input btn, // 버튼 입력
output btn_pedge, // 버튼 상승 에지 감지 출력
output btn_nedge // 버튼 하강 에지 감지 출력
);
// 17비트 클럭 분주기: 버튼 디바운싱을 위한 느린 클럭 생성
reg [16:0] clk_div;
always @(posedge clk)
clk_div = clk_div + 1; // 클럭 상승엣지마다 증가 (자동 순환)
// 분주된 클럭의 상승 에지를 검출하기 위한 와이어
wire clk_div_16_pedge;
edge_detector_p edp( // 클럭 분주기의 bit[16]에서 에지 검출
.clk(clk),
.reset_p(reset_p),
.cp(clk_div[16]),
.p_edge(clk_div_16_pedge)
);
// 디바운싱된 버튼 값을 저장하는 레지스터
reg debounced_btn;
always @(posedge clk, posedge reset_p) begin
if (reset_p)
debounced_btn = 0; // 리셋 시 버튼 값 초기화
else if (clk_div_16_pedge)
debounced_btn = btn; // 분주된 클럭에서 버튼 값 샘플링
end
// 디바운싱된 버튼 값의 상승/하강 에지 검출기
edge_detector_p ed(
.clk(clk),
.reset_p(reset_p),
.cp(debounced_btn),
.p_edge(btn_pedge), // 버튼 상승 에지 출력
.n_edge(btn_nedge) // 버튼 하강 에지 출력
);
endmodule
사용 코드_2 하위 모듈 _edge_detector
입력 신호(cp)의 상승 엣지 또는 하강 에지를 검출하는 엣지 검출기(edge detector)
module edge_detector_p(
input clk, // 클럭 입력
input reset_p, // 비동기 리셋 입력 (posedge 기준)
input cp, // 엣지를 감지할 입력 신호
output p_edge, // 양의 엣지(상승 에지) 검출 출력
output n_edge // 음의 엣지(하강 에지) 검출 출력
);
reg ff_cur, ff_old; // 현재 값과 이전 값을 저장할 플립플롭
// 클럭 상승 또는 리셋 상승 시 동작
always @(posedge clk, posedge reset_p) begin
if (reset_p) begin
ff_cur = 0; // 리셋 시 플립플롭 초기화
ff_old = 0;
end
else begin
ff_old <= ff_cur; // 이전 상태 저장
ff_cur <= cp; // 현재 입력 cp 저장
end
end
// 양의 에지 검출: 이전 값 0 → 현재 값 1
assign p_edge = {ff_cur, ff_old} == 2'b10 ? 1 : 0;
// 음의 에지 검출: 이전 값 1 → 현재 값 0
assign n_edge = {ff_cur, ff_old} == 2'b01 ? 1 : 0;
endmodule
Schematic_top_module
결과 동작
결론
1) 버튼 처리: botton_cntr
버튼은 노이즈(글리치)가 발생하므로, 디바운싱과 엣지 검출이 필요합니다.
botton_cntr 모듈은 내부적으로 다음을 포함합니다:
클럭 분주기 (clk_div)를 통해 느린 주기로 샘플링
디바운싱 처리: 지정된 주기마다 버튼 상태를 읽음
edge_detector_p 모듈을 사용해 버튼의 상승/하강 에지를 검출
2) 카운터 회로: counter_top
counter_top은 최상위 모듈로, 다음과 같은 역할을 수행합니다:
botton_cntr의 출력으로부터 버튼 하강 에지 감지
버튼이 눌릴 때마다 4비트 레지스터 count 값을 +1
리셋 시 count는 0으로 초기화
3) 7세그먼트 디코딩: fnd_4digit_cntr + decoder_7seg
fnd_4digit_cntr는 decoder_7seg 모듈을 통해 count 값을 **7세그먼트용 8비트 신호(seg_7)**로 변환