1功能概述
鬧鐘是一種既能顯示時間,又能根據人們設定的時間,發出鈴聲、樂曲等提醒信號的計時工具。現在,鬧鐘幾乎已經是上學、上班族必不可少的一個工具,主要應用在電腦、手機、電子表等方面。在20小節數字時鐘里我們介紹過,與傳統機械式計時工具相比,數字計時系統具備體積小、重量輕、抗干擾能力強、對環境要求高、高精確性、容易開發等特征。數字計時間高精度的特征,在鬧鐘功能上的應用優勢更為突出。
科學地劃分模塊,充分理順模塊間的相互關系對于FPGA設計來說非常重要。以鬧鐘設計為例,我們通過建立四個清晰直觀的模塊(數碼管顯示模塊,矩陣鍵盤掃描模塊,時鐘計數模塊,鬧鐘設定模塊),以及建立完善的信號列表和運用verilog語言編寫簡潔流暢的代碼,實現電子鬧鐘時、分、秒計時以及設置、修改、重置等功能。
具體功能要求如下:
本工程包括矩陣鍵盤和數碼管顯示模塊,共同實現一個帶有鬧鐘功能、可設置時間的數字時鐘。具體功能如下:
1. 數碼管可以顯示時十位、時個位、分十位、分個位、秒十位、秒個位。
2. 上電后,數碼管顯示000000,并開始每秒計時。
3. 按下按鍵1進入時間設置狀態。再按下按鍵1退出時間設置狀態,繼續計時。
4. 在時間設置狀態,通過按鍵2來選擇設置的時間位,在0~5之間循環選擇。
5. 在時間設置狀態,通過按鍵3來對當前選擇的時間位進行加1。
6. 在計時狀態下,按下按鍵14,進入鬧鐘時間點設置狀態;再按下按健15,退出鬧鐘設置狀態。
7. 在鬧鐘設置狀態,按下按鍵13選擇設置的時間位,此時可以按下所需要的按鍵序號設置對應鬧鐘時間。
8. 當前時間與所設置的時間點匹配上了,蜂鳴器響應5 s。
2 設計思路
我們把工程分成四個模塊,分別是數碼管顯示模塊,矩陣鍵盤掃描模塊,時鐘計數模塊,鬧鐘設定模塊。
工程頂層模塊的信號列表
信號名 |
I/O |
位寬 |
說明 |
clk |
I |
1 |
系統工作時鐘50MHz。 |
rst_n |
I |
1 |
系統復位信號,低電平有效。 |
key_col |
I |
4 |
矩陣鍵盤按鍵列信號 |
key_row |
O |
4 |
矩陣鍵盤按鍵行信號 |
bell |
O |
1 |
蜂鳴器控制信號 |
1.數碼管顯示模塊——實現將時鐘數據或者鬧鐘數據顯示到七段譯碼器上的功能。
七段譯碼器引腳圖:
根據七段譯碼器的型號共陰極或者共陽極,給予信號0點亮對應的led燈;一個八段數碼管稱為一位,多個數碼管并列在一起可構成多位數碼管,它們的段選(a,b,c,d,e,f,g,dp)連在一起,而各自的公共端稱為位選線。顯示時,都從段選線送入字符編碼,而選中哪個位選線,那個數碼管便會被點亮。例如,如果數碼管顯示數字0,那么共陰數碼管的字符編碼為00111111,即共陽數碼管的字符編碼為11000000。
信號列表如下:
信號名 |
I/O |
位寬 |
說明 |
clk |
I |
1 |
系統工作時鐘50MHz。 |
rst_n |
I |
1 |
系統復位信號,低電平有效。 |
din |
I |
32 |
每個數碼管的時間數據 |
seg_sel |
O |
8 |
數碼管位選信號 |
seg_ment |
O |
8 |
數碼管段選信號 |
在輪流顯示過程中,每位數碼管的點亮時間為1~2ms,由于人的視覺暫留現象及發光二極管的余輝效應,盡管實際上各位數碼管并非同時點亮,但只要掃描的速度足夠快,給人的印象就是一組穩定的顯示數據,不會有閃爍感。
2.矩陣鍵盤掃描模塊——4x4矩陣鍵盤,實現了矩陣鍵盤的掃描并使用以及按鍵消抖功能。通過行掃描法得到按下的鍵的位置信息。
信號列表如下:
信號名 |
I/O |
位寬 |
說明 |
clk |
I |
1 |
系統工作時鐘50MHz。 |
rst_n |
I |
1 |
系統復位信號,低電平有效。 |
key_col |
I |
4 |
矩陣鍵盤列信號 |
key_row |
O |
4 |
矩陣鍵盤行信號 |
key_out |
O |
4 |
按鍵位置信號 |
key_vld |
O |
1 |
按鍵有效信號 |
3.時鐘計數模塊——按下按鍵1則進入時鐘數字調節界面,此時利用按鍵2來位選,按鍵3來調節數字,按一次按鍵3則加1,再次按下按鍵1則恢復計數。
信號列表如下:
信號名 |
I/O |
位寬 |
說明 |
clk |
I |
1 |
系統工作時鐘50MHz。 |
rst_n |
I |
1 |
系統復位信號,低電平有效。 |
key_num |
I |
4 |
輸入按鍵值 |
key_vld |
I |
1 |
按鍵輸入有效指示 |
dout |
O |
24 |
時鐘數據輸出 |
dout_vld |
O |
24 |
時鐘數據輸出有效 |
4.鬧鐘設定模塊——實現設定鬧鐘時間功能,按下按鍵14則進入鬧鐘時間設定界面,并利用按鍵13來進行位選;然后按下對應的按鍵則設定對應的數字;按下按鍵15則退出鬧鐘設定界面。當時鐘數據和鬧鐘數據相同時,也就是到達設定時間時,蜂鳴器響5s。
信號列表如下:
信號名 |
I/O |
位寬 |
說明 |
clk |
I |
1 |
系統工作時鐘50MHz。 |
rst_n |
I |
1 |
系統復位信號,低電平有效。 |
time_now |
I |
24 |
當前輸入時間 |
time_now_vld |
I |
1 |
當前輸入時間有效 |
key_num |
I |
4 |
輸入按鍵值 |
key_vld |
I |
1 |
按鍵輸入有效指示 |
set_group |
O |
24 |
設置鬧鐘時間點 |
setting |
O |
1 |
設置狀態標志 |
bell |
O |
1 |
蜂鳴器控制信號 |
3 程序設計
工程模塊
2 clk ,
3 rst_n ,
4 key_col ,
5 key_row ,
6 seg_ment,
7 seg_sel ,
8 bell
9 );
10
11
12 parameter SEG_NUM = 6 ;
13 parameter TIME_1S = 50000000 ;
14 parameter TIME_20MS = 1000000 ;
15
16 input clk ;
17 input rst_n ;
18
19 output [3:0] key_row ;
20 output [7:0] seg_ment ;
21 output [5:0] seg_sel ;
22 input [3:0] key_col ;
23 output bell ;
24
25 wire [3:0] key_num ;
26 wire key_vld ;
27 wire [23:0] time_now ;
28 wire [23:0] time_display ;
29 wire time_now_vld ;
30 wire setting ;
31 wire [23:0] set_group ;
32
33 timer_data #(.TIME_1S(TIME_1S))timer_data_inst(
34 .clk(clk) ,
35 .rst_n(rst_n) ,
36 .dout(time_now) ,
37 .dout_vld(time_now_vld) ,
38
39 .key_num(key_num) ,
40 .key_vld(key_vld)
41 );
42
43 key_scan #(.TIME_20MS(TIME_20MS))key_scan_inst(
44 .clk(clk) ,
45 .rst_n(rst_n) ,
46 .key_col(key_col) ,
47 .key_row(key_row) ,
48 .key_out(key_num) ,
49 .key_vld(key_vld)
50 );
51
52 match_bell #(.TIME_1S(TIME_1S))match_bell_inst(
53 .clk(clk) ,
54 .rst_n(rst_n) ,
55 .time_now(time_now) ,
56 .time_now_vld(time_now_vld),
57 .key_num(key_num) ,
58 .key_vld(key_vld) ,
59 .setting(setting) ,
60 .set_group(set_group) ,
61 .bell(bell)
62 );
63
64 seg_disp #(.SEG_NUM(SEG_NUM))seg_display_inst(
65 .clk (clk) ,
66 .rst_n (rst_n) ,
67 .din(time_display),
68 .segment(seg_ment),
69 .seg_sel(seg_sel)
70 );
71
72 assign time_display=setting?set_group:time_now ;
73
74 endmodule
75
數碼管顯示模塊
2 rst_n ,
3 clk ,
4 din ,
5 seg_sel ,
6 segment
7 );
8
9
10 parameter SEG_WID = 8 ;
11 parameter SEG_NUM = 8 ;
12 parameter CNT_WID = 10 ;
13 parameter TIME_20US = 10'd1000 ;
14
15 //dp,g,f,e,d,c,b,a,
16 parameter NUM_0 = 8'b1100_0000;
17 parameter NUM_1 = 8'b1111_1001;
18 parameter NUM_2 = 8'b1010_0100;
19 parameter NUM_3 = 8'b1011_0000;
20 parameter NUM_4 = 8'b1001_1001;
21 parameter NUM_5 = 8'b1001_0010;
22 parameter NUM_6 = 8'b1000_0010;
23 parameter NUM_7 = 8'b1111_1000;
24 parameter NUM_8 = 8'b1000_0000;
25 parameter NUM_9 = 8'b1001_0000;
26 parameter NUM_ERR = 8'b1111_1111;
27
28
29 input clk ;
30 input rst_n ;
31 input [SEG_NUM*4-1:0] din ;
32 output [SEG_NUM - 1:0] seg_sel ;
33 output [SEG_WID - 1:0] segment ;
34
35 reg [SEG_NUM - 1:0] seg_sel ;
36 reg [SEG_WID - 1:0] segment ;
37
38 reg [CNT_WID - 1:0] cnt_20us ;
39 reg [SEG_NUM - 1:0] sel_cnt ;
40
41 reg [ 4-1:0] seg_tmp ;
42
43 wire add_cnt_20us ;
44 wire end_cnt_20us ;
45 wire add_sel_cnt ;
46 wire end_sel_cnt ;
47
48
49
50 always @(posedge clk or negedge rst_n)begin
51 if(rst_n==1'b0)begin
52 cnt_20us <= 0;
53 end
54 else if(add_cnt_20us)begin
55 if(end_cnt_20us)
56 cnt_20us <= 0;
57 else
58 cnt_20us <= cnt_20us + 1;
59 end
60 end
61 assign add_cnt_20us = 1;
62 assign end_cnt_20us = add_cnt_20us && cnt_20us == TIME_20US-1;
63
64
65 always @(posedge clk or negedge rst_n)begin
66 if(rst_n==1'b0)begin
67 sel_cnt <= 0;
68 end
69 else if(add_sel_cnt)begin
70 if(end_sel_cnt)
71 sel_cnt <= 0;
72 else
73 sel_cnt <= sel_cnt + 1;
74 end
75 end
76 assign add_sel_cnt = end_cnt_20us;
77 assign end_sel_cnt = add_sel_cnt && sel_cnt == SEG_NUM-1;
78
79 always @(posedge clk or negedge rst_n)begin
80 if(rst_n==1'b0)begin
81 seg_sel <= {SEG_NUM{1'b1}};
82 end
83 else begin
84 seg_sel <= ~(1'b1 << sel_cnt);
85 end
86 end
87
88 always @(*)begin
89 seg_tmp = din[(sel_cnt+1)*4-1 -:4];
90 end
91
92 always@(posedge clk or negedge rst_n)begin
93 if(rst_n==1'b0)begin
94 segment<=NUM_0;
95 end
96 else begin
97 case (seg_tmp)
98 0 : segment <= NUM_0;
99 1 : segment <= NUM_1;
100 2 : segment <= NUM_2;
101 3 : segment <= NUM_3;
102 4 : segment <= NUM_4;
103 5 : segment <= NUM_5;
104 6 : segment <= NUM_6;
105 7 : segment <= NUM_7;
106 8 : segment <= NUM_8;
107 9 : segment <= NUM_9;
108 default : segment <= NUM_ERR;
109 endcase
110 end
111 end
112
113 endmodule
矩陣鍵盤模塊
2 clk ,
3 rst_n ,
4 key_col,
5 key_row,
6 key_out,
7 key_vld
8 );
9
10 parameter TIME_20MS=1000000;
11
12 input clk ;
13 input rst_n ;
14 input [3:0] key_col ;
15
16 output [3:0] key_row ;
17
18 output [3:0] key_out ;
19 output key_vld ;
20
21 reg [3:0] key_out ;
22 reg key_vld ;
23
24 wire add_cnt_8clks ;
25 wire end_cnt_8clks ;
26 wire delay_over ;
27 wire add_row_index ;
28 wire end_row_index ;
29 wire vld ;
30 wire key_up ;
31 wire add_cnt_20ms ;
32 wire end_cnt_20ms ;
33 wire add_cnt_phase ;
34 wire end_cnt_phase ;
35 wire possible_vld ;
36
37 reg [2:0] cnt_8clks ;
38 reg [3:0] key_col_ff0 ;
39 reg [3:0] key_col_ff1 ;
40 reg [1:0] row_index ;
41 reg [3:0] key_row ;
42 reg [1:0] cnt_phase ;
43 reg [1:0] key_col_get ;
44 reg [20:0] cnt_20ms ;
45
46 always @(posedge clk or negedge rst_n)begin
47 if(rst_n==1'b0)begin
48 key_col_ff0<=4'hf;
49 key_col_ff1<=4'hf;
50 end
51 else begin
52 key_col_ff0<=key_col;
53 key_col_ff1<=key_col_ff0;
54 end
55 end
56
57 always @(posedge clk or negedge rst_n)begin
58 if(rst_n==1'b0)begin
59 cnt_phase<=0;
60 end
61 else if(add_cnt_phase)begin
62 if(end_cnt_phase)
63 cnt_phase<=0;
64 else
65 cnt_phase<=cnt_phase+1;
66 end
67 end
68 assign add_cnt_phase=end_cnt_20ms||end_row_index||delay_over||key_up;
69 assign end_cnt_phase=add_cnt_phase&&cnt_phase==4-1;
70 assign delay_over=end_cnt_8clks&&cnt_phase==3-1;
71 assign key_up=cnt_phase==4-1&&key_col_ff1==4'hf;
72
73
74 always @(posedge clk or negedge rst_n)begin
75 if(rst_n==1'b0)begin
76 cnt_20ms<=0;
77 end
78 else if(add_cnt_20ms)begin
79 if(end_cnt_20ms)
80 cnt_20ms<=0;
81 else
82 cnt_20ms<=cnt_20ms+1;
83 end
84 else
85 cnt_20ms<=0;
86 end
87 assign add_cnt_20ms=key_col_ff1!=4'hf&&cnt_phase==0;
88 assign end_cnt_20ms=add_cnt_20ms&&cnt_20ms==TIME_20MS-1;
89
90
91 always @(posedge clk or negedge rst_n)begin
92 if(rst_n==1'b0)begin
93 cnt_8clks<=0;
94 end
95 else if(add_cnt_8clks)begin
96 if(end_cnt_8clks)
97 cnt_8clks<=0;
98 else
99 cnt_8clks<=cnt_8clks+1;
100 end
101 end
102
103 assign add_cnt_8clks=cnt_phase==2-1||cnt_phase==3-1;
104 assign end_cnt_8clks=add_cnt_8clks&&cnt_8clks==8-1;
105
106 always @(posedge clk or negedge rst_n)begin
107 if(rst_n==1'b0)begin
108 row_index<=0;
109 end
110 else if(add_row_index)begin
111 if(end_row_index)
112 row_index<=0;
113 else
114 row_index<=row_index+1;
115 end
116 end
117 assign add_row_index=end_cnt_8clks&&cnt_phase==2-1;
118 assign end_row_index=add_row_index&&row_index==4-1;
119
120
121 always @(posedge clk or negedge rst_n)begin
122 if(rst_n==1'b0)begin
123 key_row<=4'b0000;
124 end
125 else if(cnt_phase==1)begin
126 key_row<=~(1<<row_index);
127 end
128 else
129 key_row<=4'b0000;
130 end
131
132 always @(posedge clk or negedge rst_n)begin
133 if(rst_n==1'b0)begin
134 key_out <= 0;
135 end
136 else if(possible_vld)begin
137 key_out <= {row_index,key_col_get};
138 end
139 else begin
140 key_out <= 0;
141 end
142 end
143
144 assign possible_vld=cnt_phase==1 && end_cnt_8clks;
145
146
147 always @(posedge clk or negedge rst_n)begin
148 if(rst_n==1'b0)begin
149 key_col_get <= 0;
150 end
151 else if(end_cnt_20ms) begin
152 if(key_col_ff1==4'b1110)
153 key_col_get <= 0;
154 else if(key_col_ff1==4'b1101)
155 key_col_get <= 1;
156 else if(key_col_ff1==4'b1011)
157 key_col_get <= 2;
158 else
159 key_col_get <= 3;
160 end
161 end
162
163 always @(posedge clk or negedge rst_n)begin
164 if(rst_n==1'b0)begin
165 key_vld <= 1'b0;
166 end
167 else if(vld)begin
168 key_vld <= 1'b1;
169 end
170 else begin
171 key_vld <= 1'b0;
172 end
173 end
174
175
176 assign vld=possible_vld && key_col_ff1[key_col_get]==1'b0;
177
178 endmodule
179
180
181
182
時鐘計數模塊
2 clk ,
3 rst_n ,
4
5 key_num ,
6 key_vld ,
7
8 dout ,
9 dout_vld
10 );
11
12 parameter DATA_W = 4 ;
13 parameter TIME_1S = 50_000_000 ;
14
15 input clk ;
16 input rst_n ;
17 input [3:0] key_num ;
18 input key_vld ;
19
20 output [23:0] dout ;
21 output dout_vld ;
22 reg dout_vld ;
23 reg pause_flag ;
24
25 reg [3:0] x ;
26 reg [3:0] y ;
27 reg [3:0] miao_g ;
28 reg [3:0] miao_s ;
29 reg [3:0] fen_g ;
30 reg [3:0] fen_s ;
31 reg [3:0] shi_g ;
32 reg [3:0] shi_s ;
33 reg [2:0] cnt_key2 ;
34
35 wire [23:0] dout ;
36 wire add_cnt_key2 ;
37 wire end_cnt_key2 ;
38 wire add_cnt ;
39 wire end_cnt ;
40 wire add_miao_g ;
41 wire end_miao_g ;
42 wire press_key3 ;
43 wire add_miao_s ;
44 wire end_miao_s ;
45 wire add_fen_g ;
46 wire end_fen_g ;
47
48 wire add_fen_s ;
49 wire end_fen_s ;
50 wire add_shi_g ;
51 wire end_shi_g ;
52 wire add_shi_s ;
53 wire end_shi_s ;
54
55 wire key_add_fen_g ;
56 wire key_add_miao_s ;
57 wire key_add_shi_g ;
58 wire key_add_fen_s ;
59 wire key_add_miao_g ;
60 wire key_add_shi_s ;
61
62
63
64 always @(posedge clk or negedge rst_n)begin
65 if(rst_n==1'b0)begin
66 pause_flag<=0;
67 end
68 else if(key_vld&&key_num==1)begin
69 if(pause_flag)
70 pause_flag<=0;
71 else
72 pause_flag<=1;
73 end
74 end
75
76
77 always @(posedge clk or negedge rst_n)begin
78 if(rst_n==1'b0)begin
79 cnt_key2<=0;
80 end
81 else if(add_cnt_key2)begin
82 if(end_cnt_key2)
83 cnt_key2<=0;
84 else
85 cnt_key2<=cnt_key2+1;
86 end
87 else if(pause_flag==0)
88 cnt_key2<=0;
89 end
90
91 assign add_cnt_key2=key_vld&&key_num==2&&pause_flag==1;
92 assign end_cnt_key2=add_cnt_key2&&cnt_key2==6-1;
93
94
95 reg [25:0] cnt;
96
97 always @(posedge clk or negedge rst_n)begin
98 if(rst_n==1'b0)begin
99 cnt<=0;
100 end
101 else if(add_cnt)begin
102 if(end_cnt)
103 cnt<=0;
104 else
105 cnt<=cnt+1;
106 end
107 end
108
109 assign add_cnt=pause_flag==0;
110 assign end_cnt=add_cnt&&cnt==TIME_1S-1;
111
112
113 always @(posedge clk or negedge rst_n)begin
114 if(rst_n==1'b0)begin
115 miao_g<=0;
116 end
117 else if(add_miao_g)begin
118 if(end_miao_g)
119 miao_g<=0;
120 else
121 miao_g<=miao_g+1;
122 end
123
124 end
125
126 assign add_miao_g=end_cnt||key_add_miao_g;
127 assign end_miao_g=add_miao_g&&miao_g==10-1;
128 assign key_add_miao_g=press_key3&&cnt_key2==0;
129
130
131 assign press_key3=pause_flag==1&&key_vld&&key_num==3;
132
133
134 always @(posedge clk or negedge rst_n)begin
135 if(rst_n==1'b0)begin
136 miao_s<=0;
137 end
138 else if(add_miao_s)begin
139 if(end_miao_s)
140 miao_s<=0;
141 else
142 miao_s<=miao_s+1;
143 end
144
145 end
146
147 assign add_miao_s=end_miao_g||key_add_miao_s;
148 assign end_miao_s=add_miao_s&&miao_s==6-1;
149
150 assign key_add_miao_s=cnt_key2==1&&press_key3;
151
152
153 always @(posedge clk or negedge rst_n)begin
154 if(rst_n==1'b0)begin
155 fen_g<=0;
156 end
157 else if(add_fen_g)begin
158 if(end_fen_g)
159 fen_g<=0;
160 else
161 fen_g<=fen_g+1;
162 end
163
164 end
165
166 assign add_fen_g=end_miao_s||key_add_fen_g;
167 assign end_fen_g=add_fen_g&&fen_g==10-1;
168
169 assign key_add_fen_g=cnt_key2==2&&press_key3;
170
171 always @(posedge clk or negedge rst_n)begin
172 if(rst_n==1'b0)begin
173 fen_s<=0;
174 end
175 else if(add_fen_s)begin
176 if(end_fen_s)
177 fen_s<=0;
178 else
179 fen_s<=fen_s+1;
180 end
181 end
182
183 assign add_fen_s=end_fen_g||(key_add_fen_s);
184 assign end_fen_s=add_fen_s&&fen_s==6-1;
185
186
187 assign key_add_fen_s=cnt_key2==3&&press_key3;
188
189
190 always @(posedge clk or negedge rst_n)begin
191 if(rst_n==1'b0)begin
192 shi_g<=0;
193 end
194 else if(add_shi_g)begin
195 if(end_shi_g)
196 shi_g<=0;
197 else
198 shi_g<=shi_g+1;
199 end
200
201 end
202
203 assign add_shi_g=end_fen_s ||key_add_shi_g;
204 assign end_shi_g=add_shi_g&& shi_g ==x -1;
205
206
207 always@(*)
208 if(shi_s==2)
209 x = 4;
210 else
211 x = 10;
212
213 assign key_add_shi_g=cnt_key2==4&&press_key3;
214
215
216 always @(posedge clk or negedge rst_n)begin
217 if(rst_n==1'b0)begin
218 shi_s<=0;
219 end
220 else if(add_shi_s)begin
221 if(end_shi_s)
222 shi_s<=0;
223 else
224 shi_s<=shi_s+1;
225 end
226 end
227
228 assign add_shi_s=end_shi_g|| key_add_shi_s;
229 assign end_shi_s=add_shi_s && shi_s==y-1;
230
231 assign key_add_shi_s=cnt_key2==5&&press_key3;
232
233 always @(*)begin
234 if(shi_g>=4)
235 y = 2;
236 else
237 y = 3;
238 end
239
240
241 assign dout = {shi_s,shi_g,fen_s,fen_g,miao_s,miao_g};
242
243 always @(posedge clk or negedge rst_n)begin
244 if(rst_n==1'b0)begin
245 dout_vld<=0;
246 end
247 else if(end_cnt)begin
248 dout_vld<=1;
249 end
250 else
251 dout_vld<=0;
252 end
253
254
255 endmodule
256
鬧鐘設定模塊
2 clk ,
3 rst_n ,
4 time_now ,
5 time_now_vld,
6 key_num ,
7 key_vld ,
8 set_group ,
9 setting ,
10 bell
11 );
12
13 parameter TIME_1S=50000000 ;
14
15 input clk ;
16 input rst_n ;
17 input [23:0] time_now ;
18 input time_now_vld ;
19 input [3:0] key_num ;
20 input key_vld ;
21
22
23 output bell ;
24 output set_group ;
25 output setting ;
26
27
28 reg bell ;
29 reg [3:0] key_num_ff0 ;
30 wire equal_flag ;
31 reg [23:0] set_group ;
32 reg setting ;
33 wire start_set ;
34 wire end_set ;
35
36
37 wire add_cnt_1s ;
38 wire end_cnt_1s ;
39 wire add_cnt_5s ;
40 wire end_cnt_5s ;
41 reg [2:0] cnt_5s ;
42 reg [25:0] cnt_1s ;
43 reg [2:0] cnt_key13 ;
44 wire add_cnt_key13 ;
45 wire end_cnt_key13 ;
46 reg set_alarm_vld ;
47 wire value_0_9 ;
48 wire value_0_5 ;
49 wire value_0_2 ;
50 wire value_0_1 ;
51 wire value_0_3 ;
52
53 always @(posedge clk or negedge rst_n)begin
54 if(rst_n==1'b0)begin
55 bell<=1;
56 end
57 else if(equal_flag)begin
58 bell<=0;
59 end
60 else if(end_cnt_5s)
61 bell<=1;
62 end
63
64
65 always @(posedge clk or negedge rst_n)begin
66 if(rst_n==1'b0)begin
67 cnt_1s<=23'b0;
68 end
69 else if(add_cnt_1s)begin
70 if(end_cnt_1s)
71 cnt_1s<=23'b0;
72 else
73 cnt_1s<=cnt_1s+1'b1;
74 end
75 end
76 assign add_cnt_1s=bell==0;
77 assign end_cnt_1s=add_cnt_1s&&cnt_1s==TIME_1S-1;
78
79 always @(posedge clk or negedge rst_n)begin
80 if(rst_n==1'b0)begin
81 cnt_5s<=0;
82 end
83 else if(add_cnt_5s)begin
84 if(end_cnt_5s)
85 cnt_5s<=0;
86 else
87 cnt_5s<=cnt_5s+1;
88 end
89 end
90
91 assign add_cnt_5s=end_cnt_1s;
92 assign end_cnt_5s=add_cnt_5s&&cnt_5s==5-1;
93
94
95 assign equal_flag=(set_group==time_now)&&time_now_vld;
96
97
98 always @(posedge clk or negedge rst_n)begin
99 if(rst_n==1'b0)begin
100 cnt_key13<=0;
101 end
102 else if(add_cnt_key13)begin
103 if(end_cnt_key13)
104 cnt_key13<=0;
105 else
106 cnt_key13<=cnt_key13+1;
107 end
108 else if(end_set)
109 cnt_key13<=0;
110 end
111
112 assign add_cnt_key13=setting&&key_vld&&key_num==13;
113 assign end_cnt_key13=add_cnt_key13&&cnt_key13==6-1;
114
115 always @(posedge clk or negedge rst_n)begin
116 if(rst_n==1'b0)begin
117 set_group<=24'h000009;
118 end
119 else if(set_alarm_vld)begin
120 if(cnt_key13==0)
121 set_group[3:0]<=key_num_ff0;
122 else if(cnt_key13==1)
123 set_group[7:4]<=key_num_ff0;
124 else if(cnt_key13==2)
125 set_group[11:8]<=key_num_ff0;
126 else if(cnt_key13==3)
127 set_group[15:12]<=key_num_ff0;
128 else if(cnt_key13==4)
129 set_group[19:16]<=key_num_ff0;
130 else if(cnt_key13==5)
131 set_group[23:20]<=key_num_ff0;
132 end
133 end
134
135
136 assign value_0_9=key_vld&&(0<=key_num&&key_num<10);
137 assign value_0_5=key_vld&&(0<=key_num&&key_num<6);
138 assign value_0_2=key_vld&&(0<=key_num&&key_num<3);
139 assign value_0_3=key_vld&&(0<=key_num&&key_num<4);
140 assign value_0_1=key_vld&&(0<=key_num&&key_num<2);
141
142 always @(posedge clk or negedge rst_n)begin
143 if(rst_n==1'b0)begin
144 set_alarm_vld<=0;
145 end
146 else if(key_vld&&setting)begin
147 if(cnt_key13==0)begin
148 if(value_0_9)
149 set_alarm_vld<=1;
150 else
151 set_alarm_vld<=0;
152 end
153 else if(cnt_key13==1)begin
154 if(value_0_5)
155 set_alarm_vld<=1;
156 else
157 set_alarm_vld<=0;
158 end
159 else if(cnt_key13==2)begin
160 if(value_0_9)
161 set_alarm_vld<=1;
162 else
163 set_alarm_vld<=0;
164 end
165 else if(cnt_key13==3)begin
166 if(value_0_5)
167 set_alarm_vld<=1;
168 else
169 set_alarm_vld<=0;
170 end
171 else if(cnt_key13==4)begin
172 if(set_group[23:20]==2)begin
173 if(value_0_3)
174 set_alarm_vld<=1;
175 else
176 set_alarm_vld<=0;
177 end
178 else if(value_0_9)
179 set_alarm_vld<=1;
180 else
181 set_alarm_vld<=0;
182 end
183 else if(cnt_key13==5)begin
184 if(0<=set_group[19:16]&&set_group[19:16]<4)begin
185 if(value_0_2)
186 set_alarm_vld<=1;
187 else
188 set_alarm_vld<=0;
189 end
190 else if(value_0_1)
191 set_alarm_vld<=1;
192 else
193 set_alarm_vld<=0;
194 end
195 end
196 else
197 set_alarm_vld<=0;
198 end
199
200 always @(posedge clk or negedge rst_n)begin
201 if(rst_n==1'b0)begin
202 key_num_ff0<=0;
203 end
204 else
205 key_num_ff0<=key_num;
206 end
207
208 always @(posedge clk or negedge rst_n)begin
209 if(rst_n==1'b0)begin
210 setting<=0;
211 end
212 else if(start_set)begin
213 setting<=1;
214 end
215 else if(end_set)begin
216 setting<=0;
217 end
218 end
219
220 assign start_set=key_vld&&key_num==14;
221 assign end_set =key_vld&&key_num==15;
222
223 endmodule
224