[FPGA]Verilog實現可自定義的倒計時器(24秒為例)


想說的話...

本次實現的是一個24秒倒計時器,功能顧名思義,進行一個24秒的倒計時操作,本文先給出一個簡單樣例,並結合仿真驗證功能,再對樣例進行拓展,成為一個可以被調用的模塊.

本文未涉及顯示模塊.

樣例_邊沿檢測計數器

代碼講解

首先給出樣例代碼.

module CntDwn
(input CK//Clock
,output[4:0]CD//CountDown
);
parameter[4:0]cd=5'd24;//Define a parameter which can be modified when called
reg[4:0]dif=0;//Difference
always@(posedge CK)
if(dif==cd)
	dif<=0;
else
	dif<=dif+1;
assign CD=cd-dif;
endmodule

這段代碼非常簡單,原理即利用了一個邊沿檢測計數器直接實現計時功能,邏輯為每檢測到一個升沿,差(dif)自增1,若差滿,即和倒計時數相等,則差清零.

在這段代碼里將倒計時數初始化為24,這個倒計時數在被其他模塊調用的時候可以被修改,可移植性好.

仿真演示

`timescale 1 ns/ 1 ns
module CntDwn_vlg_tst();
reg CK;
wire[4:0]CD;
CntDwn i1 (.CD(CD),.CK(CK));
initial begin
CK=0;
end
always begin
#1 CK<=~CK;
end
endmodule

以上是樣例代碼的一個仿真文件(.vt),通過ModelSim仿真后波形如下圖

MW7hNt.jpg

如果在仿真文件調用時修改傳遞參數,將Line 5改為

CntDwn #(.cd(10)) i1 (.CD(CD),.CK(CK));

則波形如下圖

MW7I9f.png

可見,本樣例代碼成功實現了倒計時功能,接下來進行樣例代碼的拓展.

拓展_自定義倒計時數和倒計時間隔

代碼講解

module CntDwn
(input CK//Clock
,output[4:0]CD//CountDown
);
parameter[4:0]cd=5'd24;//Define a parameter which can be modified when called
parameter[25:0]div=26'd50;//Frequency Division
reg[25:0]cnt=0;//Timer.Control the period
reg[4:0]dif=0;//Difference
always@(posedge CK)
if(cnt==div)begin
	cnt<=0;
	dif<=dif+1;
end
else if(dif==cd)
	dif<=0;
else
	cnt<=cnt+1;
assign CD=cd-dif;
endmodule

這是拓展后的代碼,加入了分頻,可以自定義倒計時的間隔,在調用時修改傳遞參數來達到自定義間隔和倒計時數的功能.

代碼中已經為分頻參數初始化為50,方便下面仿真調試.

仿真演示

仿真文件如下

`timescale 1 ns/ 1 ns
module CntDwn_vlg_tst();
reg CK;
wire[4:0]CD;
CntDwn i1 (.CD(CD),.CK(CK));
initial begin
CK=0;
end
always begin
#1 CK<=~CK;
end
endmodule

波形如下

MWbBQO.png

由於分頻參數為50,相當於比樣例滿了50倍,所以等尺寸縮放后時鍾信號已經密密麻麻的(甚至密集到只能顯示為一條粗粗的線),倒計時仍然功能正常,說明間隔功能無誤.

總結

本文概述了如何通過Verilog實現倒計時器,並且加入了波形仿真的知識,方便驗證和調試,還考慮到了參數調用的思想,增強代碼的可讀性,可維護性和可移植性.

值得說明的是,本文代碼仍有缺漏,例如在調用時如果需要倒計時數大於32(5位寬),頂層代碼中的參數位寬就要手動修改,不是很方便,一個解決方案就是將倒計時數的位寬也定義為一個WIDTH參數,使之也能夠被傳遞不同的參數.分頻參數已經定義為26位寬,基本能滿足大多數情況的需求,一般不需要進行修改位寬的操作.

如果要實現秒倒計時器,在仿真層面可以將分頻參數和自己的激勵時鍾信號周期相匹配,達到間隔為1秒的效果;如果要在開發板上實現,則需要考慮板載晶振的參數,計算分頻參數,在調用時傳遞參數或直接修改參數來達到1秒間隔.

實例_24秒倒計時器

module CntDwn_24s
(input CK//Clock
,output[4:0]CD//CountDown
);
parameter[4:0]cd=5'd24;//Define a parameter which can be modified when called
parameter[25:0]div=26'd12000000;//Frequency Division,12M
reg[25:0]cnt=0;//Timer.Control the period
reg[4:0]dif=0;//Difference
always@(posedge CK)
if(cnt==div)begin
	cnt<=0;
	dif<=dif+1;
end
else if(dif==cd)
	dif<=0;
else
	cnt<=cnt+1;
assign CD=cd-dif;
endmodule

此段代碼在板載晶振為12M的情況下正常運行.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM