計數器(至簡設計法學習筆記)

2021-10-05 05:13:18 字數 3658 閱讀 1100

三要素 初值 加1條件 結束值

三要素確定乙個計數器,逐一考慮。eg,下圖新增on訊號,作為加一條件 on訊號也是單週期訊號的延展訊號

初值為0所有計數器從0開始計數,便於閱讀(減少**的閱讀量)就不用閱讀計數器的定義部分啦,可以快速看出計數了多少次

結束值為0使得計數器迴圈重複使用計數器記完就清零 在最後乙個加一條件的時候清零。end_cnt 也是在說最後乙個加一條件

數值意義cnt = x - 1 加一條件有效的時候,數到了x下

取值格式

根據計數器產生訊號的時候, 要數x下然後變化(拉高)

assign dout = (add_cnt)&&(cnt==x-1);

結束條件

同時滿足加一條件,結束值時x-1的格式;

(無論多麼經驗豐富的工程師,對於邊界條件總要花心思來考慮)

取值範圍

範圍限定 邊界問題考慮 使用》= < 兩種符號。

range(0,8)

for(i=0;i<8;i++)

比如取前7個數 cnt>=0 && cnt<7;

從10開始 數16個 cnt>=10 && cnt<10+16;

計數框架

向框架對齊

向計數器直接對其 防止一環扣一環

先建立框架 再加其他訊號

always @(posedge clk)begin

if(!rst_n)begin

cnt0 <= 0;

endelse if(add_cnt0)begin // 加一條件滿足的時候 先判斷是否是結束 再加一

if(end_cnt0)

cnt0 <= 0;

else

cnt0 <= cnt0 + 1;

endend

//!------計數器0----0️⃣--------------

assign add_cnt0 = (dout);

assign end_cnt0 = add_cnt0&&(cnt0== 3-1 );

這一階段訓練的大都是en訊號之後,輸出一定規律的脈衝。如en訊號之後隔3個週期,輸出4個週期的高電平;隔3個週期,輸出1個,2個,3個,4個,週期高電平等等。

使用乙個或者兩個計數器來計數即可。這裡要有乙個en訊號之後表示的加一訊號(我理解為en脈衝的延拓)來持續刺激計數器的加一操作,同時這個延拓訊號的結束通常由計數器的值來進行判斷。

在en訊號脈衝之後 產生10個高電平輸出

計數器+1條件使用輸出訊號表示,輸出訊號的拉低條件使用計數器的結束條件表示。這裡的加一訊號與輸出訊號是乙個訊號。

en之後間隔10個週期 高乙個週期

這個情況就不能使用輸出訊號表示加一訊號了,flag數11個週期 更方便.

abxn模組

在練習中有很多 en訊號之後隔a個週期,有乙個b週期的高訊號,這個模式重複n次,這裡在至簡設計法的基礎上寫出了乙個實現這樣功能的模組,避免了**的重複。

//? *********************注釋開始*********************

//? 這個模組使用雙計數器 實現en訊號之後,隔a個週期,產生b個週期的高電平,這個模式重複n次

//? *********************注釋結束*********************

module a_bxn #(parameter abn_w = 4)(

input clk ,

input rst_n ,

//其他輸入訊號

input en,

input [abn_w-1:0] a,b,n,

//輸出訊號

output reg dout,

output reg [abn_w-1:0] cnt1

);//中間訊號定義

reg add_flag0;

reg [abn_w-1:0] cnt0;

wire add_cnt0,end_cnt0;

always @(posedge clk)begin

if(!rst_n)begin

cnt0 <= 0;

endelse if(add_cnt0)begin

if(end_cnt0)

cnt0 <= 0;

else

cnt0 <= cnt0 + 1;

endend

//!------計數器0----0️⃣--------------

assign add_cnt0 = (add_flag0);

assign end_cnt0 = add_cnt0&&(cnt0== a+b-1 );

wire add_cnt1,end_cnt1;

always @(posedge clk)begin

if(!rst_n)begin

cnt1 <= 0;

endelse if(add_cnt1)begin

if(end_cnt1)

cnt1 <= 0;

else

cnt1 <= cnt1 + 1;

endend

//!------計數器1-----1️⃣------------

assign add_cnt1 = (end_cnt0);

assign end_cnt1 = add_cnt1&&(cnt1== n-1 );

always @(posedge clk)begin

if(rst_n==1'b0)begin

add_flag0 <= 0;

endelse begin

if(en) add_flag0 <= 1;

else if(end_cnt1) add_flag0 <= 0;

endendalways @(posedge clk)begin

if(rst_n==1'b0)begin

dout <= 0;

endelse begin

if(add_cnt0 && cnt0==a-1) dout <= 1;

else if(end_cnt0) dout <= 0;

endendendmodule

有些時候,上述ab的值隨著這個模式重複的次序,發生變化,因此該模組還進行輸出了計數器1的計數值,可以在呼叫該模組時進行控制。這裡為了在cnt1變化後ab立即響應,使用組合邏輯來進行ab的賦值。組合邏輯的if else 要全面 (else x=x; 這樣也不行,要有確定的值)

always  @(*)begin

if(abxn_cnt1==0)

a = 4;

else if(abxn_cnt1==1)

a = 1;

else if(abxn_cnt1==2)

a = 6;

else

a = 2;

end

en訊號之後,輸出dout為2,持續5個週期,變為零

這個同階段一原理一樣,就是把脈衝換成了值。直接採用dout==2作為計數器加一條件,或者新增flag訊號,用於加一。dout訊號根據flag採用組合邏輯,或者根據cnt採用時序邏輯來產生。

計數器設計

最近看到一篇文章說要實現乙個計數器的功能,於是通過思索,設計了乙個靈活可用性高的物件計數器。裡面閃爍著 很多的火花。template class object counter object counter private static int m count template int object ...

計數器設計實驗

module cnt10 clk,rst,en,load,cout,dout,data input clk,en,rst,load input 3 0 data output 3 0 dout output cout reg 3 0 q1 reg cout assign dout q1 always...

Mysql計數器表設計

mysql create table hit counter cnt int unsigned not null engine innodb mysql update hit counter set cnt cnt 1 問題在於,對於任何想要更新這一行的事務來說,這條記錄上都有乙個全域性的互斥鎖 m...