99在线精品免费视频九九视-99在线精品视频-99在线精品视频免费观里-99在线精品视频在线观看-99在线免费播放

【案例】電子鬧鐘設(shè)計(jì)

  發(fā)布時(shí)間:2023-10-19  |    作者:管理員  |  瀏覽量:1655

案例編號(hào):001600000064

至簡設(shè)計(jì)系列_鬧鐘


--作者:小黑同學(xué)

本文為明德?lián)P原創(chuàng)及錄用文章,轉(zhuǎn)載請(qǐng)注明出處!

1.1 總體設(shè)計(jì)

1.1.1 概述

數(shù)字時(shí)鐘是采用數(shù)字電路技術(shù)實(shí)現(xiàn)時(shí)、分、秒計(jì)時(shí)顯示的裝置,可以用數(shù)字同時(shí)顯示時(shí),分,秒

的精確時(shí)間并實(shí)現(xiàn)準(zhǔn)確校時(shí),具備體積小、重量輕、抗干擾能力強(qiáng)、對(duì)環(huán)境要求高、高精確性、容易

開發(fā)等特性,在工業(yè)控制系統(tǒng)、智能化儀器表、辦公自動(dòng)化系統(tǒng)等諸多領(lǐng)域取得了極為廣泛的應(yīng)用,

諸如自動(dòng)報(bào)警、按時(shí)自動(dòng)打鈴、時(shí)間程序自動(dòng)控制、定時(shí)廣播、自定啟閉路燈、定時(shí)開關(guān)烘箱、通斷

動(dòng)力設(shè)備、甚至各種定時(shí)電器的自動(dòng)啟用等。與傳統(tǒng)表盤式機(jī)械時(shí)鐘相比,數(shù)字時(shí)鐘具有更高的準(zhǔn)確

性和直觀性,由于沒有機(jī)械裝置,其使用壽命更長。

1.1.2 設(shè)計(jì)目標(biāo)

設(shè)計(jì)一款具有鬧鐘功能的數(shù)字時(shí)鐘,具體要求如下

1、 用 8 個(gè)數(shù)碼管實(shí)現(xiàn),四個(gè)一組,每組有分鐘和秒。左邊一組是時(shí)間顯示,右邊一組用來

做鬧鐘時(shí)間。

2、 當(dāng)左邊時(shí)間等于右邊時(shí),蜂鳴器響 5 秒。

3、 鬧鐘時(shí)間和顯示時(shí)間均可通過 3 個(gè)按鍵設(shè)置。設(shè)置方法:按下按鍵 1,時(shí)鐘暫停,跳到

設(shè)置時(shí)間狀態(tài),再按下按鍵 1,回到正常狀態(tài)。通過按鍵 2,選擇要設(shè)置的位置,初始

設(shè)置秒個(gè)位,按一下,設(shè)置秒十位,再按下,設(shè)置分個(gè)位,以此類推,循環(huán)設(shè)置。通過

按鍵 3,設(shè)置數(shù)值,按一下數(shù)值加 1,如果溢出則重新變?yōu)?0。

1.1.3 系統(tǒng)結(jié)構(gòu)框圖

系統(tǒng)結(jié)構(gòu)框圖如下所示:

結(jié)構(gòu)圖共分兩個(gè),如果使用的開發(fā)板上是矩陣鍵盤的時(shí)候,對(duì)應(yīng)的結(jié)構(gòu)圖是圖一。如果使用的開

發(fā)板上是普通按鍵的時(shí)候,對(duì)應(yīng)的結(jié)構(gòu)圖是圖二。


圖一


圖二


1.1.4 模塊功能

? 按鍵檢測模塊實(shí)現(xiàn)功能

1、將外來異步信號(hào)打兩拍處理,將異步信號(hào)同步化。

2、實(shí)現(xiàn) 20ms 按鍵消抖功能,并輸出有效按鍵信號(hào)。


? 矩陣鍵盤模塊實(shí)現(xiàn)功能

1、將外來異步信號(hào)打兩拍處理,將異步信號(hào)同步化。

2、實(shí)現(xiàn) 20ms 按鍵消抖功能。

3、實(shí)現(xiàn)矩陣鍵盤的按鍵檢測功能,并輸出有效按鍵信號(hào)。

? 時(shí)間產(chǎn)生模塊實(shí)現(xiàn)功能

1、 產(chǎn)生顯示時(shí)間數(shù)據(jù)。

2、 產(chǎn)生鬧鐘時(shí)間數(shù)據(jù),

3、根據(jù)接收到的不同的按鍵信號(hào),產(chǎn)生暫停、開啟、設(shè)置時(shí)間的功能。

? 數(shù)碼管顯示模塊實(shí)現(xiàn)功能

1、 對(duì)接收到的時(shí)間數(shù)據(jù)進(jìn)行譯碼。

? 蜂鳴器模塊實(shí)現(xiàn)功能

1、 將接受到的顯示時(shí)間數(shù)據(jù)與鬧鐘時(shí)間數(shù)據(jù)進(jìn)行比較,控制蜂鳴器的開啟。

1.1.5 頂層信號(hào)



1.1.6 參考代碼

下面是使用普通按鍵的頂層代碼:

1.	module  alarm_clock(  
2.     clk       ,  
3.     rst_n     ,  
4.     key       ,  
5.     segment   ,  
6.     seg_sel   ,  
7.     beep  
8. );  
9. input                   clk             ;  
10. input                   rst_n           ;  
11. input   [2:0 ]          key             ;  
12. output  [7:0 ]          segment         ;  
13. output  [7:0 ]          seg_sel         ;  
14. output                  beep            ;  
15.   
16. wire    [7:0 ]          segment         ;  
17. wire    [7:0 ]          seg_sel         ;  
18. wire                    beep            ;  
19. wire    [3:0 ]          xs_sec_low      ;  
20. wire    [3:0 ]          xs_sec_high     ;  
21. wire    [3:0 ]          xs_min_low      ;  
22. wire    [3:0 ]          xs_min_high     ;  
23. wire    [3:0 ]          sec_low         ;  
24. wire    [3:0 ]          sec_high        ;  
25. wire    [3:0 ]          min_low         ;  
26. wire    [3:0 ]          min_high        ;  
27. wire    [25:0]          counter         ;  
28. wire    [3:0 ]          key_vld         ;  
29. wire                    flag_set        ;  
30.   
31. key_module u0(  
32.              .clk         (clk         ),  
33.              .rst_n       (rst_n       ),  
34.              .key_in      (key         ),  
35.              .key_vld     (key_vld     )  
36.              );  
37. time_data u1(  
38.              .clk         (clk         ),   
39.              .rst_n       (rst_n       ),   
40.              .key_vld     (key_vld     ),   
41.              .flag_set    (flag_set    ),   
42.              .counter     (counter     ),  
43.              .sec_low     (sec_low     ),  
44.              .sec_high    (sec_high    ),  
45.              .min_low     (min_low     ),  
46.              .min_high    (min_high    ),  
47.              .xs_sec_low  (xs_sec_low  ),   
48.              .xs_sec_high (xs_sec_high ),   
49.              .xs_min_low  (xs_min_low  ),   
50.              .xs_min_high (xs_min_high )   
51.              );  
52. beep u2(  
53.              .clk         (clk         ),   
54.              .rst_n       (rst_n       ),   
55.              .flag_set    (flag_set    ),   
56.              .counter     (counter     ),   
57.              .beep        (beep        ),  
58.              .sec_low     (sec_low     ),  
59.              .sec_high    (sec_high    ),  
60.              .min_low     (min_low     ),  
61.              .min_high    (min_high    ),  
62.              .xs_sec_low  (xs_sec_low  ),  
63.              .xs_sec_high (xs_sec_high ),  
64.              .xs_min_low  (xs_min_low  ),  
65.              .xs_min_high (xs_min_high )   
66.              );  
67. seg_disp u3(   
68.              .clk         (clk         ),   
69.              .rst_n       (rst_n       ),   
70.              .segment_data({xs_min_high,xs_min_low,xs_sec_high,xs_sec_low,min_high,min_low,sec_high,sec_low}),   
71.              .segment     (segment     ),   
72.              .seg_sel     (seg_sel     )    
73. );  
74.   
75.   
76. endmodule


下面是使用矩陣鍵盤的頂層代碼:

1.	module  alarm_clock_jvzhen(  
2.     clk       ,  
3.     rst_n     ,  
4.     key_col   ,  
5.     key_row   ,  
6.     segment   ,  
7.     seg_sel   ,  
8.     beep  
9. );  
10. input                   clk             ;  
11. input                   rst_n           ;  
12. input   [3:0 ]          key_col         ;  
13. output  [3:0 ]          key_row         ;  
14. output  [7:0 ]          segment         ;  
15. output  [7:0 ]          seg_sel         ;  
16. output                  beep            ;  
17.   
18. wire    [7:0 ]          segment         ;  
19. wire    [7:0 ]          seg_sel         ;  
20. wire                    beep            ;  
21. wire    [3:0 ]          xs_sec_low      ;  
22. wire    [3:0 ]          xs_sec_high     ;  
23. wire    [3:0 ]          xs_min_low      ;  
24. wire    [3:0 ]          xs_min_high     ;  
25. wire    [3:0 ]          sec_low         ;  
26. wire    [3:0 ]          sec_high        ;  
27. wire    [3:0 ]          min_low         ;  
28. wire    [3:0 ]          min_high        ;  
29. wire    [25:0]          counter         ;  
30. wire    [3:0 ]          key_vld         ;  
31. wire                    flag_set        ;  
32. wire    [15:0]          key_out         ;  
33.   
34. key_scan  u0(  
35.              .clk         (clk         ),  
36.              .rst_n       (rst_n       ),  
37.              .key_col     (key_col     ),  
38.              .key_row     (key_row     ),  
39.              .key_en      (key_vld     )  
40.              );  
41. time_data u1(  
42.              .clk         (clk         ),   
43.              .rst_n       (rst_n       ),   
44.              .key_vld     (key_vld     ),   
45.              .flag_set    (flag_set    ),   
46.              .counter     (counter     ),  
47.              .sec_low     (sec_low     ),  
48.              .sec_high    (sec_high    ),  
49.              .min_low     (min_low     ),  
50.              .min_high    (min_high    ),  
51.              .xs_sec_low  (xs_sec_low  ),   
52.              .xs_sec_high (xs_sec_high ),   
53.              .xs_min_low  (xs_min_low  ),   
54.              .xs_min_high (xs_min_high )   
55.              );  
56. beep u2(  
57.              .clk         (clk         ),   
58.              .rst_n       (rst_n       ),   
59.              .flag_set    (flag_set    ),   
60.              .counter     (counter     ),   
61.              .beep        (beep        ),  
62.              .sec_low     (sec_low     ),  
63.              .sec_high    (sec_high    ),  
64.              .min_low     (min_low     ),  
65.              .min_high    (min_high    ),  
66.              .xs_sec_low  (xs_sec_low  ),  
67.              .xs_sec_high (xs_sec_high ),  
68.              .xs_min_low  (xs_min_low  ),  
69.              .xs_min_high (xs_min_high )   
70.              );  
71. seg_disp u3(   
72.              .clk         (clk         ),   
73.              .rst_n       (rst_n       ),   
74.              .segment_data({xs_min_high,xs_min_low,xs_sec_high,xs_sec_low,min_high,min_low,sec_high,sec_low}),   
75.              .segment     (segment     ),   
76.              .seg_sel     (seg_sel     )    
77. );  
78.   
79.   
80. endmodule


1.2 按鍵檢測模塊設(shè)計(jì)

1.2.1 接口信號(hào)



1.2.2 設(shè)計(jì)思路

在前面的案例中已經(jīng)有按鍵檢測的介紹,所以這里不在過多介紹,詳細(xì)介紹請(qǐng)看下方鏈接:

【每周 FPGA 案例】至簡設(shè)計(jì)系列_按鍵控制數(shù)字時(shí)鐘

1.2.3 參考代碼

使用明德?lián)P的計(jì)數(shù)器模板,可以很快速很熟練地寫出按鍵消抖模塊。

1.	module  alarm_clock_jvzhen(  
2.     clk       ,  
3.     rst_n     ,  
4.     key_col   ,  
5.     key_row   ,  
6.     segment   ,  
7.     seg_sel   ,  
8.     beep  
9. );  
10. input                   clk             ;  
11. input                   rst_n           ;  
12. input   [3:0 ]          key_col         ;  
13. output  [3:0 ]          key_row         ;  
14. output  [7:0 ]          segment         ;  
15. output  [7:0 ]          seg_sel         ;  
16. output                  beep            ;  
17.   
18. wire    [7:0 ]          segment         ;  
19. wire    [7:0 ]          seg_sel         ;  
20. wire                    beep            ;  
21. wire    [3:0 ]          xs_sec_low      ;  
22. wire    [3:0 ]          xs_sec_high     ;  
23. wire    [3:0 ]          xs_min_low      ;  
24. wire    [3:0 ]          xs_min_high     ;  
25. wire    [3:0 ]          sec_low         ;  
26. wire    [3:0 ]          sec_high        ;  
27. wire    [3:0 ]          min_low         ;  
28. wire    [3:0 ]          min_high        ;  
29. wire    [25:0]          counter         ;  
30. wire    [3:0 ]          key_vld         ;  
31. wire                    flag_set        ;  
32. wire    [15:0]          key_out         ;  
33.   
34. key_scan  u0(  
35.              .clk         (clk         ),  
36.              .rst_n       (rst_n       ),  
37.              .key_col     (key_col     ),  
38.              .key_row     (key_row     ),  
39.              .key_en      (key_vld     )  
40.              );  
41. time_data u1(  
42.              .clk         (clk         ),   
43.              .rst_n       (rst_n       ),   
44.              .key_vld     (key_vld     ),   
45.              .flag_set    (flag_set    ),   
46.              .counter     (counter     ),  
47.              .sec_low     (sec_low     ),  
48.              .sec_high    (sec_high    ),  
49.              .min_low     (min_low     ),  
50.              .min_high    (min_high    ),  
51.              .xs_sec_low  (xs_sec_low  ),   
52.              .xs_sec_high (xs_sec_high ),   
53.              .xs_min_low  (xs_min_low  ),   
54.              .xs_min_high (xs_min_high )   
55.              );  
56. beep u2(  
57.              .clk         (clk         ),   
58.              .rst_n       (rst_n       ),   
59.              .flag_set    (flag_set    ),   
60.              .counter     (counter     ),   
61.              .beep        (beep        ),  
62.              .sec_low     (sec_low     ),  
63.              .sec_high    (sec_high    ),  
64.              .min_low     (min_low     ),  
65.              .min_high    (min_high    ),  
66.              .xs_sec_low  (xs_sec_low  ),  
67.              .xs_sec_high (xs_sec_high ),  
68.              .xs_min_low  (xs_min_low  ),  
69.              .xs_min_high (xs_min_high )   
70.              );  
71. seg_disp u3(   
72.              .clk         (clk         ),   
73.              .rst_n       (rst_n       ),   
74.              .segment_data({xs_min_high,xs_min_low,xs_sec_high,xs_sec_low,min_high,min_low,sec_high,sec_low}),   
75.              .segment     (segment     ),   
76.              .seg_sel     (seg_sel     )    
77. );  
78.   
79.   
80. endmodule

1.3 矩陣鍵盤模塊設(shè)計(jì)

1.3.1 接口信號(hào)



1.3.2 設(shè)計(jì)思路

在前面的案例中已經(jīng)有矩陣鍵盤的介紹,所以這里不在過多介紹,詳細(xì)介紹請(qǐng)看下方鏈接:

http://fpgabbs.com/forum.php?mod=viewthread&tid=310

1.3.3 參考代碼

1.	always  @(posedge clk or negedge rst_n)begin  
2.     if(rst_n==1'b0)begin  
3.         key_col_ff0 <= 4'b1111;  
4.         key_col_ff1 <= 4'b1111;  
5.     end  
6.     else begin  
7.         key_col_ff0 <= key_col    ;  
8.         key_col_ff1 <= key_col_ff0;  
9.     end  
10. end  
11.   
12.   
13. always @(posedge clk or negedge rst_n) begin   
14.     if (rst_n==0) begin  
15.         shake_cnt <= 0;   
16.     end  
17.     else if(add_shake_cnt) begin  
18.         if(end_shake_cnt)  
19.             shake_cnt <= 0;   
20.         else  
21.             shake_cnt <= shake_cnt+1 ;  
22.    end  
23. end  
24. assign add_shake_cnt = key_col_ff1!=4'hf;  
25. assign end_shake_cnt = add_shake_cnt  && shake_cnt == TIME_20MS-1 ;  
26.   
27.   
28. always  @(posedge clk or negedge rst_n)begin  
29.     if(rst_n==1'b0)begin  
30.         state_c <= CHK_COL;  
31.     end  
32.     else begin  
33.         state_c <= state_n;  
34.     end  
35. end  
36.   
37. always  @(*)begin  
38.     case(state_c)  
39.         CHK_COL: begin  
40.                      if(col2row_start )begin  
41.                          state_n = CHK_ROW;  
42.                      end  
43.                      else begin  
44.                          state_n = CHK_COL;  
45.                      end  
46.                  end  
47.         CHK_ROW: begin  
48.                      if(row2del_start)begin  
49.                          state_n = DELAY;  
50.                      end  
51.                      else begin  
52.                          state_n = CHK_ROW;  
53.                      end  
54.                  end  
55.         DELAY :  begin  
56.                      if(del2wait_start)begin  
57.                          state_n = WAIT_END;  
58.                      end  
59.                      else begin  
60.                          state_n = DELAY;  
61.                      end  
62.                  end  
63.         WAIT_END: begin  
64.                      if(wait2col_start)begin  
65.                          state_n = CHK_COL;  
66.                      end  
67.                      else begin  
68.                          state_n = WAIT_END;  
69.                      end  
70.                   end  
71.        default: state_n = CHK_COL;  
72.     endcase  
73. end  
74. assign col2row_start = state_c==CHK_COL  && end_shake_cnt;  
75. assign row2del_start = state_c==CHK_ROW  && row_index==3 && end_row_cnt;  
76. assign del2wait_start= state_c==DELAY    && end_row_cnt;  
77. assign wait2col_start= state_c==WAIT_END && key_col_ff1==4'hf;  
78.   
79. always  @(posedge clk or negedge rst_n)begin  
80.     if(rst_n==1'b0)begin  
81.         key_row <= 4'b0;  
82.     end  
83.     else if(state_c==CHK_ROW)begin  
84.         key_row <= ~(1'b1 << row_index);  
85.     end  
86.     else begin  
87.         key_row <= 4'b0;  
88.     end  
89. end  
90.   
91.   
92. always @(posedge clk or negedge rst_n) begin   
93.     if (rst_n==0) begin  
94.         row_index <= 0;   
95.     end  
96.     else if(add_row_index) begin  
97.         if(end_row_index)  
98.             row_index <= 0;   
99.         else  
100.             row_index <= row_index+1 ;  
101.    end  
102.    else if(state_c!=CHK_ROW)begin  
103.        row_index <= 0;  
104.    end  
105. end  
106. assign add_row_index = state_c==CHK_ROW && end_row_cnt;  
107. assign end_row_index = add_row_index  && row_index == 4-1 ;  
108.   
109.   
110. always @(posedge clk or negedge rst_n) begin   
111.     if (rst_n==0) begin  
112.         row_cnt <= 0;   
113.     end  
114.     else if(add_row_cnt) begin  
115.         if(end_row_cnt)  
116.             row_cnt <= 0;   
117.         else  
118.             row_cnt <= row_cnt+1 ;  
119.    end  
120. end  
121. assign add_row_cnt = state_c==CHK_ROW || state_c==DELAY;  
122. assign end_row_cnt = add_row_cnt  && row_cnt == 16-1 ;  
123.   
124.   
125. always  @(posedge clk or negedge rst_n)begin  
126.     if(rst_n==1'b0)begin  
127.         key_col_get <= 0;  
128.     end  
129.     else if(state_c==CHK_COL && end_shake_cnt ) begin  
130.         if(key_col_ff1==4'b1110)  
131.             key_col_get <= 0;  
132.         else if(key_col_ff1==4'b1101)  
133.             key_col_get <= 1;  
134.         else if(key_col_ff1==4'b1011)  
135.             key_col_get <= 2;  
136.         else   
137.             key_col_get <= 3;  
138.     end  
139. end  
140.   
141.   
142. always  @(posedge clk or negedge rst_n)begin  
143.     if(rst_n==1'b0)begin  
144.         key_out <= 0;  
145.     end  
146.     else if(state_c==CHK_ROW && end_row_cnt)begin  
147.         key_out <= {row_index,key_col_get};  
148.     end  
149.     else begin  
150.         key_out <= 0;  
151.     end  
152. end  
153.   
154. always  @(posedge clk or negedge rst_n)begin  
155.     if(rst_n==1'b0)begin  
156.         key_vld <= 1'b0;  
157.     end  
158.     else if(state_c==CHK_ROW && end_row_cnt && key_col_ff1[key_col_get]==1'b0)begin  
159.         key_vld <= 1'b1;  
160.     end  
161.     else begin  
162.         key_vld <= 1'b0;  
163.     end  
164. end  
165.   
166.   
167. always  @(*)begin  
168.     if(rst_n==1'b0)begin  
169.         key_en = 0;  
170.     end  
171.     else if(key_vld && key_out==0)begin  
172.         key_en = 4'b0001;  
173.     end  
174.     else if(key_vld && key_out==1)begin  
175.         key_en = 4'b0010;  
176.     end  
177.     else if(key_vld && key_out==2)begin  
178.         key_en = 4'b0100;  
179.     end  
180.     else begin  
181.         key_en = 0;  
182.     end  
183. end

1.4 時(shí)間產(chǎn)生模塊設(shè)計(jì)

1.4.1 接口信號(hào)



1.4.2 設(shè)計(jì)思路

根據(jù)題目功能要求可知,要顯示的時(shí)間就是在完整的數(shù)字時(shí)鐘的基礎(chǔ)上,減少了時(shí)的高位和低位

的顯示,再介紹架構(gòu)之前,先了解一下本模塊其他幾個(gè)信號(hào)的作用。

設(shè)置狀態(tài)指示信號(hào) flag_set:該信號(hào)初始狀態(tài)為低電平,表示模塊處于正常工作狀態(tài),當(dāng)按下按

鍵 key1 時(shí),設(shè)置狀態(tài)指示信號(hào)進(jìn)行翻轉(zhuǎn),變?yōu)楦唠娖?,表示進(jìn)入到設(shè)置狀態(tài)。

設(shè)置位計(jì)數(shù)器 sel_cnt:該計(jì)數(shù)器表示要設(shè)置的位,初始狀態(tài)為 0,表示可以設(shè)置鬧鐘的秒低位,

當(dāng)其為 1 時(shí)表示可以設(shè)置鬧鐘的秒的高位,按照這樣的順序依次類推,當(dāng)其為 7 的時(shí)候,表示可以設(shè)

置顯示時(shí)間的分高位。加一條件為 key_vld[1]==1'b1,表示按下按鍵 key2 的時(shí)候加一;結(jié)束條件為 8,

顯示時(shí)間的四個(gè)數(shù)碼管加上鬧鐘的四個(gè)數(shù)碼管共 8 個(gè),所以數(shù) 8 個(gè)就清零。

由此可提出 5 個(gè)計(jì)數(shù)器的架構(gòu),如下圖所示:



該架構(gòu)由 5 個(gè)計(jì)數(shù)器組成:時(shí)鐘計(jì)數(shù)器 counter、秒低位計(jì)數(shù)器 xs_sec_low、秒高位計(jì)數(shù)器 xs

_sec_high、分低位計(jì)數(shù)器 xs_min_low、分高位計(jì)數(shù)器 xs_min_high。

時(shí)鐘計(jì)數(shù)器 counter:用于計(jì)算 1 秒的時(shí)鐘個(gè)數(shù),加一條件為 flag_set==1'b0,表示剛上電時(shí)開

始計(jì)數(shù),key1 按下之后,進(jìn)入設(shè)置模式,停止計(jì)數(shù),再按下又重新開始計(jì)數(shù);結(jié)束條件為 5000000

0,表示數(shù)到 1 秒就清零。

秒低位計(jì)數(shù)器 xs_sec_low:用于對(duì) 1 秒進(jìn)行計(jì)數(shù),加一條件為(sel_cnt==5-1 && set_en) || e

nd_counter,表示在設(shè)置狀態(tài)下可通過按鍵 key3 來控制加一,或者在正常狀態(tài)時(shí)數(shù)到 1 秒就加 1;

結(jié)束條件為 10,表示數(shù)到 10 秒就清零。

秒高位計(jì)數(shù)器 xs_sec_high:用于對(duì) 10 秒進(jìn)行計(jì)數(shù),加一條件為(sel_cnt==6-1 && set_en) ||

end_xs_sec_low,表示在設(shè)置狀態(tài)下可通過按鍵 key3 來控制加一,或者在正常狀態(tài)時(shí)數(shù)到 10 秒就

加 1;結(jié)束條件為 6,表示數(shù)到 60 秒就清零。

分低位計(jì)數(shù)器 xs_min_low:用于對(duì) 1 分進(jìn)行計(jì)數(shù),加一條件為(sel_cnt==7-1 && set_en) || e

nd_xs_sec_high,表示在設(shè)置狀態(tài)下可通過按鍵 key3 來控制加一,或者在正常狀態(tài)時(shí)數(shù)到 1 分就加

1;結(jié)束條件為 10,表示數(shù)到 10 分就清零。

分高位計(jì)數(shù)器 xs_min_high:用于對(duì) 10 分進(jìn)行計(jì)數(shù),加一條件為(sel_cnt==8-1 && set_en) ||

end_xs_min_low,表示在設(shè)置狀態(tài)下可通過按鍵 key3 來控制加一,或者在正常狀態(tài)時(shí)數(shù)到 10 分就

加 1;結(jié)束條件為 6,表示數(shù)到 60 分就清零。

上面介紹了顯示時(shí)間的計(jì)數(shù)器架構(gòu),下面我們來思考一下鬧鐘部分的架構(gòu)。

我們都知道鬧鐘的工作原理,它本身不會(huì)自動(dòng)計(jì)數(shù),需要我們手動(dòng)設(shè)置。根據(jù)本設(shè)計(jì)的功能要求,

有四個(gè)數(shù)碼管來顯示設(shè)置的鬧鐘秒的高低位和分的高低位,因此我們提出四個(gè)計(jì)數(shù)器組成的架構(gòu),這


四個(gè)計(jì)數(shù)器相互獨(dú)立,互不干涉,結(jié)構(gòu)圖如下:

該架構(gòu)由 4 個(gè)計(jì)數(shù)器組成:秒低位計(jì)數(shù)器 sec_low、秒高位計(jì)數(shù)器 sec_high、分低位計(jì)數(shù)器 mi

n_low、分高位計(jì)數(shù)器 min_high。

秒低位計(jì)數(shù)器 sec_low:用于對(duì)鬧鐘秒的低位進(jìn)行計(jì)數(shù),加一條件為 sel_cnt==1-1 && set_en,

表示在設(shè)置狀態(tài)下通過按鍵 key3 來控制加一 ;結(jié)束條件為 10,表示最大能設(shè)置為 9,超過之后便

清零。

秒高位計(jì)數(shù)器 sec_high:用于對(duì)鬧鐘秒的高位進(jìn)行計(jì)數(shù),加一條件為 sel_cnt==2-1 && set_en,

表示在設(shè)置狀態(tài)下可通過按鍵 key3 來控制加一;結(jié)束條件為 6,表示最大能設(shè)置為 5,超過之后便

清零。

分低位計(jì)數(shù)器 min_low:用于對(duì)鬧鐘分的低位進(jìn)行計(jì)數(shù),加一條件為 sel_cnt==3-1 && set_en,

表示在設(shè)置狀態(tài)下可通過按鍵 key3 來控制加一;結(jié)束條件為 10,表示最大能設(shè)置為 9,超過之后便

清零。

分高位計(jì)數(shù)器 min_high:用于對(duì)鬧鐘分高位進(jìn)行計(jì)數(shù),加一條件為 sel_cnt==4-1 && set_en,

表示在設(shè)置狀態(tài)下可通過按鍵 key3 來控制加一;結(jié)束條件為 6,表示最大能設(shè)置為 5,超過之后便

清零。


1.4.3 參考代碼

使用明德?lián)P的計(jì)數(shù)器模板,可以很快速很熟練地寫出時(shí)間產(chǎn)生模塊。

always  @(posedge clk or negedge rst_n)begin
2.     if(rst_n==1'b0)begin
3.         flag_set<=1'b0;
4.     end
5.     else if(key_vld[0]==1'b1)begin
6.         flag_set<=~flag_set;
7.     end
8.     else begin
9.         flag_set<=flag_set;
10.     end
11. end
12.
13.
14. always @(posedge clk or negedge rst_n) begin 
15.     if (rst_n==0) begin
16.         sel_cnt <= 0; 
17.     end
18.     else if(add_sel_cnt) begin
19.         if(end_sel_cnt)
20.             sel_cnt <= 0; 
21.         else
22.             sel_cnt <= sel_cnt+1 ;
23.    end
24. end
25. assign add_sel_cnt = key_vld[1]==1'b1;
26. assign end_sel_cnt = add_sel_cnt  && sel_cnt == 8-1 ;
27.
28.
29. always  @(posedge clk or negedge rst_n)begin
30.     if(rst_n==1'b0)begin
31.         set_en<=1'b0;
32.     end
33.     else if(flag_set==1'b1 && key_vld[2]==1'b1)begin
34.         set_en<=1'b1;
35.     end
36.     else begin
37.         set_en<=1'b0;
38.     end
39. end
40.
41.
42. always @(posedge clk or negedge rst_n) begin 
43.     if (rst_n==0) begin
44.         counter <= 0; 
45.     end
46.     else if(add_counter) begin
47.         if(end_counter)
48.             counter <= 0; 
49.         else
50.             counter <= counter+1 ;
51.    end
52. end
53. assign add_counter = flag_set==1'b0;
54. assign end_counter = add_counter  && counter == 26'd5000_0000-1;
55.
56.
57. always @(posedge clk or negedge rst_n) begin 
58.     if (rst_n==0) begin
59.         sec_low <= 0; 
60.     end
61.     else if(add_sec_low) begin
62.         if(end_sec_low)
63.             sec_low <= 0; 
64.         else
65.             sec_low <= sec_low+1 ;
66.    end
67. end
68. assign add_sec_low = sel_cnt==1-1 && set_en;
69. assign end_sec_low = add_sec_low  && sec_low == 10-1 ;
70.
71.
72. always @(posedge clk or negedge rst_n) begin 
73.     if (rst_n==0) begin
74.         sec_high <= 0; 
75.     end
76.     else if(add_sec_high) begin
77.         if(end_sec_high)
78.             sec_high <= 0; 
79.         else
80.             sec_high <= sec_high+1 ;
81.    end
82. end
83. assign add_sec_high = sel_cnt==2-1 && set_en;
84. assign end_sec_high = add_sec_high  && sec_high == 6-1 ;
85.
86.
87. always @(posedge clk or negedge rst_n) begin 
88.     if (rst_n==0) begin
89.         min_low <= 0; 
90.     end
91.     else if(add_min_low) begin
92.         if(end_min_low)
93.             min_low <= 0; 
94.         else
95.             min_low <= min_low+1 ;
96.    end
97. end
98. assign add_min_low = sel_cnt==3-1 && set_en;
99. assign end_min_low = add_min_low  && min_low == 10-1 ;
100.
101. always @(posedge clk or negedge rst_n) begin 
102.     if (rst_n==0) begin
103.         min_high <= 0; 
104.     end
105.     else if(add_min_high) begin
106.         if(end_min_high)
107.             min_high <= 0; 
108.         else
109.             min_high <= min_high+1 ;
110.    end
111. end
112. assign add_min_high = sel_cnt==4-1 && set_en;
113. assign end_min_high = add_min_high  && min_high == 6-1 ;
114.
115.
116. always @(posedge clk or negedge rst_n) begin 
117.     if (rst_n==0) begin
118.         xs_sec_low <= 0; 
119.     end
120.     else if(add_xs_sec_low) begin
121.         if(end_xs_sec_low)
122.             xs_sec_low <= 0; 
123.         else
124.             xs_sec_low <= xs_sec_low+1 ;
125.    end
126. end
127. assign add_xs_sec_low = (sel_cnt==5-1 && set_en) || end_counter;
128. assign end_xs_sec_low = add_xs_sec_low && xs_sec_low == 10-1 ;
129.
130.
131. always @(posedge clk or negedge rst_n) begin 
132.     if (rst_n==0) begin
133.         xs_sec_high <= 0; 
134.     end
135.     else if(add_xs_sec_high) begin
136.         if(end_xs_sec_high)
137.             xs_sec_high <= 0; 
138.         else
139.             xs_sec_high <= xs_sec_high+1 ;
140.    end
141. end
142. assign add_xs_sec_high = (sel_cnt==6-1 && set_en) || end_xs_sec_low;
143. assign end_xs_sec_high = add_xs_sec_high  && xs_sec_high == 6-1 ;
144.
145.
146. always @(posedge clk or negedge rst_n) begin 
147.     if (rst_n==0) begin
148.         xs_min_low <= 0; 
149.     end
150.     else if(add_xs_min_low) begin
151.         if(end_xs_min_low)
152.             xs_min_low <= 0; 
153.         else
154.             xs_min_low <= xs_min_low+1 ;
155.    end
156. end
157. assign add_xs_min_low = (sel_cnt==7-1 && set_en) || end_xs_sec_high;
158. assign end_xs_min_low = add_xs_min_low  && xs_min_low == 10-1 ;
159.
160.
161. always @(posedge clk or negedge rst_n) begin 
162.     if (rst_n==0) begin
163.         xs_min_high <= 0; 
164.     end
165.     else if(add_xs_min_high) begin
166.         if(end_xs_min_high)
167.             xs_min_high <= 0; 
168.         else
169.             xs_min_high <= xs_min_high+1 ;
170.    end
171. end
172. assign add_xs_min_high = (sel_cnt==8-1 && set_en) || end_xs_min_low;
173. assign end_xs_min_high = add_xs_min_high  && xs_min_high == 6-1 ;

1.5 數(shù)碼管顯示模塊設(shè)計(jì)


1.5.1 接口信號(hào)



1.5.2 設(shè)計(jì)思路

在前面的案例中已經(jīng)有數(shù)碼管顯示的介紹,所以這里不在過多介紹,詳細(xì)介紹請(qǐng)看下方鏈接:

http://fpgabbs.com/forum.php?mod=viewthread&tid=399

1.5.3 參考代碼

174.	always @(posedge clk or negedge rst_n) begin 
175.     if (rst_n==0) begin
176.         delay <= 0; 
177.     end
178.     else if(add_delay) begin
179.         if(end_delay)
180.             delay <= 0; 
181.         else
182.             delay <= delay+1 ;
183.    end
184. end
185. assign add_delay = 1;
186. assign end_delay = add_delay  && delay == 2000-1 ;
187.
188.
189.
190.
191. always @(posedge clk or negedge rst_n) begin 
192.     if (rst_n==0) begin
193.         delay_time <= 0; 
194.     end
195.     else if(add_delay_time) begin
196.         if(end_delay_time)
197.             delay_time <= 0; 
198.         else
199.             delay_time <= delay_time+1 ;
200.    end
201. end
202. assign add_delay_time = end_delay;
203. assign end_delay_time = add_delay_time  && delay_time == 8-1 ;
204.
205.
206. assign segment_tmp  = segment_data[(1+delay_time)*4-1 -:4];
207. always  @(posedge clk or negedge rst_n)begin
208.     if(rst_n==1'b0)begin
209.         segment <= ZERO;
210.     end
211.     else begin
212.         case(segment_tmp)
213.             4'd0:segment <= ZERO;
214.             4'd1:segment <= ONE  ;
215.             4'd2:segment <= TWO  ;
216.             4'd3:segment <= THREE;
217.             4'd4:segment <= FOUR ;
218.             4'd5:segment <= FIVE ;
219.             4'd6:segment <= SIX  ;
220.             4'd7:segment <= SEVEN;
221.             4'd8:segment <= EIGHT;
222.             4'd9:segment <= NINE ;
223.             default:begin
224.                 segment <= segment;
225.             end
226.         endcase
227.     end
228. end
229.
230.
231. always  @(posedge clk or negedge rst_n)begin
232.     if(rst_n==1'b0)begin
233.         seg_sel <= 8'b1111_1111;
234.     end
235.     else begin
236.         seg_sel <= ~(8'b1<<delay_time);
237.     end
238. end

1.6 蜂鳴器模塊設(shè)計(jì)

1.6.1 接口信號(hào)



1.6.2 設(shè)計(jì)思路

本模塊主要通過將顯示時(shí)間與設(shè)置的鬧鐘時(shí)間進(jìn)行比較,如果相同的話,就控制 beep 拉低,持

續(xù)時(shí)間為 5 秒。由此提出一個(gè)計(jì)數(shù)器的架構(gòu),如下圖所示。



該架構(gòu)由蜂鳴器控制信號(hào) beep、秒計(jì)數(shù)器 miao 和鬧鐘觸發(fā)指示信號(hào) flag_add 組成。

秒計(jì)數(shù)器秒:用于對(duì) 5 秒的時(shí)間進(jìn)行計(jì)數(shù),加一條件為 flag_add && end_counter,表示當(dāng)鬧

鐘被觸發(fā),并且經(jīng)過 1 秒的時(shí)間就加一;結(jié)束條件為 5,表示數(shù)完 5 秒就清零。

鬧鐘觸發(fā)指示信號(hào) flag:當(dāng)其為高電平時(shí)表示鬧鐘被觸發(fā),低電平表示沒有被觸發(fā)。初始狀態(tài)為

低電平,從低變高的條件為 sec_low==xs_sec_low&&sec_high==xs_sec_high&&min_low==xs_min

_low&&min_high==xs_min_high&&init&&!key1_func,表示當(dāng)顯示時(shí)間的秒高低位、分高低位和鬧鐘

設(shè)置的秒高低位、分高低位相等,同時(shí)不處于剛上電的初始狀態(tài)和設(shè)置狀態(tài)時(shí),鬧鐘被觸發(fā);從高變

低的條件為 end_miao,表示當(dāng) 5 秒數(shù)完之后,就拉低。

蜂鳴器控制信號(hào) beep:當(dāng)其為低電平時(shí),控制蜂鳴器響,為高電平時(shí)不響。初始狀態(tài)為高電平,

從高變低的條件為 flag_add,表示計(jì)數(shù)器開始計(jì)數(shù)之后便將其拉低,當(dāng)檢測到 flag_add=0 的時(shí)候,

便將其拉高。

1.6.3 參考代碼

239.	always  @(posedge clk or negedge rst_n)begin
240.     if(rst_n==1'b0)begin
241.         flag_add <= 0;
242.     end
243.     else if(sec_low==xs_sec_low&&sec_high==xs_sec_high&&min_low==xs_min_low&&min_high==xs_min_high&&init&&flag_set==0)begin
244.         flag_add <= 1;
245.     end
246.     else if(end_miao)begin
247.         flag_add <= 0;
248.     end
249. end
250.
251.
252. always@(*)begin
253.     if(!sec_low&&!sec_high&&!min_low&&!min_high)begin
254.         init=0;
255.     end
256.     else begin
257.         init=1;
258.     end
259. end
260.
261.
262. always @(posedge clk or negedge rst_n) begin 
263.     if (rst_n==0) begin
264.         miao <= 0; 
265.     end
266.     else if(add_miao) begin
267.         if(end_miao)
268.             miao <= 0; 
269.         else
270.             miao <= miao+1 ;
271.    end
272. end
273. assign add_miao = flag_add && end_counter;
274. assign end_miao = add_miao  && miao == 5-1 ;
275.
276.
277. always@(posedge clk or negedge rst_n)begin
278.      if(rst_n==1'b0)begin
279.         beep<=1'b1;
280.     end
281.     else if(flag_add)begin
282.         beep<=1'b0;
283.     end
284.     else
285.         beep<=1'b1;
286. end


1.7 效果和總結(jié)

? 下圖是該工程在 mp801 開發(fā)板上的現(xiàn)象

其中按鍵 s4 控制數(shù)字時(shí)鐘的暫停與開始,按鍵 s3 來選擇需要設(shè)置的位,按鍵 s2 設(shè)置數(shù)值。左

邊四個(gè)數(shù)碼管顯示的是時(shí)鐘的時(shí)間,右邊四個(gè)數(shù)碼管顯示的是鬧鐘設(shè)置的時(shí)間。



? 下圖是該工程在 db603 開發(fā)板上的現(xiàn)象

其中按鍵 s1 控制數(shù)字時(shí)鐘的暫停與開始,按鍵 s2 來選擇需要設(shè)置的位,按鍵 s3 設(shè)置數(shù)值。左

邊四個(gè)數(shù)碼管顯示的是時(shí)鐘的時(shí)間,右邊四個(gè)數(shù)碼管顯示的是鬧鐘設(shè)置的時(shí)間。



? 下圖是該工程在 ms980 試驗(yàn)箱上的現(xiàn)象

其中按鍵 s1 控制數(shù)字時(shí)鐘的暫停與開始,按鍵 s2 來選擇需要設(shè)置的位,按鍵 s3 設(shè)置數(shù)值。左

邊四個(gè)數(shù)碼管顯示的是時(shí)鐘的時(shí)間,右邊四個(gè)數(shù)碼管顯示的是鬧鐘設(shè)置的時(shí)間。



由于該項(xiàng)目的上板現(xiàn)象是動(dòng)態(tài)的,開始、暫停、時(shí)間設(shè)置等現(xiàn)象無法通過圖片表現(xiàn)出來,想觀看

完整現(xiàn)象的朋友可以看一下現(xiàn)象演示的視頻。

溫馨提示:明德?lián)P2023推出了全新課程——邏輯設(shè)計(jì)基本功修煉課,降低學(xué)習(xí)FPGA門檻的同時(shí),增加了學(xué)習(xí)的趣味性,并組織了考試贏積分活動(dòng)

http://m.cqqtmy.cn/ffkc/415.html

(點(diǎn)擊→了解課程詳情?)感興趣請(qǐng)聯(lián)系易老師:13112063618(微信同步)



本文TAG:

Copyright ? 2012-2023 版權(quán)所有:深圳明德?lián)P科技教育有限公司

主站蜘蛛池模板: 一个色综合网 | 精品国精品自拍自在线 | 久久久久久国产精品mv | 欧美精品在线观看视频 | 啪一啪在线 | 成人精品一区二区www | 婷婷影院在线综合免费视频 | 三级毛片黄色 | 99久久精品毛片免费播放 | 国产一区二区高清视频 | 男女性高爱潮免费网站 | 最近中国免费高清观看 | 国产理论视频在线观看 | 精品国产成人a在线观看 | 日韩在线观看一区二区不卡视频 | 中国hd高清╳xxx | 小明成人免费视频 | 91拍拍在线观看 | 免费人成年短视频在线观看免费网站 | 亚州精品一区二区三区 | 免费看黄色网址 | 国产免费又色又爽又黄在线观看 | 午夜激情福利视频 | 国产精品久久成人影院 | 丁香天堂网| www.日韩视频 | 2022年国产精品久久久久 | 爱爱小视频在线观看 | 亲子乱子xxxxxx | 色青青草原桃花久久综合 | 50-60岁老妇女一级毛片 | 国产成人久久精品区一区二区 | 啪啪天堂 | 国产精品国产香蕉在线观看网 | 五月丁六月停停 | 久久精品视频在线播放 | 亚洲国产第一区二区三区 | 国产三级日本三级日产三 | 国产freexxxx性播放麻豆 | 日韩欧美二区在线观看 | 日本第一次处毛片 |