Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- verilog
- hc-sr04
- vivado
- Recursion
- Pspice
- soc 설계
- structural modeling
- Edge Detector
- stop watch
- ring counter
- Algorithm
- ATMEGA128A
- java
- uart 통신
- prescaling
- D Flip Flop
- behavioral modeling
- half adder
- test bench
- BASYS3
- LED
- FND
- gpio
- KEYPAD
- dataflow modeling
- i2c 통신
- Linked List
- pwm
- atmega 128a
- DHT11
Archives
- Today
- Total
거북이처럼 천천히
Stop Watch - 1 본문
1. Stop Watch
- 이번에 구현한 Stop Watch 코드는 본인 스스로 구현한 것이기 때문에 아래 게시글에서 구현한 Stop Watch 코드와 약간의 차이가 있을 수 있으나, 알고리즘 관점에서는 큰 차이를 갖지 않는다.
- Stop Watch의 동작 원리 및 자세한 코드 설명은 아래 게시글을 참고하길 바란다.
2. Source code of Stop Watch
< Source, Clock divider 10 >
// Clock divider 10.
module clk_div_10 (
input clk, reset_p,
input clk_source,
output clk_div_10,
output clk_div_10_nedge, clk_div_10_pedge );
wire clk_source_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
reg [3:0] count;
always @(posedge clk or posedge reset_p) begin
if(reset_p) count = 0;
else if(clk_source_nedge) begin
if(count >= 9) count = 0;
else count = count + 1;
end
end
assign clk_div_10 = (count < 5)? 0 : 1;
edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_10), .n_edge(clk_div_10_nedge), .p_edge(clk_div_10_pedge));
endmodule
< Source, BCD 100진 Counter >
// BCD 100진 Counter.
module bcd_100_counter (
input clk, reset_p,
input clk_resource,
output reg [3:0] bcd10, bcd1 );
wire clk_resource_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_resource), .n_edge(clk_resource_nedge));
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin bcd10 = 0; bcd1 = 0; end
else if(clk_resource_nedge) begin
if(bcd1 >= 9) begin
bcd1 = 0;
if(bcd10 >= 9) bcd10 = 0;
else bcd10 = bcd10 + 1;
end
else bcd1 = bcd1 + 1;
end
end
endmodule
< Source, BCD 60진 Counter >
// BCD 60진 Counter.
module bcd_60_counter (
input clk, reset_p,
input clk_resource,
output reg [3:0] bcd10, bcd1 );
wire clk_resource_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_resource), .n_edge(clk_resource_nedge));
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin bcd10 = 0; bcd1 = 0; end
else if(clk_resource_nedge) begin
if(bcd1 >= 9) begin
bcd1 = 0;
if(bcd10 >= 5) bcd10 = 0;
else bcd10 = bcd10 + 1;
end
else bcd1 = bcd1 + 1;
end
end
endmodule
< Source, Top Module of Stop Watch >
module Stop_Watch_0(
input clk, reset_p,
input [2:0] btn,
output [3:0] com,
output [7:0] seg_7 );
// Get One Cycle Pulse of button.
wire btn_start, btn_lap, btn_clear;
button_cntr button_start_control (.clk(clk), .reset_p(reset_p), .button_source(btn[0]), .button_pedge(btn_start));
button_cntr button_lap_control (.clk(clk), .reset_p(reset_p), .button_source(btn[1]), .button_pedge(btn_lap));
button_cntr button_clear_control (.clk(clk), .reset_p(reset_p), .button_source(btn[2]), .button_pedge(btn_clear));
// Declare Reset Variable & new clk signal
wire new_reset = btn_clear | reset_p;
wire new_clk = start_stop_mode & clk;
// Declare Mode
wire start_stop_mode;
t_flip_flop t_flip_flop_mode (.clk(clk), .reset_p(new_reset), .button(btn_start), .q(start_stop_mode));
// Get One cycle pulse of msec, sec.
wire clk_1usec, clk_1msec, clk_10msec, clk_1sec;
clk_div_100 clk_div_1usec (.clk(new_clk), .reset_p(new_reset), .clk_div_100(clk_1usec));
clk_div_1000 (.clk(clk), .reset_p(new_reset), .clk_source(clk_1usec), .clk_div_1000(clk_1msec));
clk_div_10 (.clk(clk), .reset_p(new_reset), .clk_source(clk_1msec), .clk_div_10_nedge(clk_10msec));
clk_div_1000 (.clk(clk), .reset_p(new_reset), .clk_source(clk_1msec), .clk_div_1000_nedge(clk_1sec));
// BCD Counter
wire [3:0] bcd10_sec, bcd1_sec, bcd10_msec, bcd1_msec;
bcd_60_counter bcd_60_counter_0 (.clk(clk), .reset_p(new_reset), .clk_resource(clk_1sec), .bcd10(bcd10_sec), .bcd1(bcd1_sec));
bcd_100_counter bcd_100_counter_0 (.clk(clk), .reset_p(new_reset), .clk_resource(clk_10msec), .bcd10(bcd10_msec), .bcd1(bcd1_msec));
// Data of time
wire [15:0] current_time;
reg [15:0] lap_time;
assign current_time = {bcd10_sec, bcd1_sec, bcd10_msec, bcd1_msec};
// Declare Lap time
always @(posedge clk or posedge reset_p) begin
if(reset_p | btn_clear) lap_time = 16'b0;
else if(btn_lap) lap_time = current_time;
else lap_time = lap_time;
end
// Select data of time
wire stopWatch_Lap_mode;
t_flip_flop t_flip_flop_lap (.clk(clk), .reset_p(new_reset), .button(btn_lap), .q(stopWatch_Lap_mode));
wire [15:0] hex_value = (stopWatch_Lap_mode)? lap_time : current_time;
// Print the time to FND.
fnd_cntr control_fnd (.clk(clk), .reset_p(reset_p), .hex_value(hex_value), .com(com), .seg_7(seg_7));
endmodule
3. 구현 영상
4. 전체 소스 코드
// Top Module
module Stop_Watch_0(
input clk, reset_p,
input [2:0] btn,
output [3:0] com,
output [7:0] seg_7 );
// Get One Cycle Pulse of button.
wire btn_start, btn_lap, btn_clear;
button_cntr button_start_control (.clk(clk), .reset_p(reset_p), .button_source(btn[0]), .button_pedge(btn_start));
button_cntr button_lap_control (.clk(clk), .reset_p(reset_p), .button_source(btn[1]), .button_pedge(btn_lap));
button_cntr button_clear_control (.clk(clk), .reset_p(reset_p), .button_source(btn[2]), .button_pedge(btn_clear));
// Declare Reset Variable & new clk signal
wire new_reset = btn_clear | reset_p;
wire new_clk = start_stop_mode & clk;
// Declare Mode
wire start_stop_mode;
t_flip_flop t_flip_flop_mode (.clk(clk), .reset_p(new_reset), .button(btn_start), .q(start_stop_mode));
// Get One cycle pulse of msec, sec.
wire clk_1usec, clk_1msec, clk_10msec, clk_1sec;
clk_div_100 clk_div_1usec (.clk(new_clk), .reset_p(new_reset), .clk_div_100(clk_1usec));
clk_div_1000 (.clk(clk), .reset_p(new_reset), .clk_source(clk_1usec), .clk_div_1000(clk_1msec));
clk_div_10 (.clk(clk), .reset_p(new_reset), .clk_source(clk_1msec), .clk_div_10_nedge(clk_10msec));
clk_div_1000 (.clk(clk), .reset_p(new_reset), .clk_source(clk_1msec), .clk_div_1000_nedge(clk_1sec));
// BCD Counter
wire [3:0] bcd10_sec, bcd1_sec, bcd10_msec, bcd1_msec;
bcd_60_counter bcd_60_counter_0 (.clk(clk), .reset_p(new_reset), .clk_resource(clk_1sec), .bcd10(bcd10_sec), .bcd1(bcd1_sec));
bcd_100_counter bcd_100_counter_0 (.clk(clk), .reset_p(new_reset), .clk_resource(clk_10msec), .bcd10(bcd10_msec), .bcd1(bcd1_msec));
// Data of time
wire [15:0] current_time;
reg [15:0] lap_time;
assign current_time = {bcd10_sec, bcd1_sec, bcd10_msec, bcd1_msec};
// Declare Lap time
always @(posedge clk or posedge reset_p) begin
if(reset_p | btn_clear) lap_time = 16'b0;
else if(btn_lap) lap_time = current_time;
else lap_time = lap_time;
end
// Select data of time
wire stopWatch_Lap_mode;
t_flip_flop t_flip_flop_lap (.clk(clk), .reset_p(new_reset), .button(btn_lap), .q(stopWatch_Lap_mode));
wire [15:0] hex_value = (stopWatch_Lap_mode)? lap_time : current_time;
// Print the time to FND.
fnd_cntr control_fnd (.clk(clk), .reset_p(reset_p), .hex_value(hex_value), .com(com), .seg_7(seg_7));
endmodule
// BCD 60진 Counter.
module bcd_60_counter (
input clk, reset_p,
input clk_resource,
output reg [3:0] bcd10, bcd1 );
wire clk_resource_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_resource), .n_edge(clk_resource_nedge));
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin bcd10 = 0; bcd1 = 0; end
else if(clk_resource_nedge) begin
if(bcd1 >= 9) begin
bcd1 = 0;
if(bcd10 >= 5) bcd10 = 0;
else bcd10 = bcd10 + 1;
end
else bcd1 = bcd1 + 1;
end
end
endmodule
// BCD 100진 Counter.
module bcd_100_counter (
input clk, reset_p,
input clk_resource,
output reg [3:0] bcd10, bcd1 );
wire clk_resource_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_resource), .n_edge(clk_resource_nedge));
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin bcd10 = 0; bcd1 = 0; end
else if(clk_resource_nedge) begin
if(bcd1 >= 9) begin
bcd1 = 0;
if(bcd10 >= 9) bcd10 = 0;
else bcd10 = bcd10 + 1;
end
else bcd1 = bcd1 + 1;
end
end
endmodule
// Button control
module button_cntr (
input clk, reset_p,
input button_source,
output reg button,
output button_pedge, button_nedge );
reg [16:0] count;
always @(posedge clk or posedge reset_p) begin
if(reset_p) count = 0;
else begin
if(count >= 99999) count = 0;
else count = count + 1;
end
end
wire clk_1ms;
assign clk_1ms = (count < 50000)? 0 : 1;
wire clk_1ms_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_1ms), .n_edge(clk_1ms_nedge));
always @(posedge clk or posedge reset_p) begin
if(reset_p) button = 0;
else if(clk_1ms_nedge) button = button_source;
else button = button;
end
edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(button), .p_edge(button_pedge), .n_edge(button_nedge));
endmodule
// T Flip - Flop
module t_flip_flop (
input clk, reset_p,
input button,
output reg q);
always @(posedge clk or posedge reset_p) begin
if(reset_p) q = 0;
else if(button) q = ~ q;
else q = q;
end
endmodule
// Control FND.
module fnd_cntr (
input clk, reset_p,
input [15:0] hex_value,
output [3:0] com,
output [7:0] seg_7 );
// Ring counter of com value
ring_counter ring_counter_0 (.clk(clk), .reset_p(reset_p), .com(com));
// Selecting seg_7 value
reg [3:0] value;
always @(*) begin
case (com)
4'b1110 : value = hex_value[3:0];
4'b1101 : value = hex_value[7:4];
4'b1011 : value = hex_value[11:8];
4'b0111 : value = hex_value[15:12];
default : value = value;
endcase
end
decoder_of_seg_7 decoder_7_segment (.hex_value(value), .seg_7(seg_7));
endmodule
// Ring Counter
module ring_counter (
input clk, reset_p,
output reg [3:0] com );
wire clk_1usec, clk_1msec;
clk_div_100 clk_usec (.clk(clk), .reset_p(reset_p), .clk_div_100(clk_1usec));
clk_div_1000 clk_msec(.clk(clk), .reset_p(reset_p), .clk_source(clk_1usec), .clk_div_1000_nedge(clk_1msec));
always @(posedge clk or posedge reset_p) begin
if(reset_p) com = 4'b1110;
else if(clk_1msec) begin
if(com == 4'b0111) com = 4'b1110;
else com = {com[2:0], 1'b1};
end
end
endmodule
// Clock divider 10.
module clk_div_10 (
input clk, reset_p,
input clk_source,
output clk_div_10,
output clk_div_10_nedge, clk_div_10_pedge );
wire clk_source_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
reg [3:0] count;
always @(posedge clk or posedge reset_p) begin
if(reset_p) count = 0;
else if(clk_source_nedge) begin
if(count >= 9) count = 0;
else count = count + 1;
end
end
assign clk_div_10 = (count < 5)? 0 : 1;
edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_10), .n_edge(clk_div_10_nedge), .p_edge(clk_div_10_pedge));
endmodule
// Clock divider 60.
module clk_div_60 (
input clk, reset_p,
input clk_source,
output clk_div_60,
output clk_div_60_nedge, clk_div_60_pedge );
wire clk_source_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
reg [5:0] clk_div_60_count;
always @(posedge clk or posedge reset_p) begin
if(reset_p) clk_div_60_count = 0;
else if(clk_source_nedge) begin
if(clk_div_60_count >= 59) clk_div_60_count = 0;
else clk_div_60_count = clk_div_60_count + 1;
end
end
assign clk_div_60 = (clk_div_60_count < 30)? 0 : 1;
edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_60), .n_edge(clk_div_60_nedge), .p_edge(clk_div_60_pedge));
endmodule
// Clock divider 100.
module clk_div_100 (
input clk, reset_p,
output clk_div_100,
output clk_div_100_nedge, clk_div_100_pedge );
reg [6:0] clk_div_100_count;
always @(posedge clk or posedge reset_p) begin
if(reset_p) clk_div_100_count = 0;
else begin
if(clk_div_100_count >= 99) clk_div_100_count = 0;
else clk_div_100_count = clk_div_100_count + 1;
end
end
assign clk_div_100 = (clk_div_100_count < 50)? 0 : 1;
edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100), .n_edge(clk_div_100_nedge), .p_edge(clk_div_100_pedge));
endmodule
// Clock divider 1000.
module clk_div_1000 (
input clk, reset_p,
input clk_source,
output clk_div_1000,
output clk_div_1000_nedge, clk_div_1000_pedge );
wire clk_source_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
reg [9:0] clk_div_1000_count;
always @(posedge clk or posedge reset_p) begin
if(reset_p) clk_div_1000_count = 0;
else if(clk_source_nedge) begin
if(clk_div_1000_count >= 999) clk_div_1000_count = 0;
else clk_div_1000_count = clk_div_1000_count + 1;
end
end
assign clk_div_1000 = (clk_div_1000_count < 500)? 0 : 1;
edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_1000), .n_edge(clk_div_1000_nedge), .p_edge(clk_div_1000_pedge));
endmodule
// Decoder of 7-segment.
module decoder_of_seg_7 (
input [3:0] hex_value,
output reg [7:0] seg_7);
always @(hex_value) begin
case (hex_value)
0 : seg_7 = 8'b0000_0011; //common anode, 0이 켜지는거임
1 : seg_7 = 8'b1001_1111; // 1
2 : seg_7 = 8'b0010_0101; // 2
3 : seg_7 = 8'b0000_1101; // 3
4 : seg_7 = 8'b1001_1001; // 4
5 : seg_7 = 8'b0100_1001; // 5
6 : seg_7 = 8'b0100_0001; // 6
7 : seg_7 = 8'b0001_1111; // 7
8 : seg_7 = 8'b0000_0001; // 8
9 : seg_7 = 8'b0000_1001; // 9
10 : seg_7 = 8'b0001_0001; // A
11 : seg_7 = 8'b1100_0001; // b
12 : seg_7 = 8'b0110_0011; // C
13 : seg_7 = 8'b1000_0101; // d
14 : seg_7 = 8'b0110_0001; // E
15 : seg_7 = 8'b0111_0001; // F
endcase
end
endmodule
// Edge detector.
module edge_detector (
input clk, reset_p,
input cp,
output n_edge, p_edge );
reg flip_flop_current, flip_flop_old;
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin flip_flop_current <= 0; flip_flop_old <=0; end
else begin
flip_flop_current <= cp;
flip_flop_old <= flip_flop_current;
end
end
assign p_edge = ({flip_flop_current, flip_flop_old} == 2'b10)? 1 : 0;
assign n_edge = ({flip_flop_current, flip_flop_old} == 2'b01)? 1 : 0;
endmodule
'RTL Design > Verilog 연습' 카테고리의 다른 글
4X4 Matrix KeyPad - 2 (0) | 2024.08.10 |
---|---|
4X4 Matrix KeyPad - 1 (0) | 2024.08.09 |
Advanced Clock (0) | 2024.08.06 |
Normal Clock (0) | 2024.08.04 |
비동기식 카운터 (Asynchronous counter) (0) | 2024.07.11 |