基於logisim的運動碼錶設計

運動碼錶屬於一個小型的數字系統,既然是基於logisim的設計,自然是全部用原理圖方式實現的。我覺得雖然業界HDL的設計方式很常見,但是基於原理圖的設計經過這個項目以後我認爲算是一個基本功,基於原理圖設計可以大大加深對數字電路底層的認知,使你的verilog似乎有了靈魂,也算是一種“內功修煉”吧。
總結出來以下幾點:

  1. 數字系統一定要模塊化設計
  2. 設計流程: 設計需求分析(外部數據,控制輸入,輸出,顯示)-> 拆分爲功能模塊 -> 功能模塊的數據通路(此時不考慮控制信號,只要數據鏈路通了就行)-> 構建控制單元(如何從外部控制輸入轉化到內部的控制信號)。
    以上需要注意的是儘量設計moore型電路,輸出只與狀態有關;melay型電路屬於異步電路了。

這個題目來自華科的譚志虎老師MOOC第二章,強烈推薦大家去看一下。
需求分析

模塊劃分:

首先碼錶的計數功能得有,你得有從0 - 9999的BCD計數器
接着從數字到數碼管的顯示,你需要數碼管顯示驅動
store是存儲的功能,需要寄存器;嘗試更新記錄那麼肯定就需要數據,那麼比較器不可少;另外數碼管顯示驅動有兩個數據來源:BCD計數器和寄存器,需要一個MUX。彙總列個表:
在這裏插入圖片描述

模塊實現

時間計數器

BCD計數器一共有4位,每位都是0到9。 用verilog寫so easy,那基於原理圖的設計呢?BCD計數器是一個狀態機!
verilog裏面三段式狀態機:產生次態,產生輸出,狀態切換。
原理圖設計時一模一樣,10個狀態0-9,狀態編碼0000-1001(對應verilog parameter);求狀態轉換方程組(對應verilog case)和輸出方程組(對應verilog 三段式寫在最後的產生輸出);說到這裏數字電路基礎好一些的應該都知道怎麼設計了,直接上圖:
在這裏插入圖片描述
1位的BCD計數器做好了,設計的時候添加了en和carry位,每當計數到9的時候carry=1,注意moore電路輸出只與狀態有關,所以carry=1會維持計數 = 9整個狀態! carry用於多位BCD計數器級聯!
4位的怎麼做呢?
能carry接下一級的clk嗎?不能!因爲那樣的話下一級剛到9,上一級就會加1,舉個例子,你會看到 09 直接到19的現象!
應該是carry接下一級的en,但是這洋還有問題,4個BCD計數器位3,2,1,0。這樣做第0位到第1位沒問題,當你計數到90,你會發現你的位2也開始加了,這很顯然是不正確的!
位2的en需要用位1和位0過與門得到!位3同理!如下圖:
在這裏插入圖片描述
時間計數器設計完畢!

數碼管驅動

數碼管驅動是將數字0-9轉化爲數碼管的 0 - 9 輸出;
數碼管元件有a - g七根管加一個小數點共8位輸入! 小數點可以單獨處理,我們設計驅動電路的時候4輸入,7輸出即可,純組合邏輯;
在logisim中可以藉助真值表自動生成組合邏輯電路,在logisim裏面把真值表填完就行了,每一個輸入數字對應一個數碼管圖形!
組合電路非常龐大, 就不放啦,也沒啥好看的。
在我們的數字系統中,需要有16位的輸入(4乘4),32位輸出(4*7 + 4個小數點,只有第3位的數碼管需要小數點),如下圖:
在這裏插入圖片描述

16位寄存器

其實就是16個 D觸發器 並聯(我見過挺多並聯級聯混用的,我很反對),不過爲了畫圖方便一些,也體現出模塊化設計思想;分成4 組4位寄存器即可;
如下圖:
在這裏插入圖片描述

16位無符號數比較器

這裏也分成4組 4位無符號數比較器 來進行設計;
4位無符號數比較器設計 基於 logisim自帶組件 1位無符號數比較器來設計。
如下圖:
在這裏插入圖片描述
注意一下great,equal,less的邏輯即可,不算難。
16位的無符號數比較器的圖其實就是把上面那個圖的一位比較器換成4位比較器,其他部分不變,如下圖:
在這裏插入圖片描述

MUX

1位的MUX如下圖:
在這裏插入圖片描述
logisim中的邏輯門是支持多位寬的,例如與門都是16位輸入是可以的;
這裏可以直接修改與門的位寬嗎?不可以,因爲sel只有1位,不可以將1位的sel輸入16位的邏輯與門。不過現實中的邏輯與門器件並不支持多位寬。
基於1位MUX構建16位MUX,就直接上圖了:
在這裏插入圖片描述

模塊封裝圖

基本模塊都是實現了的,以前數電老師說數電就像下圍棋,現在總算有點感覺了!用基本模塊去搭建數據通路!!
放一下模塊封裝圖:
在這裏插入圖片描述

數據通路構建

根據你的功能把總體的數據通路給構建出來,把每個部件的數據來源想清楚!!!
構思一下:計數器在不停地加1,數據可以直接給到碼錶驅動嗎?不合適,因爲碼錶驅動還需要接受來自寄存器的數據;明顯就需要加入MUX了;
store的功能需要仔細想想,在沒有計數的情況下直接store應該顯示99.99,在有計數的情況下應該更新記錄並且顯示,可以肯定的是寄存器的數據來源肯定得有99.99,也得有計時器;
更新記錄的實現方式爲,將store的輸入和計時器輸入送入比較器,得到小於輸出時,將寄存器的使能打開,否則不打開即可實現更新。
總體框圖如下:
在這裏插入圖片描述

控制單元構建

控制單元將外部的輸入轉換爲內部的控制信號,是整個設計裏面最難的部分;先放一個框圖:
在這裏插入圖片描述
控制單元本質上也是一個狀態機,而且要設計成moore型的,輸出只與狀態有關;那都有哪些狀態?狀態直接怎麼切換?狀態有對應着什麼輸出呢?
我經過反覆思索,覺得狀態的規劃通過輸出來進行確定,一個輸出對應一個狀態,輸入導致了狀態的切換,這是一個整體構思的過程,就像列寫狀態轉換圖一樣。
復位後的狀態作爲起始態,每個輸入都會切換狀態;不過這裏輸入太多(我們經常寫的序列檢測器只有0/1兩種輸入,這裏有5個輸入),每個輸入產生一個次態,次態之後又接受輸入產生次態,能把人給繞暈了,所以要進行狀態切換的簡化,我手寫了一份狀態轉換/輸出表,也算是狀態規劃表吧:
在這裏插入圖片描述
可以看到我一共規劃了7個狀態,編碼0到6,爲什麼會有這些狀態?完全從輸出出發!,一個狀態對應一個輸出!
舉例說明:RST狀態下,五個輸入分別爲 0 1 1 1 0;一旦收到start,應當把RST變0,TMen變1,輸出變化了,就算下一個狀態,命名爲狀態1;同理,收到store,顯示99.99,對應5個輸入爲 1 1 1 0 0,命名爲狀態2;
有人會問,假如狀態0收到stop怎麼處理,我的做法是這個算當前狀態下的無效輸入,不處理,保持原來的狀態,通過這種做法可以大大減少狀態的數量。
在1態下(start計數狀態),只認識stop(收到stop進入3態)和rst,其他保持原態;
在2態下(store狀態,顯示99.99),只認識start和rst,其他保持原態;
這個4態是幹什麼的? 4態是 0 1 1 1 1,用於start清0,因爲注意需求那裏有一個start的清零效果,4態會自動跳到1態(收到rst還是跳0),4態只會維持一個時鐘週期。
在3態下(start -> stop狀態),可以start,進入4態;可以store,下面就要判斷NewRecord了(通過比較器產生),有New信號,打開寄存器使能SDen,否則關閉,分別對應5態和6態;
5,6兩個只認爲start和rst有效;

碼錶控制器還是一個三段式狀態機,具體如下:
在這裏插入圖片描述
我起初很鬱悶狀態轉換單元爲什麼會有8個輸入? 因爲狀態機需要狀態反饋! 數電老師以前講過,時序電路需要反饋!可惜當初只隨意聽了聽,我看那個8輸入愣了好久,實在是慚愧,慚愧,慚愧。
我又手寫了一份狀態轉換表幫助理解:
在這裏插入圖片描述
產生輸出的組合邏輯並不難,用卡諾圖用真值表都行;
產生次態的組合邏輯8輸入,3輸出,真值表有2^8 = 256行,我是一行一行填的,說多了都是淚(logisim有真值表產生組合邏輯的功能);
真值表有含RST的128行直接歸0,4態會直接跳1態(除非RST),無效輸入保持原來的狀態,真正有效的行數沒有多少
這裏寫一段verilog感嘆verilog大法好(就寫個梗概意思,狀態切換部分簡單明瞭太多了):

reg [2:0] state,nextstate;
parameter S0=3'b000,S1=3'b001,S2=3'b010,S3=3'b011;
parameter S4=3'b100,S5=3'b101,S6=3'b110;

always@(posedge clk or posedge rst)
	if(rst) state <= S0;
	else state <= nextstate;

always@(state or start or stop or store or rst or NewRecord)
begin
	case(state)
	S0: 
		begin
			if(rst)
				nextstate = S0;
			else if(start)
				nextstate = S1;
			else if(store)
				nextstate = S2;
			else 
				nextstate = S0;
		end
	S1: 
		begin
			if(rst)
				nextstate = S0;
			else if(stop)
				nextsate = S3;
			else
				nextstate = S1;
		end
	S2:
		begin
			if(rst)
				nextstate = S0;
			else if(start)
				nextstate = S4;
			else
				nextstate = S2;
		end
	S3:
		begin
			if(rst)
				nextstate = S0;
			else if(start)
				nextstate = S4;
			else if(store)
				begin
					if(NewRecord)
						nextstate = S5;
					else 
						nextstate = S6;
				end
			else
				nextstate = S3;
		end
	S4:
		begin
			if(rst)
				nextstate = S0;
			else 
				nextstate = S1;
		end
	S5:
		begin
			if(rst)
				nextstate = S0;
			else if(start)
				nextstate = S4;
			else 
				nextstate = S5;				
		end
	S6:
		begin
			if(rst)
				nextstate = S0;
			else if(start)
				nextstate = S4;
			else 
				nextstate = S6;				
		end
	default: nextstate = S0;
end 

總結

以上就是運動碼錶設計的全部,有興趣探討的同學可以私聊我,我可以提供logisim的circ源文件;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章