每按同乙個按鍵時會隨機得到乙個1—6中的乙個隨機數字,並用數碼管顯示得到的數值。對兩次按鍵得到的數值進行比較,若前者大,則最低兩位led顯示為「亮」、「滅」,後者較大,則最後兩位led顯示狀態改為「滅」、「亮」。
本次課程設計的實質是使數碼管隨機顯示乙個數字,以達擲骰子時隨機出數的效果,因此在小組討論並查閱資料後我們總結出以下兩種方案:
1. 查詢fpga中是否含有類似於c語言中rand()的隨機函式,並搞清楚其用法和效果,弄清楚後進行實驗,並在按下按鍵後使隨機函式發生作用,並顯示該資料,再將資料存入內部變數,並在其內部進行比較,將比較結果對映到led最後兩位進行顯示。
2. 類似於***一樣,讓數碼管顯示1~6六個數字,並高速滾動,然後通過按鍵暫停並顯示,由於數碼管顯示數字在高速滾動狀態下,人眼無法準確分清楚此時是什麼數字,所以根據概率學來說六個數字每個具有等可能性,這樣就能保證暫停的數字具有隨機性,儲存和比較模組原理與方案1相似。
方案選擇
由於第一種方案在實施起來時沒有像第二種的***一樣,使人感覺有互動性,並且用函式隨機顯示數字會讓人感覺突兀,並像是在「出千」。因此我們選用第二種方案進行本次課程設計
由於cyclone iv板載系統時鐘為50mhz,時鐘頻率過大,無法表現出程式效果(或者效果不明顯),所以我們需要分頻。
分頻器原理:以系統時鐘上公升沿為標準,對系統時鐘的上公升沿計數,並給出乙個訊號變數(或普通變數)給出初值,計夠一定次數以後對其變數電平反轉,即通過電平反轉重新造出來乙個方波,以達到分頻的目的。例如:對50mhz時鐘二分頻,就是對系統時鐘上公升沿計數,當機構2499999個數時對電平變數chz1進行反轉,即可得到乙個以0.5ms為週期的方波,則分頻計算公式:
分頻器程式:
ck:process(clk) --分頻器程式
begin
ifrising_edge(clk) then
ift="0000011010111100000111111" then—此處數值沒有具體計算
t<="0000000000000000000000000";
clk1hz<=notclk1hz;
else
t<=t+1;
endif;
endif;
end process ck;
結構體中數字掃瞄:將數字掃瞄模組寫在結構體中,使fpga在執行程式時能夠迴圈掃瞄數字,使數碼管高速滾動數字。達到每個在暫停時,停止的每個數字具有等可能性。
結構體中數字掃瞄:
output<="1111001"wheninput="0001"else—本程式寫在結構體的begin下
"0100100"wheninput="0010"else
"0110000"wheninput="0011"else
"0011001"wheninput="0100"else
"0010010"wheninput="0101"else
"0000011"wheninput="0110";
程序中數字掃瞄:定義中間變數,對其進行1-6的迴圈加一計數,然後再將其送到數碼管顯示。
程序中數字掃瞄:
if (clk1hz'event and clk1hz='1')then
if(a='1' and b='1') then
tmp:=tmp+1;
if(tmp=7) then
tmp:=1;
endif;
case tmp is
when 1=> input<="0001";
when 2=> input<="0010";
when 3=> input<="0011";
when 4=> input <="0100";
when 5=> input<="0101";
when 6=> input<="0110";
when others => input<="0000";
end case;
endif;
end if;
本次課程設計我們想用撥碼開關以代替按鍵,本以為撥碼開關不需要按鍵消抖但最終的實驗效果卻不盡如人意,仍需要按鍵消抖,所以本次設計時我們改了一下,利用兩個按鍵對其進行暫停。如果用乙個按鍵或撥碼開關,必須要加按鍵消抖,否則會有一定干擾。
消抖原理:類似於51微控制器按鍵消抖,先檢驗其是否按下,若被按下則延時一定時間,將其電平振盪的時間「濾」掉(在fpga則數5ms的系統時鐘過濾掉電平振盪的時間)。
按鍵暫停以及儲存程式:
if(a='0') then
tim:=tim+1;
if(tim=1) then
ran1<=tmp;
elsif(tim=2) then
ran2<=tmp;
endif;
endif;
注意:本模組程式未加按鍵消抖程式,如用單一按鍵需對按鍵加消抖程式。
乙個按鍵的暫停草稿程式(加有消抖,但並未實踐)
if(a='0') then
ifrising_edge(clk) then
ift="0010011010111100000111111" then--此處數值沒有具體計算
t<="0000000000000000000000000";
else
t<=t+1;
endif;
endif;
waituntil(t=」0010011010111100000111111」);
if(a=」0」)then
tim:=tim+1;
if(tim=1) then
ran1<=tmp;
elsif(tim=2) then
ran2<=tmp;
endif;
endif;
end if
在程式內部定義兩個變數(由於總開關為閉合狀態所以不用考慮掉電保護問題),用於儲存先後兩次按鍵按下的數字,然後對其變數進行比較若前者較大對映到led則最後兩個燈顯示為「亮」、「滅」,反之後者大則led顯示為「滅」、「亮」。
比較模組程式:
compare:process(ran1,ran2)
begin
if (ran1>ran2) then
led<="01";
elsif (ran1led<="10";
elsif (ran1=ran2) then
led<="00";
end if;
end process compare;
在本次設計中,我們對兩種方案進行考量,最終選擇較為方便實現的方案,並且具有一定互動性。個人認為該方案的實現效果更好,但唯一的遺憾就是沒有用乙個按鍵實現數字暫停。因為在當時的情況下本人事情較多,無法考慮更多的情況,對於消抖的延時沒有想清楚原理,所以沒有大膽的實踐。時間緊任務重只能選擇最優方案。
模擬擲骰子(Python)
模擬擲骰子實際是抽取 1 6之間的 隨機數問題,涉及random模組,後面版本的資料視覺化主要應用matplotlib.pyplot模組。1.0 模擬乙個骰子的結果。首先定義roll dice 函式,從1 6之間隨機抽取乙個整數作為擲骰子的結果。在主函式中定義乙個長度為6的列表 初始值為0 記錄每個...
使用Pygal模擬擲骰子
將使用python視覺化包pygal來生成可縮放的向量圖形檔案。對於需要在尺寸 不同的螢幕上顯示的圖表,這很有用,因為它們將自動縮放,以適合 者的螢幕。使用pygal來建立直方圖 from random import randint class die 表示乙個骰子的類 def init self,...
leetcode演算法題 擲骰子模擬
動態規劃 dp i j k 表示投擲第i次,點數為j,k表示連續次數狀態轉移 j出現一次的組合數等於上一輪投出非點數j的所有情況和 dp i j 1 sum dp i 1 j 本輪投出連續k次的點數j的數量情況等於上一輪連續投出k 1次的點數j的數量情況 dp i j k dp i 1 j k 1 ...