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 | 29 | 30 | 31 |
Tags
- java
- dataflow modeling
- i2c 통신
- FND
- pwm
- uart 통신
- verilog
- Linked List
- ATMEGA128A
- BASYS3
- LED
- hc-sr04
- soc 설계
- prescaling
- Pspice
- DHT11
- Algorithm
- Recursion
- half adder
- test bench
- KEYPAD
- behavioral modeling
- structural modeling
- ring counter
- gpio
- atmega 128a
- vivado
- D Flip Flop
- Edge Detector
- stop watch
Archives
- Today
- Total
거북이처럼 천천히
Verilog RTL 설계(7월 18일 - 5, Stop Watch - 4) 본문
1. 4초 때 리셋 버튼을 누른 뒤, 다시 Stop watch를 실행하니 56초때 분값이 증가한다.
1.1. 문제 현상
- 4초 때 리셋 버튼을 누른 뒤, 다시 Stop Watch를 실행하니 56초때 분값이 증가하는 현상을 확인할 수 있다.
1.2. 문제 원인
- BCD 60진 Counter를 통해 현재까지 Counter가 counting한 값을 초기화 시켜줌으로서 cur_time 값을 초기화시켜주었으며, lap_time도 btn_clear가 활성화되면 초기화시켜줌으로서 0분 0초로 만들어 주었다.
- 그러나, BCD 60진 Counter가 Counting함에 있어 기준 펄스가 되는 clk_sec와 clk_min에 대해서 초기화를 시켜주지 않았다.
- 따라서 clk_sec과 clk_min 펄스파는 clear 된 것과 상관없이 계속 초기화전 상태의 펄스파를 만들어 냄으로서 BCD 60진 Counter는 해당 펄스 파형에 따라 Counting하여 이러한 문제점이 발생한 것이다.
1.3. 문제 해결 방안
- reset 버튼이 눌렸을 경우, 모드에 대한 초기화, 시간에 대한 초기화 뿐만 아니라 clk_sec와 clk_min에 대한 초기화도 필요하다.
- 따라서 아래와 같이 수정함으로서 reset_p 뿐만 아니라 reset 버튼이 눌렸을 경우 clk_sec와 clk_min이 초기화 되도록 설계할 필요가 있다.
1.4. 수정된 코드
< 수정 전, 코드 >
clk_div_n clk_div_sec(.clk(clk), .reset_p(reset_p), .clk_source(clk_usec), .prescale(1000000), .clk_div_n_nedge(clk_sec));
clk_div_n clk_div_min(.clk(clk), .reset_p(reset_p), .clk_source(clk_sec), .prescale(60), .clk_div_n_nedge(clk_min));
< 수정 후, 코드 >
clk_div_n clk_div_sec(.clk(clk), .reset_p(reset_start), .clk_source(clk_usec), .prescale(1000000), .clk_div_n_nedge(clk_sec));
clk_div_n clk_div_min(.clk(clk), .reset_p(reset_start), .clk_source(clk_sec), .prescale(60), .clk_div_n_nedge(clk_min));
1.5. 구현 영상
2. Stop Watch의 전체 소스 코드
module Stop_Watch(
input clk, reset_p,
input [2:0] btn,
output [3:0] com,
output [7:0] seg_7 );
// Control Stop Watch
wire btn_start, btn_lap, btn_clear;
button_cntr control_btn_set (.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_nedge(btn_start));
button_cntr control_btn_lap (.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_nedge(btn_lap));
button_cntr control_btn_clear (.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_nedge(btn_clear));
// Control Start / Stop mode.
wire reset_start = reset_p | btn_clear;
wire start_stop;
t_flip_flop t_flip_flop_0 (.clk(clk), .reset_p(reset_start), .t(btn_start), .q(start_stop));
// Control Lap mode
wire lap;
t_flip_flop t_flip_flop1 (.clk(clk), .reset_p(reset_start), .t(btn_lap), .q(lap));
// Control clk.
wire clk_start;
assign clk_start = (start_stop)? clk : 0;
// Get One Cycle Pulse of Second , Minute
wire clk_usec, clk_sec, clk_min;
clk_div_100 clk_div_usec (.clk(clk_start), .reset_p(reset_p), .clk_div_100(clk_usec));
clk_div_n clk_div_sec(.clk(clk), .reset_p(reset_start), .clk_source(clk_usec), .prescale(1000000), .clk_div_n_nedge(clk_sec));
clk_div_n clk_div_min(.clk(clk), .reset_p(reset_start), .clk_source(clk_sec), .prescale(60), .clk_div_n_nedge(clk_min));
// BCD 60 Counter (add claer function)
wire [3:0] min10, min1, sec10, sec1;
counter_bcd_60_clear counter_sec(.clk(clk), .reset_p(reset_p), .clk_time(clk_sec), .clear(btn_clear), .bcd1(sec1), .bcd10(sec10));
counter_bcd_60_clear counter_min(.clk(clk), .reset_p(reset_p), .clk_time(clk_min), .clear(btn_clear), .bcd1(min1), .bcd10(min10));
// Combine data.
wire [15:0] hex_value, cur_time;
reg [15:0] lap_time;
assign cur_time = {min10, min1, sec10, sec1};
always @(posedge clk or posedge reset_p) begin
if(reset_p | btn_clear) lap_time = 0;
else if(btn_lap) lap_time = cur_time;
end
assign hex_value = (lap)? lap_time : cur_time;
fnd_cntr fnd(.clk(clk), .reset_p(reset_p), .value(hex_value), .com(com), .seg_7(seg_7));
endmodule
// T Flip Flop
module t_flip_flop (
input clk, reset_p,
input t,
output reg q );
always @(posedge clk or posedge reset_p) begin
if(reset_p) q = 0;
else q = (t)? ~q : q;
end
endmodule
// Control Button.
module button_cntr (
input clk, reset_p,
input btn,
output btn_pedge, btn_nedge);
// Get 1ms One Cycle Pulse
reg [16:0] counter;
always @(posedge clk or posedge reset_p) begin
if(reset_p) counter = 0;
else begin
if(counter >= 99999) counter = 0;
else counter = counter + 1;
end
end
wire clk_1ms, clk_1ms_nedge;
assign clk_1ms = (counter < 50000) ? 0 : 1;
edge_detector_n edge_dector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_1ms), .n_edge(clk_1ms_nedge));
// D Flip-Flop을 이용한 button 값 읽기
reg debounced_btn;
always @(posedge clk or posedge reset_p) begin
if(reset_p) debounced_btn = 0;
else if(clk_1ms_nedge) debounced_btn = btn;
end
edge_detector_n edge_dector_1 (.clk(clk), .reset_p(reset_p), .cp(debounced_btn), .n_edge(btn_nedge), .p_edge(btn_pedge));
endmodule
module counter_bcd_60_clear (
input clk, reset_p,
input clk_time,
input clear,
output reg [3:0] bcd1, bcd10 );
wire clk_time_nedge;
edge_detector_n edge_dector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_time), .n_edge(clk_time_nedge));
always @(posedge clk or posedge reset_p) begin
if(reset_p | clear) begin
bcd1 = 0;
bcd10 = 0;
end
else if(clk_time_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 60 Counter.
module counter_bcd_60(
input clk, reset_p,
input clk_time,
output reg [3:0] bcd1, bcd10 );
// Get One Cycle of clk_time
wire clk_time_nedge;
edge_detector_n edge_dector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_time), .n_edge(clk_time_nedge));
// Counter
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin
bcd1 = 0;
bcd10 = 0;
end
else if(clk_time_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
// Prescaler n
module clk_div_n (
input clk, reset_p,
input clk_source,
input [31:0] prescale,
output clk_div_n, clk_div_n_nedge );
// Get one cycle pulse of clk_source
wire clk_source_nedge;
edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
// Counting
integer counter;
always @(posedge clk or posedge reset_p) begin
if(reset_p) counter = 0;
else if(clk_source_nedge) begin
if(counter >= prescale-1) counter = 0;
else counter = counter + 1;
end
end
// Get clk_div_n wave, One cycle pulse of clk_div_n.
assign clk_div_n = (counter < prescale / 2)? 0 : 1;
edge_detector_n edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_n), .n_edge(clk_div_n_nedge));
endmodule
// Prescaler 100.
module clk_div_100 (
input clk, reset_p,
input clk_div_100,
input clk_div_100_nedge );
reg [6:0] counter;
always @(posedge clk or posedge reset_p) begin
if(reset_p) counter = 0;
else begin
if(counter >= 99) counter = 0;
else counter = counter + 1;
end
end
assign clk_div_100 = (counter < 50)? 0 : 1;
edge_detector_n edge_dector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100), .n_edge(clk_div_100_nedge));
endmodule
// Control FND
module fnd_cntr (
input clk, reset_p,
input [15:0] value,
output reg [3:0] com,
output [7:0] seg_7 );
// prescaler 100000
reg[16:0] counter;
always @(posedge clk or posedge reset_p) begin
if(reset_p) counter = 0;
else begin
if(counter >= 99999) counter = 0;
else counter = counter + 1;
end
end
wire clk_1ms, clk_1ms_nedge;
assign clk_1ms = (counter < 50000)? 0 : 1;
edge_detector_n edge_dector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_1ms), .n_edge(clk_1ms_nedge));
// Shifting com.
always @(posedge clk or posedge reset_p) begin
if(reset_p) com = 4'b1110;
else if(clk_1ms_nedge) begin
if(com == 4'b0111) com = 4'b1110;
else com = {com[2:0], 1'b1};
end
end
// Get FND data.
reg [3:0] hex_value;
always @(com) begin
case(com)
4'b1110 : hex_value = value[3:0];
4'b1101 : hex_value = value[7:4];
4'b1011 : hex_value = value[11:8];
4'b0111 : hex_value = value[15:12];
default : hex_value = hex_value;
endcase
end
decoder_7seg fnd(.hex_value(hex_value), .seg_7(seg_7));
endmodule
// Decoder of 7-Segment.
module decoder_7seg (
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_n (
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 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 RTL 설계' 카테고리의 다른 글
Verilog RTL 설계(7월 22일 - 2, FSM 형식으로 Keypad 재구현) (2) | 2024.07.23 |
---|---|
Verilog RTL 설계(7월 22일 - 1, 4X4 Matrix Keyboard - 1) (4) | 2024.07.23 |
Verilog RTL 설계(7월 18일 - 4, Stop Watch - 3) (0) | 2024.07.22 |
Verilog RTL 설계(7월 18일 - 3, Stop Watch - 2) (0) | 2024.07.21 |
Verilog RTL 설계(7월 18일 - 2, Stop Watch - 1) (0) | 2024.07.21 |