前言
本次實驗內(nèi)容承接上一篇文章數(shù)碼管電子時鐘,在此基礎(chǔ)上新增兩個功能:
1.設(shè)置時間
2.設(shè)置鬧鐘,到點響鈴
一丶需求分析
模塊:beep counter seg_driver top
其中:
1.設(shè)置時間
2.設(shè)置鬧鐘,到點響鈴
這兩個功能都整合在counter模塊,里面設(shè)置的重要信號如下所示
1.設(shè)置時間
我們需要利用開發(fā)板上的按鍵來設(shè)置時分秒HH:MM:SS
思路:Counter:
rst_n:復(fù)位按鍵 【相當(dāng)于開發(fā)板上的key1】
Key[0]:空閑狀態(tài)—電子時鐘 【相當(dāng)于開發(fā)板上的key1】
Key[1]:設(shè)置時間 【相當(dāng)于開發(fā)板上的key2】
Key[2]:設(shè)置鬧鐘 【相當(dāng)于開發(fā)板上的key3】
按鍵切換三個狀態(tài):
1.空閑狀態(tài)—就是一個時鐘
輸出dout_time給seg_driver模塊顯示時間
2.設(shè)置時間—設(shè)置當(dāng)前的時分秒,改一下幾個計時器里面的初值
修改counter里面的6個計時器的值,暫停計時
Key[0]:切換修改的時間位,切換到哪一位,哪一位閃爍 【相當(dāng)于開發(fā)板上的key2】
Key[1]:加1 【相當(dāng)于開發(fā)板上的key3】
Key[2]:確定–退出 【相當(dāng)于開發(fā)板上的key4】
3.設(shè)置鬧鐘—設(shè)置個條件,到幾時幾分幾秒蜂鳴器響
修改counter里面的6個計時器的值,暫停計時
Key[0]:切換修改的時間位,切換到哪一位,哪一位閃爍 【相當(dāng)于開發(fā)板上的key2】
Key[1]:加1 【相當(dāng)于開發(fā)板上的key3】
Key[2]:確定–退出(確定之后輸出dout_time給beep模塊作為響鈴時間) 【相當(dāng)于開發(fā)板上的key4】
2.設(shè)置鬧鐘
方式與設(shè)置時間基本完全一樣,區(qū)別在設(shè)置鬧鐘的時間不給電子時鐘,電子時鐘保持設(shè)置的時間計時
二丶工程源碼
1.counter
module counter (
input wire clk ,
input wire rst_n ,
input wire [2:0] key ,
output reg [19:0] dout_time , //輸出時間 HH:MM:SS
output wire beep_r
);
//計數(shù)器
reg [25:0] cnt ;
wire add_cnt;
wire end_cnt;
//S計時器
//個位 (0~9)
reg [3:0] cnt_s_bit;
wire add_cnt_s_bit;
wire end_cnt_s_bit;
reg [3:0] set_cnt_s_bit;
wire add_set_cnt_s_bit;
wire end_set_cnt_s_bit;
reg [3:0] clock_cnt_s_bit;
wire add_clock_cnt_s_bit;
wire end_clock_cnt_s_bit;
//十位 (0~5)
reg [2:0] cnt_s_ten;
wire add_cnt_s_ten;
wire end_cnt_s_ten;
reg [2:0] set_cnt_s_ten;
wire add_set_cnt_s_ten;
wire end_set_cnt_s_ten;
reg [2:0] clock_cnt_s_ten;
wire add_clock_cnt_s_ten;
wire end_clock_cnt_s_ten;
//M計時器
//個位 (0~9)
reg [3:0] cnt_m_bit;
wire add_cnt_m_bit;
wire end_cnt_m_bit;
reg [3:0] set_cnt_m_bit;
wire add_set_cnt_m_bit;
wire end_set_cnt_m_bit;
reg [3:0] clock_cnt_m_bit;
wire add_clock_cnt_m_bit;
wire end_clock_cnt_m_bit;
//十位 (0~5)
reg [2:0] cnt_m_ten;
wire add_cnt_m_ten;
wire end_cnt_m_ten;
reg [2:0] set_cnt_m_ten;
wire add_set_cnt_m_ten;
wire end_set_cnt_m_ten;
reg [2:0] clock_cnt_m_ten;
wire add_clock_cnt_m_ten;
wire end_clock_cnt_m_ten;
//H計時器
//個位 (0~9)
reg [3:0] cnt_h_bit;
wire add_cnt_h_bit;
wire end_cnt_h_bit;
reg [3:0] set_cnt_h_bit;
wire add_set_cnt_h_bit;
wire end_set_cnt_h_bit;
reg [3:0] clock_cnt_h_bit;
wire add_clock_cnt_h_bit;
wire end_clock_cnt_h_bit;
//十位 (0~2)
reg [1:0] cnt_h_ten;
wire add_cnt_h_ten;
wire end_cnt_h_ten;
reg [1:0] set_cnt_h_ten;
wire add_set_cnt_h_ten;
wire end_set_cnt_h_ten;
reg [1:0] clock_cnt_h_ten;
wire add_clock_cnt_h_ten;
wire end_clock_cnt_h_ten;
reg [3:0] cnt_flag;
reg [3:0] set_cnt_flag;
reg [3:0] clock_cnt_flag;
reg [2:0] state_c; //現(xiàn)態(tài)
reg [2:0] state_n; //次態(tài)
reg [5:0] select_seg; //在設(shè)置時間和設(shè)置鬧鐘的時候切換位選
wire [19:0] set_time_dout;
wire [19:0] idel_dout;
wire [19:0] clock_dout;
parameter MAX_CNT=26'd50_000_000;
//定義狀態(tài)
localparam IDEL =3'b001, //空閑狀態(tài)
SET_TIME =3'b010, //設(shè)置時間
SET_CLOCK=3'b100; //設(shè)置鬧鐘
//狀態(tài)轉(zhuǎn)移條件
wire idel_TO_set_time;
wire idel_TO_set_clock;
wire set_time_TO_idel;
wire set_clock_TO_idel;
//狀態(tài)機(jī)第一段--狀態(tài)轉(zhuǎn)移
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state_c<=IDEL;
end
else
state_c<=state_n;
end
//狀態(tài)機(jī)第二段--組合邏輯
always @(*) begin
case (state_c)
IDEL: begin
if (idel_TO_set_time) begin
state_n=SET_TIME;
end
else if(idel_TO_set_clock) begin
state_n=SET_CLOCK;
end
else
state_n=state_c;
end
SET_TIME: begin
if (set_time_TO_idel) begin
state_n=IDEL;
end
else
state_n=state_c;
end
SET_CLOCK: begin
if (set_clock_TO_idel) begin
state_n=IDEL;
end
else
state_n=state_c;
end
default :state_n=IDEL;
endcase
end
assign idel_TO_set_time=state_c==IDEL&&key[0];
assign idel_TO_set_clock=state_c==IDEL&&key[1];
assign set_time_TO_idel=state_c==SET_TIME&&key[2];
assign set_clock_TO_idel=state_c==SET_CLOCK&&key[2];
//select_seg
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
select_seg<=6'b000_000;
end
else if(idel_TO_set_time||idel_TO_set_clock) begin
select_seg<=6'b000_001;
end
else if((state_c==SET_TIME||state_c==SET_CLOCK)&&(key[0])) begin
select_seg<={select_seg[4:0],select_seg[5]};
end
end
//clock_cnt_s_bit clock_cnt_s_ten clock_cnt_m_bit clock_cnt_m_ten clock_cnt_h_bit clock_cnt_h_ten
//秒計數(shù)器---個位(0~9)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clock_cnt_s_bit<=0;
end
else if (add_clock_cnt_s_bit) begin
if (end_clock_cnt_s_bit) begin
clock_cnt_s_bit<=0;
end
else
clock_cnt_s_bit<=clock_cnt_s_bit+1;
end
end
assign add_clock_cnt_s_bit=state_c==SET_CLOCK&&select_seg==6'b000_001&&key[1];
assign end_clock_cnt_s_bit=add_clock_cnt_s_bit&&clock_cnt_s_bit==9||idel_TO_set_clock;
//秒計數(shù)器---十位(0~5)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clock_cnt_s_ten<=0;
end
else if (add_clock_cnt_s_ten) begin
if (end_clock_cnt_s_ten) begin
clock_cnt_s_ten<=0;
end
else
clock_cnt_s_ten<=clock_cnt_s_ten+1;
end
end
assign add_clock_cnt_s_ten=state_c==SET_CLOCK&&select_seg==6'b000_010&&key[1];
assign end_clock_cnt_s_ten=add_clock_cnt_s_ten&&clock_cnt_s_ten==5||idel_TO_set_clock;
//分計數(shù)器---個位(0~9)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clock_cnt_m_bit<=0;
end
else if (add_clock_cnt_m_bit) begin
if (end_clock_cnt_m_bit) begin
clock_cnt_m_bit<=0;
end
else
clock_cnt_m_bit<=clock_cnt_m_bit+1;
end
end
assign add_clock_cnt_m_bit=state_c==SET_CLOCK&&select_seg==6'b000_100&&key[1];
assign end_clock_cnt_m_bit=add_clock_cnt_m_bit&&clock_cnt_m_bit==9||idel_TO_set_clock;
//分計數(shù)器---十位(0~5)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clock_cnt_m_ten<=0;
end
else if (add_clock_cnt_m_ten) begin
if (end_clock_cnt_m_ten) begin
clock_cnt_m_ten<=0;
end
else
clock_cnt_m_ten<=clock_cnt_m_ten+1;
end
end
assign add_clock_cnt_m_ten=state_c==SET_CLOCK&&select_seg==6'b001_000&&key[1];
assign end_clock_cnt_m_ten=add_clock_cnt_m_ten&&clock_cnt_m_ten==5||idel_TO_set_clock;
//時計數(shù)器---個位(0~9)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clock_cnt_h_bit<=0;
end
else if (add_clock_cnt_h_bit) begin
if (end_clock_cnt_h_bit) begin
clock_cnt_h_bit<=0;
end
else
clock_cnt_h_bit<=clock_cnt_h_bit+1;
end
end
assign add_clock_cnt_h_bit=state_c==SET_CLOCK&&select_seg==6'b010_000&&key[1];
assign end_clock_cnt_h_bit=add_clock_cnt_h_bit&&clock_cnt_h_bit==clock_cnt_flag||idel_TO_set_clock;
//時計數(shù)器---十位(0~2)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clock_cnt_h_ten<=0;
end
else if (add_clock_cnt_h_ten) begin
if (end_clock_cnt_h_ten) begin
clock_cnt_h_ten<=0;
end
else
clock_cnt_h_ten<=clock_cnt_h_ten+1;
end
end
assign add_clock_cnt_h_ten=state_c==SET_CLOCK&&select_seg==6'b100_000&&key[1];
assign end_clock_cnt_h_ten=add_clock_cnt_h_ten&&clock_cnt_h_ten==2||idel_TO_set_clock;
//判斷小時計時器十位是否記到 2
always @(*) begin
if (clock_cnt_h_ten==2) begin
clock_cnt_flag=4'd3;
end
else
clock_cnt_flag=4'd9;
end
assign clock_dout={clock_cnt_h_ten,clock_cnt_h_bit,clock_cnt_m_ten,clock_cnt_m_bit,clock_cnt_s_ten,clock_cnt_s_bit};
///
///
//set_cnt_s_bit set_cnt_s_ten set_cnt_m_bit set_cnt_m_ten set_cnt_h_bit set_cnt_h_ten
//秒計數(shù)器---個位(0~9)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
set_cnt_s_bit<=0;
end
else if (add_set_cnt_s_bit) begin
if (end_set_cnt_s_bit) begin
set_cnt_s_bit<=0;
end
else
set_cnt_s_bit<=set_cnt_s_bit+1;
end
end
assign add_set_cnt_s_bit=state_c==SET_TIME&&select_seg==6'b000_001&&key[1];
assign end_set_cnt_s_bit=add_set_cnt_s_bit&&set_cnt_s_bit==9||idel_TO_set_time;
//秒計數(shù)器---十位(0~5)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
set_cnt_s_ten<=0;
end
else if (add_set_cnt_s_ten) begin
if (end_set_cnt_s_ten) begin
set_cnt_s_ten<=0;
end
else
set_cnt_s_ten<=set_cnt_s_ten+1;
end
end
assign add_set_cnt_s_ten=state_c==SET_TIME&&select_seg==6'b000_010&&key[1];
assign end_set_cnt_s_ten=add_set_cnt_s_ten&&set_cnt_s_ten==5||idel_TO_set_time;
//分計數(shù)器---個位(0~9)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
set_cnt_m_bit<=0;
end
else if (add_set_cnt_m_bit) begin
if (end_set_cnt_m_bit) begin
set_cnt_m_bit<=0;
end
else
set_cnt_m_bit<=set_cnt_m_bit+1;
end
end
assign add_set_cnt_m_bit=state_c==SET_TIME&&select_seg==6'b000_100&&key[1];
assign end_set_cnt_m_bit=add_set_cnt_m_bit&&set_cnt_m_bit==9||idel_TO_set_time;
//分計數(shù)器---十位(0~5)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
set_cnt_m_ten<=0;
end
else if (add_set_cnt_m_ten) begin
if (end_set_cnt_m_ten) begin
set_cnt_m_ten<=0;
end
else
set_cnt_m_ten<=set_cnt_m_ten+1;
end
end
assign add_set_cnt_m_ten=state_c==SET_TIME&&select_seg==6'b001_000&&key[1];
assign end_set_cnt_m_ten=add_set_cnt_m_ten&&set_cnt_m_ten==5||idel_TO_set_time;
//時計數(shù)器---個位(0~9)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
set_cnt_h_bit<=0;
end
else if (add_set_cnt_h_bit) begin
if (end_set_cnt_h_bit) begin
set_cnt_h_bit<=0;
end
else
set_cnt_h_bit<=set_cnt_h_bit+1;
end
end
assign add_set_cnt_h_bit=state_c==SET_TIME&&select_seg==6'b010_000&&key[1];
assign end_set_cnt_h_bit=add_set_cnt_h_bit&&set_cnt_h_bit==set_cnt_flag||idel_TO_set_time;
//時計數(shù)器---十位(0~2)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
set_cnt_h_ten<=0;
end
else if (add_set_cnt_h_ten) begin
if (end_set_cnt_h_ten) begin
set_cnt_h_ten<=0;
end
else
set_cnt_h_ten<=set_cnt_h_ten+1;
end
end
assign add_set_cnt_h_ten=state_c==SET_TIME&&select_seg==6'b100_000&&key[1];
assign end_set_cnt_h_ten=add_set_cnt_h_ten&&set_cnt_h_ten==2||idel_TO_set_time;
//判斷小時計時器十位是否記到 2
always @(*) begin
if (set_cnt_h_ten==2) begin
set_cnt_flag=4'd3;
end
else
set_cnt_flag=4'd9;
end
assign set_time_dout={set_cnt_h_ten,set_cnt_h_bit,set_cnt_m_ten,set_cnt_m_bit,set_cnt_s_ten,set_cnt_s_bit};
///
///
//計數(shù)器
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt<=0;
end
else if (add_cnt) begin
if (end_cnt) begin
cnt<=0;
end
else
cnt<=cnt+1;
end
end
assign add_cnt=state_c==IDEL||state_c==SET_CLOCK;
assign end_cnt=add_cnt&&(cnt==MAX_CNT-1||set_time_TO_idel);
//秒計時器---個位(0~9)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_s_bit<=1;
end
else if(set_time_TO_idel) begin
cnt_s_bit<=set_cnt_s_bit; //在設(shè)置時間確定之后將設(shè)置的值賦給計時器
end
else if (add_cnt_s_bit) begin
if (end_cnt_s_bit) begin
cnt_s_bit<=0;
end
else
cnt_s_bit<=cnt_s_bit+1;
end
end
assign add_cnt_s_bit=end_cnt;
assign end_cnt_s_bit=add_cnt_s_bit&&cnt_s_bit==9;
//秒計時器---十位(0~5)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_s_ten<=0;
end
else if(set_time_TO_idel) begin
cnt_s_ten<=set_cnt_s_ten;
end
else if (add_cnt_s_ten) begin
if (end_cnt_s_ten) begin
cnt_s_ten<=0;
end
else
cnt_s_ten<=cnt_s_ten+1;
end
end
assign add_cnt_s_ten=end_cnt_s_bit;
assign end_cnt_s_ten=add_cnt_s_ten&&cnt_s_ten==5;
//分計時器---個位(0~9)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_m_bit<=0;
end
else if(set_time_TO_idel) begin
cnt_m_bit<=set_cnt_m_bit;
end
else if (add_cnt_m_bit) begin
if (end_cnt_m_bit) begin
cnt_m_bit<=0;
end
else
cnt_m_bit<=cnt_m_bit+1;
end
end
assign add_cnt_m_bit=end_cnt_s_ten;
assign end_cnt_m_bit=add_cnt_m_bit&&cnt_m_bit==9;
//分計時器---十位(0~5)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_m_ten<=0;
end
else if(set_time_TO_idel) begin
cnt_m_ten<=set_cnt_m_ten;
end
else if (add_cnt_m_ten) begin
if (end_cnt_m_ten) begin
cnt_m_ten<=0;
end
else
cnt_m_ten<=cnt_m_ten+1;
end
end
assign add_cnt_m_ten=end_cnt_m_bit;
assign end_cnt_m_ten=add_cnt_m_ten&&cnt_m_ten==5;
//時計時器---個位(0~9)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_h_bit<=0;
end
else if(set_time_TO_idel) begin
cnt_h_bit<=set_cnt_h_bit;
end
else if (add_cnt_h_bit) begin
if (end_cnt_h_bit) begin
cnt_h_bit<=0;
end
else
cnt_h_bit<=cnt_h_bit+1;
end
end
assign add_cnt_h_bit=end_cnt_m_ten;
assign end_cnt_h_bit=add_cnt_h_bit&&cnt_h_bit==cnt_flag;
//時計時器---十位(0~2)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_h_ten<=0;
end
else if(set_time_TO_idel) begin
cnt_h_ten<=set_cnt_h_ten;
end
else if (add_cnt_h_ten) begin
if (end_cnt_h_ten) begin
cnt_h_ten<=0;
end
else
cnt_h_ten<=cnt_h_ten+1;
end
end
assign add_cnt_h_ten=end_cnt_h_bit;
assign end_cnt_h_ten=add_cnt_h_ten&&cnt_h_ten==2;
//判斷小時計時器十位是否記到 2
always @(*) begin
if (cnt_h_ten==2) begin
cnt_flag=4'd3;
end
else
cnt_flag=4'd9;
end
assign idel_dout={cnt_h_ten,cnt_h_bit,cnt_m_ten,cnt_m_bit,cnt_s_ten,cnt_s_bit}; //拼接成 HH:MM:SS
///
///
//dout_time輸出
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
dout_time<=20'b0;
end
else begin
case (state_c)
IDEL:dout_time<=idel_dout; //控制數(shù)碼管顯示對應(yīng)狀態(tài)的值
SET_TIME:dout_time<=set_time_dout;
SET_CLOCK:dout_time<=clock_dout;
default :dout_time<=IDEL;
endcase
end
end
assign beep_r=clock_dout==idel_dout; //比較設(shè)置的鬧鐘與現(xiàn)在的時間,結(jié)果輸出給beep模塊,到點鬧鈴
endmodule //counter
2.seg_driver
module seg_driver (
input wire clk,
input wire rst_n,
input wire [19:0] dout_time,
output reg [5:0] sel,
output reg [7:0] seg
);
reg [3:0] seg_flag;
reg dot; //小數(shù)點 用來顯示 HH.MM.SS 這樣的格式
//10ms計時器---用來切換數(shù)碼管位選,以達(dá)到輪流顯示時間的各位(肉眼可以看到動態(tài)的時間計數(shù))
reg [15:0] cnt;
wire add_cnt;
wire end_cnt;
parameter MAX_CNT =50_000 ,
ZERO =7'b100_0000,
ONE =7'b111_1001,
TWO =7'b010_0100,
THREE =7'b011_0000,
FOUR =7'b001_1001,
FIVE =7'b001_0010,
SIX =7'b000_0010,
SEVEN =7'b111_1000,
EIGHT =7'b000_0000,
NINE =7'b001_0000;
//計時器
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt<=0;
end
else if(add_cnt) begin
if (end_cnt) begin
cnt<=0;
end
else
cnt<=cnt+1;
end
end
assign add_cnt=1'b1;
assign end_cnt=add_cnt&&cnt==MAX_CNT-1;
//切換數(shù)碼管位選
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
sel<=6'b111_110;
end
else if(cnt==MAX_CNT-1) begin
sel<={sel[4:0],sel[5]};
end
end
//切換數(shù)碼管段選
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
seg_flag<=0;
end
else begin
case (sel)
6'b111_110: begin seg_flag<=dout_time[19:18]; dot<=1'b1;end //小時 十位
6'b111_101: begin seg_flag<=dout_time[17:14]; dot<=1'b0;end //小時 個位
6'b111_011: begin seg_flag<=dout_time[13:11]; dot<=1'b1;end //分鐘 十位
6'b110_111: begin seg_flag<=dout_time[10:7]; dot<=1'b0;end //分鐘 個位
6'b101_111: begin seg_flag<=dout_time[6:4]; dot<=1'b1;end //秒 十位
6'b011_111: begin seg_flag<=dout_time[3:0]; dot<=1'b1;end //秒 個位
default :seg_flag<=0;
endcase
end
end
//段選譯碼
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
seg<=8'b1111_1111;
end
else begin
case (seg_flag)
0: seg<={dot,ZERO} ;
1: seg<={dot,ONE} ;
2: seg<={dot,TWO} ;
3: seg<={dot,THREE} ;
4: seg<={dot,FOUR} ;
5: seg<={dot,FIVE} ;
6: seg<={dot,SIX} ;
7: seg<={dot,SEVEN} ;
8: seg<={dot,EIGHT} ;
9: seg<={dot,NINE} ;
default: seg<=8'b1111_1111;
endcase
end
end
endmodule //seg_driver
3.key_debounce
module key_debounce (
input wire clk, //系統(tǒng)時鐘 50MHz
input wire rst_n, //復(fù)位信號
input wire key, //按鍵輸入信號
output reg key_done //消抖之后的按鍵信號
);
reg key_r0; //同步信號(濾波作用,濾除小于一個周期的抖動)
reg key_r1; //打拍
reg flag; //標(biāo)志位
wire nedge; //下降沿檢測(檢測到下降沿代表開始抖動)
//計時器定義
reg [19:0] cnt;
wire add_cnt; //計時器開啟
wire end_cnt; //計時記滿
parameter MAX_CNT=20'd1_000_000; //20ms延時
//同步
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
key_r0<=1'b1;
end
else
key_r0<=key;
end
//打拍
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
key_r1<=1'b1;
end
else
key_r1<=key_r0;
end
assign nedge = ~key_r0 & key_r1; //檢測到下降沿拉高
//標(biāo)志位
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
flag<=1'b0;
end
else if (nedge) begin
flag<=1'b1;
end
else if (end_cnt) begin
flag<=1'b0;
end
end
//延時模塊
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt<=20'b0;
end
else if (add_cnt) begin
if (end_cnt) begin
cnt<=20'b0;
end
else
cnt<=cnt+1;
end
end
assign add_cnt=flag; //計時器開啟
assign end_cnt=add_cnt&&cnt==MAX_CNT-1; //計時器關(guān)閉
//key_done輸出
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
key_done<=1'b0;
end
else if (end_cnt) begin //延時滿20ms采樣
key_done<=~key_r0;
end
else
key_done<=1'b0;
end
endmodule //key_debounce
4.beep
module beep (
input wire clk,
input wire rst_n,
input wire beep_r,
output reg beep_out
);
reg [25:0] cnt;
wire add_cnt;
wire end_cnt;
parameter MAX_CNT=26'd50_000_000;
//計時器
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt<=0;
end
else if(add_cnt) begin
if (end_cnt) begin
cnt<=0;
end
else
cnt<=cnt+1;
end
end
assign add_cnt=1;
assign end_cnt=add_cnt&&cnt==MAX_CNT-1;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
beep_out<=1;
end
else if(beep_r) begin
beep_out<=0;
end
else if (end_cnt) begin
beep_out<=1;
end
else
beep_out<=beep_out;
end
endmodule //beep
5.頂層模塊
module top (
input wire clk , //系統(tǒng)時鐘
input wire rst_n , //復(fù)位信號
input wire [2:0] key , //三個按鍵
output wire [5:0] sel , //數(shù)碼管位選
output wire [7:0] seg , //數(shù)碼管段選
output wire beep_out
);
wire [19:0] dout_time;
wire [2:0] key_done;
wire beep_r;
//例化計時模塊
counter u_counter(
.clk (clk) ,
.rst_n (rst_n) ,
.key (key_done) ,
.dout_time (dout_time) , //輸出時間 HH:MM:SS
.beep_r (beep_r)
);
//例化數(shù)碼管驅(qū)動
seg_driver u_seg_driver(
.clk (clk) ,
.rst_n (rst_n) ,
.sel (sel) ,
.seg (seg) ,
.dout_time (dout_time)
);
//例化按鍵消抖
key_debounce key_debounce2(
.clk (clk), //系統(tǒng)時鐘 50MHz
.rst_n (rst_n), //復(fù)位信號
.key (key[0]), //按鍵輸入信號
.key_done (key_done[0]) //消抖之后的按鍵信號
);
key_debounce key_debounce3(
.clk (clk), //系統(tǒng)時鐘 50MHz
.rst_n (rst_n), //復(fù)位信號
.key (key[1]), //按鍵輸入信號
.key_done (key_done[1]) //消抖之后的按鍵信號
);
key_debounce key_debounce4(
.clk (clk), //系統(tǒng)時鐘 50MHz
.rst_n (rst_n), //復(fù)位信號
.key (key[2]), //按鍵輸入信號
.key_done (key_done[2]) //消抖之后的按鍵信號
);
//例化鬧鐘模塊
beep u_beep(
.clk (clk),
.rst_n (rst_n),
.beep_r (beep_r),
.beep_out (beep_out)
);
endmodule //top
三丶模塊原理圖
四丶管腳信息
五丶上板驗證
數(shù)碼管電子時鐘(設(shè)置時間+設(shè)置鬧鐘)文章來源:http://www.zghlxwxcb.cn/news/detail-403323.html
六丶源碼
https://github.com/xuranww/update_digital_clock.git文章來源地址http://www.zghlxwxcb.cn/news/detail-403323.html
到了這里,關(guān)于【FPGA】數(shù)碼管電子時鐘(可設(shè)置時間和鬧鐘)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!