• 方案介紹
    • 一、摘要
    • 二、概述
    • 三、頂層模塊
    • 四、計分模塊
    • 五、Testbench
    • 六、仿真圖結(jié)果
    • 七、綜合即實現(xiàn)結(jié)果
    • 八、結(jié)論
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

羽毛球計分器Basys3開發(fā)板VHDL代碼帶設(shè)計報告

加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

名稱:羽毛球計分器Basys3開發(fā)板verilog代碼帶設(shè)計報告(代碼在文末下載)

軟件:VIVADO

語言:VHDL

代碼功能:

羽毛球計分器:

1、計分器可以同時顯示2位選手的分?jǐn)?shù),每個選手的分?jǐn)?shù)通過1bit的輸入按鍵信號控制,按一次加一分,一共2個按鍵對應(yīng)2個不同的分?jǐn)?shù)。

2、分?jǐn)?shù)最高為21分,誰先達(dá)到21分則獲勝,比賽結(jié)束,同時通過LED顯示獲勝的選手。

3、分?jǐn)?shù)通過7段數(shù)碼管顯示,一共4個數(shù)碼管,其中2個顯示選手1的分?jǐn)?shù),另外2個顯示選手2的分?jǐn)?shù)。

4、分?jǐn)?shù)達(dá)到21分后顯示持續(xù)5秒后自動清零,或者有復(fù)位信號也會清零。

FPGA代碼Verilog/VHDL代碼資源下載:www.hdlcode.com

本代碼已在Basys3開發(fā)板驗證,開發(fā)板如下,其他開發(fā)板可以修改管腳適配:

basys3開發(fā)板.png

演示視頻:

設(shè)計報告文檔(節(jié)選,完整報告付費(fèi)后可下載):

羽毛球計分器設(shè)計報告(節(jié)選)

一、摘要

本題目要求設(shè)計使用VHDL語言設(shè)計一個羽毛球計分器,計分器可以同時顯示2位選手的分?jǐn)?shù),每個選手的分?jǐn)?shù)通過1bit的輸入按鍵信號控制,按一次加一分,一共2個按鍵對應(yīng)2個不同的分?jǐn)?shù)。分?jǐn)?shù)最高為21分,誰先達(dá)到21分則獲勝,比賽結(jié)束,同時通過LED顯示獲勝的選手。分?jǐn)?shù)通過7段數(shù)碼管顯示,一共4個數(shù)碼管,其中2個顯示選手1的分?jǐn)?shù),另外2個顯示選手2的分?jǐn)?shù),分?jǐn)?shù)達(dá)到21分后顯示持續(xù)5秒后自動清零,或者有復(fù)位信號也會清零。通過這個計分器可以用來在羽毛球比賽中計分。

二、概述

本報告設(shè)計的是一個羽毛球計分器,可記錄并顯示2個選手分?jǐn)?shù),每個選手的分?jǐn)?shù)通過1bit的輸入按鍵信號控制,按一次加一分,一共2個按鍵對應(yīng)2個不同的分?jǐn)?shù)。分?jǐn)?shù)最高為21分,誰先達(dá)到21分則獲勝,比賽結(jié)束,同時通過LED顯示獲勝的選手。分?jǐn)?shù)通過7段數(shù)碼管顯示,一共4個數(shù)碼管,其中2個顯示選手1的分?jǐn)?shù),另外2個顯示選手2的分?jǐn)?shù),分?jǐn)?shù)達(dá)到21分后顯示持續(xù)5秒后自動清零,或者有復(fù)位信號也會清零。

本工程代碼一共可以分為3個模塊,分別為頂層模塊badminton_scoreboard、計分模塊badminton_score和顯示模塊display。其中計分模塊根據(jù)按鍵控制對應(yīng)選手的分?jǐn)?shù),按一次加1分,加到21分獲勝并不再增加,并且需要控制獲勝后的led指示燈和獲勝后持續(xù)5秒后返回初始狀態(tài)。顯示模塊用于將計分模塊的二進(jìn)制分?jǐn)?shù)轉(zhuǎn)換為便于數(shù)碼管顯示的BCD碼分?jǐn)?shù),然后控制數(shù)碼管的位選信號和段選信號分別顯示AB兩組選手的分?jǐn)?shù)(分為個位和十位顯示)。頂層模塊調(diào)用計分模塊和顯示模塊,將計分模塊的分?jǐn)?shù)輸入到顯示模塊,其他信號連接到外部IO接口。

三、頂層模塊

頂層模塊badminton_scoreboard的實體定義如下:

entity badminton_scoreboard is

Port ( clk : in STD_LOGIC;

bit_sel : out STD_LOGIC_VECTOR (3 downto 0);

seg_sel : out STD_LOGIC_VECTOR (7 downto 0);

reset : in STD_LOGIC;

player_A_point : in STD_LOGIC;

player_B_point : in STD_LOGIC;

win_A_led : out STD_LOGIC;

win_B_led : out STD_LOGIC);

end badminton_scoreboard;

頂層模塊輸入包括時鐘clk信號,復(fù)位reset信號,2個按鍵player_A_point和player_B_point。輸出為2個led燈win_A_led和win_B_led,2個數(shù)碼管控制信號bit_sel和seg_sel ,其中bit_sel為4bit,控制當(dāng)前顯示哪個數(shù)碼管,seg_sel為8bit信號,控制當(dāng)前點亮的數(shù)碼管的顯示值,通過bit_sel信號的時分復(fù)用可以使4個數(shù)碼管同時顯示不同的值。頂層模塊調(diào)用計分模塊和顯示模塊,用于將兩個模塊連接,代碼如下:

--call Scoring module

U_badminton_score: badminton_score

PORT MAP(

clk ? ? ? ? ? ? =>clk,

reset ? ? ? ? ? =>reset,--reset

player_A_point ?=>player_A_point,--player_A_point key

player_B_point ?=>player_B_point,--player_B_point key

score_A ? ? ? ? =>score_A,----A score

score_B ? ? ? ? =>score_B,----B score

win_A_led ? ? ? =>win_A_led,--A win LED

win_B_led ? ? ? =>win_B_led--B win LED

);

--call Display module

U_display: display

PORT MAP(

clk ? ? ? ? =>clk,

score_A ? ? =>score_A,--A score

score_B ? ? =>score_B,--B score

bit_sel ? ? =>bit_sel,--Digital tube position selection

seg_sel ? ? =>seg_sel--Digital tube section selection

);

首先調(diào)用Scoreboard模塊,可以得到2個選手的分?jǐn)?shù),即score_1信號和score_2信號,再調(diào)用數(shù)碼管顯示模塊segment_display,將score_1信號和score_2信號輸入到segment_display模塊中,最終通過7segment_display的bit_select和lednum_select信號進(jìn)行顯示。

四、計分模塊

計分模塊的輸入包括時鐘clk信號,復(fù)位reset信號,2個按鍵player_A_point和player_B_point。輸出為2個led燈LED_1和LED_2,和2個分?jǐn)?shù)信號score_1和score_2。

實體定義如下:

--Scoring module

ENTITY badminton_score IS

PORT (

clk ? ? ? ? ? ? : IN STD_LOGIC;

reset ? ? ? ? ? : IN STD_LOGIC;--reset

player_A_point ?: IN STD_LOGIC;--player_A_point key

player_B_point ?: IN STD_LOGIC;--player_B_point key

score_A ? ? ? ? : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);----A score

score_B ? ? ? ? : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);----B score

win_A_led ? ? ? : OUT STD_LOGIC;--A win LED

win_B_led ? ? ? : OUT STD_LOGIC--B win LED

);

END badminton_score;

為了控制按鍵按下后加一分,可以通過一個process進(jìn)程,判斷按鍵是否按下然后控制分?jǐn)?shù)加1,但是由于按鍵信號相對于時鐘信號是一個持續(xù)時間很長的信號,所以需要將按鍵信號縮短為只持續(xù)一個時鐘周期的信號,可以通過檢測按鍵上升沿實現(xiàn)。實現(xiàn)方法如下:

Basys3板子上一個有4個數(shù)碼管,四個數(shù)碼管有4個位選信號控制當(dāng)前點亮哪個數(shù)碼管,然后4個數(shù)碼管共用8位段選信號。因此需要通過時分復(fù)用的方式依次點亮4個數(shù)碼管才能同時顯示4個數(shù)字。Basys3板子上的數(shù)碼管位選為低電平選中,即低電平時顯示,高電平時不顯示。段選信號也是低電平點亮,高電平熄滅。如下圖所示,圖中可以看到,若要顯示數(shù)字0,需要將ABCDF全部點亮,G和DP不點亮,因此,按DP,G,F(xiàn),E,D,C,B,A的順序就是11000000。即十六進(jìn)制的C0。

設(shè)計代碼如下:

PROCESS (clk)

BEGIN

五、Testbench

Testebnch用于產(chǎn)生仿真測試激勵,即模擬頂層模塊的輸入時鐘、復(fù)位、按鍵A、按鍵B

等信號,觀察輸出的信號是否正確。由于testbench是一個模擬輸入,所以實體可以是空的,如下:

entity test is

-- ?Port ( );

end test;

然后調(diào)用頂層模塊

u_badminton_scoreboard:badminton_scoreboard

Port MAP(

clk =>clk,

bit_sel =>bit_sel,

seg_sel =>seg_sel,

reset =>reset,

player_A_point =>player_A_point,

player_B_point =>player_B_point,

win_A_led =>win_A_led,

win_B_led =>win_B_led

);

根據(jù)要求,模擬的時鐘信號為1KHz,如下,500us高電平和500us低電平:

PROCESS

BEGIN

clk <= '0';

WAIT FOR 500 us;

clk <= '1';

WAIT FOR 500 us;

END PROCESS;

根據(jù)計分器的實際功能,設(shè)計激勵信號為:先復(fù)位,使代碼初始化,然后重復(fù)按下10次player_A_point按鍵,模塊A選手贏得10分,然后重復(fù)按下10次player_B_point按鍵,模塊B選手贏得10分,最后再重復(fù)按下12次player_A_point按鍵,模塊A選手贏得12分。使A分?jǐn)?shù)可以達(dá)到21,以觀察得到21分后的信號變化,對應(yīng)的testebnch代碼如下:

六、仿真圖結(jié)果

使用上述testbench仿真,分別看計分模塊和數(shù)碼管顯示模塊。

1.計分模塊仿真

下圖為計分模塊的仿真圖

上圖中,reset信號為高電平后,score_A和score_B均為0,表示復(fù)位,分?jǐn)?shù)清零。

隨后player_A_point信號和player_B_point分別交替產(chǎn)生10個個高電平脈沖,AB對應(yīng)的分?jǐn)?shù)也由0依次變?yōu)?0。然后只有player_A_point信號繼續(xù)再來12個高電平脈沖。A的分?jǐn)?shù)繼續(xù)增長達(dá)到21后,在來高電平脈沖分?jǐn)?shù)不再增加。并且在A分?jǐn)?shù)為21后,win_LED_A拉高,表示A獲勝。并且一直持續(xù)了5秒后自動清零。從上面兩個仿真圖可以看到計分模塊實現(xiàn)了模塊對應(yīng)功能,仿真正確。

2. 數(shù)碼管顯示模塊仿真

下圖中score_A、score_B是輸入的8位二進(jìn)制分?jǐn)?shù),d2表示分?jǐn)?shù)A的十位,d2表示分?jǐn)?shù)B的個位,c2表示分?jǐn)?shù)score_B的十位,c1表示score_B的個位。圖中當(dāng)score_A為19時,對應(yīng)d2=1,d1=9,十位和個位均正確。

下圖中bit_sel依次產(chǎn)生低電平信號,選通對應(yīng)數(shù)碼管。當(dāng)數(shù)碼管顯示0時段選信號seg_sel等于十六進(jìn)制的C0。顯示1時為十六進(jìn)制F9。圖中當(dāng)score_A等于1、score_B等于0時,數(shù)碼管應(yīng)該顯示01,00,故對應(yīng)的編碼值為,C0,F(xiàn)9,C0,C0,與仿真圖一致。故數(shù)碼管顯示模塊仿真正確。

七、綜合即實現(xiàn)結(jié)果

對代碼進(jìn)行綜合實現(xiàn),結(jié)果如下圖所示

資源消耗LUT為113,F(xiàn)F為104,IO為18,BUFG為1.

八、結(jié)論

本設(shè)計使用VHDL設(shè)計了羽毛球計分器,系統(tǒng)分為3個部分,分別為頂層模塊、計分模塊、顯示模塊。頂層模塊調(diào)用計分模塊和顯示模塊,用于將兩個模塊連接,使其組合到一起。經(jīng)過testbench仿真,計分模塊完成了根據(jù)按鍵控制對應(yīng)選手的分?jǐn)?shù),并且需要控制獲勝后的led指示燈和獲勝后持續(xù)5秒后返回初始狀態(tài)。顯示模塊完成了將計分模塊的分?jǐn)?shù)轉(zhuǎn)換為數(shù)碼管顯示的內(nèi)容。最終仿真結(jié)果表明程序?qū)崿F(xiàn)了網(wǎng)球計分器的全部功能。

部分代碼展示:

LIBRARY?ieee;
???USE?ieee.std_logic_1164.all;
???USE?ieee.std_logic_unsigned.all;
--Scoring?module
ENTITY?badminton_score?IS
???PORT?(
??????clk?????????????:?IN?STD_LOGIC;
??????reset???????????:?IN?STD_LOGIC;--reset?
??????player_A_point??:?IN?STD_LOGIC;--player_A_point?key
??????player_B_point??:?IN?STD_LOGIC;--player_B_point?key
??????score_A?????????:?OUT?STD_LOGIC_VECTOR(7?DOWNTO?0);----A?score
??????score_B?????????:?OUT?STD_LOGIC_VECTOR(7?DOWNTO?0);----B?score
??????win_A_led???????:?OUT?STD_LOGIC;--A?win?LED
??????win_B_led???????:?OUT?STD_LOGIC--B?win?LED
???);
END?badminton_score;
ARCHITECTURE?behave?OF?badminton_score?IS
???
???SIGNAL?player_A_point_temp1?:?STD_LOGIC?:=?'0';
???SIGNAL?player_A_point_temp2?:?STD_LOGIC?:=?'0';
???
???SIGNAL?player_B_point_temp1?:?STD_LOGIC?:=?'0';
???SIGNAL?player_B_point_temp2?:?STD_LOGIC?:=?'0';
???
???SIGNAL?A_point_add??????????:?STD_LOGIC;
???SIGNAL?B_point_add??????????:?STD_LOGIC;
???
???SIGNAL?count????????????????:?STD_LOGIC_VECTOR(15?DOWNTO?0)?:=?"0000000000000000";
???
???SIGNAL?score_A_temp????????:?STD_LOGIC_VECTOR(7?DOWNTO?0);
???SIGNAL?score_B_temp????????:?STD_LOGIC_VECTOR(7?DOWNTO?0);
???
???SIGNAL?A_win_flag??????????:?STD_LOGIC:='0';
???SIGNAL?B_win_flag??????????:?STD_LOGIC:='0';
BEGIN
???score_A?<=?score_A_temp;--Output?score?A
???score_B?<=?score_B_temp;--Output?score?B
???
???--D?trigger?to?synchronization?of?player_A_point
???PROCESS?(clk)
???BEGIN
??????IF?(clk'EVENT?AND?clk?=?'1')?THEN
?????????player_A_point_temp1?<=?player_A_point;
?????????player_A_point_temp2?<=?player_A_point_temp1;
??????END?IF;
???END?PROCESS;
???
???--D?trigger?to?synchronization?of?player_B_point
???PROCESS?(clk)
???BEGIN
??????IF?(clk'EVENT?AND?clk?=?'1')?THEN
?????????player_B_point_temp1?<=?player_B_point;
?????????player_B_point_temp2?<=?player_B_point_temp1;
??????END?IF;
???END?PROCESS;
???
???A_point_add?<=?player_A_point_temp1?AND?(NOT(player_A_point_temp2));--Rising?edge?of?key?A
???B_point_add?<=?player_B_point_temp1?AND?(NOT(player_B_point_temp2));--Rising?edge?of?key?B
??
???--Time?5?seconds
???PROCESS?(clk)
???BEGIN
??????IF?(clk'EVENT?AND?clk?=?'1')?THEN
?????????IF?(reset?=?'1')?THEN--reset
????????????count?<=?"0000000000000000";
?????????ELSIF?(A_win_flag?=?'1'?OR?B_win_flag?=?'1')?THEN--win?flag?for?A?or?B
????????????count?<=?count?+?"0000000000000001";--count?to?5?seconds
?????????ELSE
????????????count?<=?"0000000000000000";
?????????END?IF;
??????END?IF;
???END?PROCESS;
???
???--Control?A's?score
???PROCESS?(clk)
???BEGIN
??????IF?(clk'EVENT?AND?clk?=?'1')?THEN
?????????IF?(reset?=?'1')?THEN
????????????score_A_temp?<=?"00000000";
????????????A_win_flag<='0';--clera?A?flag
?????????ELSIF?(count?=?"0001001110001000")?THEN--if?count=5000,clk?=1KHz?count?for?5000?means?5seconds
????????????score_A_temp?<=?"00000000";--reset?scoreA
????????????A_win_flag<='0';--clera?A?flag
?????????ELSIF?(score_A_temp?>=?"00010101"??and?(score_A_temp-score_B_temp)>="00000010"?and?(score_A_temp>score_B_temp))?THEN--when?score?is?more?then?21?and?bigger?then?2
???????????????score_A_temp?<=?score_A_temp;--21
???????????????A_win_flag<='1';--A?win?flag
?????????ELSIF?(A_point_add?=?'1')?THEN--add?key
--????????????IF?(score_A_temp?>=?"00010101"??and?(score_A_temp-score_B_temp)>="00000010"?and?(score_A_temp>score_B_temp))?THEN--when?score?is?more?then?21?and?bigger?then?2
--???????????????score_A_temp?<=?score_A_temp;--21
--???????????????A_win_flag<='1';--A?win?flag
--????????????ELSE
???????????????score_A_temp?<=?score_A_temp?+?"00000001";--increase?one?
--????????????END?IF;
?????????ELSE
????????????score_A_temp?<=?score_A_temp;--keep
?????????END?IF;
??????END?IF;
???END?PROCESS;
???
???--Control?B's?score
???PROCESS?(clk)
???BEGIN
??????IF?(clk'EVENT?AND?clk?=?'1')?THEN
?????????IF?(reset?=?'1')?THEN
????????????score_B_temp?<=?"00000000";
?????????????B_win_flag<='0';--clera?B?flag
?????????ELSIF?(count?=?"0001001110001000")?THEN--if?count=5000,clk?=1KHz?count?for?5000?means?5seconds
????????????score_B_temp?<=?"00000000";--reset?score?B
?????????????B_win_flag<='0';--clera?B?flag????????
?????????ELSIF?(score_B_temp?>=?"00010101"??and?(score_B_temp-score_A_temp)>="00000010"?and?(score_B_temp>score_A_temp))?THEN--when?score?is?more?then?21?and?bigger?then?2
????????????????score_B_temp?<=?score_B_temp;--when?21?keep?21
????????????????B_win_flag<='1';--B?win?flag
?????????ELSIF?(B_point_add?=?'1')?THEN--add?key
--????????????IF?(score_B_temp?>=?"00010101"??and?(score_B_temp-score_A_temp)>="00000010"?and?(score_B_temp>score_A_temp))?THEN--when?score?is?more?then?21?and?bigger?then?2
--???????????????score_B_temp?<=?score_B_temp;--when?21?keep?21
--???????????????B_win_flag<='1';--B?win?flag
--????????????ELSE
???????????????score_B_temp?<=?score_B_temp?+?"00000001";--increase?one?
--????????????END?IF;
?????????ELSE
????????????score_B_temp?<=?score_B_temp;--keep
?????????END?IF;
??????END?IF;
???END?PROCESS;

代碼文件及完整設(shè)計報告(付費(fèi)下載):

點擊鏈接獲取代碼文件:http://www.hdlcode.com/index.php?m=home&c=View&a=index&aid=287

相關(guān)推薦