일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- LED
- gpio
- prescaling
- vivado
- behavioral modeling
- ATMEGA128A
- ring counter
- BASYS3
- soc 설계
- Linked List
- java
- Pspice
- stop watch
- dataflow modeling
- test bench
- i2c 통신
- verilog
- atmega 128a
- FND
- structural modeling
- half adder
- Edge Detector
- DHT11
- hc-sr04
- Recursion
- D Flip Flop
- KEYPAD
- Algorithm
- uart 통신
- pwm
- Today
- Total
거북이처럼 천천히
Verilog RTL 설계(7월 19일 - 1, Cooking Timer - 1) 본문
1. Cooking Timer
- 꽤 늦었지만, 휴일을 통해 Cooking Timer을 구현해보도록 하겠다.
- Cooking Timer는 주방에서 사용하는 Timer라고 보면 이해하기 쉬울 수 있다.
- 시간을 설정한 뒤, 1초씩 Down Counting하다가 0분 0초가 되었을 때, 알람(Buzz)가 울리도록 설계할 것이다.
2. State diagram
- Cooking Timer는 2가지 모드를 갖는다.
- Start mode : Cooking Timer가 세팅된 시간부터 1초씩 Down Counting하는 모드
- Set mode : Cooking Timer의 시작 시간을 세팅하는 모드 - btn[0]를 btn_start_set 버튼으로 지정하여 btn[0]에 의해 모드 전환이 발생하며, 이를 상태도로 표현하면 다음과 같다.
- 이외에도 btn[1] ~ btn[3] 버튼을 각각 다음과 같은 이름 및 역활을 부여하였다.
- btn[1] : Set mode에서 분 값을 조절하는 버튼
- btn[2] : Set mode에서 초 값을 조절하는 버튼
- btn[3] : Buzz가 울릴 경우, Buzz을 끄는 버튼
3. Cooking Timer의 기본 틀 생성
3.1. Cooking Timer의 동작
- Cooking Timer는 2가지 모드(Start mode, Set mode)를 가지며, start_set 변수를 통해 현재의 모드를 결정한다.
- start_set 변수 값이 1이면 Start mode이며, 변수 값이 0이면 Set mode임을 의미한다.
- Set mode 일 경우, btn[1]과 btn[2]을 통해 Cooking Timer의 초기 세팅 시간 값을 조절할 수 있으며,
Start mode 일 경우, 초기 세팅된 시간을 시작으로 1초씩 Down Counting하게 된다.
3.2. Cooking Timer에서는 어떤 Counter들이 필요한가?
- Set mode에서 btn[1]과 btn[2]에 의해 Cooking Timer의 초기 세팅 시간 값을 Up Counting해서 조절해야 하기
때문에 BCD 60진 up Counter가 필요할 것이다.
- Start mode에서는 초기 세팅 시간을 시작으로 1초씩 down counting 해야 하기 때문에 BCD 60진 down Counter가
필요할 것이다.
3.3. Cooking Timer의 기본 틀에 대한 소스 코드
- 소스 코드와 함께 Cooking Timer의 동작에 대해 설명하고자 한다.
- button control, clock divider, FND Control 등의 모듈은 이전 게시글에서 사용하고, 설명하였기 때문에 이에 대한
자세한 설명은 생략하고, 추가된 모듈을 중점으로 설명을 하도록 하겠다.
- button control, clock divdier, FND Control에 대해서 궁금하다면 아래 게시글을 참고 하길 바란다.
https://jbhdeve.tistory.com/273
< Top Module of Cooking Timer의 변수 선언 >
module Cooking_Timer_0(
input clk, reset_p,
input [2:0] btn,
output [3:0] com,
output [7:0] seg_7,
output [1:0] mode_led );
// Mode led
assign mode_led [1:0] = (start_set)? 2'b10 : 2'b01;
endmodule
- mode_led는 현재 모드 상태를 LED로 표현하기 위한 변수이다.
- 첫 번째 LED는 set 모드, 두 번째 LED는 start 모드임을 나타낸다.
< 주기가 1초인 One Cycle Pulse 얻기 >
// 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));
- Set mode에서 1초마다 Down Counting할 것이기 때문에 주기가 1초인 One Cycle Pulse가 필요하다.
- Q) Stop Watch, Normal Watch에서 사용했던 주기가 1분인 One Cycle Pulse는 필요하지 않는가?
- A) Cooking Timer의 분 값이 변화하는 시점은 초 값이 0초 되었을 때이기 때문에 초 값이 0초가 되었음을
알려주는 One Cycle Pulse가 필요하지 1분인 One Cycle Pulse는 필요하지 않다.
< Chattering 문제를 방지하기 위해 Button Control 모듈을 통해 버튼의 One Cycle Pulse 얻는다. >
// Get One Cycle Pulse of Button.
wire btn_start_set, btn_min, btn_sec;
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 모듈은 D-Flip Flop을 이용하여 1msec delay time을 갖고, Button 값을 읽는 모듈이다.
- button 값을 1msec 동안의 delay time을 갖고, 버튼 값을 읽기 때문에 1msec 동안 발생한 불안정한 버튼 값을 무시 및 읽지 않고, 안정된 버튼 값을 읽음으로서 버튼 Chattering문제를 해결할 수 있다.
< Set 모드일 때, 버튼을 통해 분, 초 값을 조정할 수 있다. >
// 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진 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
- bcd_60_up_counter 모듈은 아래 조건을 만족했을 경우에만 1씩 Up Counting을 하게 된다.
- 분 or 초 버튼이 눌렀을 경우
- start_set 변수 값이 0일 경우 - 분 or 초 버튼이 누를 경우, 버튼 값이 0 → 1 로 변화하면서 Positive edge 발생시키게 된다.
- set mode에서 분 or 초 버튼을 통해 시간을 세팅하기 때문에 set mode에서만 Up Counter가 동작하도록 하기 위해서 start_set 값이 0인 경우에만 동작하도록 설계한다.
< Start 모드일 때, 1초씩 Down Counting을 하기 위해 Loadable down counter를 설계한다. >
// 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));
// 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 );
// Get One Cycle Pulse of clk_source
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 // Reset BCD10, BCD1
else begin
if(!start_set) // Load BCD10, BCD1 of Set mode
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
- Set mode에서 Start mode로 전환되어 1초씩 Down Counting하기 위해서는 "Set 모드에서 몇 분 몇 초로 세팅되었는가?"에 대해서 알 필요가 있으며, 이를 위해 "Loadable BCD 60진 Counter"를 만들었다.
- Loadable BCD 60진 Down Counter는 start_set 값이 0 → 1 로 변화할 때, BCD 60진 Up Counter로 부터 세팅된 BCD10, BCD1 값을 받고, 이를 시작점으로 1초씩 Down Counting을 한다.
- 이를 위해 start_set 값이 0인 (= Set mode인 상태) 동안에는 계속해서 Up Counter로부터 BCD10, BCD1 값을 받는다.
- start_set값이 1인 (= Start mode인 상태) 동안에는 주기가 1초인 One Cycle Pulse가 활성화된 상태에서만 1초씩 다운 카운팅을 하게 된다.
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ - Q) 분 BCD 60진 Down Counter는 왜 clock Source를 clk_1min이 아닌 초 BCD 60진 Down Counter에서 0초일 때마다 발생하는 One Cycle Pulse를 받는가?
- A) "언제 분 값이 1씩 감소해야 하는가?"에 대한 질문을 생각해 볼 필요가 있다. 이전에 다루었던 Stop Watch, Noraml Clock는 초 값이 60초 일 때, 1분씩 증가했다. 그러나, Cooking Timer는 반대로 초 값이 0초일때마다 1분씩 감소한다. 이는 분 값이 감소하는 것은 1분마다 감소하는 것이 아닌 랜덤으로 발생하는 초 값이 0초 일때마다 감소하는 것이기 때문에 초 BCD 60진 Down Counter에서 0초일 때마다 발생하는 One Cycle Pulse (sec_zero_signal) 가 활성화 되었는가를 기준으로 삼을 필요가 있다.
- Q) 이를 위해서 초 BCD 60진 Down Counter에서만 sec_zero_signal wire를 사용하는가?
- A) 그렇다. 분 BCD 60진 Down Counter에게 "0초입니다. 분 값을 1분 줄여주세요." 라고 알려줄 신호가 필요하기 때문에 이를 위해 sec_zero_signal 를 1초 동안만 활성화 시킴으로서 분 BCD 60진 Down Counter는 이를 바탕으로 1분씩 Down Counting을 실시한다.
< Set, Start 모드의 시간 값을 결합한 뒤, start_set 변수 값에 의해 현재 모드에 맞는 값을 선택한다. >
// 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;
- 결합 연산자를 통해 분과 초의 BCD10, BCD1를 결합한다.
- 그러고 난 뒤. start_set 변수 값을 통해 현재 모드에 알맞는 시간 값을 선택하여 hex_value 와이어와 연결한다.
< 모드 변환 버튼을 누를 때마다 모드 변환하며, Cooking Timer가 0분 0초에 도달하면 모드 값을 초기화 한다. >
// Start_set mode 선언 및 0분 0초가 되면 Reset하기.
reg start_set;
always @(negedge clk or posedge reset_p) begin
if(reset_p) start_set = 0;
else if(hex_value_cur == 16'b0) begin
start_set = 0;
end
else if(btn_start_set) start_set = ~ start_set;
end
- 모드 변환 버튼인 btn_start_set 을 누를 때마다 start_set 값을 Toggle시켜 모드를 변환하게 된다.
- Cooking Timer가 0분 0초에 도달하면 start_set 값은 0으로 초기화되며, Down Counting은 멈추고, 다시 Setting mode로 전환된다.
< 현재 모드에 맞게 선택된 시간을 FND로 출력한다. >
// 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));
4. 구현 영상
5. 전체 소스 코드
// Top module of Cooking Timer
module Cooking_Timer_0(
input clk, reset_p,
input [2:0] btn,
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] = clk_1sec;
// 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;
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));
// 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) start_set = 0;
else if(hex_value_cur == 16'b0) begin
start_set = 0;
end
else if(btn_start_set) start_set = ~ start_set;
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일 - 2, DHT11 구현 (1) ) (0) | 2024.08.10 |
---|---|
Verilog RTL 설계(7월 19일 - 2, Cooking Timer - 2) (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 |
Verilog RTL 설계(7월 31일 - 3, PWM - 3) (0) | 2024.08.01 |