名稱:羽毛球計分器Basys3開發(fā)板verilog代碼帶設(shè)計報告(代碼在文末下載)
軟件:VIVADO
語言:VHDL
代碼功能:
羽毛球計分器:
1、計分器可以同時顯示2位選手的分數(shù),每個選手的分數(shù)通過1bit的輸入按鍵信號控制,按一次加一分,一共2個按鍵對應(yīng)2個不同的分數(shù)。
2、分數(shù)最高為21分,誰先達到21分則獲勝,比賽結(jié)束,同時通過LED顯示獲勝的選手。
3、分數(shù)通過7段數(shù)碼管顯示,一共4個數(shù)碼管,其中2個顯示選手1的分數(shù),另外2個顯示選手2的分數(shù)。
4、分數(shù)達到21分后顯示持續(xù)5秒后自動清零,或者有復(fù)位信號也會清零。
FPGA代碼Verilog/VHDL代碼資源下載:www.hdlcode.com
本代碼已在Basys3開發(fā)板驗證,開發(fā)板如下,其他開發(fā)板可以修改管腳適配:
演示視頻:
設(shè)計報告文檔(節(jié)選,完整報告付費后可下載):
羽毛球計分器設(shè)計報告(節(jié)選)
一、摘要
本題目要求設(shè)計使用VHDL語言設(shè)計一個羽毛球計分器,計分器可以同時顯示2位選手的分數(shù),每個選手的分數(shù)通過1bit的輸入按鍵信號控制,按一次加一分,一共2個按鍵對應(yīng)2個不同的分數(shù)。分數(shù)最高為21分,誰先達到21分則獲勝,比賽結(jié)束,同時通過LED顯示獲勝的選手。分數(shù)通過7段數(shù)碼管顯示,一共4個數(shù)碼管,其中2個顯示選手1的分數(shù),另外2個顯示選手2的分數(shù),分數(shù)達到21分后顯示持續(xù)5秒后自動清零,或者有復(fù)位信號也會清零。通過這個計分器可以用來在羽毛球比賽中計分。
二、概述
本報告設(shè)計的是一個羽毛球計分器,可記錄并顯示2個選手分數(shù),每個選手的分數(shù)通過1bit的輸入按鍵信號控制,按一次加一分,一共2個按鍵對應(yīng)2個不同的分數(shù)。分數(shù)最高為21分,誰先達到21分則獲勝,比賽結(jié)束,同時通過LED顯示獲勝的選手。分數(shù)通過7段數(shù)碼管顯示,一共4個數(shù)碼管,其中2個顯示選手1的分數(shù),另外2個顯示選手2的分數(shù),分數(shù)達到21分后顯示持續(xù)5秒后自動清零,或者有復(fù)位信號也會清零。
本工程代碼一共可以分為3個模塊,分別為頂層模塊badminton_scoreboard、計分模塊badminton_score和顯示模塊display。其中計分模塊根據(jù)按鍵控制對應(yīng)選手的分數(shù),按一次加1分,加到21分獲勝并不再增加,并且需要控制獲勝后的led指示燈和獲勝后持續(xù)5秒后返回初始狀態(tài)。顯示模塊用于將計分模塊的二進制分數(shù)轉(zhuǎn)換為便于數(shù)碼管顯示的BCD碼分數(shù),然后控制數(shù)碼管的位選信號和段選信號分別顯示AB兩組選手的分數(shù)(分為個位和十位顯示)。頂層模塊調(diào)用計分模塊和顯示模塊,將計分模塊的分數(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個選手的分數(shù),即score_1信號和score_2信號,再調(diào)用數(shù)碼管顯示模塊segment_display,將score_1信號和score_2信號輸入到segment_display模塊中,最終通過7segment_display的bit_select和lednum_select信號進行顯示。
四、計分模塊
計分模塊的輸入包括時鐘clk信號,復(fù)位reset信號,2個按鍵player_A_point和player_B_point。輸出為2個led燈LED_1和LED_2,和2個分數(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進程,判斷按鍵是否按下然后控制分數(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。即十六進制的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分數(shù)可以達到21,以觀察得到21分后的信號變化,對應(yīng)的testebnch代碼如下:
六、仿真圖結(jié)果
使用上述testbench仿真,分別看計分模塊和數(shù)碼管顯示模塊。
1.計分模塊仿真
下圖為計分模塊的仿真圖
上圖中,reset信號為高電平后,score_A和score_B均為0,表示復(fù)位,分數(shù)清零。
隨后player_A_point信號和player_B_point分別交替產(chǎn)生10個個高電平脈沖,AB對應(yīng)的分數(shù)也由0依次變?yōu)?0。然后只有player_A_point信號繼續(xù)再來12個高電平脈沖。A的分數(shù)繼續(xù)增長達到21后,在來高電平脈沖分數(shù)不再增加。并且在A分數(shù)為21后,win_LED_A拉高,表示A獲勝。并且一直持續(xù)了5秒后自動清零。從上面兩個仿真圖可以看到計分模塊實現(xiàn)了模塊對應(yīng)功能,仿真正確。
2. 數(shù)碼管顯示模塊仿真
下圖中score_A、score_B是輸入的8位二進制分數(shù),d2表示分數(shù)A的十位,d2表示分數(shù)B的個位,c2表示分數(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等于十六進制的C0。顯示1時為十六進制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é)果
對代碼進行綜合實現(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)選手的分數(shù),并且需要控制獲勝后的led指示燈和獲勝后持續(xù)5秒后返回初始狀態(tài)。顯示模塊完成了將計分模塊的分數(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è)計報告(付費下載):
點擊鏈接獲取代碼文件:http://www.hdlcode.com/index.php?m=home&c=View&a=index&aid=287