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
- gpio
- pwm
- dataflow modeling
- stop watch
- BASYS3
- KEYPAD
- java
- vivado
- prescaling
- half adder
- Pspice
- D Flip Flop
- Edge Detector
- uart 통신
- behavioral modeling
- structural modeling
- Linked List
- DHT11
- Recursion
- soc 설계
- LED
- test bench
- atmega 128a
- ring counter
- ATMEGA128A
- FND
- Algorithm
- verilog
- i2c 통신
- hc-sr04
Archives
- Today
- Total
거북이처럼 천천히
Verilog RTL 설계(7월 19일 - 2, Cooking Timer - 2) 본문
1. Cooking Timer에 Buzz를 추가하자.
- 시중에 팔고 있는 Cooking Timer는 0분 0초가 되면 알람을 울려 사용자에게 0분 0초가 되었음을 알린다.
- 이전에 구현한 Cooking Timer에서 추가적으로 해당 기능을 추가해보도록 하겠다.
2. 수정된 소스 코드
- 이전 게시글에서 구현한 소스 코드를 바탕으로 구현하겠으며, 수정된 코드를 중점으로 설명하도록 하겠다.
https://jbhdeve.tistory.com/290
< 알람이 울리고 있는지 여부를 LED로 표현한다. >
// Mode led
assign mode_led [1:0] = (start_set)? 2'b10 : 2'b01;
assign mode_led [2] = buzz;
< 알람이 울리는 조건과 알람을 꺼지는 조건을 다음과 같이 정의하였다. >
// Start_set mode 선언 및 0분 0초가 되면 Reset하기.
reg start_set;
always @(negedge clk or posedge reset_p) begin
if(reset_p) begin start_set = 0; buzz = 0; end
else if(hex_value_cur == 16'b0 && start_set) begin
start_set = 0;
buzz = 1;
end
else if(btn_start_set) start_set = ~ start_set;
else if(btn_alarm_off) buzz = 0;
end
- start_set 변수 값이 1인 (= Start mode) 인 동시에 현재의 시간 (= hex_value_cur)이 0일 경우, start_set 값을 초기화하는 동시에 buzz = 1을 대입하여 알람과 연결된 포트에 신호를 줌으로서 알람을 울리게 만들었다.
- btn[3], btn_alarm_off 버튼이 눌리면 buzz = 0을 대입하여 알람을 끄도록 만들었다.
3. 구현 영상
4. 전체 소스 코드
// Top Module of Cooking Timer
module Cooking_Timer_0(
input clk, reset_p,
input [3:0] btn,
output reg buzz,
output [3:0] com,
output [7:0] seg_7,
output [2:0] mode_led );
// Mode led
assign mode_led [1:0] = (start_set)? 2'b10 : 2'b01;
assign mode_led [2] = buzz;
// Get One Cycle Puls of 1sec, 1min
wire clk_1usec, clk_1msec, clk_1sec;
clk_div_100 clk_div_1usec (.clk(clk), .reset_p(reset_p), .clk_div_100(clk_1usec));
clk_div_1000 clk_div_1msec (.clk(clk), .reset_p(reset_p), .clk_source(clk_1usec), .clk_div_1000_nedge(clk_1msec));
clk_div_1000 clk_div_1sec (.clk(clk), .reset_p(reset_p), .clk_source(clk_1msec), .clk_div_1000_nedge(clk_1sec));
// Get One Cycle Pulse of Button.
wire btn_start_set, btn_min, btn_sec, btn_alarm_off;
button_cntr control_btn_start(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pedge(btn_start_set));
button_cntr control_btn_min(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pedge(btn_min));
button_cntr control_btn_second(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pedge(btn_sec));
button_cntr control_btn_alarm_off(.clk(clk), .reset_p(reset_p), .btn(btn[3]), .btn_pedge(btn_alarm_off));
// Set minute, second on set mode.
wire [3:0] bcd10_min_set, bcd1_min_set, bcd10_sec_set, bcd1_sec_set;
bcd_60_up_counter bcd_60_up_counter_min (.clk(clk), .reset_p(reset_p), .btn(btn_min), .bcd10(bcd10_min_set), .bcd1(bcd1_min_set), .start_set(start_set));
bcd_60_up_counter bcd_60_up_counter_sec (.clk(clk), .reset_p(reset_p), .btn(btn_sec), .bcd10(bcd10_sec_set), .bcd1(bcd1_sec_set), .start_set(start_set));
// BCD 60진 Down Counter
wire second_zero_signal;
wire [3:0] bcd10_min_stop, bcd1_min_stop, bcd10_sec_stop, bcd1_sec_stop;
bcd_60_down_counter bcd_60_down_counter_sec (.clk(clk), .reset_p(reset_p), .start_set(start_set), .loadable_bcd10(bcd10_sec_set), .loadable_bcd1(bcd1_sec_set),
.clk_source(clk_1sec), .sec_zero_signal(second_zero_signal), .bcd10(bcd10_sec_stop), .bcd1(bcd1_sec_stop));
bcd_60_down_counter bcd_60_down_counter_min (.clk(clk), .reset_p(reset_p), .start_set(start_set), .loadable_bcd10(bcd10_min_set), .loadable_bcd1(bcd1_min_set),
.clk_source(second_zero_signal), .bcd10(bcd10_min_stop), .bcd1(bcd1_min_stop));
// Start_set mode 선언 및 0분 0초가 되면 Reset하기.
reg start_set;
always @(negedge clk or posedge reset_p) begin
if(reset_p) begin start_set = 0; buzz = 0; end
else if(hex_value_cur == 16'b0 && start_set) begin
start_set = 0;
buzz = 1;
end
else if(btn_start_set) start_set = ~ start_set;
else if(btn_alarm_off) buzz = 0;
end
// Combine data of time.
wire [15:0] hex_value_set, hex_value_cur;
assign hex_value_set = {bcd10_min_set, bcd1_min_set, bcd10_sec_set, bcd1_sec_set};
assign hex_value_cur = {bcd10_min_stop, bcd1_min_stop, bcd10_sec_stop, bcd1_sec_stop};
wire [15:0] hex_value;
assign hex_value = (start_set)? hex_value_cur : hex_value_set;
// Print Data of 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진 Down Counter
module bcd_60_down_counter (
input clk, reset_p,
input clk_source,
input start_set,
input [3:0] loadable_bcd10, loadable_bcd1,
output reg sec_zero_signal,
output reg [3:0] bcd10, bcd1 );
wire clk_source_nedge;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin bcd10 = 0; bcd1 = 0; sec_zero_signal = 0;end
else begin
if(!start_set)
begin bcd10 = loadable_bcd10; bcd1 = loadable_bcd1; end
else if(clk_source_nedge) begin
if(bcd1 == 0) begin
bcd1 = 9;
if(bcd10 == 0)
begin bcd10 = 5; sec_zero_signal = 1; end
else
begin bcd10 = bcd10 - 1; end
end
else begin bcd1 = bcd1 - 1; end
end
else sec_zero_signal = 0;
end
end
endmodule
// BCD 60진 Up Counter
module bcd_60_up_counter (
input clk, reset_p,
input btn,
input start_set,
output reg [3:0] bcd10, bcd1 );
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin bcd10 = 0; bcd1 = 0; end
else if(btn && !start_set) begin
if(bcd1 >= 9) begin
bcd1 = 0;
if(bcd10 >= 5) bcd10 = 0;
else bcd10 = bcd10 + 1;
end
else bcd1 = bcd1 + 1;
end
end
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;
end
endmodule
// Button Control
module button_cntr (
input clk, reset_p,
input btn,
output btn_pedge, btn_nedge );
// Get One Cycle Puls of 1msec.
wire clk_1usec, clk_1msec;
clk_div_100 clk_div_1usec (.clk(clk), .reset_p(reset_p), .clk_div_100(clk_1usec));
clk_div_1000 clk_div_1msec (.clk(clk), .reset_p(reset_p), .clk_source(clk_1usec), .clk_div_1000_nedge(clk_1msec));
reg out_button;
always @(posedge clk or posedge reset_p) begin
if(reset_p) out_button = 0;
else if(clk_1msec) out_button = btn;
end
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(out_button), .n_edge(btn_nedge), .p_edge(btn_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] count;
always @(posedge clk or posedge reset_p) begin
if(reset_p) count = 0;
else if(clk_source_nedge) begin
if(count >= 59) count = 0;
else count = count + 1;
end
end
assign 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 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] count;
always @(posedge clk or posedge reset_p) begin
if(reset_p) count = 0;
else if(clk_source_nedge) begin
if(count >= 999) count = 0;
else count = count + 1;
end
end
assign clk_div_n = (count < 500)? 0 : 1;
edge_detector edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_n), .n_edge(clk_div_1000_nedge), .p_edge(clk_div_1000_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] count;
always @(posedge clk or posedge reset_p) begin
if(reset_p) count = 0;
else begin
if(count >= 99) count = 0;
else count = count + 1;
end
end
assign clk_div_100 = (count < 50)? 0 : 1;
edge_detector edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100), .n_edge(clk_div_100_nedge), .p_edge(clk_div_100_pedge));
endmodule
// FND Control
module fnd_cntr (
input clk, reset_p,
input [15:0] hex_value,
output [3:0] com,
output [7:0] seg_7 );
ring_counter ring_counter_com (.clk(clk), .reset_p(reset_p), .com(com));
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_seg7 decoder_7_segment (.hex_value(value), .seg_7(seg_7));
endmodule
// Ring Counter of Com value.
module ring_counter (
input clk, reset_p,
output reg [3:0] com );
// Get One Cycle Pulse of 1msec.
wire clk_1usec, clk_1msec;
clk_div_100 clk_div_1usec (.clk(clk), .reset_p(reset_p), .clk_div_100(clk_1usec));
clk_div_1000 clk_div_1msec (.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) com = {com[2:0], com[3]};
end
endmodule
// Decoder of 7-segment.
module decoder_seg7 (
input [3:0] hex_value,
output reg [7:0] seg_7 );
always @(*) 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 RTL 설계' 카테고리의 다른 글
Verilog RTL 설계(7월 23일 - 3, DHT11 구현 (2) ) (0) | 2024.08.10 |
---|---|
Verilog RTL 설계(7월 23일 - 2, DHT11 구현 (1) ) (0) | 2024.08.10 |
Verilog RTL 설계(7월 19일 - 1, Cooking Timer - 1) (0) | 2024.08.08 |
Verilog RTL 설계(8월 1일 - 1, PWM - 5) (0) | 2024.08.02 |
Verilog RTL 설계(7월 31일 - 4, PWM - 4) (0) | 2024.08.01 |