Full Code는 맨 아래에~
[Button controller]
📌 Button controller module
자주 사용하는 기능이니까 모듈로 만들어 버리자.
module button_cntr(
input clk, reset_p,
input btn,
output btn_pe, btn_ne
);
// DFF를 위한 분주기
reg [16:0] clk_div = 0; // 이렇게 = 0 해놓으면 시뮬레이션에서 자동으로 0으로 초기화된다.
// 보드에서 쓸 때는 시스템적으로 0으로 초기화
always @(posedge clk) clk_div = clk_div + 1;
// Debounce
wire debounced_btn;
D_flip_flop_n debnc(.d(btn), .clk(clk_div[16]), .rst(reset_p), .q(debounced_btn)); // 바운싱 제거용 DFF
// synchronization(Edge Detecting)
edge_detector_n edg(.clk(clk), .cp_in(debounced_btn), .rst(reset_p), .p_edge(btn_pe), .n_edge(btn_ne)); // Edge Detector
// p_edge(btn_pe) : 버튼을 눌렀을 때 동작
// n_edge(btn_ne) : 버튼을 눌렀다 뗄 떄 동작
// 둘 중에 필요한 것만 골라서 쓰면 된다.
endmodule
✅ tip) 오류가 있는지 간단하게 체크하는 법
해당 모듈을 Top으로 놓고 시뮬레이션돌려보면 된다.
문법에 오류가 있다면, 시뮬레이션 안 열림.
구문오류는 이걸로 검증 안 됨.
[Time Setting]
📌 Time Setting
버튼의 입력에 따라 시간을 셋팅할 수 있도록 구현해볼 것이다.
📌 Time Setting Code
module cook_timer(
input clk, reset_p,
input [2:0] btn,
output [3:0] com,
output [7:0] seg_7
);
// button
wire start, incsec, incmin;
button_cntr btn_start_stop(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(start)); // start/stop
button_cntr btn_incsec(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pe(incsec)); // sec+
button_cntr btn_incmin(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pe(incmin)); // min+
// 풀다운 저항을 사용하여 버튼 회로를 구성하였으므로 pose_edge 사용
// 풀다운이므로 0(Low)이 계속 입력되고 있다가 버튼누르면 1(High)이 걸리게 된다. 따라서 Pose_edge 사용
// pose_edge : 버튼 누른 순간 동작 - 풀다운과 연결
// neg_edge : 버튼 눌렀다 떼는 순간 동작 - 풀업과 연결
// Time set
wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(incsec), .dec1(sec1_set), .dec10(sec10_set)); // sec up_counter
wire [3:0] min1_set, min10_set;
counter_dec_60 up_min(.clk(clk), .reset_p(reset_p), .clk_time(incmin), .dec1(min1_set), .dec10(min10_set)); // min up_counter
reg [15:0] set_time;
always @(posedge clk, posedge reset_p) begin
if(reset_p) set_time = 0;
else set_time = {min10_set, min1_set, sec10_set, sec1_set};
end
wire [15:0] value;
assign value = set_time;
FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(value), .com(com), .seg_7(seg_7)); /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
endmodule
✅ Edge_Detector에 대해 궁금하다면?
[Down Counter]
📌 Down Counter
Time Setting에서 입력된 값을 받아 Down Count하는 기능을 구현해보자.
// Loadable_60bit_Down_Counter
module loadable_down_counter_dec_60(
input clk, reset_p,
input clk_time,
input load_enable, // user가 입력한 값을 받아오는 기능 추가
input [3:0] set_value1, set_value10, // 입력한 값
output reg [3:0] dec1, dec10,
output reg dec_clk // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
);
always @(posedge clk, posedge reset_p) begin
if(reset_p) begin // 출력으로 나가는 것들이 리셋됨
dec1 <= 0;
dec10 <= 0;
dec_clk <= 0;
end
// load_enable = 1이면, 입력된 값을 받아온다.
else if(load_enable == 1) begin
dec1 <= set_value1;
dec10 <= set_value10;
end
else if(clk_time) begin // 카운팅에 적용한 clk_time = high가 되면 카운팅 시작
if(dec1 == 0) begin
dec1 <= 9;
if(dec10 == 0) begin // 우리는 min과 sec 둘 다 구현하는 것이므로, min down counter에 신호를 넣어줘야 된다.
dec10 <= 5;
dec_clk <= 1; // dec10, dec1 = 0, 0 이 되고 이후에 5, 9가 되면서 dec_clk 상승 펄스 발생
end
else dec10 <= dec10 - 1;
end
else dec1 <= dec1 - 1;
end
else dec_clk <= 0;
end
endmodule
📌 Simulation
Setting
① clk, clk_time : 100ns
② reset_p : 1주고 load_enable : 0주고 100ns 돌림 // 수동으로 리셋해줘야됨
③ reset_p : 0주고 load_enable : 1주고 100ns 돌림 // load_enable 활성화해서 setting된 값을 받아옴.
④ load_enable : 0주고 5000ns 돌림
dec1(1의 자리)은 9~0까지 Down count
dec10(10의 자리)은 5~0까지 Down count
sec10, sec1 둘 다 0이 되면, dec_clk 펄스 발생(○ 부분)
📌 Simulation(by Testbench)
Test_bench Code
module tb_loadable_down_counter_dec_60(); // tb는 입출력이 없다.
// 입력은 다 reg
// 출력은 다 wire
reg clk, reset_p;
reg clk_time;
reg load_enable; // user가 입력한 값을 받아오는 기능 추가
reg [3:0] set_value1, set_value10; // 입력한 값
wire [3:0] dec1, dec10;
wire dec_clk; // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
loadable_down_counter_dec_60 DUT(.clk(clk), .reset_p(reset_p), .clk_time(clk_time), .load_enable(load_enable),
.set_value1(set_value1), .set_value10(set_value10), .dec1(dec1), .dec10(dec10), .dec_clk(dec_clk));
// 입력값 초기화
initial begin
clk = 0;
reset_p = 1;
clk_time = 0;
load_enable = 1;
set_value1 = 5; set_value10 = 3;
end
// clock 생성
always #5 clk = ~clk; // 10ns짜리 clock, always문은 Sensitivity list 없으면 무한 반복
// clock에 따라 테스트값 입력
initial begin
#10; reset_p = 0; #10;
load_enable = 0; #10;
#980;
clk_time = 1; #10
clk_time = 0; #990; // 1000ns동안 1클락의 펄스가 들어온다.
clk_time = 1; #10
clk_time = 0; #990; // 즉, 1ms마다 down count된다.
clk_time = 1; #10
clk_time = 0; #990;
clk_time = 1; #10
clk_time = 0; #990;
clk_time = 1; #10
clk_time = 0; #990;
$stop;
end
endmodule
✅ for문을 활용하여 좀 더 간단하게 작성할 수도 있다.
// 1000ns동안 1클락의 펄스가 들어온다.
for(integer i = 0 ; i < 40 ; i = i+1) begin // 즉, 1ms마다 down count된다.
if(i < 40) begin
clk_time = 1; #10;
clk_time = 0; #990;
end
end
✅ $display 함수를 사용하면,
console창에서 출력되도록 설정할 수도 있다.
for(integer i = 0 ; i < 40 ; i = i+1) begin // 즉, 1ms마다 down count된다.
if(i < 40) begin
clk_time = 1; #10;
clk_time = 0; #990;
$display("%d%d", dec10, dec1);
end
end
✅ Testbench work flow
① DUT Instsnce
② 변수선언
③ 입력값 초기화
④ clock 생성
⑤ clock에 따라 테스트 값 입력
⑥ 시뮬레이션
cf) RTL Workflow(작업 순서)
① Circuit Design(회로설계)
② Simulation(시뮬레이션)
③ Circuit Synthesis(회로 합성)
④ Implementation (Circuit Realization, 회로 구현)
⑤ Bitstream Generation(비트스트림생성)
⑥ Deployment on Board(보드에 올려서)
⑦ Testing on Board(보드에서 테스트)
✅ TestBench에 대해 더 궁금하다면?
Result
Simulation하고 Run을 눌러줘야 전부 다 출력된다.
[Down Counter 적용]
module cook_timer(
input clk, reset_p,
input [2:0] btn,
output [3:0] com,
output [7:0] seg_7
);
// button
wire start, incsec, incmin;
button_cntr btn_start_stop(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(start)); // start/stop
t_flip_flop_p tff_start_stop(.clk(clk), .rst(reset_p), .t(start), .q(start_stop));
button_cntr btn_incsec(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pe(incsec)); // sec+
button_cntr btn_incmin(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pe(incmin)); // min+
// Time Prescaler(clock Library)
wire clk_usec, clk_msec, clk_sec;
clock_usec usec_clk(.clk(clk), .reset_p(reset_p), .clk_usec(clk_usec));
clock_div_1000 msec_clk(.clk(clk), .clk_source(clk_usec), .reset_p(reset_p), .clk_div_1000(clk_msec));
clock_div_1000 sec_clk(.clk(clk), .clk_source(clk_msec), .reset_p(reset_p), .clk_div_1000(clk_sec));
clock_min min_clk(.clk(clk), .clk_sec(clk_sec), .reset_p(reset_p), .clk_min(clk_min));
// Time set
wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(incsec), .dec1(sec1_set), .dec10(sec10_set)); // sec up_counter
wire [3:0] min1_set, min10_set;
counter_dec_60 up_min(.clk(clk), .reset_p(reset_p), .clk_time(incmin), .dec1(min1_set), .dec10(min10_set)); // min up_counter
// load_enable을 start_stop에 연결하면, start 시(start_stop = 1)계속해서 값을 불러와버린다.
// 따라서 start_stop = 0일때만 1이 들어가도록 설계(start 변수의 참거짓에 따라 load_enable 변화하도록)
wire clk_start, load_enable;
wire dec_clk; // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
wire [3:0] sec1, sec10, min1, min10;
assign clk_start = start_stop ? clk_sec : 0; // 대표적인 MUX 생성 방법
assign load_enable = ~start_stop ? start : 0; // start_stop = 0 이면, start 변수 사용
// load_enable에는 edge 한 번만 주어야 하므로 start 사용
// Down Counter 적용
loadable_down_counter_dec_60 dc_sec(.clk(clk), .reset_p(reset_p), .clk_time(clk_start), .load_enable(load_enable),
.set_value1(sec1_set), .set_value10(sec10_set),
.dec1(sec1), .dec10(sec10), .dec_clk(dec_clk));
loadable_down_counter_dec_60 dc_min(.clk(clk), .reset_p(reset_p), .clk_time(dec_clk), .load_enable(load_enable),
.set_value1(min1_set), .set_value10(min10_set), // dc_sec의 dec_clk를 받아서 min 카운트에 사용
.dec1(min1), .dec10(min10));
// Setting Time for FND
reg [15:0] set_time;
always @(posedge clk, posedge reset_p) begin
if(reset_p) set_time = 0;
else set_time = {min10_set, min1_set, sec10_set, sec1_set};
end
// Count Time for FND
reg [15:0] count_time;
always @(posedge clk, posedge reset_p) begin
if(reset_p) count_time = 0;
else count_time = {min10, min1, sec10, sec1};
end
wire [15:0] value;
assign value = start_stop ? count_time : set_time; // start_stop의 참거짓에 따라 FND에 출력하는 값 달라짐.
FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(value), .com(com), .seg_7(seg_7)); /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
endmodule
[Timeout]
📌 Timeout 기능 구현
위 그림과 같이 Count time의 모든 bit를 묶어서 OR 연산하게 되면,
모든 bit가 0일 때만 timeout 변수가 0이 된다.
이 논리를 활용하여 Finish와 Alarm 기능을 구현해보자.
// time = 0 도달 시, Finish & Alarm 발생
wire timeout, alarm_start;
assign timeout = |count_time; // 뒤의 모든 비트를 OR 연산한 결과(베릴로그에서만 사용할 수 있는 문법)
edge_detector_n edg_timeout(.clk(clk), .cp_in(timeout), .rst(reset_p), .n_edge(alarm_start)); // timeout 발생 시, alarm edge 발생
✅ Verilog Code snippet
위 코드에서처럼 Verilog에서만 사용할 수 있는 연산법이 존재하며, 그 예시는 아래와 같다.
wire A;
reg [15:0] B;
assign A = | B;
○ A = | B
: B의 bit 중 하나라도 1인 bit가 있다면, A가 1로 설정되도록 하는 연산.
즉, | 뒤에 있는 변수의 모든 bit를 OR연산한 뒤, A에 대입하라는 의미이다.
📌 Timeout Code
Counting이 끝나면, Timer가 Stop되고 설정했던 시간이 다시 출력되도록 구현
(reset 기능이 따로 있으므로, 좀 더 UX를 고려하여 구현해보았다.)
module cook_timer(
input clk, reset_p,
input [2:0] btn,
output [3:0] com,
output [7:0] seg_7
);
// button
wire start, incsec, incmin;
wire timeout, alarm_start;
wire t_start_stop;
// or (t_start_stop, start, alarm_start); // Verilog에서 구조적 모델링 하지 마!!!!
assign t_start_stop = start ? 1 : (alarm_start ? 1 : 0); // alarm이 발생하거나 start가 1일 때, t_start_stop = 1
button_cntr btn_start_stop(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(start)); // start/stop
t_flip_flop_p tff_start_stop(.clk(clk), .rst(reset_p), .t(t_start_stop), .q(start_stop)); // 버튼눌렀을 때, alarm 발생 시, start_stop 변수 토글
button_cntr btn_incsec(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pe(incsec)); // sec+
button_cntr btn_incmin(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pe(incmin)); // min+
// Time Prescaler(clock Library)
wire clk_usec, clk_msec, clk_sec;
clock_usec usec_clk(.clk(clk), .reset_p(reset_p), .clk_usec(clk_usec));
clock_div_1000 msec_clk(.clk(clk), .clk_source(clk_usec), .reset_p(reset_p), .clk_div_1000(clk_msec));
clock_div_1000 sec_clk(.clk(clk), .clk_source(clk_msec), .reset_p(reset_p), .clk_div_1000(clk_sec));
clock_min min_clk(.clk(clk), .clk_sec(clk_sec), .reset_p(reset_p), .clk_min(clk_min));
// Time set
wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(incsec), .dec1(sec1_set), .dec10(sec10_set)); // sec up_counter
wire [3:0] min1_set, min10_set;
counter_dec_60 up_min(.clk(clk), .reset_p(reset_p), .clk_time(incmin), .dec1(min1_set), .dec10(min10_set)); // min up_counter
// load_enable을 start_stop에 연결하면, start 시(start_stop = 1)계속해서 값을 불러와버린다.
// 따라서 start_stop = 0일때만 1이 들어가도록 설계(start 변수의 참거짓에 따라 load_enable 변화하도록)
wire clk_start, load_enable;
wire dec_clk; // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
wire [3:0] sec1, sec10, min1, min10;
assign clk_start = start_stop ? clk_sec : 0; // 대표적인 MUX 생성 방법
assign load_enable = ~start_stop ? start : 0; // start_stop = 0 이면, start 변수 사용
// load_enable에는 edge 한 번만 주어야 하므로 start 사용
loadable_down_counter_dec_60 dc_sec(.clk(clk), .reset_p(reset_p), .clk_time(clk_start), .load_enable(load_enable),
.set_value1(sec1_set), .set_value10(sec10_set),
.dec1(sec1), .dec10(sec10), .dec_clk(dec_clk));
loadable_down_counter_dec_60 dc_min(.clk(clk), .reset_p(reset_p), .clk_time(dec_clk), .load_enable(load_enable),
.set_value1(min1_set), .set_value10(min10_set),
.dec1(min1), .dec10(min10));
// Setting Time for FND
reg [15:0] set_time;
always @(posedge clk, posedge reset_p) begin
if(reset_p) set_time = 0;
else set_time = {min10_set, min1_set, sec10_set, sec1_set};
end
// Count Time for FND
reg [15:0] count_time;
always @(posedge clk, posedge reset_p) begin
if(reset_p) count_time = 0;
else count_time = {min10, min1, sec10, sec1};
end
// time = 0 도달 시,
// wire timeout, alarm_start; // 여기에 써도 오류는 안 난다.(Verilog의 코드는 병렬구조이기 때문에) 하지만 위에서 해당 변수를 사용하므로 위로 올리도록 하자.
assign timeout = |count_time; // 뒤의 모든 비트를 OR 연산한 결과(베릴로그에서만 사용할 수 있는 문법)
edge_detector_n edg_timeout(.clk(clk), .cp_in(timeout), .rst(reset_p), .n_edge(alarm_start)); // timeout 발생 시, alarm edge 발생
wire [15:0] value;
assign value = start_stop ? count_time : set_time;
FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(value), .com(com), .seg_7(seg_7)); /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
endmodule
[Alarm]
📌 Alarm 기능 구현
Timeout이 발생하면 alarm이 발생하고,
alarm_off 버튼을 누르면, 알람이 꺼지도록 설계
(부저를 사용해도 되지만, 시끄러우므로 LED로 대체)
📌 Alarm 기능 Code I
wire alarm;
t_flip_flop_p tff_alarm_on_off(.clk(clk), .rst(btn[3]), .t(alarm_start), .q(alarm));
assign LED_bar[0] = alarm;
Timeout 시, Alarm이 발생하고
Alarm_off 버튼 누르면, Alarm이 Off된다.
📌 Alarm 기능 Code II
보통 알람 시계는 어떤 버튼을 눌러도 Alarm이 Off된다.
UX를 좀 더 고려하여, 아무 버튼이나 눌러도 Alarm이 꺼지게끔 구현해보자.
// Alarm On/Off를 위한 기능
wire alarm, alarm_off;
assign alarm_off = |{btn, reset_p}; // 모든 버튼을 다 묶어버려서 넣어주면, 어떤 버튼을 눌러도 alarm이 다 리셋된다.
t_flip_flop_p tff_alarm_on_off(.clk(clk), .rst(alarm_off), .t(alarm_start), .q(alarm));
assign LED_bar[0] = alarm;
[Full code]
※ xdc file
## This file is a general .xdc for the Cora Z7-07S Rev. B
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project
## PL System Clock
set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L13P_T2_MRCC_35 Sch=sysclk
create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 4} [get_ports { clk }];#set
## RGB LEDs
#set_property -dict { PACKAGE_PIN L15 IOSTANDARD LVCMOS33 } [get_ports { Y[0] }]; #IO_L22N_T3_AD7N_35 Sch=led0_b
#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { Y[1] }]; #IO_L16P_T2_35 Sch=led0_g
##set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { led0_r }]; #IO_L21P_T3_DQS_AD14P_35 Sch=led0_r
#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { Y[2] }]; #IO_0_35 Sch=led1_b
#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { Y[3] }]; #IO_L22P_T3_AD7P_35 Sch=led1_g
##set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { led1_r }]; #IO_L23N_T3_35 Sch=led1_r
## Buttons
set_property -dict { PACKAGE_PIN D20 IOSTANDARD LVCMOS33 } [get_ports { reset_p }]; #IO_L4N_T0_35 Sch=btn[0]
#set_property -dict { PACKAGE_PIN D19 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L4P_T0_35 Sch=btn[1]
#set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets up_down_IBUF]
## Pmod Header JA
#set_property -dict { PACKAGE_PIN Y18 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L17P_T2_34 Sch=ja_p[1]
#set_property -dict { PACKAGE_PIN Y19 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L17N_T2_34 Sch=ja_n[1]
#set_property -dict { PACKAGE_PIN Y16 IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L7P_T1_34 Sch=ja_p[2]
#set_property -dict { PACKAGE_PIN Y17 IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L7N_T1_34 Sch=ja_n[2]
#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L12P_T1_MRCC_34 Sch=ja_p[3]
#set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L12N_T1_MRCC_34 Sch=ja_n[3]
#set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L22P_T3_34 Sch=ja_p[4]
#set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L22N_T3_34 Sch=ja_n[4]
## Pmod Header JB
#set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L8P_T1_34 Sch=jb_p[1]
#set_property -dict { PACKAGE_PIN Y14 IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L8N_T1_34 Sch=jb_n[1]
#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L1P_T0_34 Sch=jb_p[2]
#set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L1N_T0_34 Sch=jb_n[2]
#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L18P_T2_34 Sch=jb_p[3]
#set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L18N_T2_34 Sch=jb_n[3]
#set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L4P_T0_34 Sch=jb_p[4]
#set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L4N_T0_34 Sch=jb_n[4]
## Crypto SDA
#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { crypto_sda }];
## Dedicated Analog Inputs
#set_property -dict { PACKAGE_PIN K9 IOSTANDARD LVCMOS33 } [get_ports { v_p }]; #VP_0 Sch=xadc_v_p
#set_property -dict { PACKAGE_PIN L10 IOSTANDARD LVCMOS33 } [get_ports { v_n }]; #VN_0 Sch=xadc_v_n
## ChipKit Outer Analog Header - as Single-Ended Analog Inputs
## NOTE: These ports can be used as single-ended analog inputs with voltages from 0-3.3V (ChipKit analog pins A0-A5) or as digital I/O.
## WARNING: Do not use both sets of constraints at the same time!
#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { vaux1_p }]; #IO_L3P_T0_DQS_AD1P_35 Sch=ck_an_p[0]
#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { vaux1_n }]; #IO_L3N_T0_DQS_AD1N_35 Sch=ck_an_n[0]
#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { vaux9_p }]; #IO_L5P_T0_AD9P_35 Sch=ck_an_p[1]
#set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports { vaux9_n }]; #IO_L5N_T0_AD9N_35 Sch=ck_an_n[1]
#set_property -dict { PACKAGE_PIN K14 IOSTANDARD LVCMOS33 } [get_ports { vaux6_p }]; #IO_L20P_T3_AD6P_35 Sch=ck_an_p[2]
#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { vaux6_n }]; #IO_L20N_T3_AD6N_35 Sch=ck_an_n[2]
#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { vaux15_p }]; #IO_L24P_T3_AD15P_35 Sch=ck_an_p[3]
#set_property -dict { PACKAGE_PIN J16 IOSTANDARD LVCMOS33 } [get_ports { vaux15_n }]; #IO_L24N_T3_AD15N_35 Sch=ck_an_n[3]
#set_property -dict { PACKAGE_PIN J20 IOSTANDARD LVCMOS33 } [get_ports { vaux5_p }]; #IO_L17P_T2_AD5P_35 Sch=ck_an_p[4]
#set_property -dict { PACKAGE_PIN H20 IOSTANDARD LVCMOS33 } [get_ports { vaux5_n }]; #IO_L17N_T2_AD5N_35 Sch=ck_an_n[4]
#set_property -dict { PACKAGE_PIN G19 IOSTANDARD LVCMOS33 } [get_ports { vaux13_p }]; #IO_L18P_T2_AD13P_35 Sch=ck_an_p[5]
#set_property -dict { PACKAGE_PIN G20 IOSTANDARD LVCMOS33 } [get_ports { vaux13_n }]; #IO_L18N_T2_AD13N_35 Sch=ck_an_n[5]
## ChipKit Outer Analog Header - as Digital I/O
## NOTE: The following constraints should be used when using these ports as digital I/O.
set_property -dict { PACKAGE_PIN F17 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L6N_T0_VREF_35 Sch=ck_a[0]
set_property -dict { PACKAGE_PIN J19 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L10N_T1_AD11N_35 Sch=ck_a[1]
set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L12P_T1_MRCC_35 Sch=ck_a[2]
#set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { ck_a3 }]; #IO_L11P_T1_SRCC_35 Sch=ck_a[3]
#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { ck_a4 }]; #IO_L21N_T3_DQS_AD14N_35 Sch=ck_a[4]
#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { ck_a5 }]; #IO_L6P_T0_34 Sch=ck_a[5]
## ChipKit Inner Analog Header - as Differential Analog Inputs
## NOTE: These ports can be used as differential analog inputs with voltages from 0-1.0V (ChipKit analog pins A6-A11) or as digital I/O.
## WARNING: Do not use both sets of constraints at the same time!
#set_property -dict { PACKAGE_PIN C20 IOSTANDARD LVCMOS33 } [get_ports { vaux0_p }]; #IO_L1P_T0_AD0P_35 Sch=ad_p[0]
#set_property -dict { PACKAGE_PIN B20 IOSTANDARD LVCMOS33 } [get_ports { vaux0_n }]; #IO_L1N_T0_AD0N_35 Sch=ad_n[0]
#set_property -dict { PACKAGE_PIN F19 IOSTANDARD LVCMOS33 } [get_ports { vaux12_p }]; #IO_L15P_T2_DQS_AD12P_35 Sch=ad_p[12]
#set_property -dict { PACKAGE_PIN F20 IOSTANDARD LVCMOS33 } [get_ports { vaux12_n }]; #IO_L15N_T2_DQS_AD12N_35 Sch=ad_n[12]
#set_property -dict { PACKAGE_PIN B19 IOSTANDARD LVCMOS33 } [get_ports { vaux8_p }]; #IO_L2P_T0_AD8P_35 Sch=ad_p[8]
#set_property -dict { PACKAGE_PIN A20 IOSTANDARD LVCMOS33 } [get_ports { vaux8_n }]; #IO_L2N_T0_AD8N_35 Sch=ad_n[8]
## ChipKit Inner Analog Header - as Digital I/O
## NOTE: The following constraints should be used when using the inner analog header ports as digital I/O.
#set_property -dict { PACKAGE_PIN C20 IOSTANDARD LVCMOS33 } [get_ports { ck_a6 }]; #IO_L1P_T0_AD0P_35 Sch=ad_p[0]
#set_property -dict { PACKAGE_PIN B20 IOSTANDARD LVCMOS33 } [get_ports { ck_a7 }]; #IO_L1N_T0_AD0N_35 Sch=ad_n[0]
#set_property -dict { PACKAGE_PIN F19 IOSTANDARD LVCMOS33 } [get_ports { ck_a8 }]; #IO_L15P_T2_DQS_AD12P_35 Sch=ad_p[12]
#set_property -dict { PACKAGE_PIN F20 IOSTANDARD LVCMOS33 } [get_ports { ck_a9 }]; #IO_L15N_T2_DQS_AD12N_35 Sch=ad_n[12]
#set_property -dict { PACKAGE_PIN B19 IOSTANDARD LVCMOS33 } [get_ports { ck_a10 }]; #IO_L2P_T0_AD8P_35 Sch=ad_p[8]
#set_property -dict { PACKAGE_PIN A20 IOSTANDARD LVCMOS33 } [get_ports { ck_a11 }]; #IO_L2N_T0_AD8N_35 Sch=ad_n[8]
## ChipKit Outer Digital Header
set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { seg_7[1] }]; #IO_L11P_T1_SRCC_34 Sch=ck_io[0]
set_property -dict { PACKAGE_PIN V13 IOSTANDARD LVCMOS33 } [get_ports { seg_7[5] }]; #IO_L3N_T0_DQS_34 Sch=ck_io[1]
set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { seg_7[0] }]; #IO_L5P_T0_34 Sch=ck_io[2]
set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { seg_7[4] }]; #IO_L5N_T0_34 Sch=ck_io[3]
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { seg_7[3] }]; #IO_L21P_T3_DQS_34 Sch=ck_io[4]
set_property -dict { PACKAGE_PIN V18 IOSTANDARD LVCMOS33 } [get_ports { seg_7[2] }]; #IO_L21N_T3_DQS_34 Sch=ck_io[5]
set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { seg_7[7] }]; #IO_L19N_T3_VREF_34 Sch=ck_io[6]
set_property -dict { PACKAGE_PIN R14 IOSTANDARD LVCMOS33 } [get_ports { seg_7[6] }]; #IO_L6N_T0_VREF_34 Sch=ck_io[7]
set_property -dict { PACKAGE_PIN N18 IOSTANDARD LVCMOS33 } [get_ports { com[0] }]; #IO_L13P_T2_MRCC_34 Sch=ck_io[8]
set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { com[1] }]; #IO_L8N_T1_AD10N_35 Sch=ck_io[9]
set_property -dict { PACKAGE_PIN U15 IOSTANDARD LVCMOS33 } [get_ports { com[2] }]; #IO_L11N_T1_SRCC_34 Sch=ck_io[10]
set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { com[3] }]; #IO_L12N_T1_MRCC_35 Sch=ck_io[11]
#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L14P_T2_AD4P_SRCC_35 Sch=ck_io[12]
#set_property -dict { PACKAGE_PIN G15 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L19N_T3_VREF_35 Sch=ck_io[13]
## ChipKit Inner Digital Header
set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { LED_bar[0] }]; #IO_L19P_T3_34 Sch=ck_io[26]
set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { LED_bar[1] }]; #IO_L2N_T0_34 Sch=ck_io[27]
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { LED_bar[2] }]; #IO_L3P_T0_DQS_PUDC_B_34 Sch=ck_io[28]
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { LED_bar[3] }]; #IO_L10P_T1_34 Sch=ck_io[29]
set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { LED_bar[4] }]; #IO_L9P_T1_DQS_34 Sch=ck_io[30]
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { LED_bar[5] }]; #IO_L9N_T1_DQS_34 Sch=ck_io[31]
set_property -dict { PACKAGE_PIN T17 IOSTANDARD LVCMOS33 } [get_ports { LED_bar[6] }]; #IO_L20P_T3_34 Sch=ck_io[32]
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { LED_bar[7] }]; #IO_L20N_T3_34 Sch=ck_io[33]
set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L23N_T3_34 Sch=ck_io[34]
#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { ck_io35 }]; #IO_L23P_T3_34 Sch=ck_io[35]
#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { ck_io36 }]; #IO_L8P_T1_AD10P_35 Sch=ck_io[36]
#set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVCMOS33 } [get_ports { ck_io37 }]; #IO_L11N_T1_SRCC_35 Sch=ck_io[37]
#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { ck_io38 }]; #IO_L13N_T2_MRCC_35 Sch=ck_io[38]
#set_property -dict { PACKAGE_PIN H18 IOSTANDARD LVCMOS33 } [get_ports { ck_io39 }]; #IO_L14N_T2_AD4N_SRCC_35 Sch=ck_io[39]
#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { ck_io40 }]; #IO_L16N_T2_35 Sch=ck_io[40]
#set_property -dict { PACKAGE_PIN L20 IOSTANDARD LVCMOS33 } [get_ports { ck_io41 }]; #IO_L9N_T1_DQS_AD3N_35 Sch=ck_io[41]
## ChipKit SPI
#set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports { ck_miso }]; #IO_L10N_T1_34 Sch=ck_miso
#set_property -dict { PACKAGE_PIN T12 IOSTANDARD LVCMOS33 } [get_ports { ck_mosi }]; #IO_L2P_T0_34 Sch=ck_mosi
#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { ck_sck }]; #IO_L19P_T3_35 Sch=ck_sck
#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { ck_ss }]; #IO_L6P_T0_35 Sch=ck_ss
## ChipKit I2C
#set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports { ck_scl }]; #IO_L24N_T3_34 Sch=ck_scl
#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { ck_sda }]; #IO_L24P_T3_34 Sch=ck_sda
##Misc. ChipKit signals
#set_property -dict { PACKAGE_PIN M20 IOSTANDARD LVCMOS33 } [get_ports { ck_ioa }]; #IO_L7N_T1_AD2N_35 Sch=ck_ioa
## User Digital I/O Header J1
#set_property -dict { PACKAGE_PIN L19 IOSTANDARD LVCMOS33 } [get_ports { user_dio[1] }]; #IO_L9P_T1_DQS_AD3P_35 Sch=user_dio[1]
#set_property -dict { PACKAGE_PIN M19 IOSTANDARD LVCMOS33 } [get_ports { user_dio[2] }]; #IO_L7P_T1_AD2P_35 Sch=user_dio[2]
#set_property -dict { PACKAGE_PIN N20 IOSTANDARD LVCMOS33 } [get_ports { user_dio[3] }]; #IO_L14P_T2_SRCC_34 Sch=user_dio[3]
#set_property -dict { PACKAGE_PIN P20 IOSTANDARD LVCMOS33 } [get_ports { user_dio[4] }]; #IO_L14N_T2_SRCC_34 Sch=user_dio[4]
#set_property -dict { PACKAGE_PIN P19 IOSTANDARD LVCMOS33 } [get_ports { user_dio[5] }]; #IO_L13N_T2_MRCC_34 Sch=user_dio[5]
#set_property -dict { PACKAGE_PIN R19 IOSTANDARD LVCMOS33 } [get_ports { user_dio[6] }]; #IO_0_34 Sch=user_dio[6]
#set_property -dict { PACKAGE_PIN T20 IOSTANDARD LVCMOS33 } [get_ports { user_dio[7] }]; #IO_L15P_T2_DQS_34 Sch=user_dio[7]
#set_property -dict { PACKAGE_PIN T19 IOSTANDARD LVCMOS33 } [get_ports { user_dio[8] }]; #IO_25_34 Sch=user_dio[8]
#set_property -dict { PACKAGE_PIN U20 IOSTANDARD LVCMOS33 } [get_ports { user_dio[9] }]; #IO_L15N_T2_DQS_34 Sch=user_dio[9]
#set_property -dict { PACKAGE_PIN V20 IOSTANDARD LVCMOS33 } [get_ports { user_dio[10] }]; #IO_L16P_T2_34 Sch=user_dio[10]
#set_property -dict { PACKAGE_PIN W20 IOSTANDARD LVCMOS33 } [get_ports { user_dio[11] }]; #IO_L16N_T2_34 Sch=user_dio[11]
#set_property -dict { PACKAGE_PIN K19 IOSTANDARD LVCMOS33 } [get_ports { user_dio[12] }]; #IO_L10P_T1_AD11P_35 Sch=user_dio[12]
※ Clock Library & Counter
// Cora board sys clock : 125MHz
// 1 clock 당, 8ns
// Micro sec clock
module clock_usec(
input clk, reset_p,
input enable,
output clk_usec
);
// 125개 카운트하면 1us
reg [6:0] cnt_8nsec;
wire cp_usec; // cp : clock pulse
always @(posedge clk, posedge reset_p) begin
if(reset_p) cnt_8nsec = 0; // reset이 들어오면 cnt = 0
else if(cnt_8nsec >= 124) cnt_8nsec = 0; // 0부터 124번까지 카운트하면 다시 0으로
else cnt_8nsec = cnt_8nsec + 1;
end
assign cp_usec = cnt_8nsec < 63 ? 0 : 1; // 0~62 : 0, 63~124 : 1
// 비정규 clock이므로 동기화가 필요하다.
edge_detector_n edg(.clk(clk), .cp_in(cp_usec), .rst(reset_p), .n_edge(clk_usec)); /// 안 쓰는 출력은 빼버리면 된다.
endmodule
// min clock
module clock_min(
input clk, clk_sec, reset_p,
output clk_min
);
// 60개 카운트하면 1s
reg [5:0] cnt_sec;
reg cp_min; // cp : clock pulse
always @(posedge clk, posedge reset_p) begin
if(reset_p) cnt_sec = 0; // reset이 들어오면 cnt = 0
else if(clk_sec) begin
if (cnt_sec >= 29) begin
cnt_sec = 0; // 0부터 번까지 카운트하면 다시 0으로
cp_min = ~cp_min;
end
else cnt_sec = cnt_sec + 1;
end
end // 이렇게 카운트가 짝수일 경우, 위와 같이 코딩하여 1bit 줄일 수 있다.
// 비정규 clock이므로 동기화가 필요하다.
edge_detector_n edg_min(.clk(clk), .cp_in(cp_min), .rst(reset_p), .n_edge(clk_min)); /// 안 쓰는 출력은 빼버리면 된다.
endmodule
// 1000분주 clock
module clock_div_1000(
input clk, clk_source, reset_p,
output clk_div_1000
);
reg [8:0] cnt_clk_source;
reg cp_div_1000; // cp : clock pulse
always @(posedge clk, posedge reset_p) begin
if(reset_p) cnt_clk_source = 0; // reset이 들어오면 cnt = 0
else if(clk_source) begin
if (cnt_clk_source >= 499) begin
// if (cnt_clk_source >= 999) begin
cnt_clk_source = 0; // 0부터 499번까지 카운트하면 다시 0으로
cp_div_1000 = ~cp_div_1000;
end
else cnt_clk_source = cnt_clk_source + 1;
end
end // 이렇게 카운트가 짝수일 경우, 위와 같이 코딩하여 1bit 줄일 수 있다.
// 비정규 clock이므로 동기화가 필요하다.
edge_detector_n edg_div_1000(.clk(clk), .cp_in(cp_div_1000), .rst(reset_p), .n_edge(clk_div_1000)); /// 안 쓰는 출력은 빼버리면 된다.
endmodule
// 60bit_Counter
module counter_dec_60(
input clk, reset_p,
input clk_time,
output reg [3:0] dec1, dec10
);
always @(posedge clk, posedge reset_p) begin
if(reset_p) begin
dec1 = 0;
dec10 = 0;
end
else if(clk_time) begin
if(dec1 >= 9) begin
dec1 <= 0;
if(dec10 >= 5) dec10 = 0;
else dec10 <= dec10 + 1;
end
else dec1 <= dec1 + 1;
end
end
endmodule
// Loadable_60bit_Down_Counter
module loadable_down_counter_dec_60(
input clk, reset_p,
input clk_time,
input load_enable, // user가 입력한 값을 받아오는 기능 추가
input [3:0] set_value1, set_value10, // 입력한 값
output reg [3:0] dec1, dec10,
output reg dec_clk // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
);
always @(posedge clk, posedge reset_p) begin
if(reset_p) begin
dec1 <= 0;
dec10 <= 0;
dec_clk <= 0;
end
else if(load_enable == 1) begin
dec1 <= set_value1;
dec10 <= set_value10;
end
else if(clk_time) begin
if(dec1 == 0) begin
dec1 <= 9;
if(dec10 == 0) begin // 우리는 min과 sec 둘 다 구현하는 것이므로, min down counter에 신호를 넣어줘야 된다.
dec10 <= 5;
dec_clk <= 1; // dec10, dec1 = 0, 0 이 되고 이후에 5, 9가 되면서 dec_clk 상승 펄스 발생
end
else dec10 <= dec10 - 1;
end
else dec1 <= dec1 - 1;
end
else dec_clk <= 0;
end
endmodule
※ main code
module cook_timer(
input clk, reset_p,
input [3:0] btn,
output [3:0] com,
output [7:0] seg_7,
output [7:0] LED_bar
);
// button
wire start, incsec, incmin;
wire timeout, alarm_start;
wire t_start_stop;
// or (t_start_stop, start, alarm_start); // Verilog에서 구조적 모델링 하지 마!!!!
assign t_start_stop = start ? 1 : (alarm_start ? 1 : 0); // alarm이 발생하거나 start가 1일 때, t_start_stop = 1
button_cntr btn_start_stop(.clk(clk), .reset_p(reset_p), .btn(btn[0]), .btn_pe(start)); // start/stop
t_flip_flop_p tff_start_stop(.clk(clk), .rst(reset_p), .t(t_start_stop), .q(start_stop)); // 버튼눌렀을 때, alarm 발생 시, start_stop 변수 토글
button_cntr btn_incsec(.clk(clk), .reset_p(reset_p), .btn(btn[1]), .btn_pe(incsec)); // sec+
button_cntr btn_incmin(.clk(clk), .reset_p(reset_p), .btn(btn[2]), .btn_pe(incmin)); // min+
// Time Prescaler(clock Library)
wire clk_usec, clk_msec, clk_sec;
clock_usec usec_clk(.clk(clk), .reset_p(reset_p), .clk_usec(clk_usec));
clock_div_1000 msec_clk(.clk(clk), .clk_source(clk_usec), .reset_p(reset_p), .clk_div_1000(clk_msec));
clock_div_1000 sec_clk(.clk(clk), .clk_source(clk_msec), .reset_p(reset_p), .clk_div_1000(clk_sec));
clock_min min_clk(.clk(clk), .clk_sec(clk_sec), .reset_p(reset_p), .clk_min(clk_min));
// Time set
wire [3:0] sec1_set, sec10_set; // 사용자 경험(UX)애 맞춰서 UI를 설계하는 것이 중요하다. -> min, sec 동작시키자.
counter_dec_60 up_sec(.clk(clk), .reset_p(reset_p), .clk_time(incsec), .dec1(sec1_set), .dec10(sec10_set)); // sec up_counter
wire [3:0] min1_set, min10_set;
counter_dec_60 up_min(.clk(clk), .reset_p(reset_p), .clk_time(incmin), .dec1(min1_set), .dec10(min10_set)); // min up_counter
// load_enable을 start_stop에 연결하면, start 시(start_stop = 1)계속해서 값을 불러와버린다.
// 따라서 start_stop = 0일때만 1이 들어가도록 설계(start 변수의 참거짓에 따라 load_enable 변화하도록)
wire clk_start, load_enable;
wire dec_clk; // 다음 자리(예 : minute)에 신호(펄스)를 주기 위한 변수
wire [3:0] sec1, sec10, min1, min10;
assign clk_start = start_stop ? clk_sec : 0; // 대표적인 MUX 생성 방법
assign load_enable = ~start_stop ? start : 0; // start_stop = 0 이면, start 변수 사용
// load_enable에는 edge 한 번만 주어야 하므로 start 사용
loadable_down_counter_dec_60 dc_sec(.clk(clk), .reset_p(reset_p), .clk_time(clk_start), .load_enable(load_enable),
.set_value1(sec1_set), .set_value10(sec10_set),
.dec1(sec1), .dec10(sec10), .dec_clk(dec_clk));
loadable_down_counter_dec_60 dc_min(.clk(clk), .reset_p(reset_p), .clk_time(dec_clk), .load_enable(load_enable),
.set_value1(min1_set), .set_value10(min10_set),
.dec1(min1), .dec10(min10));
// Setting Time for FND
reg [15:0] set_time;
always @(posedge clk, posedge reset_p) begin
if(reset_p) set_time = 0;
else set_time = {min10_set, min1_set, sec10_set, sec1_set};
end
// Count Time for FND
reg [15:0] count_time;
always @(posedge clk, posedge reset_p) begin
if(reset_p) count_time = 0;
else count_time = {min10, min1, sec10, sec1};
end
// time = 0 도달 시,
// wire timeout, alarm_start; // 여기에 써도 오류는 안 난다.(Verilog의 코드는 병렬구조이기 때문에) 하지만 위에서 해당 변수를 사용하므로 위로 올리도록 하자.
assign timeout = |count_time; // 뒤의 모든 비트를 OR 연산한 결과(베릴로그에서만 사용할 수 있는 문법)
edge_detector_n edg_timeout(.clk(clk), .cp_in(timeout), .rst(reset_p), .n_edge(alarm_start)); // timeout 발생 시, alarm edge 발생
// Alarm On/Off를 위한 기능
wire alarm, alarm_off;
assign alarm_off = |{btn, reset_p}; // 모든 버튼을 다 묶어버려서 넣어주면, 어떤 버튼을 눌러도 alarm이 다 리셋된다.
t_flip_flop_p tff_alarm_on_off(.clk(clk), .rst(alarm_off), .t(alarm_start), .q(alarm));
assign LED_bar[0] = alarm;
wire [15:0] value;
assign value = start_stop ? count_time : set_time;
FND_4digit_cntr fnd_cntr(.clk(clk), .rst(reset_p), .value(value), .com(com), .seg_7(seg_7)); /// 컨트롤러가 분주기 가지고 있으니 그냥 clk준다.
endmodule