数码管电子时钟
文章目錄
- 前言
- 一、回顧數碼管
- 二、任務描述
- 三、系統框圖
- 四、模塊調用
- 五、模塊原理圖
- 六、工程源碼
- 6.2 時鐘計數模塊代碼
- 6.2 數碼管驅動模塊代碼
- 6.3 頂層模塊代碼
- 七、仿真測試
- 7.1 測試代碼
- 7.2 仿真結果
- 八、管腳信息
- 九、運行效果
- 總結
前言
一、回顧數碼管
??Cyclone IV開發板上的數碼管一共有6個,我們每次只能選擇其中一個顯示,怎么解決電子時鐘時、分、秒同時顯示呢?要實現電子時鐘首先要了解什么是余暉效應。
??余暉效應一般指視覺暫留。 視覺暫留現象即視覺暫停現象(Persistence of vision,Visual staying phenomenon,duration of vision)又稱“余暉效應”。只要數碼管位選信號切換得足夠快,數碼管由亮到滅這一過程是需要一段時間的,由于時間很短,我們的眼睛是沒有辦法分清此時此刻數碼管的狀態,給人的感覺就是數碼管是一直亮的。以此來達到欺騙人眼的效果,這樣就可以實現同時顯示時、分、秒。
二、任務描述
??使用數碼管設計電子時鐘,計數器部分有3種實現方法:
- 方法1:計數器個數少,設計簡單,但是后面數碼管譯碼時,需要對計數值取余、取整,分離出時、分、秒的個位和十位,比較耗費組合邏輯資源;
- 方法2:3個計數器,后面數碼管譯碼時,需要對時、分、秒計數值取余、取整,分離出時、分、秒的個位和十位,比較耗費組合邏輯資源;
- 方法3:6個計數器,相對復雜一點,但是計數值直接就是時、分、秒的個位和十位值,不需要除法器進行取余、取整操作,使用的觸發器資源略多,但節省組合邏輯資源。
??本實驗使用方法1,其他方法同學們可以自行嘗試。
??我們最后實現的效果如圖2所示,由于開發板上的數碼管沒有冒號(:),所以我們直接忽略冒號。
三、系統框圖
- 計數器模塊:產生時、分、秒計數值;
- 數碼管驅動模塊:對時、分、秒計數值進行譯碼,產生驅動數碼管動態顯示數字的位選信號和段選信號。
四、模塊調用
圖4. 模塊關系示意圖五、模塊原理圖
圖5. 模塊原理圖六、工程源碼
6.2 時鐘計數模塊代碼
module counter(input wire clk ,//時鐘input wire rst_n,//復位信號output reg [4:0] hour ,//小時output reg [5:0] min ,//分鐘output reg [5:0] sec//秒);parameter MAX_NUM = 26'd49_999_999;//1s parameter TOTAL_SEC = 17'd86399 ;//24x60x60s reg [25:0] cnt_sec ;//秒計數器 reg [16:0] cnt_time;//計時器//計時1s秒鐘模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_sec <= 26'd0;end else if(cnt_sec == MAX_NUM)begincnt_sec <= 26'd0;end else begincnt_sec <= cnt_sec + 1'd1;end end //時間模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_time <= 17'd0;end else if(cnt_time == TOTAL_SEC && cnt_sec == MAX_NUM)begincnt_time <= 17'd0;end else if(cnt_sec == MAX_NUM)begincnt_time <= cnt_time + 1'd1;end else begincnt_time <= cnt_time;end end //取出時分秒模塊 always@(*)beginhour = cnt_time / 12'd3600 ;//小時min = (cnt_time % 12'd3600) / 6'd60;//分鐘sec = (cnt_time % 12'd3600) % 6'd60;//秒 end endmodule6.2 數碼管驅動模塊代碼
module seg_driver(input wire clk ,//時鐘input wire rst_n,//復位信號input wire [4:0] hour ,//小時input wire [5:0] min ,//分鐘input wire [5:0] sec ,//秒output reg [5:0] seg_sel,output reg [7:0] seg_ment );parameter CNT_20US = 10'd999;//20微秒 wire [3:0] sec_low ;//秒的低位 wire [2:0] sec_high ;//秒的高位 wire [3:0] min_low ;//分鐘的低位 wire [2:0] min_high ;//分鐘的高位 wire [1:0] hour_low ;//小時的低位 wire [1:0] hour_high;//小時的高位 reg [9:0] cnt ;//計數器,計20us時間 reg [3:0] number ;//顯示時分秒寄存器//計時模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt <= 10'd0; end else if(cnt == CNT_20US)begincnt <= 10'd0;end else begincnt <= cnt + 1'd1;end end //位選信號切換模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)beginseg_sel <= 6'b011111;//初始化第一個數碼管亮end else if(cnt == CNT_20US)beginseg_sel <= {seg_sel[0],seg_sel[5:1]};//每隔20us進行位移操作end else beginseg_sel <= seg_sel;//其他時間保持不變end end //位選信號譯碼模塊 always@(*)begincase(seg_sel)6'b011111: number = sec_low ;//秒的低位給第一個數碼管顯示6'b101111: number = sec_high ;//秒的高位給第二個數碼管顯示6'b110111: number = min_low ;//分鐘的低位給第三個數碼管顯示6'b111011: number = min_high ;//分鐘的高位給第四個數碼管顯示6'b111101: number = hour_low ;//小時的低位給第五個數碼管顯示6'b111110: number = hour_high;//小時的高位給第六個數碼管顯示default: number = sec_low ;endcase end //段選信號譯碼模塊 always@(posedge clk or negedge rst_n)beginif(!rst_n)beginseg_ment <= 8'b1100_0000;//初始化顯示0endelse begincase(number)4'd0: seg_ment <= 8'b1100_0000;//數碼管顯示04'd1: seg_ment <= 8'b1111_1001;//數碼管顯示14'd2: seg_ment <= 8'b1010_0100;//數碼管顯示24'd3: seg_ment <= 8'b1011_0000;//數碼管顯示34'd4: seg_ment <= 8'b1001_1001;//數碼管顯示44'd5: seg_ment <= 8'b1001_0010;//數碼管顯示54'd6: seg_ment <= 8'b1000_0010;//數碼管顯示64'd7: seg_ment <= 8'b1111_1000;//數碼管顯示74'd8: seg_ment <= 8'b1000_0000;//數碼管顯示84'd9: seg_ment <= 8'b1001_0000;//數碼管顯示9default: seg_ment <= 8'b1100_0000;//數碼管顯示0endcase end end assign sec_low = sec % 4'd10 ;//秒的低位如59秒--->9 assign sec_high = sec / 4'd10 ;//秒的高位如59秒--->5 assign min_low = min % 4'd10 ;//分鐘的低位如59--->9 assign min_high = min / 4'd10 ;//分鐘的高位如59--->5 assign hour_low = hour % 4'd10;//小時的低位如23--->3 assign hour_high = hour / 4'd10;//小時的高位如23--->2 endmodule6.3 頂層模塊代碼
module digital_clock(input wire clk ,//時鐘input wire rst_n,//復位信號output wire [5:0] seg_sel,//數碼管位選信號output wire [7:0] seg_ment//數碼管段選信號); parameter MAX_NUM = 26'd49_999_999;//1s parameter TOTAL_SEC = 17'd86399 ;//60x24x24s parameter CNT_20US = 10'd999 ;//20us wire [4:0] hour;//小時 wire [5:0] min ;//分鐘 wire [5:0] sec ;//秒 //實例化計數器模塊 counter#(.MAX_NUM(MAX_NUM),.TOTAL_SEC(TOTAL_SEC)) u_counter( .clk (clk) , .rst_n (rst_n),.hour (hour) , .min (min) , .sec (sec));//實例化數碼管驅動模塊 seg_driver#(.CNT_20US(CNT_20US)) u_seg_driver( .clk (clk) , .rst_n (rst_n) , .hour (hour) , .min (min) , .sec (sec) ,.seg_sel (seg_sel), .seg_ment (seg_ment) );endmodule七、仿真測試
7.1 測試代碼
`timescale 1ns/1ns module digital_clock_tb();parameter MAX_NUM = 26'd5 ;//100ns parameter TOTAL_SEC = 17'd100;//100x5x100ns parameter CNT_20US = 11'd1 ;//20ns,位選信號切換間隔 parameter CYCLE = 20 ;//20ns,模擬時鐘 reg clk ;//時鐘寄存器 reg rst_n;//復位寄存器wire [5:0] seg_sel ;//位選信號 wire [7:0] seg_ment;//段選信號always#(CYCLE/2) clk = ~clk;//模擬時鐘信號 //初始化 initial beginclk = 1'b0 ;//時鐘初始化為0rst_n = 1'b0 ;//復位信號初始化為0#(CYCLE) ;//延遲一個周期rst_n = 1'b1 ;//復位信號置1#(MAX_NUM * TOTAL_SEC * CYCLE);//延遲一段時間$stop ;//停止 end //實例化數字時鐘頂層模塊 digital_clock#(.MAX_NUM(MAX_NUM) ,.TOTAL_SEC(TOTAL_SEC),.CNT_20US(CNT_20US)) u_digital_clock( .clk (clk) ,//時鐘 .rst_n (rst_n) ,//復位信號.seg_sel (seg_sel),//數碼管位選信號 .seg_ment(seg_ment)//數碼管段選信號); endmodule7.2 仿真結果
圖6. 仿真結果八、管腳信息
| SEL0 | A4 |
| SEL1 | B4 |
| SEL2 | A3 |
| SEL3 | B3 |
| SEL4 | A2 |
| SEL5 | B1 |
| DIG0 | B7 |
| DIG1 | A8 |
| DIG2 | A6 |
| DIG3 | B5 |
| DIG4 | B6 |
| DIG5 | A7 |
| DIG6 | B8 |
| DIG7 | A5 |
| CLOCK(時鐘) | E1 |
| KEY1 | E15 |
九、運行效果
數碼管電子時鐘
總結
??電子時鐘是在數碼管動態顯示實驗基礎上開發的項目,只要你熟悉數碼管動態顯示項目流程,在開發電子時鐘的時候也會游刃有余。以上就是數碼管電子時鐘的全部內容,后期將推出什么是ip課程。敬請期待,謝謝你的觀看!
總結
- 上一篇: # 标题Windows最强神器,WIN+
- 下一篇: 电脑死机故障解决方法全面汇总