0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

二進(jìn)制轉(zhuǎn)BCD碼需要幾步?——漫談大四加三算法的Verilog實(shí)現(xiàn)

FPGA學(xué)習(xí)交流 ? 2019-04-26 18:29 ? 次閱讀

Hi,大家好!我是至芯科技的李老師。

今天講課的題目比較有意思,它是一個(gè)小問題:把二進(jìn)制變成BCD碼需要幾步?
請(qǐng)大家思考一下。有同學(xué)可能回答需要三步,為什么???
因?yàn)榘。汛笙蠓胚M(jìn)冰箱里需要三步,第一步,把冰箱門打開,第二步,把大象放進(jìn)去,第三步,把冰箱門關(guān)上。
類似的,把二進(jìn)制變成BCD碼,也需要三步。
blablablabla ......
當(dāng)然啦,這是開玩笑了。不過,歪打正著,答案確實(shí)是三步。
究竟是怎么回事呢?我們下面細(xì)細(xì)說來,原理說透之后,我們演示一下具體的Verilog實(shí)現(xiàn)過程。

首先,看一下下面這張表格,把二進(jìn)制(8’hFF)轉(zhuǎn)換為BCD(12’h255)的步驟列表。

image.png

什么是二進(jìn)制轉(zhuǎn)BCD?有什么用?

4位二進(jìn)制是16進(jìn)制數(shù),而生活中常用的數(shù)制是10進(jìn)制數(shù)。
怎么樣用計(jì)算機(jī)來理解、表達(dá)生活中的10進(jìn)制數(shù)?這就需要進(jìn)行16進(jìn)制數(shù)與10進(jìn)制數(shù)的相互轉(zhuǎn)換了。
BCD碼(Binary-Coded Decimal)正是計(jì)算機(jī)常用的一種表達(dá)方式。
它是一種以二進(jìn)制表示的十進(jìn)制數(shù)碼。
比如說,至芯科技ZX-1開發(fā)板上的六位數(shù)碼管顯示數(shù)字可以是16進(jìn)制的000000~FFFFFF,但是更為方便的方法是000000~999999。
六位數(shù)碼管顯示六位數(shù)字用十六進(jìn)制,比如說是0F423F,誰(shuí)也不知道是多少,但是它對(duì)應(yīng)的十進(jìn)制數(shù)999999,大家肯定很熟悉。
很多場(chǎng)合,我們和機(jī)器之間溝通用10進(jìn)制更方便,但計(jì)算機(jī)是用01編碼的。需要進(jìn)行人機(jī)之間的溝通和轉(zhuǎn)換。
解決的方法就是用二進(jìn)制的方式來存儲(chǔ)、計(jì)算數(shù)值,但是用10進(jìn)制的方式來顯示這些數(shù)值,BCD碼就起到了橋梁的作用。
注意,16進(jìn)制屬于二進(jìn)制的一種形式,希望大家理解這點(diǎn),包括8進(jìn)制也是。

當(dāng)然,道理容易明白。但究竟機(jī)器又是怎樣實(shí)現(xiàn)二進(jìn)制和BCD碼的轉(zhuǎn)換的呢?
注意,轉(zhuǎn)換是雙向的,既可以把二進(jìn)制轉(zhuǎn)換成BCD碼,也可以把BCD碼轉(zhuǎn)換成二進(jìn)制數(shù)。
可以想象BCD碼轉(zhuǎn)成二進(jìn)制相對(duì)比較簡(jiǎn)單。
舉個(gè)例子吧,比如說BCD碼255,要轉(zhuǎn)換成二進(jìn)制。
計(jì)算機(jī)里面存的BCD碼是12'h255(對(duì)應(yīng)二進(jìn)制為12'b0010_0101_0101),肯定不能直接進(jìn)行運(yùn)算,必須要轉(zhuǎn)換成機(jī)器識(shí)別的二進(jìn)制數(shù)值12'h0FF(對(duì)應(yīng)二進(jìn)制為12'b0000_1111_1111)。
先算前兩位,直接2*10+5,得到結(jié)果25,然后再將結(jié)果*10+下一位,即25*10+5,最終結(jié)果為255,完了。
就這么簡(jiǎn)單。當(dāng)然這里255只有三位BCD位,如果更多的話,以此類推。
將前一步結(jié)果*10+下一位,得到當(dāng)前結(jié)果。
當(dāng)然實(shí)現(xiàn)起來還有一些小的技巧,x*10要占用乘法器資源,如果乘法器資源足夠那無所謂,但在資源有限的情況下通常用(x<<3)+(x<<1)(對(duì)應(yīng)x*8+x*2)來實(shí)現(xiàn)。
即用移位和加法來代替乘法操作。
當(dāng)然也可以把BCD數(shù)字的每一位直接變成各種左移數(shù)值的組合,比如x*100 = x*64 + x*32 * x*4 = (x<<6) +( x<<5) + (x<<2)。
上面就是BCD碼轉(zhuǎn)成二進(jìn)制的實(shí)現(xiàn)原理,這個(gè)比較簡(jiǎn)單,我們這里略微帶過。

本課重點(diǎn)講解的是反過來怎么實(shí)現(xiàn),即怎么把二進(jìn)制轉(zhuǎn)換成BCD碼?
比如說,二進(jìn)制數(shù)12'h0FF,要轉(zhuǎn)換成BCD碼255。
這個(gè)有點(diǎn)難,常見的做法是使用上圖中提到的大四加三算法。
當(dāng)然你可以用查表法,比如說256以內(nèi)的數(shù)值,直接用查表的方式,一一對(duì)應(yīng),就像我們FPGA采用LUT表實(shí)現(xiàn)真值表那樣,或者說用ROM表來根據(jù)不同輸入得到不同輸出。
這樣當(dāng)然也是可以的,不過,它的范圍往往比較有限,不適于數(shù)量比較大的情況。

下面,我們就隆重有請(qǐng)本次課堂的主角——大四加三算法,隆重登場(chǎng)。

大四加三算法

如果前面那張表格,大家能看懂的話,我們就可以直入主題了。
從表中我們可以看到,把二進(jìn)制變成BCD碼,也需要三步。

首先,明白問題的輸入和輸出要求,這是最起碼的,即輸入二進(jìn)制數(shù)(比如8’hFF),要求輸出對(duì)應(yīng)的BCD碼(對(duì)應(yīng)為BCD碼12'h255)。
大四加三算法就是實(shí)現(xiàn)的過程。

第一步:準(zhǔn)備階段。
我們將輸入二進(jìn)制數(shù)在高位補(bǔ)齊全0的BCD位,生成二進(jìn)制全序列的初始狀態(tài)。
BCD部分對(duì)應(yīng)二進(jìn)制位數(shù)為4的整數(shù)倍,最大數(shù)值上限不得小于輸入值位數(shù)對(duì)應(yīng)上限。

第二步:移位階段。
第二步比較復(fù)雜。這一步分為多個(gè)小步,每小步將二進(jìn)制全序列進(jìn)行一次組合的左移操作。
之所以稱之為組合的左移操作,是因?yàn)榘ㄒ淮我莆坏念A(yù)操作(即BCD位大四加三)和單純的全序列左移操作。
具體這一步的操作過程,我們后面還會(huì)細(xì)講。
實(shí)際上大象那個(gè)比喻,也是第二步比較復(fù)雜。呵呵。
一旦原理明白了,我們編寫Verilog代碼想必也就水到渠成了。后面就是Verilog語(yǔ)言練習(xí)和具體實(shí)現(xiàn)的事了。

第三步:輸出階段。
這一步,最簡(jiǎn)單,實(shí)際上第二步的最后環(huán)節(jié)已經(jīng)得出結(jié)果了,只不過它包含在全序列里面,我們只要取出需要的BCD部分,輸出即可。

大四加三算法原理簡(jiǎn)介

我們?cè)倩氐降诙缴蟻?,?shí)質(zhì)上也是大四加三算法上來。
第一步、第三步就是準(zhǔn)備和結(jié)束的階段,等同于打開冰箱門、關(guān)閉冰箱門。重點(diǎn)還是在于大象怎么放到冰箱里的。

第二步里面分為多個(gè)小步,每小步依次進(jìn)行a、b操作,小步次數(shù) = 輸入二進(jìn)制位數(shù)。
a操作:BCD位如果大于四,則加三。
b操作:全序列左移一位。

大四加三,準(zhǔn)確的說是≥5加3,實(shí)質(zhì)上是≥10加6,或者說大9加6。
因?yàn)?/span>BCD碼各位是從0到9,而4位二進(jìn)制數(shù)的范圍是0到15,將16進(jìn)制數(shù)轉(zhuǎn)換為10進(jìn)制數(shù)時(shí),從0到9不必變化,10到15加6變成16到21,對(duì)應(yīng)BCD碼為10到15。
之所以不叫大九加六,是因?yàn)榇笏募尤?/span>≥5加3)就是大九加六的一半(≥10加6),左移一位時(shí)通過后面的進(jìn)位(0/1),可以確定該BCD位左移一位之后是奇數(shù)還是偶數(shù)。
而且BCD只有為5/6/7時(shí)(此時(shí)>4,而<8)才進(jìn)行加三操作,變成8/9/10(對(duì)應(yīng)BCD碼1000/1001/1010),高位均為1,通過左移一位,正好對(duì)左邊高位BCD位產(chǎn)生進(jìn)位。

這樣說有點(diǎn)抽象,那張表格如果大家沒有一步步演變清楚的話,可以先弄清楚了。這樣有助于理解這個(gè)算法。
當(dāng)然這個(gè)算法嚴(yán)謹(jǐn)?shù)淖C明過程肯定也是有的,李凡老師也提到過,有興趣的話可以深入鉆研一下。
這里,我們就先用歸納的方法,檢驗(yàn)這種算法確實(shí)是能一步步將二進(jìn)制數(shù)轉(zhuǎn)換成BCD碼。
表中輸入的是8位二進(jìn)制數(shù),位數(shù)更多,實(shí)質(zhì)上原理是一樣的,每位之間的遞進(jìn)關(guān)系是2倍,每四位之間的遞進(jìn)關(guān)系是16倍,你在增加位數(shù),遞進(jìn)的關(guān)系都是一樣的。
當(dāng)然我們也可以自己推導(dǎo)一下12位二進(jìn)制數(shù),或者更多位,滿足一下我們的好奇心和求知欲。
就像圖示的表格一樣,只不過位數(shù)增加了而已。

本堂課要解決的課題

原理講過之后,我們要做一個(gè)更多位數(shù)的例子。
也就是開發(fā)板六位數(shù)碼管顯示的的問題,我們讓六位數(shù)碼管循環(huán)顯示十進(jìn)制數(shù)000000~999999。

十進(jìn)制數(shù)000000~999999在計(jì)算機(jī)里面,用于顯示實(shí)際上是BCD碼000000~999999,而用于計(jì)算處理則是二進(jìn)制數(shù)20'h00000~20'hF423F(對(duì)應(yīng)20'd0~20'd99999)。
在循環(huán)顯示的時(shí)候,我們控制部分要對(duì)計(jì)數(shù)器進(jìn)行加一操作,這時(shí)候是對(duì)二進(jìn)制數(shù)進(jìn)行操作。
在顯示輸出的時(shí)候,我們將二進(jìn)制數(shù)轉(zhuǎn)換為BCD碼,輸出給數(shù)碼管進(jìn)行顯示。這時(shí)候,就用到了二進(jìn)制數(shù)轉(zhuǎn)換為BCD碼的操作,也就是大四加三算法。
所以說,這個(gè)例子對(duì)大四加三算法模塊的輸入輸出要求是,輸入20位的二進(jìn)制數(shù)20'h00000~20'hF423F(對(duì)應(yīng)20'd0~20'd99999),要求輸出對(duì)應(yīng)的6位BCD碼000000~999999,對(duì)應(yīng)二進(jìn)制位數(shù)是24位。
顯然這里的20位輸入24位輸出,比表格中的8位輸入12位輸出要多了很多,當(dāng)然我們不是手工推導(dǎo),而是要用FPGA來做,用Verilog代碼來建模。

建模主體框架

首先建立工程文件夾b2bcd,編寫頂層模塊b2bcd.v文件。

module b2bcd (din, dout);

input [19:0] din;

output [23:0] dout;

wire [43:0] data [20:0];

assign data[0] = {24'b0, din}; //第一步:準(zhǔn)備階段。將輸入二進(jìn)制數(shù)在高位補(bǔ)齊全0的BCD位,生成二進(jìn)制全序列的初始狀態(tài)。


shift s01 (.datain(data[0]), .dataout(data[1])); //第二步:移位階段。依次進(jìn)行20個(gè)小步操作。具體動(dòng)作在shift子模塊中描述。
shift s02 (.datain(data[1]), .dataout(data[2]));
shift s03 (.datain(data[2]), .dataout(data[3]));
shift s04 (.datain(data[3]), .dataout(data[4]));
shift s05 (.datain(data[4]), .dataout(data[5]));
shift s06 (.datain(data[5]), .dataout(data[6]));
shift s07 (.datain(data[6]), .dataout(data[7]));
shift s08 (.datain(data[7]), .dataout(data[8]));
shift s09 (.datain(data[8]), .dataout(data[9]));
shift s10 (.datain(data[9]), .dataout(data[10]));
shift s11 (.datain(data[10]), .dataout(data[11]));
shift s12 (.datain(data[11]), .dataout(data[12]));
shift s13 (.datain(data[12]), .dataout(data[13]));
shift s14 (.datain(data[13]), .dataout(data[14]));
shift s15 (.datain(data[14]), .dataout(data[15]));
shift s16 (.datain(data[15]), .dataout(data[16]));
shift s17 (.datain(data[16]), .dataout(data[17]));
shift s18 (.datain(data[17]), .dataout(data[18]));
shift s19 (.datain(data[18]), .dataout(data[19]));
shift s20 (.datain(data[19]), .dataout(data[20]));

assign dout = data[20][43:20]; //第三步:輸出階段。取出BCD部分,作為輸出。

endmodule

b2bcd.v文件

image.png

建模shift移位子模塊

shift移位子模塊shift.v文件如下:

module shift (datain, dataout);

input [43:0] datain;

output [43:0] dataout;

wire [43:0] data;

assign data[19:0] = datain[19:0];

preshift p0 (.d4in(datain[23:20]), .d4out(data[23:20])); //對(duì)應(yīng)第二步各小步下的a操作,此處為6個(gè)BCD位的大四加三操作。具體動(dòng)作見preshift移位預(yù)操作子模塊。
preshift p1 (.d4in(datain[27:24]), .d4out(data[27:24]));
preshift p2 (.d4in(datain[31:28]), .d4out(data[31:28]));
preshift p3 (.d4in(datain[35:32]), .d4out(data[35:32]));
preshift p4 (.d4in(datain[39:36]), .d4out(data[39:36]));
preshift p5 (.d4in(datain[43:40]), .d4out(data[43:40]));

assign dataout = {data[42:0], 1'b0}; //對(duì)應(yīng)第二步各小步下的b操作,此處為全序列的左移移位操作。

endmodule

shift子模塊shift.v

image.png

建模preshift預(yù)移位操作子模塊

preshift預(yù)移位操作子模塊preshift.v文件如下:

module preshift (d4in, d4out);

input [3:0] d4in;

output reg [3:0] d4out;

always @ (*)
begin
if (d4in > 4)
begin
d4out = d4in + 3; //如果大于四,則加三
end
else
begin
d4out = d4in; //如果不大于四,則不變
end
end

endmodule

preshift預(yù)移位操作子模塊preshift.v

image.png

preshift預(yù)移位操作子模塊,也可以這樣寫

module preshift (d4in, d4out);

input [3:0] d4in;

output [3:0] d4out;

assign d4out = (d4in > 4) ? d4in + 4'd3 : d4in; //如果大于四,則加三,否則不變。

// always (*)
// begin
// if (d4in > 4)
// begin
// d4out = d4in + 3;
// end
// else
// begin
// d4out = d4in;
// end
// end

endmodule

preshift預(yù)移位操作子模塊的另一種寫法

image.png

編寫Testbench模塊


Testbench模塊b2bcd_tb.v文件如下:

`timescale 1ns/1ps

module b2bcd_tb;

reg [19:0] din;

wire [23:0] dout;

integer i;

b2bcd dut (.din(din), .dout(dout));

initial
begin
din = 0;
for (i=0; i<=999999; i=i+1) #10 din = i; ? ? ? ? ? ? ? ?//六位數(shù)碼管循環(huán)顯示000000~999999


#100 $stop;
end

endmodule

Testbench模塊b2bcd_tb.v文件

image.png

仿真運(yùn)行結(jié)果

設(shè)置好仿真之后,可以看到仿真結(jié)果。
此時(shí)將din的數(shù)據(jù)格式設(shè)置為無符號(hào)數(shù)Unsigned,將dout的數(shù)據(jù)格式設(shè)置為十六進(jìn)制數(shù)Hexadecimal。
可以看到兩種不同碼制的數(shù)據(jù)保持了完全一致。
從一個(gè)方面驗(yàn)證了大四加三算法的正確性。

仿真運(yùn)行結(jié)果圖示

image.png

generate for語(yǔ)句改寫shift移位子模塊shift.v文件

我們注意到由于存在重復(fù)性操作,相同的語(yǔ)句往往寫好多次。當(dāng)然參數(shù)會(huì)稍微有所差異。
有個(gè)偷懶的辦法,就是采用generate for語(yǔ)句。
generate for語(yǔ)句改寫的shift移位子模塊shift.v文件如下所示:

module shift (datain, dataout);

input [43:0] datain;

output [43:0] dataout;

wire [43:0] data;

assign data[19:0] = datain[19:0];

// preshift p0 (.d4in(datain[23:20]), .d4out(data[23:20]));
// preshift p1 (.d4in(datain[27:24]), .d4out(data[27:24]));
// preshift p2 (.d4in(datain[31:28]), .d4out(data[31:28]));
// preshift p3 (.d4in(datain[35:32]), .d4out(data[35:32]));
// preshift p4 (.d4in(datain[39:36]), .d4out(data[39:36]));
// preshift p5 (.d4in(datain[43:40]), .d4out(data[43:40]));

genvar i;

generate for (i=0; i<24; i=i+4)
begin : g4i
preshift p (.d4in(datain[23+i:20+i]), .d4out(data[23+i:20+i])); //對(duì)應(yīng)第二步各小步下的a操作,此處為6個(gè)BCD位的大四加三操作。具體動(dòng)作見preshift移位預(yù)操作子模塊。
end
endgenerate

assign dataout = {data[42:0], 1'b0}; //對(duì)應(yīng)第二步各小步下的b操作,此處為全序列的左移移位操作。

endmodule

generate for語(yǔ)句改寫的shift移位子模塊shift.v文件

image.png

generate for語(yǔ)句改寫頂層模塊b2bcd.v文件

同樣的道理,我們對(duì)頂層模塊b2bcd.v文件的重復(fù)性語(yǔ)句也進(jìn)行了改寫。
generate for語(yǔ)句改寫的頂層模塊b2bcd.v文件如下所示:

module b2bcd (din, dout);

input [19:0] din;

output [23:0] dout;

wire [43:0] data [20:0];

assign data[0] = {24'b0, din}; //第一步:準(zhǔn)備階段。將輸入二進(jìn)制數(shù)在高位補(bǔ)齊全0的BCD位,生成二進(jìn)制全序列的初始狀態(tài)。

genvar i;

generate for (i=0; i<20; i=i+1)
begin : g4i
shift s (.datain(data), .dataout(data[i+1])); //第二步:移位階段。依次進(jìn)行20個(gè)小步操作。具體動(dòng)作在shift子模塊中描述。
end
endgenerate

assign dout = data[20][43:20]; //第三步:輸出階段。取出BCD部分,作為輸出。

endmodule

第二步的小步次數(shù)優(yōu)化

前面表格中我們提到,第二步的最初3小步可以去除,因?yàn)樽畛?小步除了左移操作,在BCD位大四加三操作中并不發(fā)生變化。
因此可以在第一步直接將原初始狀態(tài)左移三位,原第二步直接跳過前3小步執(zhí)行即可。
優(yōu)化結(jié)果體現(xiàn)在頂層模塊b2bcd.v文件中,如下所示:

module b2bcd (din, dout);

input [19:0] din;

output [23:0] dout;


wire [43:0] data [20:0];

// assign data[0] = {24'b0, din};
assign data[3] = {21'b0, din, 3'b0}; //第一步:準(zhǔn)備階段。將輸入二進(jìn)制數(shù)在高位補(bǔ)齊全0的BCD位,直接左移三位,生成二進(jìn)制全序列的初始狀態(tài)。

genvar i;

// generate for (i=0; i<20; i=i+1)
generate for (i=3; i<20; i=i+1)
begin : g4i
shift s (.datain(data), .dataout(data[i+1])); //第二步:移位階段。依次進(jìn)行17個(gè)(20-3)小步操作。具體動(dòng)作在shift子模塊中描述。
end
endgenerate

assign dout = data[20][43:20]; //第三步:輸出階段。取出BCD部分,作為輸出。

endmodule

第二步的小步次數(shù)優(yōu)化結(jié)果體現(xiàn)在頂層模塊b2bcd.v文件中

image.png

查看RTL視圖——頂層模塊b2bcd.v


頂層模塊b2bcd.v的視圖如下所示。
其中最下面為全局視圖,上面為左邊、右邊的局部視圖,可以看到17個(gè)子步shift移位模塊逐次遞進(jìn)的一個(gè)結(jié)果。

17個(gè)子步shift移位模塊逐次遞進(jìn)的RTL視圖

image.png

shift移位子模塊shift.v的RTL視圖如下。

image.png


preshift移位預(yù)操作子模塊preshift.v的RTL視圖

image.png?


加入數(shù)碼管驅(qū)動(dòng)模塊seg7.v文件

為了更直觀地看到數(shù)碼管顯示效果,在已經(jīng)做好的工程文件中加入編寫好的數(shù)碼管驅(qū)動(dòng)模塊seg7.v文件。
數(shù)碼管驅(qū)動(dòng)模塊seg7.v文件如下所示。

module seg7 (clk, rst_n, data, sel, seg);

input clk, rst_n;
input [23:0] data;

output reg [2:0] sel;
output reg [7:0] seg;


reg [19:0] count;
reg clk_1ms;

always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
clk_1ms <= 1;
end
else
begin
if (count < 24999)
begin
count <= count + 20'd1;
end
else
begin
count <= 0;
clk_1ms <= ~clk_1ms;
end
end
end


reg [2:0] state;
reg [3:0] data_temp;

always @ (posedge clk_1ms or negedge rst_n)
begin
if (!rst_n)
begin
sel <= 0;
data_temp <= 0;
state <= 0;
end
else
begin
case (state)
0 : begin
sel <= 0;
data_temp <= data[23:20];
state <= 1;
end

1 : begin
sel <= 1;
data_temp <= data[19:16];
state <= 2;
end

2 : begin
sel <= 2;
data_temp <= data[15:12];
state <= 3;
end

3 : begin
sel <= 3;
data_temp <= data[11:8];
state <= 4;
end

4 : begin
sel <= 4;
data_temp <= data[7:4];
state <= 5;
end

5 : begin
sel <= 5;
data_temp <= data[3:0];
state <= 0;
end

default : state <= 0;

endcase
end
end


always @ (*)
begin

if (!rst_n)
begin
seg = 8'b1111_1111;
end
else
begin
case (data_temp)
0 : seg = 8'b1100_0000; //d0
1 : seg = 8'b1111_1001; //d1
2 : seg = 8'b1010_0100; //d2
3 : seg = 8'b1011_0000; //d3
4 : seg = 8'b1001_1001; //d4
5 : seg = 8'b1001_0010; //d5
6 : seg = 8'b1000_0010; //d6
7 : seg = 8'b1111_1000; //d7
8 : seg = 8'b1000_0000; //d8
9 : seg = 8'b1001_0000; //d9
10 : seg = 8'b1000_1000; //dA
11 : seg = 8'b1000_0011; //db
12 : seg = 8'b1100_0110; //dC
13 : seg = 8'b1010_0001; //dd
14 : seg = 8'b1000_0110; //dE
15 : seg = 8'b1000_1110; //dF
default : seg = 8'b1000_1110; //dF
endcase
end
end

endmodule

創(chuàng)建新的頂層模塊top.v

創(chuàng)建新的頂層模塊top.v,循環(huán)生成要顯示的數(shù)字000000~999999,顯示數(shù)字每100ms更新一次,通過b2bcd模塊轉(zhuǎn)換成BCD碼,然后輸出給數(shù)碼管驅(qū)動(dòng)模塊。
新的頂層模塊top.v文件如下所示。

module top (clk, rst_n, sel, seg);

input clk, rst_n;

output [2:0] sel;
output [7:0] seg;


reg [31:0] count;
reg [19:0] din;

wire [23:0] dout;

parameter T100ms = 5_000_000;

always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
count <= 0;
din <= 0;
end
else
begin
if (count < T100ms - 1) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//顯示數(shù)字每100ms更新一次
begin
count <= count + 1;
end
else
begin

count <= 0;
if (din < 999999) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//循環(huán)生成要顯示的數(shù)字000000~999999
begin
din <= din + 20'd1;
end
else
begin
din <= 0;
end
end
end
end

b2bcd b2bcd
(
.din(din),
.dout(dout)
);

seg7 seg7
(
.clk(clk),
.rst_n(rst_n),
.data(dout),
.sel(sel),
.seg(seg)
);


endmodule

參照.tcl文件設(shè)置好FPGA管腳


參照EP4CE10F17C8Nzx_1.tcl文件內(nèi)容,對(duì)FPGA芯片管腳進(jìn)行設(shè)置。

EP4CE10F17C8Nzx_1.tcl文件相關(guān)內(nèi)容如下所示。FPGA芯片配置結(jié)果如圖所示。

#set_global_assignment -name FAMILY "Cyclone IV"
#set_global_assignment -name DEVICE ep4ce10f17c8n

set_location_assignment PIN_E1 -to clk

# KEY 輕觸按鍵
set_location_assignment PIN_L3 -to key[0]

# SEG7 x 8 七段數(shù)碼管
set_location_assignment PIN_L6 -to sel[2]
set_location_assignment PIN_N6 -to sel[1]
set_location_assignment PIN_M7 -to sel[0]
set_location_assignment PIN_T11 -to seg[0]
set_location_assignment PIN_T10 -to seg[1]
set_location_assignment PIN_T9 -to seg[2]
set_location_assignment PIN_T8 -to seg[3]
set_location_assignment PIN_T7 -to seg[4]
set_location_assignment PIN_T6 -to seg[5]
set_location_assignment PIN_T5 -to seg[6]
set_location_assignment PIN_T4 -to seg[7]

FPGA芯片配置結(jié)果截圖

image.png

.sof文件下載到FPGA


全編譯FPGA工程,生成.sof文件,連接至芯ZX-1開發(fā)板并上電。
打開Programmer通過Jtag口,將.sof文件下載到FPGA進(jìn)行在線仿真。
.sof文件下載界面如下圖所示。

image.png

開發(fā)板運(yùn)行效果

開發(fā)板運(yùn)行效果如下圖所示。
經(jīng)檢查,開發(fā)板運(yùn)行效果與設(shè)計(jì)相符。

課程小結(jié)

本節(jié)課帶領(lǐng)大家學(xué)習(xí)了二進(jìn)制轉(zhuǎn)換成BCD碼的原理,并使用Verilog實(shí)現(xiàn)大四加三算法的建模,結(jié)合六位數(shù)碼管顯示,在至芯ZX-1開發(fā)板上演示了程序結(jié)果。
希望大家通過本次課程的學(xué)習(xí),掌握大四加三算法的原理,熟練編寫相關(guān)FPGA工程,掌握Verilog語(yǔ)法和相關(guān)開發(fā)工具。
課程到此結(jié)束,謝謝大家觀賞。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1624

    文章

    21538

    瀏覽量

    600475
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    二進(jìn)制處理中的一些技巧

    二進(jìn)制和十進(jìn)制的處理中,有時(shí)候一些小技巧是很有用的。 1、把十進(jìn)制數(shù)轉(zhuǎn)換成二進(jìn)制數(shù) (1)在MATLAB中有一個(gè)函數(shù)dec2bin,可以把正整數(shù)轉(zhuǎn)換為2
    的頭像 發(fā)表于 07-05 11:51 ?431次閱讀

    二進(jìn)制串行計(jì)數(shù)器工作原理是什么?

    的工作原理進(jìn)行深入解析,幫助你更好地理解這一數(shù)字電路的核心組件。 一、二進(jìn)制串行計(jì)數(shù)器的基本概念 二進(jìn)制串行計(jì)數(shù)器是一種基于二進(jìn)制數(shù)制的計(jì)數(shù)器,它按照二進(jìn)制數(shù)的規(guī)律進(jìn)行計(jì)數(shù)。與傳統(tǒng)的
    的頭像 發(fā)表于 05-28 15:52 ?602次閱讀

    BCD在PLC中的應(yīng)用與含義

    BCD是英文"Binary-Coded Decimal"的縮寫,直譯的意思是“二進(jìn)制編碼的十進(jìn)制數(shù)”,這種編碼的數(shù)制本質(zhì)上是十進(jìn)制BCD
    發(fā)表于 03-21 11:17 ?2280次閱讀
    <b class='flag-5'>BCD</b><b class='flag-5'>碼</b>在PLC中的應(yīng)用與含義

    如何實(shí)現(xiàn)二進(jìn)制BCD碼數(shù)據(jù)的相互轉(zhuǎn)變?

    如何實(shí)現(xiàn)二進(jìn)制BCD碼數(shù)據(jù)的相互轉(zhuǎn)變? 二進(jìn)制碼是將十進(jìn)制數(shù)字表示為二進(jìn)制數(shù)和十
    的頭像 發(fā)表于 02-18 14:51 ?2853次閱讀

    二進(jìn)制與邏輯電平的變化范圍

    二進(jìn)制中的兩個(gè)數(shù)字0和1稱為位(bit, 是二進(jìn)制數(shù)字binary digit的縮寫)。在數(shù)字電路中,使用兩個(gè)不同的電平表示這兩個(gè)位。一般情況下,1 用高電平表示,0用低電平表示,這種邏輯體制稱為正邏輯。
    的頭像 發(fā)表于 02-04 16:54 ?1055次閱讀
    <b class='flag-5'>二進(jìn)制</b>與邏輯電平的變化范圍

    鴻蒙二進(jìn)制數(shù)組創(chuàng)建

    背景 c++層數(shù)據(jù)都是二進(jìn)制,需要轉(zhuǎn)換成arrayBuffer透?jìng)鞯絜ts層給業(yè)務(wù)使用,但是鴻蒙的使用下面兩個(gè)api創(chuàng)建出來的二進(jìn)制數(shù)組數(shù)據(jù)都是錯(cuò)誤的。 接口
    的頭像 發(fā)表于 01-31 15:24 ?1180次閱讀

    器種類有多少種類型

    二進(jìn)制-十進(jìn)制器將二進(jìn)制碼轉(zhuǎn)換為十進(jìn)制,通常用于計(jì)算機(jī)系統(tǒng)中。最常見的
    的頭像 發(fā)表于 01-19 14:13 ?565次閱讀

    二進(jìn)制、八進(jìn)制、十六進(jìn)制在現(xiàn)實(shí)當(dāng)中有什么意義?

    二進(jìn)制、八進(jìn)制、十六進(jìn)制在現(xiàn)實(shí)當(dāng)中有什么意義? 二進(jìn)制、八進(jìn)制和十六進(jìn)制在現(xiàn)實(shí)生活中有著廣泛的應(yīng)
    的頭像 發(fā)表于 01-16 11:14 ?4321次閱讀

    10進(jìn)制轉(zhuǎn)換為二進(jìn)制算法

    進(jìn)制轉(zhuǎn)換為二進(jìn)制是計(jì)算機(jī)科學(xué)中非?;A(chǔ)且重要的概念之一。在理解和應(yīng)用計(jì)算機(jī)科學(xué)的基礎(chǔ)知識(shí)時(shí),掌握這個(gè)算法是至關(guān)重要的。 在開始講解十進(jìn)制轉(zhuǎn)換為二進(jìn)
    的頭像 發(fā)表于 01-15 10:32 ?2266次閱讀

    10進(jìn)制轉(zhuǎn)換為二進(jìn)制算法

    10進(jìn)制轉(zhuǎn)換為二進(jìn)制是計(jì)算機(jī)領(lǐng)域中非常重要的一個(gè)問題。在計(jì)算機(jī)中,所有的數(shù)據(jù)都是以二進(jìn)制形式進(jìn)行存儲(chǔ)和處理的。因此,我們常常需要將10進(jìn)制數(shù)
    的頭像 發(fā)表于 01-11 09:14 ?1923次閱讀

    labview二進(jìn)制字符串轉(zhuǎn)數(shù)值

    字符串是一種常見的數(shù)據(jù)類型,它表示了以二進(jìn)制形式存儲(chǔ)的數(shù)據(jù)。當(dāng)我們需要將這些二進(jìn)制字符串轉(zhuǎn)換為數(shù)值時(shí),LabVIEW提供了一些常用的函數(shù)和方法,可以幫助我們完成這個(gè)任務(wù)。 首先,我們需要
    的頭像 發(fā)表于 01-05 16:20 ?2283次閱讀

    你知道十進(jìn)制轉(zhuǎn)二進(jìn)制如何進(jìn)行轉(zhuǎn)換嗎?

    你知道十進(jìn)制轉(zhuǎn)二進(jìn)制如何進(jìn)行轉(zhuǎn)換嗎? 當(dāng)我們提到數(shù)字系統(tǒng)時(shí),最常見的是十進(jìn)制系統(tǒng)和二進(jìn)制系統(tǒng)。十進(jìn)制
    的頭像 發(fā)表于 12-20 17:05 ?1267次閱讀

    二進(jìn)制DAC示例介紹

    電子發(fā)燒友網(wǎng)站提供《二進(jìn)制DAC示例介紹.pdf》資料免費(fèi)下載
    發(fā)表于 11-28 11:23 ?1次下載
    <b class='flag-5'>二進(jìn)制</b>DAC示例介紹

    二進(jìn)制最佳接收原理 二進(jìn)制最佳接收機(jī)的實(shí)現(xiàn)形式有哪兩種?

    二進(jìn)制最佳接收原理 二進(jìn)制最佳接收機(jī)的實(shí)現(xiàn)形式有哪兩種? 二進(jìn)制最佳接收原理是計(jì)算機(jī)通信中的重要概念,它是指在二進(jìn)制通信中通過一定的方法,使
    的頭像 發(fā)表于 11-27 16:19 ?911次閱讀

    二進(jìn)制數(shù)據(jù)及取值范圍的計(jì)算方法

    本文介紹二進(jìn)制數(shù)據(jù)的相關(guān)知識(shí),如定義、取值范圍計(jì)算、轉(zhuǎn)換為十進(jìn)制的方法以及一些常見位數(shù)的二進(jìn)制數(shù)據(jù)的取值范圍等。
    的頭像 發(fā)表于 11-08 15:48 ?1816次閱讀
    <b class='flag-5'>二進(jìn)制</b>數(shù)據(jù)及取值范圍的計(jì)算方法