스탑워치를 표시할 7세그먼트 디스플레이 제어 모듈을 완성한 뒤 분, 초, 밀리초를 계산하여 세그먼트로 전송하는 스탑워치 모듈 설계를 진행했습니다.
Stopwatch 모듈 정의
Module Name: stopwatch
Inputs
- rst
- clk
- [1:0] mode:스탑워치가 Mode 1에서만 값을 세그먼트로 보낼 때 사용
- btn1: Start/Stop 버튼
- btn0: Reset 버튼
Outputs
- reg [13:0] value: 스탑워치를 통해 계산한 네자리 값을 출력
Registers
- reg [3:0] sec0_1, sec0_01: 0.1초, 0.01초의 값을 저장하는 레지스터. 0~9까지의 숫자를 저장하므로 4비트 사용
- reg [5:0] sec, min: 초, 분의 값을 저장하는 레지스터. 0~59까지의 숫자를 저장하므로 6비트 사용
- reg [20:0] timeval: 매 clk마다 값을 증가시켜 1,250,000이 되면 0.01초 값 증가
Stopwatch
Logic
스탑워치 작동 시 start/stop 동작은 왼쪽 버튼(btn1)으로 전환되고, 오른쪽 버튼(btn0)을 누르면 동작이 멈추고 즉시 초기화하도록 설계했습니다. 이 동작을 FSM으로 구현하여 다음과 같이 설계했습니다.
1. IDLE
- st 신호가 HIGH일 때 현재 상태를 IDLE로 변환
- 레지스터 sec0_01, sec0_1, sec, min와 value를 모두 초기화
- btn1이 눌렸을 경우에만 START상태로 이전
2. START
- 매 clk마다 증가하는 timeval 변수를 검사하여 시간 측정: timeval이 1,250,000에 도달하면 시간은 1,250,000/125M = 0.01s
- 0.01초마다 timeval을 초기화하며, sec0_01 값을 증가
- sec0_01값을 검사하여 sec0_1 값 증가
- sec0_1값을 검사하여 sec 값 증가
- sec 값을 검사하여 min 값 증가
- min이 0일 때(아직 1분이 지나지 않았을 때) 세그먼트로 전송하는 값 value를 초.밀리초로 구성
- min이 1 이상일 때 value를 분.초로 구성
- btn1이 눌리면 PAUSE 상태로 이전
- btn0이 눌리면 IDLE 상태로 이전(초기화)
3. PAUSE
- PAUSE상태에서는 어떠한 동작도 하지 않음(시간 증가 X)
- btn1이 눌리면 다시 START 상태로 돌아가 기존의 값에서 계속 시간 측정
- bnt0이 눌리면 IDLE 상태로 이전(초기화)
stopwatch.v
더보기
`timescale 1ns / 1ps
module stopwatch(
input rst,
input clk,
input [1:0] mode,
input btn1,
input btn0,
output reg [13:0] value
);
reg [3:0] sec0_1, sec0_01;
reg [5:0] sec, min;
reg [20:0] timeval;
//FSM: IDLE(0) -> START(1) <-> PAUSE(2) -> IDLE(0)
localparam IDLE = 2'b00, START = 2'b01, PAUSE = 2'b10;
reg [1:0] curr_state;
always @(posedge clk) begin
if(rst) begin
sec0_01 <= 0; sec0_1 <= 0; sec <= 0; min <= 0;
curr_state <= IDLE;
end
else begin
if(mode == 1) begin
case(curr_state)
IDLE: begin //IDLE
sec0_01 <= 0; sec0_1 <= 0; sec <= 0; min <= 0;
value <= 0;
if(btn1) curr_state <= START;
else curr_state <= IDLE;
end
START: begin
if(timeval < 1250000) timeval <= timeval+1; //125_000_0 = 125_000_000/100 => 0.01s
else begin
timeval <= 0;
sec0_01 <= sec0_01+1;
end
if(sec0_01>9) begin //0.09 다음 clk에서 0.1초 증가, 0.00초로 초기화
sec0_01 <= 0;
sec0_1 <= sec0_1+1;
if(sec0_1 > 8) begin //0.9초가 지나면 1초 증가
sec0_1 <= 0;
sec <= sec+1;
if(sec > 58) begin //59초가 지나면 1분 증가
sec <= 0;
min <= min+1;
end
end
end
if(min) value <= min*100+sec; //1분이 넘어서 min>0이면 분.초 표시
else value <= sec*100+sec0_1*10+sec0_01; //1분이 되지 않아 min == 0이면 초.밀리초 표시
if(btn1) curr_state <= PAUSE;
else if(btn0) curr_state <= IDLE;
end
2: begin //btn1을 누르면 일시정지, 이 때 btn0을 누르면 초기화, 다시 btn1을 누르면 시간 카운트
if(btn1) curr_state <= START;
else if(btn0) curr_state <= IDLE;
end
endcase
end //if(mode == 1) end
end //if(rst) else end
end //always end
endmodule
'자습시간 > Verilog' 카테고리의 다른 글
Vivado와 Vitis를 이용한 Pmod OLED 제어 [Pmod IP 이용] (0) | 2025.02.14 |
---|---|
Verilog 복습 프로젝트(3) - Decoder 설계 [Pmod KYPD 이용] (0) | 2025.02.12 |
Verilog 복습 프로젝트(1) - 7세그먼트 제어 (0) | 2025.02.11 |
Verilog 복습 프로젝트 - 스탑워치 / 계산기 / 타이머 / Pmod OLED (0) | 2025.02.11 |