06-BCD计数器设计与应用——小梅哥FPGA设计思想与验证方法视频教程配套文档
芯航線——普利斯隊長精心奉獻
?
實驗?zāi)康?#xff1a;1.掌握BCD碼的原理、分類以及優(yōu)缺點
???????? 2.設(shè)計一個多位的8421碼計數(shù)器并進行驗證
???????? 3.學(xué)會基本的錯誤定位以及修改能力 ????
實驗平臺:無
實驗原理:
????BCD碼(Binary-Coded Decimal)又被稱為二進碼十進數(shù)、二-十進制代碼是一種十進制的數(shù)字編碼,用4位二進制數(shù)來表示十進制數(shù)中的0~9個十個數(shù)之一。BCD編碼又可以分成有權(quán)碼和無權(quán)碼兩種,其中有權(quán)碼如:8421碼、2421碼以及5421等;無權(quán)碼如:余3碼、格雷碼以及余3循環(huán)碼等。
????BCD碼中最常用的是8421碼,其四個bit權(quán)值分別是8,4,2,1;同理5421碼各位的權(quán)依次為5,4,2,1,5421碼特點是最高位連續(xù)5個0后連續(xù)5個1,故其當(dāng)計數(shù)器采用這種編碼時,最高位可產(chǎn)生對稱方波輸出;余3碼是在8421碼上加加0011的出來的;碼格雷碼的特點是任意兩個相鄰的代碼只有一位二進制數(shù)不同,編碼格式不唯一;余3循環(huán)具有格雷碼的特點還具有編碼的首尾可以連接來進行循環(huán),這樣可用反饋移位寄存器來實現(xiàn),硬件實現(xiàn)簡單。下面表6-1給出常見的幾種編碼格式:
| 十進制數(shù) | 8421碼 | 余3碼 | 2421碼 | 5421碼 | 格雷碼 | 余3循環(huán)碼 |
| 0 | 0000 | 0011 | 0000 | 0000 | 0000 | 0010 |
| 1 | 0001 | 0100 | 0001 | 0001 | 0001 | 0110 |
| 2 | 0010 | 0101 | 0010 | 0010 | 0011 | 0111 |
| 3 | 0011 | 0110 | 0011 | 0011 | 0010 | 0101 |
| 4 | 0100 | 0111 | 0100 | 0100 | 0110 | 0100 |
| 5 | 0101 | 1000 | 1011 | 1000 | 0111 | 1100 |
| 6 | 0110 | 1001 | 1100 | 1001 | 0101 | 1101 |
| 7 | 0111 | 1010 | 1101 | 1010 | 0100 | 1111 |
| 8 | 1000 | 1011 | 1110 | 1011 | 1100 | 1110 |
| 9 | 1001 | 1100 | 1111 | 1100 | 1101 | 1010 |
表6-1 常見的BCD碼
在實際使用中如不特指BCD碼格式均為代指8421碼。通過以上介紹將十進制895轉(zhuǎn)換為BCD碼就是1001_1001_0101,同理若將BCD碼1001_0110_0100轉(zhuǎn)換為十進制數(shù)即為964。
BCD碼的運算規(guī)則:BCD碼是十進制數(shù),而運算器對數(shù)據(jù)做加減運算時,都是按二進制運算規(guī)則進行處理的。這樣,當(dāng)將BCD碼傳送給運算器進行運算時,其結(jié)果需要修正。修正的規(guī)則是:當(dāng)兩個BCD碼相加,如果和等于或小于 1001(即十進制數(shù)9),不需要修正;如果相加之和在 1010 到1111(即十六進制數(shù) 0AH~0FH)之間,則需加 'd6也就是'b0110進行修正;如果相加時,本位產(chǎn)生了進位,也需加 6 進行修正。下面舉例說明:計算5+8,將5和8轉(zhuǎn)換為8421 BCD碼后輸入加法器,則運算如下:0 1 0 1 + 1 0 0 0 = 1 1 0 1 結(jié)果大于9,+ 0 1 1 0 即加 6 修正得出1 0 0 1 1,補充高位為0001_0011。5+8=13,結(jié)論正確。
BCD碼的主要應(yīng)用之一就是數(shù)碼管,假設(shè)我們要將十進制數(shù)158顯示,一般解決辦法是先要除法運算158/100= 1得出百位,再取余158%100 = 58后繼續(xù)進行除法運算58 / 10 = 5得出十位,再進行一次取余158%10 = 8,得到個位。以上過程可以看出需要除法,但是由于除法運算是比較消耗計算時間導(dǎo)致整體需要的指令周期太久。但是如果我們先將其轉(zhuǎn)換為BCD碼,則可大幅度減少運算時間。具體例子會在數(shù)碼管一講詳細介紹。
實驗步驟:
按照02章所講,建立工程子文件夾后,新建一個以名為BCD_Counter的工程保存在prj下,并在本工程目錄的rtl文件夾下新建verilog file文件在此文件下輸入以下內(nèi)容并以BCD_Counter.v保存。
| module BCD_Counter(Clk, Cin, Rst_n, Cout, q); ? input Clk;//計數(shù)基準(zhǔn)時鐘 input Cin; //計數(shù)器進位輸入 input Rst_n; //系統(tǒng)復(fù)位 ? output reg Cout; //計數(shù)進位輸出 output [3:0]q; //計數(shù)值輸出 ? reg [3:0]cnt; //定義計數(shù)器寄存器 ? //執(zhí)行計數(shù)過程 always@(posedge Clk or negedge Rst_n) if(Rst_n == 1'b0) cnt <= 4'd0; else if(Cin == 1'b1)begin if(cnt == 4'd9) cnt <= 4'd0; else cnt <= cnt + 1'b1; end else cnt <= cnt; ? //產(chǎn)生進位輸出信號 always@(posedge Clk or negedge Rst_n) if (!Rst_n) Cout <= 1'b0; else if(Cin == 1'b1 && cnt ==4'd9) Cout <= 1'b1; else Cout <= 1'b0; ? assign q = cnt; ? endmodule |
?
進行分析和綜合直至沒有錯誤以及警告。
????為了測試仿真編寫測試激勵文件,新建BCD_Counter_tb.v文件保存到testbench文件夾下,輸入以下內(nèi)容再次進行分析和綜合直至沒有錯誤以及警告。本激勵文件除產(chǎn)生正常的時鐘以及復(fù)位信號外,還生成了重復(fù)30次的占空比為1:5周期為120ns的cin信號。
| `timescale 1ns/1ns ? `define clock_period 20 ? module BCD_Counter_tb; ? reg Clk; reg Cin; reg Rst_n; ? wire Cout; wire [3:0]q; ? BCD_Counter BCD_Counter0( .Clk(Clk), .Cin(Cin), .Rst_n(Rst_n), .Cout(Cout), .q(q) ); ? initial Clk = 1'b1; always#(`clock_period/2) Clk = ~Clk; ? initial begin Rst_n = 1'b0; Cin = 1'b0; #(`clock_period*200); Rst_n = 1'b1; #(`clock_period*20); repeat(30)begin Cin = 1'b1; #`clock_period; Cin = 1'b0; #(`clock_period*5); end #(`clock_period*20); $stop; end ? endmodule |
?
設(shè)置好仿真腳本后進行功能仿真,可以看到如圖6-1所示的波形文件,可以看出在復(fù)位信號置高后,每當(dāng)進位輸入信號cin為高時計數(shù)值輸出q完成一次自加,直到計數(shù)值為9后清零重新計數(shù)并產(chǎn)生進位信號。
圖6-1 功能仿真波形圖
現(xiàn)在以上面的BCD計數(shù)器為基礎(chǔ)設(shè)計級聯(lián)的多位BCD計數(shù)器,這里我們將計數(shù)器位數(shù)設(shè)置為12,即3個BCD計數(shù)器級聯(lián)既可以實現(xiàn)。新建verilog file文件在此文件下輸入以下內(nèi)容并以BCD_Counter_top.v保存至rtl文件夾下。本文件實現(xiàn)了例化與調(diào)用BCD_counter.v文件并將進位信號根據(jù)需要連接。
| module BCD_Counter_top(Clk, Cin, Rst_n, Cout, q); ? input Clk;//計數(shù)基準(zhǔn)時鐘 input Cin; //計數(shù)器進位輸入 input Rst_n; //系統(tǒng)復(fù)位 ? output Cout; //計數(shù)進位輸出 output [11:0]q; //計數(shù)值輸出 ? wire Cout0,Cout1; wire [3:0]q0,q1,q2; ? assign q = {q2,q1,q0}; ? BCD_Counter BCD_Counter0( .Clk(Clk), .Cin(Cin), .Rst_n(Rst_n), .Cout(Cout0), .q(q0) ); ? BCD_Counter BCD_Counter1( .Clk(Clk), .Cin(Cout0), .Rst_n(Rst_n), .Cout(Cout1), .q(q1) ); ? BCD_Counter BCD_Counter2( .Clk(Clk), .Cin(Cout1), .Rst_n(Rst_n), .Cout(Cout), .q(q2) ); ? endmodule |
將上述的文件設(shè)置為頂層,并再次進行分析和綜合直至沒有錯誤以及警告。點擊RTL viewer,可以看到圖6-2的模塊結(jié)構(gòu),可以看出符合預(yù)期目的。
圖6-2多級BCD計數(shù)器RTL視圖
為了測試仿真編寫測試激勵文件,新建BCD_Counter_top_tb.v文件保存到testbench文件夾下,輸入以下內(nèi)容再次進行分析和綜合直至沒有錯誤以及警告。本激勵文件為了簡化分析,復(fù)位后將cin一直置高,并延遲一定的時間。由于現(xiàn)在為三級BCD計數(shù)器,計數(shù)器滿值為十六進制的999,特將仿真時間進行了延長至5000個時鐘周期。
| `timescale 1ns/1ns ? `define clock_period 20 ? module BCD_Counter_top_tb; ? reg Clk; reg Cin; reg Rst_n; ? wire Cout; wire [11:0]q; ? BCD_Counter_top BCD_Counter_top0( .Clk(Clk), .Cin(Cin), .Rst_n(Rst_n), .Cout(Cout), .q(q) ); ? initial Clk = 1'b1; always#(`clock_period/2) Clk = ~Clk; ? initial begin Rst_n = 1'b0; Cin = 1'b0; #(`clock_period*200); Rst_n = 1'b1; #(`clock_period*20); Cin = 1'b1; #(`clock_period*5000); $stop; end ? endmodule |
????設(shè)置好仿真腳本后進行功能仿真,可以看到如圖6-3所示的波形文件,可以看到進位輸出信號cout在計數(shù)值q變?yōu)槭M制999后延遲了兩個系統(tǒng)周期才有輸出,不符合既定設(shè)計,即設(shè)計存在錯誤。
圖6-3 多級BCD計數(shù)器初次功能仿真
????為了定位錯誤,將子模塊的相關(guān)信號加入到wave欄,并再次仿真查看內(nèi)部數(shù)據(jù)的信息進行分析解決。
????在Modelsim找到Inatance窗口找到頂層文件,如圖6-4-1所示點擊加號后可以看到本頂層設(shè)計調(diào)用的模塊。如圖6-4-2所示單擊不同的模塊在Object欄可以看到其端口列表,選中需要的右鍵Add Wave,即可將內(nèi)部信號加入到波形窗口。這里我門將每個模塊的計數(shù)值輸出信號q以及進位輸出信號cout加入到波形窗口中。
圖6-4-1 添加內(nèi)部信號到wave窗口
圖6-4-2 添加內(nèi)部信號到wave窗口
單擊工具欄中的Restart來復(fù)位仿真,在彈出對話框中全選后點擊OK,點擊Run-All來重啟仿真。
圖6-5-1 復(fù)位仿真
圖6-5-2 復(fù)位仿真
圖6-6 重啟仿真
可以看到仿真后加入內(nèi)部信號的波形較亂沒有層次,這里介紹一個分組操作,我們首先ctrl+A選中所有wave窗口中的波形,后ctrl+G進行分組。分組后如圖6-7所示,放大局部信號可以看到照成這個原因是由于每一級的BCD計數(shù)器的進位輸出信號均延遲了一個時鐘周期,從而導(dǎo)致頂層文件進位輸出cout信號輸出延遲了三個時鐘周期的問題,此時的計數(shù)器值已經(jīng)變?yōu)榱耸M制的002,而不再是999。
圖6-7 加入內(nèi)部信號的功能仿真波形
這樣我們就定位了錯誤,只需將修改進位輸出信號cout修改為與計數(shù)值信號q計數(shù)到9時同時輸出。將進位產(chǎn)生信號的邏輯修改為如下,且將Cout的類型改為普通wire型。
| assign Cout = (Cin == 1'b1 && cnt == 4'd9); |
再次仿真后可以看到在圖6-8-1中十六進制的999時輸出進位信號,符合了原定的要求,我們可以再將顯示格式修改為二進制數(shù),如圖6-8-2中在計數(shù)值q為1001_1001_1001產(chǎn)生進位信號,通過前面所講的BCD碼原理將其轉(zhuǎn)換為BCD碼的格式也是999。
圖6-8-1 修改后的BCD計數(shù)器波形圖
圖6-8-2 修改后的BCD計數(shù)器波形圖
至此,就完成了一個BCD計數(shù)器的設(shè)計,并且學(xué)會了基本的調(diào)試修改能力。具體BCD計數(shù)器的板級驗證,可以參考后續(xù)文檔關(guān)于芯航線數(shù)碼管的驅(qū)動設(shè)計。
?
備注:在修改設(shè)計后如果進行單獨的功能仿真,會發(fā)現(xiàn)在圖6-9中進位信號存在毛刺(glitch),這里的解決辦法很多,其中之一就是在后續(xù)設(shè)計中通過預(yù)估正常信號與毛刺信號的時間寬度來進行篩選,也可以通過相關(guān)約束來解決;硬件方面可以外接濾波電容來消除其影響。
圖6-9 毛刺信號
轉(zhuǎn)載于:https://www.cnblogs.com/xiaomeige/p/5500950.html
總結(jié)
以上是生活随笔為你收集整理的06-BCD计数器设计与应用——小梅哥FPGA设计思想与验证方法视频教程配套文档的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 四十三 常用内建模块 base64
- 下一篇: 【常用正则大全】