Profile - TW062


TW062

B3 - Bouncing Ball Box



Semi-Finals


[print]


Project Paper - view as Preliminary(2010/07/21), Final(2010/11/01), Draft, Latest

1. 設計介紹 (Preliminary Paper)

概念 :

   
        本專案目標將嘗試以數位電路體現一個實體迷宮球環境(見圖1.1.jpg)。概念上是一個800*480*240的空間,內部含有一個球體以及各種障礙物場景資訊。
 
觀察與操作方式 :
 
使用者可透過小螢幕觀測場景內部球體移動的過程,並透過手持含有加速度儀晶片的模組,直接對球體產生物理影響。
也就是說一般情況下,使用者直接透過加速度晶片與系統互動。在需要更改系統參數時,可透過觸控式螢幕選擇與更改參數。
參數包含場景資訊、顯示截面小地圖、反射、摩擦等物理性質參數。
 
設計目的
本設計主要為娛樂取向,因實體迷宮球占有一定體積、且場景無法作太大變化。透過軟體的實現,其多樣性可以大幅度增加,只要使用者介面以及控制方式與實體物件沒有兩樣,且特效元素足夠,相信本設計有相當潛力打進迷宮球市場。
 
應用領域
本設計核心主要是在點投影顯示以及物理模型中碰撞、摩擦、牛頓運動定律的描述上,因此,只要與這些領域有相關的應用,本設計皆可作簡單擴充後支援。
 
 
目標使用者
任何對新奇事物具有好奇心的年輕人、物理教學者、物理學習者。
 
使用資源 :
 
透過整合LTM (LCD Touch panel Module)、Accelerometer 、以及各類記憶體模組,達成物理性質計算、顯示、以及生動的使用者互動功能。同時為了作這些晶片、硬體資源的整合,我們需要一個足夠強大的FPGA系統先來測試,恰好Altera DE系列多媒體平台上剛好具有我們所需要的大部分資源,因此我們便決定使用該系統當作我們的測試平台。
 
 
 
研究課題:
          
繪圖方面:
 
i.關於視覺效果
 
顯示方面,我們需要對立體場景點投影到螢幕上才能達到我們所需要的立體空間視覺效果。另外,各種物件相互遮蔽的問題也是影響視覺效果的因素。主要就是在考慮如何在一個平面螢幕上協助使用者對球體所在位置附近的空間資訊正確判斷。
我們也會在適當時候顯示球體位置附近的截面空間小地圖,以彌補單一營幕顯示三維場景的不足。
 
ii.為了動畫的顯示流暢,每一幀的顯示物件我們要求全部繪製完成需在1/30秒內
 
 
iii為了避面顯示貼圖的破碎,我們會實現一個顯示雙緩衝來提升顯示的效能,一方面避免寫入與讀取的速率同步的限制,一方面增加畫面繪圖的彈性。
 
 
物理方面:
i.三維多角度反彈
我們需要處理物件物理上的多角度碰撞反彈問題
ii.同樣為了動畫的顯示流暢,我們需盡量減少物理計算所耗費的時間,同時也須兼顧虛擬空間與實體功間中物理特性的校正,譬如加速度以及速度資訊。
          
系統整合方面:
各種不同的硬體資源之間,像是LTM與SDRAM、SSRAM與flash等,溝通方式以及執行速率均有不同。要設計使得各模組間相互溝通能順利進行,是最基本且重要的考量。 
(Revision: 6 / 2010-06-30 23:42:00)

2. 功能描述 (Final Project Paper)

3. 效能參數 (Final Project Paper)

4. 設計架構 (Preliminary Paper)

軟體流程圖:

 

硬體設計模擬方塊圖:


其中共分為五大部分:
黃色:所有外連設備(觸控面板、眾記憶體)
紅色:背景寫入
綠色:物理參數處理
藍色:顯示區塊
紫色:中央控制單元,專管軟體流程與硬體間的整合

 

(Revision: 3 / 2010-06-30 23:20:14)

5. 設計方法 (Final Project Paper)

 

  
0. 前述
 0.1 文例
1. 主結構概述
 1.1 模組區塊圖
2. 特殊演算法
 2.1 物理特性計算
 2.2 三維轉二維演算法
 2.3 貼圖遮蔽演算法
 2.4 二維繪圖
3. 程式說明
3.1物理特性模組(PHYSICS.v)
3.2加速度計模組(acc_SPI.v)
3.3雙暫存緩衝模組(DOUBLE_BUFFER.v)
3.4 SDRAM初始化模組(SDRAM_init.v)
3.5 LTM模組(LTM_process.v)
3.6 SDRAM繪圖模組(DRAW_TO_SDRAM.v)
3.7貼圖遮蔽模控制組(threeDTotwoD_control.v)
3.8三維轉二維模組(threeDTotwoD.v)
3.9靜態隨機存取記憶體模組(ssram.v)
3.10快閃記憶體寫入靜態隨機存取記憶體模組(flashtossram.v)
3.11靜態隨機存取記憶體讀取模組(ssram_re.v)
3.12靜態隨機存取記憶體寫入模組(ssram_wr.v)
3.13簡易除法模組(divide.v)
 
 
 
 
 
 
 
 
 
0. 前述
本技術手冊內容為數位電路實驗期末專題,以中文來進行撰寫。唯少數無常用中文譯名的專有名詞和程式碼檔名及其內容部份,為求閱讀上的方便,將會直接以英文來表示。至於其他中文翻譯為確定的專有名詞,將會在其後以小括號註解其原文。
 
0.1 文例
 
{0,1} :大括號內名詞通常代表數字序列。
[reset] :中引號名詞通常代表該名詞意味著變數名稱。
「初始化」:引號名詞通常代表該名詞意味特殊意義,集合或事件,或是其他段落標題。
註:以下說明裡的變數名稱皆指其在所屬檔案裡的變數名稱,故可能會出現重複的現象
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1. 主結構概述
1.1 模組區塊圖
 
 
 
2. 特殊演算法
2.1 物理特性計算
反彈演算法與牛頓運動定律演算法
 
以下以pseudo code概念描述之
while(1){
 
//X,_fY_f,Z_f代表球心空間位置
//vx,vy,vz代表球體移動速度
//
//n0[k],n1[k],n2[k]代表球心到第k個偵測點的單位方向向量
//sx[k],sy[k],sz[k]代表第k個偵測點在空間中的位置
for( i=0 ; I < 60 ; ++i){
        sx[i] = X_f + 19 * n0[i];
        sy[i] = Y_f + 19 * n1[i];
        sz[i] = Z_f + 19 * n2[i];
        if( sx[i],sy[i],sz[i]組成的座標在反彈執行區域內 ) {
beep[i]=1;
have_beep = 1;}
else{
 beep[i]=0;
}
//N0,N1,N2代表概念上的反射面的方向資訊
N0 = N1 = N2 = 0;
for( i = 0 ; i<60; ++i){
        N0 +=n0[i]*beep[i];
        N1 +=n1[i]*beep[i];
        N2 +=n2[i]*beep[i];
}
 
///////////////////////////////
//v_norm_x,v_norm_y,v_norm_z代表球體速度在(N0,N1,N2)上且方向一//致的正投影,即球體速度與概念上的反射面垂直的分量。
//v_para_x,v_para_y,v_para_z代表球體速度與概念上的反射面平行的分//向。
v_norm_x =abs( ((vx*N0+vy*N1+vz*N2)/(N0*N0+N1*N1+N2*N2))) *N0;
v_norm_y =abs( ((vx*N0+vy*N1+vz*N2)/(N0*N0+N1*N1+N2*N2)))*N1;
v_norm_z = abs( ((vx*N0+vy*N1+vz*N2)/(N0*N0+N1*N1+N2*N2)))*N2;
v_para_x = vx + (-v_norm_x);
v_para_y = vy + (-v_norm_y);
v_para_z = vz + (-v_norm_z);
//new_vx,new_vy,new_vz 充當球體考慮反彈後的速度
new_vx = v_para_x * friction_ratio + (- v_norm_x * reflection_ratio);
new_vy = v_para_y * friction_ratio + (- v_norm_y * reflection_ratio);
new_vz = v_para_z * friction_ratio + (- v_norm_z * reflection_ratio);
//new_x,new_y,new_z 充當球體考慮反彈後的位置
new_x =X_f+(-v_norm_x*2);
new_y =Y_f+(-v_norm_x*2);
new_z =Z_f+(-v_norm_x*2);
//意思是果斷地將球直接移出反射區域。系數”2”為一個保險用比例
 
X =( have_beep)?new_x : (X + vx);
Y =( have_beep)?new_x : (Y + vy);
Z =( have_beep)?new_x : (Z + vz);
 
vx =( have_beep)?new_vx : limitation(vx + ax*ascale);
vy =( have_beep)?new_vy : limitation(vy+ ay*ascale);
vz =( have_beep)?new_vz : limitation(vz + az*ascale);
//limitation表示各方向速限,最大值為+1,最小值為-1,單位為像素
//ax為來自加速度儀晶片的加速度資訊ascale為虛擬空間與實體空間加 
//
速度比例校正參數
}
}
 
2.2 三維轉二維演算法
在計算球運動的方式之後,需要把它轉到螢幕上去顯示,故要將其三維座標轉換成相對應的二維座標。
    三維轉二維的做法大致上分成兩種:(1)正交投影(Orthographic projection ) (2)透視投影(Perspective projection)。此次顯示採用的是透視投影法,如下圖所示。將視點(perspective)和想要投影的點連線,再找到和投影平面的交點就是投影的結果。例如:圖中A點投影在Z = k的平面上的點就是B點。
規格設定是X軸:800Y軸:480Z軸:240(單位:像素),視點選在(400,240,1200),投影到Z = 240(單位:像素)的平面,所算出的投影公式:
其中下標代表示三維、二維,XYZ為對應的座標。
此一投影實踐於3.8 三維轉二維模組(threeDTotwoD)模組
 
2.3 貼圖遮蔽演算法
在整個長方體(座標和三維轉二維演算法相同)內將其切割成三邊大小為的立方體區塊,故總共有個,目的是將其當作最小單位,來建構障礙物,並將每一個立方體區塊的八個頂點依照下圖編號,上色時以四個頂點決定一個面,一面塗一個顏色,由於一次最多只會看到三個面,所以完全沒有邊相連的兩個面塗相同顏色。各面的編號如下表所示,在傳送每個面時,會將四頂點的XY座標分開傳。

平面編號
頂點
face1
3478
face2
12345678
face3
24681357

 
由於此小立方體在轉成二維座標去上色的時候,會有互相遮蔽的問題,如下面左右兩圖所示,其中的數字代表區塊(block)上色的順序,左邊的上色順序造成不合理的結果,因為中間多了一塊不可能看得到的顏色,要像右邊的作法,所做出來的圖才是正確的的,因此,不可以就照座標順序一直畫下去,須想方法讓它們的遮蔽關係是合理的。
          
    最簡單的解決方法就是從距離視點最遠的區塊塗到距離最近的區塊,由於在不同Z值上的區塊直接照順序就剛好是從遠排到近,故不必特別去排序。而不同XY得排序法會因為所處的區域不同,造成須有不同的順序,因此把其分成四大區域(1,2,3,4),如下圖所示。在各區域只要依照箭頭所示的方向依序上色,所畫出的結果就是合理的,可以由下圖看出先畫X還是Y是沒有影響的,不過,實踐上是先畫X再畫Y再畫Z,比較符合一般的直覺。
此一演算法實踐於” 3.7 貼圖遮蔽模控制組(threeDTotwoD_control)模組,其中每一個區塊是以最靠近原點的頂點(以三維座標而言)為代表。
 
2.4 二維繪圖
此演算法為將一完整立體圖形在特定視角下可見的三個面,其四個座標點的資料分別轉為一整面的離散座標點,並將其寫入靜態隨機存取記憶體(ssram,以下簡稱為記憶體)中。首先見下圖:
    此圖表示了原始四點的資料分佈位置,其預定形成的面共有三種情況,在圖中以三種不同的顏色來表示,輸入的順序皆為圖上標示數字的由小而大。此三種情況分別為正方形和兩個分別在X方向以及Y方向平行的梯形。由於記憶體的寫入一次只能寫入一個單位(cell)的資訊,故此處形成面的每一座標點皆需一個一個依序寫入。
    此處採用的是逐行分別寫入的方式,此處行代表與四邊形平行邊平行的方向。首先須先將原始四點座標分類為起始邊和結束邊,每當其中一行寫入完成後便沿起始邊和結束邊跟新此次行輸入的起始和結束位置,跟新方式為列座標加一、行座標加斜率值,並重新寫入下一行,直到完成整個四邊形的寫入。逐行移動的方向為上圖標示編號的由小到大,當三個方向的面皆完成後便可得到一立方體的平面視圖。
    但是需注意輸入的點順序和其所形成的面的位置關係會因為原本的立方體所在的位置而不同,共會有以下四種情況:
因此當每一行的起始點在作列方向移動時,需考慮行方向的座標值移動方向,此部份可透過計算斜率時帶有正負號來完成。以下為簡易流程圖:
此演算法可以透過有限狀態機(finite state machine)來達成。
3. 程式說明
3.1物理特性模組(PHYSICS.v)
介面:

變數名
類型
大小(bits)
說明
clk
輸入
1
時序資訊,用以驅動本模組。本次實作本模組的操作頻率為10MHz
reset
輸入
1
初始化命令參數,邏輯值為{0}時及執行本模組的初始化動作。
ax,ay,az
輸入
8
來自acc_SPI模組的加速度儀晶片所偵測到的三方向加速度資訊,格式為8位元的2補數。
X,Y,Z
輸出
32
當前球體空間位置,格式為2補數,但本次實作理論實際數字範圍皆為0~800的正數。
cube_x_cnt,
cube_y_cnt,
cube_z_cnt
輸入
5
4
3
threeDTotwoD_control模組在此模組中查詢空間資訊的相關參數,供空間資訊繪圖參考
fill
輸出
1
回應threeDTotwoD_control模組在此模組中查詢空間資訊的相關參數
<以下均為測試用參數,對外沒有實質應用功能>
user_X_f,
user_Y_f,
user_Z_f
輸入
32
用以測試偵測點計算模組(SENSOR_OPERATION)正確性的測資輸入,一開始作用是由測試者決定球心座標。
count_wire
輸出
11
用以觀測相態
N0,N1,N2
輸出
32
內部線路,用以溝通計算出的反射方向,格式為IEEE-754 Floating Point
id0, ids0
輸出
7
內部傳遞參數,與cube_x_cnt功能相同。
n0,ns0
輸出
32
內部傳遞參數,與fill功能相同
have_beep
輸出
1
內部傳遞參數,是偵測點計算模組(SENSOR_OPERATION)用以告知移動計算模組(CAL_MOVE)球體是否該發生碰撞行為。
out_test
輸出
1
輸出時序信號供測試參考。

 

PHYSICS
CAL_MOVE
SENSOR_OPERATION
AREA_MAP
NORMAL_VECTOR
acc_SPI
DRAW_TO_SDRAM
ThreeDTotwoD_control
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


 

重要資料流向示意
說明:
上圖,本模組包含若干子模組,SENSOR_OPERATION, CAL_MOVE, NORMAL_VECTOR,AREA_MAP四個主要子模組。對外的溝通行為包含傳送球體空間座標給DRAW_TO_SDRAM、傳送空間障礙物資訊給ThreeDTotwoD_control、以及接收acc_SPI處理的加速度偵測儀資訊。
        本模組主要功能就是計算球體的運動行為,包含位置、速度、加速度、碰撞模型,關於物理模型的詳細資訊, 2.1 物理特性計算
 
資料演算流程:
        SENSOR_OPERATION首先先以球體目前所在位置,以及NORMAL_VECTOR所提供的偵測點相對於球體位置的方向向量,推算出60個碰撞偵測點在空間中的所在位置,之後參考AREA_MAP所提供的空間資訊去判斷這六十個偵測點是否進入碰撞執行區域,進而推算出反射方向資訊。
        CAL_MOVE接著根據反射方向計算球體在下一步在空間中可能的所在位置。
        其中每一個步驟會動用到大量的浮點數運算,我們在模組內因此安排了若干個FPGA板所提供的mega function形式的浮點數整數轉換器、加法器、乘法器……等。
        以下將以圖示表示詳細資料流以及各單位所占用的運算資源與運算時間。
 
       
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 圖 總共具有三個浮點數家法器、三個浮點數乘法器、以及三個浮點數轉整數轉換器
 
SENSOR_OPERATION中,第一部分都是在處理碰撞偵測點的位置以及是否有碰撞事件發生。
    之後就是把具有碰撞事件的偵測點向量全部加總。我們善用加法器可連續指定的特性,兩兩一組連續送入,以減少每一次運算需要7cycle time在時間上耗費。最後得到的就是代表碰撞面的方向資訊向量。
 
    這個向量之後會送入CAL_MOVE中,繼續計算碰撞、牛頓運動定律以求出球體位置。
    CAL_MOVE中,具有三個浮點數乘法器、一個浮點數加法器、一個浮點數倒數器、一個浮點數轉整數轉換器(用來將浮點數座標轉至整數以傳送到DRAW_TO_SDRAM模組繪出球體)、一個整數轉浮點數轉換器(用在處理來自acc_SPI加速度資訊)以及一個浮點數大小比較器。
 
計算的排程概念同上,詳細演算流程請參閱物理特性計算相關章節。整個CAL_MOVE計算從開始到完成需要約110cycle time,加上前面SENSOR_OPERATION所需要的180cycle time,整個物理模組計算所花的時間就約花費290cycle time。在10MHzclk的驅動下,整個運算所花實體時間約為0.03ms
在外部,只要所設定的物理運算週期大於290cycle time都是在可調整的範圍內。我們目前設定一次物理運算週期為100010MHz,也就是說,物理模組的計算周期為0.1ms
 
 
 
3.2加速度計模組(acc_SPI.v)
介面:

名稱
類型
位元數
功能
reset
input
1
重置訊號,用以重設加速度計。
clk
input
1
模組所需的時脈,需為4MHz
ready
output
1
讀值改變訊號。1時為正在改變。
Xa
output
8
X方向加速度讀值。
Ya
output
8
Y方向加速度讀值。
Za
output
8
Z方向加速度讀值。
cs_o
output
1
加速度計的晶片選擇訊號。
spclk_o
output
1
加速度計SPI介面時脈。
sdio_io
inout
1
加速度計SPI介面資料。
drdy
input
1
加速度計測量完成訊號。

功能說明:
    此模組的功能是用來和外界的加速度計模組做溝通,並將其量測到的加速度值分別以XYZ三方向各8位元,二進位補數法來表示之。再設定上是用SPI介面和加速度計做聯繫,其波形如下:
http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/FreescaleMMA7455LDeviceDocumentation.pdf (figure 11&12)
其每次動作共有16個時脈週期,並以[cs]為低電位時做為一週期,其中第一個時脈送出寫入讀取訊號,後接6位元的暫存器位址,並在隔一時脈後讀入或輸出其值(8位元)
程式說明:
   整體構成為兩個有限狀態機(finite state machine),其中一個用來「重設」加速度模組的設定,另一為用來讀取加速度值,兩者以一個控制用位元[mode]來決定哪一有限狀態機的輸出訊號將外連至加速度計。
重設部份
    「重設」的部份其以[reset]為零作為起始訊號,將其狀態[step]回覆到開始狀態(0),並開始動作。
控制用特殊參數

 
ini_pattern
記錄此週期所要輸出的資料流。
ini_sel
選擇所要使用的[ini_pattern]。有關[ini_pattern]所代表的意義,請參見(http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/FreescaleMMA7455LDeviceDocumentation.pdf)

各狀態功能及動作如下:

0
起始狀態,所有控制參數回復初始值。
1~16
依序輸出[ini_pattern]的值。
17
[reg_sel]檢查是否還有需要輸入的[ini_pattern],若有則回到狀態1重新輸入。若無則進入閒置狀態。
18
閒置狀態,此時[mode]轉為1,連至實體加速度的介面轉至讀取部份。

 
讀取部份
    讀取部份則是依據由加速度計傳來的[drdy]訊號來開始動作,此訊號為加速度計量測完成的訊號,約以60Hz的頻率來變化。此外位了減少輸出值[Xa][Ya][Za]的變化時間。此處是先將讀值存取到加速度讀值緩衝[Xa_in][Ya_in][Za_in]後再一次改變。
控制用特殊參數:

 
read_pattern
記錄要讀取的暫存器位置。
reg_sel
選擇此次要讀取的暫存器。
w_counter
用來決定目前[read_pattern]的輸出位元。
r_counter
用來決定目前從[sdio_io]的讀值要寫入哪一位元。
rw
目前[sdio_io]的運作模式。(1:write0:read)

各狀態功能及動作如下:

0
起始狀態,所有控制參數回復初始值。
1~8
依序輸出[read_pattern]的值。
9~16
讀入[sdio_io]的值,並將其依序寫入加速度讀值緩衝。
17
[reg_sel]檢查是否XYZ方向加速度值都以讀取完畢,若無則回到狀態1
18
[Xa_in][Ya_in][Za_in]寫入[Xa][Ya][Za]
19
閒置狀態。等下次[drdy]為高電位時再回到狀態0

 
3.3雙暫存緩衝模組(DOUBLE_BUFFER.v)
介面:

變數名
類型
大小(bits)
說明
clk_50M
時序輸入
1
50MHz的時序信號輸入,之後會通過一個PLL變頻器產生出40MHz的時序信號供SDRAM記憶體寫入功能使用
clk_40Mo
時序輸出
1
向外送出的時序信號,目的是讓外界需要顯示功能的模組藉此達到時序同步
reset
重設
1
重至訊號,在其為邏輯0時執行重置
write_done
輸入
1
外界模組在寫入動作完成時,需藉由將write_done持續設為邏輯{1}(至少直到偵測到[turn_sign]信號變為邏輯{1}為止)告訴本模組外界寫入動作已完成,可以允許兩個記憶體讀寫角色交換
turn_sign
輸出
1
在記憶體讀寫角色交換後,本模組會對外界,以約33MHz的頻率產生一個邏輯{1}的突波告知記憶體讀寫角色已成功交換,可以進行下一回合的顯示寫入動作。
switch
輸入
1
測試期間遺留的變數,對目前功能沒有重要作用
mask
輸入
1
SDRAM記憶體寫入資料遮罩。若為邏輯{1}則表示命令SDRAM無視當前的待寫入資料:[writer_data]
 
 
 
 
writer_syq
輸出
1
本模組執行SDRAM的寫入動作時是以12[clk_40o]個時間長度為一個大回合。當writer_syq為邏輯{1}時,表示內部寫入程序正在一個大回合的最終階段,告知外界準備開始下一回合的寫入動作。關於本模組寫入回合的設計,請參照後續說明
writer_col
輸入
13
資料待寫入SDRAM的目標行位址
writer_row
輸入
13
資料待寫入SDRAM的目標列位址
writer_data
輸入
16
待寫入資料
 
 
 
 
HD
直接與LTM硬體溝通的參數,請參閱LTM_process相關章節。
VD
DEN
R
G
B
NCLK
reset_o
<以下區域為直接與兩個SDRAM硬體溝通的相關參數>
DRAM_A0
輸出
13
用以告知SDRAM寫入/讀取資料的位址資訊。
DRAM_D0
輸出/輸入
16
用以與SDRAM溝通寫入/讀取的資料內容
CLK0
輸出
1
送入控制SDRAM的時序資訊。向SDRAM寫入資料時須送入[clk_40o]的時序資訊;從SDRAM讀取資料時須送入[clk_33M]的時序資訊(LTM模組顯示頻率同步)
CKE0
輸出
1
時序開關。在本次設計為永遠設為邏輯{0},意指要求晶片永遠對時序有反應。
LDQM0
輸出
1
下八位資料讀寫遮罩,本次設計為向SDRAM寫入資料時參考[mask]信號;從SDRAM讀取資料時則永遠為邏輯{0}(意指不遮蔽)
UDQM0
輸出
1
上八位資料讀寫遮罩。在本次設計中其邏輯值與[LDQM0]邏輯一致。
WE0
輸出
1
控制SDRAM的功能參數。與[CAS0][RAS0]以一定型式互相配合方有作用,欲知本次被使用到的功能,請參照本章「說明」相關小節;欲知SDRAM對此參數的完整功能支援,請參照SDRAM說明文件。
CAS0
輸出
1
RAS0
輸出
1
CS0
輸出
1
chip select」的縮寫,邏輯{1}時代表晶片不動作
BA0
輸出
2
 
 
 
 
 
DRAM_A1
輸出
13
功能概念與上述同名參數相同,只是專門掌管另一個實體SDRAM
DRAM_D1
輸出
16
CLK1
輸出
1
CKE1
輸出
1
LDQM1
輸出
1
UDQM1
輸出
1
WE1
輸出
1
CAS
輸出
1
RAS1
輸出
1
CS1
輸出
1
BA1
輸出
2

 
說明:
DOUBLE_BUFFER」模組由兩個「SDRAM_init」、一個寫入程序管理區塊、一個讀取程序管理區塊、以及一個「LTM_process」所組成,主要的功能是作為從顯示資訊到「LTM」顯示器之間的記憶體緩衝區。兩個「SDRAM_init」除了初始化命令出現的同時執行對SDRAM硬體的初始化外,其餘時間控制權是由「DOUBLE_BUFFER」模組內部的寫入程序管理區塊以及讀取程序管理區塊直接掌管。
模組黑盒子使用方式:
由於所有需要顯示的資料在本次架構中是規定全部必須經過「DOUBLE_BUFFER」的管理,因此,從顯示資料開始,往LTM顯示器的方向看去,這可以視為一個專門管理顯示功能的模組。所有需要利用顯示功能的其他模組,只要遵守本次架構對DOUBLE_BUFFER的使用規則,便可達到顯示目的
 
以下說明我們對每一幀畫面資料的假設與輸入要求方式
 
i.                    顯示解析度為800(col)*480(row)。每個像素為16bitRGB565分配方式。
ii.                  輸入方式規定一個回合必須「連續輸入八個同列像素」的資料(但這8個為一組的資料,位址彼此之間沒有規定關係)。倘若其中某個像素想要跳過不覆蓋任何值可利用[mask]功能跳過。[mask]是提供資料遮罩。倘若不想要因強制的規定形式而被迫必須對顯示畫面的像素作任何更改,可將[mask]邏輯值送入邏輯{1}
iii.                這八個同列的像素,起始像素位址的行位址必須是八的倍數才會有正常顯示功能。
iv.                 記憶體內部資料除了經過關機狀態以外都不會消失,因此若要顯示黑屏請自行對顯示畫面所有像素送入資料{16’h0000}
v.                   每一幀畫面的所有像素都輸入完畢後,可以回合為時間單位,須將[writer_done]改為邏輯{1},且將[mask]設為邏輯{1}或隨便指定列與行位址為畫面外範圍,直到收到[turn_page]的回應,以通知讀取程序管理區塊可以讀取本幀畫面。當讀取程序管理區塊開始切換讀取本幀畫面時,[turn_page]會出現一定長時間(133MHz頻率的時序週期)的突波回應已換頁,之後可以將[writer_done]暫時改回為邏輯{0},繼續輸入下一幀畫面資料。請注意[turn_page]信號出現的位址並不以回合為單位
vi.                 目前的版本,外部模組尚無法從「DOUBLE_BUFFER」查看最新寫入的資料。故資料方向為單方向。請應用者注意。
 
 
 
 
 
 
 
 
 
 
 


 

[clk_40Mo]
[writer_syq]
[writer_row]
像素的列位址Rn
[writer_col]
任意八個像素的起始行位址(必須是八的倍數)Cn
[writer_done]
[turn_page]
D1. D2. D3 D4 ..D5 D6 D7 .D8
[writer_data]
(無作用)
(無作用)
此區塊可重複執行輸入回合
請在輸入最後一個像素以後,才將[writer_done]設為{1}
可能須等待若干回合直至[turn_page]出現
M1 M2 M3 M4M5 M6 M7M8
[mask]
(無作用)
設為邏輯{1}
(無作用)
(無作用)
設為邏輯{1}
[turn_page信號可能出現在此區任何位置]
開始下一幀影像的輸入

 
 
 
 
 
 
 
 
 
 
模組內部運作形式:

[writer_data],[writer_col],[writer_row],[mask]
{Z}
{Z}
SDRAM0
SDRAM1
wrcmd
rdcmd
module : LTM_process
LTM
SDRAM_init0
SDRAM_init1
1            0

內部,wrcmdrdcmd是本模組中兩個概念上的控制區域,是為寫入程序管理區塊與讀取程序管理區塊。中線條代表資料流的概念走向。由於兩個實體SDRAM的資料排線各自只有一套IO,因此SDRAM是無法作到同時讀取資料又同時寫入資料的。而且SDRAM的寫入讀取都需要透過一定複雜的命令來執行,在須同時兼顧顯示速率、命令正確性以及與LTM硬體可正常溝通的情況下,就必須有這兩個管理區塊來專門執行讀取寫入的動作。
圖中的MUX、開關概念的方向,是由程式內部的[RW_state]參數值決定。當值為邏輯{0}時,表示資料寫入至SDRAM1LTM讀取SDRAM0內部的資料;當值為邏輯{1}時,表示資料寫入至SDRAM0LTM讀取SDRAM1內部存放的資料。[RW_state]的參數,只有在[writer_done]為邏輯{1}LTM掃描至其概念頁的結尾時,才會翻轉,進而影響整個內部的讀取/寫入模式。
 
 
寫入程序管理區塊
寫入程序管理區塊,基本上就是連續性不間斷第對外部輸出SDRAM的寫入命令,而他目前是否有實際管理到任何記憶體也不在乎。他可以視為是一個具有12state的有限相態機器(finite state machine) 因為一個穩定、具有可隨時換列、換頁的寫入程序最穩定狀態,經過本組研究發現需要12個命令相態,因此就如此體現。我們所設計的命令如下所示:

相態
[WRCMD_addr]
[WRCMD_ras]
[WRCMD_cas]
[WRCMD_we]
[WRCMD_ba]
命令,及動作說明
0
{2'b0,1'b1,10'b0}
0
1
0
[writer_col]的值大於或等於400時為{01},其他時候為{00}
precharge all bank
1
13'b0
1
1
1
NOP
2
[writer_row]的值
0
1
1
Activate a bank and a row
3
13’b0
1
1
1
NOP
4
[writer_col]對應至記憶體位址的值
1
0
0
輸入第一個行位址/寫入D1
5
13’b0
1
1
1
寫入D2
6
13’b0
1
1
1
寫入D3
7
13’b0
1
1
1
寫入D4
8
13’b0
1
1
1
寫入D5
9
13’b0
1
1
1
寫入D6
10
13’b0
1
1
1
寫入D7
11
13’b0
1
1
1
寫入D8

所有像態變化時機均為負緣觸發
 
本次所使用的SDRAM型號為IS42S16160B,結構上含有4bank,每個bank含有13bits(4096)row,以及9bits(512)column,每個位址記憶16bits。但本次所需要用到的顯示解析度為 800 * 480 ,而且LTM的掃描方向又是以水平方向為優先,因此若只是直接讓512處理column對應到800個像素上是不夠用的,勢必要有其他記憶體對應方式。
 
本次處理的對應方式是讓0~399的顯示像素資訊儲存於bank00~399column內,讓400~799的顯示像素資訊儲存於bank10~399column內,如此的好處是記憶體換算公式比較簡單。
 
從使用介面到這一層的命令,可知需要在某些資料上應用若干個延遲機器。比方說[writer_data]到真正寫入D1之間相差了4個時序週期(clk),這就需要對[writer_data]4個時序週期的延遲。
 
其他詳細的命令資訊請參閱SDRAM使用手冊。
 
 
讀取程序管理區塊
讀取程序管理區塊主要功能是建立LTMSDRAM之間資訊能夠正常溝通的管道。
若要SDRAMLTM配合使用,那SDRAM就要支援LTM的「連續不斷地」讀取動作。因此,讀取程序管理區塊就必須設計為具有八個像態的有限相態機器。
各相態功能如下:
 

相態(n回合)[RDCMD_phase]
[RDCMD_addr]
[WRCMD_ras]
[WRCMD_cas]
[WRCMD_we]
[WRCMD_ba]
命令,及動作說明
0
讀取的列位址
0
1
1
[writer_col]的值大於或等於400時為{01},其他時候為{00}
Activate a bank and a row/讀取Dn-15
1
13’b0
1
1
1
NOP/讀取Dn-16
2
讀取的行位址(A0~A8),且A10必須設為1,其餘填{0}
1
0
1
Read with auto precharge/讀取Dn-17
3
13’b0
1
1
1
NOP/讀取Dn-18
4
13’b0
1
1
1
讀取Dn1
5
13’b0
1
1
1
讀取Dn2
6
13’b0
1
1
1
讀取Dn3
7
13’b0
1
1
1
讀取Dn4

所有像態變化時機均為負緣觸發
 
可以發現,讀取回合與命令回合中間相差了四個時序週期,因此,要讓LTMSDRAM順利溝通,同樣也是需要若干個延遲機器。
另外,讀取程序管理區塊與寫入程序管理區塊內部所使用的所有flip-flop的變化順間都是使用時序資訊的負緣觸發,但在LTM不然,因此就要處理正負緣觸發之間的溝通問題。
 
       
 
 
 
 
 
 
 
 
 
 
 

以下舉SDRAMLTM溝通的時間表一例。
[rdclk]
[projector_x]%8
[RDCMD_data_out]
[RDCMD_ba]
[RDCMD_addr]
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
7
[RDCMD_phase]
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
[RDCMD_phase]會根據[projector_x]的值除以8的餘數來調整自己的值
2
[projector_x]
211
212
213
214
215
216
217
218
219
220
221
222
233
234
235
236
D1
D2
223
224
225
226
227
228
229
230
231
232
D3
D4
D5
D6
D7
D8
D9
D10
D11
……
……
……
……
[projector_x]的值大於等於611則數值為1,其餘為0,意思是可見螢幕範圍的左半邊儲存於bank0,右半邊儲存於bank1,故讀取時也要讀取對應的bank
[projector_x]的值產生
……
LTM_process模組提供的像素的掃描位置,216為螢幕可見的最左端位址,1016為最右端
SDRAM硬體恰好會在rdclk的正緣觸發時改變送出的值。
0
1
2
3
4
5
6
7

 
3.4 SDRAM初始化模組(SDRAM_init.v)
介面:

變數名
類型
大小(bits)
說明
clk_reset
時序輸入
1
用來驅動執行SDRAM初始化的時序信號
clk_in
時序輸入
1
用來送入SDRAM硬體的時序信號,只有在SDRAM初始化程序完成以後其信號才會導入SDRAM內。其邏輯值可以與[clk_reset]無關係
addr
 
 
讓其他模組控制SDRAM的參數,只有在SDRAM初始化程序完成以後其信號才會導入SDRAM內。
data_in
 
 
data_out
 
 
we
 
 
cas
 
 
ras
 
 
ba
 
 
mask
 
 
reset
 
 
用以命令SDRAM初始化程序開始的參數
operating
 
 
邏輯值為{1}表示告訴外界初始化程序執行中,記憶體暫由此模組接管;{0}表示初始化程序完成,記憶體交由外部模組接管。
sel
 
 
用以管理,處理inout線路的高阻抗狀態參數。因SDRAMwe的邏輯值並不完全表示SDRAM當前是讀取或寫入的狀態,因此inout的線路就要另闢此參數作管理。
<以下區域為直接SDRAM硬體溝通的相關參數>
DRAM_A
輸出
13
用以告知SDRAM寫入/讀取資料的位址資訊。
DRAM_D
輸出/輸入
16
用以與SDRAM溝通寫入/讀取的資料內容
CLK
輸出
1
送入控制SDRAM的時序資訊。向SDRAM寫入資料時須送入[clk_40o]的時序資訊;從SDRAM讀取資料時須送入[clk_33M]的時序資訊(LTM模組顯示頻率同步)
CKE
輸出
1
時序開關。在本次設計為永遠設為邏輯{0},意指要求晶片永遠對時序有反應。
LDQM
輸出
1
下八位資料讀寫遮罩,本次設計為向SDRAM寫入資料時參考[mask]信號;從SDRAM讀取資料時則永遠為邏輯{0}(意指不遮蔽)
UDQM
輸出
1
上八位資料讀寫遮罩。在本次設計中其邏輯值與[LDQM0]邏輯一致。
WE
輸出
1
控制SDRAM的功能參數。與[CAS0][RAS0]以一定型式互相配合方有作用,欲知本次被使用到的功能,請參照本章「說明」相關小節;欲知SDRAM對此參數的完整功能支援,請參照SDRAM說明文件。
CAS
輸出
1
RAS
輸出
1
CS
輸出
1
chip select」的縮寫,邏輯{1}時代表晶片不動作
BA
輸出
2
bank
 
 
 
 

 
說明:
由於SDRAM的初始化程序相對複雜,故本模組目的只是在於為SDRAM的初始化程序提供一個包裝。讓使用SDRAM的使用者透過簡單輸入一個觸發信號[reset]來對SDRAM作初始化。
        本模組內部在初始化所作的程序完全遵照SDRAM  IS42S16160B說明文件中的指示(下圖),詳情請參閱IS42S16160B晶片相關說明文件。
 
在初始化程序執行時,[operating]的邏輯值為{1},本模組擁有該實體SDRAM的管理權限;在初始化程序執行完畢後,則SDRAM的權限則全部交由外部模組控制,包含命令、時序資訊、以及資料流。
另外必須注意的是,本模組對控管SDRAM的輸入輸出腳位事先作了區分,分別以[data_in]以及[data_out]來配合SDRAMDRAM_D腳位輸入輸出的資料流。控制DRAM_D腳位輸入輸出的角色依據是[sel]的邏輯值。當[sel]邏輯值為{1}時,表示DRAM_D腳位在本模組當作信號輸入,本模組內相應對策是將其接至高阻抗以讀取資料;反之則當其為信號輸出,由[data_in]負責提供輸出信號。
也就是說,外部模組可直接控制[sel]的邏輯值,並以[data_in]來決定輸入實體SDRAM的資料,並以[data_out]接收來自於實體SDRAM的資料,藉此免除後續輸入輸出應用的衍生問題。
 
3.5 LTM模組(LTM_process.v)
介面:

變數名
類型
大小(bits)
說明
reset
輸入
1
重設訊號
clk50M
輸入
1
33.3M的時序
pattern_R
輸入
8
雙暫存緩衝模組要送給LTM紅色的資訊
pattern_G
輸入
8
雙暫存緩衝模組要送給LTM綠色的資訊
pattern_B
輸入
8
雙暫存緩衝模組要送給LTM藍色的資訊
NCLK
輸出
1
送給LTM 33.3M時序
HD
輸出
1
送給LTM 的水平同步訊號
VD
輸出
1
送給LTM 的垂直同步訊號
DEN
輸出
1
送給LTM 的資料有效化訊號(data enable signal
R
輸出
8
送給LTM紅色的資訊
G
輸出
8
送給LTM綠色的資訊
B
輸出
8
送給LTM藍色的資訊
reset_o
輸出
1
送給LTMGRESET訊號(global reset)
projector_x
輸出
11
送給雙暫存緩衝模組目前掃到的X座標
projector_y
輸出
10
送給雙暫存緩衝模組目前掃到的Y座標

 
說明:
    閱讀儀器所附的資料冊TRDB_LTM_UserGuide_v1.23.pdf),可知顯示的格式(3-2章),唯一須要注意的是要將訊號改成和NCLK的正緣觸發對齊才能正常運作。此本模組是依照的解析度實踐,掃完一整頁的波形如下圖二所示。
圖一:每一行的波形
圖二:每一頁的波形
    將螢幕(即每一頁)想像成如下圖所示可以方便理解。先掃完一行X再掃下一行,到最後一個像素,會在回到原點從頭掃一次。需要注意的是X軸的時間單位是一個NCLK,但Y軸的單位是1056NCLK,所要求的值都在寫在資料冊(datasheet)中。原始碼中會有用來記錄目前掃到的像素座標(x_cnt, y_cnt),而顏色的資訊只有在掃到紅色的區塊的時候才需要送出,故會有用來記錄的變數[display_area],其餘的變數皆和上兩圖的相同。
 
重要變數:

變數名稱
功能
宣告形式
x_cnt
記錄目前掃到的像素X座標
reg [10:0] x_cnt
y_cnt
記錄目前掃到的像素Y座標
reg [9:0] y_cnt
display_area
記錄是否到需要送出顏色資訊的位元
reg display_area;

 
3.6 SDRAM繪圖模組(DRAW_TO_SDRAM.v)
介面:

變數名
類型
大小(bits)
說明
clk_50M
輸入
1
時序資訊,用以驅動本模組。本次實作本模組的操作頻率為40MHz,與DOUBLE_BUFFER的寫入程序管理模組的驅動時序完全相同。
reset
輸入
1
初始化命令參數,邏輯值為{0}時及執行本模組的初始化動作。
<以下為直接與DOUBLE_BUFFER模組溝通的參數>
turn_sign
輸入
1
來自DOUBLE_BUFFER模組的換頁提醒。詳情請參照DOUBLE_BUFFER模組說明章節。
writer_syq
輸入
1
來自DOUBLE_BUFFER模組的寫入程序同步化信號,詳情請參照DOUBLE_BUFFER模組說明章節
mask_i
輸出
1
直接與DOUBLE_BUFFER模組溝通,詳情請參照DOUBLE_BUFFER模組說明章節
writer_col
輸出
13
writer_row
輸出
13
writer_data
輸出
16
write_done_i
輸出
1
<以下參數為來自PHYSICS模組的資訊>
X_in,Y_in,Z_in
輸入
13
為來自PHYSICS模組所計算出的球體位置資訊
<以下參數為直接與ssram模組溝通的參數>
writer_col_bg_pseudo
輸出
13
ssram要求讀取記憶體的行位址
writer_row_bg_pseudo
輸出
13
ssram要求讀取記憶體的列位址
ssdata
輸入
16
ssram回應的記憶體內容
<以下為測試用參數,無實質應用功能>
*switch
輸入
1
來自開關,用以測試DOUBLE_BUFFER功能的正確性
*mask
輸入
1
來自開關,用以測試DOUBLE_BUFFER功能的正確性

 
說明:
DRAW_TO_SDRAM的主要功能就是作為顯示畫面貼圖的排程,包含背景資訊與球體。
每一幀的貼圖順序都是由一個繪圖排程區塊先將背景資訊由ssram寫入到DOUBLE_BUFFER,之後再將球體繪至畫面的目標位置。
        繪圖排程區塊作用說明如下表

相態
命令參數
監視參數
描述
0
[call_bg] = 1’b0;
[call_ball] = 1’b0;
[write_done_i]=1’b1
[turn_sign]
閒置狀態,持續發送繪圖完成信號並等待DOUBLE_BUFFER的換頁信號出現,才跳至相態1
1
[call_bg] = 1’b1;
[call_ball] = 1’b0;
[write_done_i]=1’b0
[writer_bg_done]
觸發背景繪圖區塊開始作用,並將DOUBLE_BUFFER繪圖權限交由背景繪圖區塊。其後就等待背景繪圖權限回應繪圖動作完成,跳至相態2
2
[call_bg] = 1’b0;
[call_ball] = 1’b1;
[write_done_i]=1’b0
[writer_ball_done]
觸發球體繪圖區塊開始作用,並將DOUBLE_BUFFER繪圖權限交由球體繪圖區塊。其後就等待背景繪圖權限回應繪圖動作完成,跳回像態0

 
如此,若要增加其他繪圖物件,只要考慮相互遮蔽問題後,在繪圖排程區塊內加入排程,只要適當管理好直接與DOUBLE_BUFFER模組溝通的參數如前表<直接與DOUBLE_BUFFER模組溝通的參數>一區內所有參數,並遵守相關寫入規則(包含與繪圖排程區塊的溝通以及DOUBLE_BUFFER寫入程序管理區塊要求原則)即可。
 
背景繪圖區塊
背景資訊在經過ThreeDTotwoD之後相關模組編譯後的結果是儲存在ssram內部,因此,DRAW_TO_SDRAM就必須具有與ssram溝通的能力。ssram內部也存在一個ssram_re模組專門服務DRAW_TO_SDRAM的讀取工作。
首先,已知的事實是,在DOUBLE_BUFFER內部,已經將寫入程序管理區塊設計為十二個cycle time為一個寫入週期的形式(詳細內容請見DOUBLE_BUFFER說明相關章節。),因此,ssram_re也是設計為十二個cycle time為一個讀取週期的形式,只是這兩者之間對同步化信號校正的位置有些不同,我們舉圖例說明。

[clk_50M]
col n+1
[writer_col_pseudo]
row n+1
[writer_row_pseudo]
col n
[writer_col]
row n
[writer_row]
[writer_col][writer_row]分別為[writer_col_pseudo][writer_row_pseudo]的一個寫入回合延遲
[writer_syq]

 
 
 
 
 
 
球體繪圖模組(DRAW_BALL)
介面

變數名
類型
大小(bits)
說明
clk_50M
輸入
1
時序資訊,用以驅動本模組。本次實作本模組的操作頻率為40MHz,與DOUBLE_BUFFER的寫入程序管理模組的驅動時序完全相同。
<以下為直接與DOUBLE_BUFFER模組溝通的參數>
turn_sign_wire
輸入
1
來自DOUBLE_BUFFER模組的換頁提醒。詳情請參照DOUBLE_BUFFER模組說明章節。
writer_syq
輸入
1
來自DOUBLE_BUFFER模組的寫入程序同步化信號,詳情請參照DOUBLE_BUFFER模組說明章節
mask_ball
輸出
1
直接與DOUBLE_BUFFER模組溝通,詳情請參照DOUBLE_BUFFER模組說明章節
writer_col_ball
輸出
13
writer_row_ball
輸出
13
writer_ball_done
輸出
16
write_done_i
輸出
1
<以下參數為來自PHYSICS模組的資訊>
X_in,Y_in,Z_in
輸入
13
為來自PHYSICS模組所計算出的球體位置資訊

 
說明:
本模組專門負責讀取一球心在空間中的位置以後,並考慮深淺對球體半徑造成的影響以後,在二維顯視器上顯示的動作。
        在目前的版本,球體在深淺不同的位置時,球體顯示的顏色也有所不同,目的是方便區別深淺位置;另外,我們透過對[draw_ball_mask]的控制,繪製球體時以棋盤式地方式繪上,便造成球體的半透明效果,如此可簡單避免場景遮蔽的不自然感。
        要繪出圓形的球體,我們使用了畢氏定理計算繪圖像素與球心位置的距離與半徑的比較,來決定[draw_ball_mask]的開關,如此可輕鬆繪出圓形的球體。
 
3.7貼圖遮蔽模控制組(threeDTotwoD_control.v)
介面:

變數名
類型
大小(bits)
說明
reset
輸入
1
重設訊號
clk
輸入
1
輸入時序
call
輸入
1
啟動此模組訊號
fill
輸入
1
目前區塊(cube)是否需要上色,邏輯1代表要上色,邏輯0代表不需要,接到物理特性模組
map_done
輸入
1
目前區塊是否上色完畢訊號,邏輯1代表要上色完畢,接到靜態隨機存取記憶體模組
cube_x_cnt
輸出
5
目前區塊的X座標
cube_y_cnt
輸出
4
目前區塊的Y座標
cube_z_cnt
輸出
3
目前區塊的Z座標
face1_x
輸出
40
編號face1的面四頂點X座標匯流排(bus
face1_y
輸出
36
編號face1的面四頂點Y座標匯流排(bus
face2_x
輸出
40
編號face2的面四頂點X座標匯流排(bus
face2_y
輸出
36
編號face2的面四頂點Y座標匯流排(bus
face3_x
輸出
40
編號face3的面四頂點X座標匯流排(bus
face3_y
輸出
36
編號face3的面四頂點Y座標匯流排(bus
map_start
輸出
1
開始將目前區塊的三個面上色的訊號,靜態隨機存取記憶體寫入模組
done
輸出
1
所有區塊上色完畢訊號,邏輯1代表完成

註:所有的輸出訊號都是跟著clk的正緣觸發。
說明:
    詳細的演算法見貼圖遮蔽演算法」章節,須要注意的是區塊cube)的編號,就是以每一個區塊是以最靠近原點的頂點(以三維座標而言)為代表,除以40,例如:(40, 80, 120) à (1,2,3)。原始碼中運用到三維轉二維模組(threeDTotwoD)組合電路的編號就是貼圖遮蔽演算法」章節中頂點的編號。
    靜態隨機存取記憶體寫入模組間的溝通方式如上圖所示,當需要上色時,[map_start]的訊號會成為邏輯1的時候,靜態隨機存取記憶體寫入模組開始動作,當靜態隨機存取記憶體寫入模組完成動作後,會把[map_done]訊號變成邏輯1,接著[map_start]的訊號會成為邏輯0
    下圖為此模組中的狀態圖(state diagram),當start的訊號為邏輯0時,會一直停在狀態零,start的訊號為邏輯1時變成狀態一,之後藉由判斷目前區塊是否需要上色,決定是要跳到狀態二去上色(依照上一段所提到的溝通方式去下指令),還是在狀態一繼續判斷下一個區塊,當所有區塊都上色完畢之後,會從狀態一或二跳到狀態三,並將[done]訊號變成邏輯1,等待[call]訊號變成邏輯0就跳回狀態零。

狀態
功能
state0
閒置狀態
state1
決定是否要上色或繼續判斷下一個區塊
state2
SSRAM模組下開始上色指令
state3
等待start信號變成邏輯0

 
重要變數說明:

變數名
功能
宣告形式
state
顯示現在所在的狀態(state
reg [1:0] state;
section
顯示現在所在的區域
reg [1:0] section;

註:區域的編號方法見貼圖遮蔽演算法」章節
 
NextCube模組:
    在原始碼當中用到的NextCube這個模組,功能是由目前區塊(cube)的編號計算出下一個區塊(cube)的編號(順序見貼圖遮蔽演算法」章節),而當目前是最後一個區塊時,會傳回此區塊座標,並將last訊號改成邏輯1
 
3.8三維轉二維模組(threeDTotwoD.v)
介面:

變數名
類型
大小(bits)
說明
reset
輸入
1
重設訊號
X_3D
輸入
10
像素的三維X座標
Y_3D
輸入
9
像素的三維Y座標
Z_3D
輸入
8
像素的三維Z座標
X_2D_o
輸出
10
像素的二維X座標
Y_2D_o
輸出
9
像素的二維Y座標

 
說明:
    實踐三維轉二維演算法」中的公式,原始碼中須要注意的有兩點,
(1) 分成四種情況判斷的目的是不要讓相減的結果變成負的,造成溢位的現象。
(2) 為了讓相除的結果不是純小數(因為可能會被四捨五入變成0),故先將相乘項做出來再做除法。公式中重複的項也沒有獨立出來做,也是因為會出現純小數。
    本實踐事實上是用近似的方法,因為實際須轉換的點距離最短也有40像素,故使用座標只取到整數的做法的話,並不會因此把兩個不同的三維點投影到相同的二維點,但要精確的去做的話也沒有關係,只是可能需要用到magafuction,不過,此應用並沒有此必要。
 
3.9靜態隨機存取記憶體模組(ssram.v)
介面:

名稱
類型
位元數
功能
clk
input
1
模組運作用時脈。(40Mhz)
X
input
10
讀取起始X位置。
Y
input
9
讀取起始Y位置。
sig
input
1
讀取回復起始訊號。
data
output
16
輸出從“ssram”讀得之訊號。
s_addr
output
19
“ssram”位址線。
s_data
input
32
“ssram”資料輸入線。
adsc
output
1
“ssram” 位址移動控制訊號,新位址讀入。
adsp
output
1
“ssram” 位址移動控制訊號,起始位置讀入。
adv
output
1
“ssram” 位址移動控制訊號,位址移動。
ce1
output
1
“ssram” 晶片啟動訊號1
ce3
output
1
“ssram” 晶片啟動訊號3
oe
output
1
“ssram” 輸出允許訊號。

 
功能說明:
    此模組的功能是用於將“ssram”中的資料讀出,運作方式為當[sig]為高電位時將狀態[step]回復到0,重新開始讀取。否則便以12個時脈唯一週期的方式來連續運作。一週期讀取出來的資料為{[Y][X]}值到{[Y][X]+7}共八單位(每單位16位元)依序讀出。有關於讀取時和所需要的靜態隨機存取記憶體相關波形,請見下圖:
其中各參數的輸出是依據[step]的值來改變。有關於波形代表的涵義,請見靜態隨機存取記憶體之datasheet: “ 61VPS_LPS-51236A_102418A.pdf”
 
程式說明:
    此處是以有限狀態機的方式來實現上述動作,其各狀態功能如下:

0
週期起始。
1
“ssram”初始位址寫入。
2~9
“ssram”資料輸出。
10~11
閒置狀態,並於最後回到狀態0

 
3.10快閃記憶體寫入靜態隨機存取記憶體模組(flashtossram.v)
1.介面

名稱
類型
位元數
功能
clk
input
1
模組運作用時脈。(2.5Mhz)
start
input
1
開始訊號。
finish
output
1
完成訊號。
s_addr
output
19
“ssram”位址排線。
s_data
output
32
“ssram”資料排線。
adsc
output
1
“ssram”位址移動控制訊號,新位址讀入。
adsp
output
1
“ssram”位址移動控制訊號,起始位置讀入。
adv
output
1
“ssram”位址移動控制訊號,位址移動。
ce1
output
1
“ssram”晶片啟動訊號1
ce3
output
1
“ssram”晶片啟動訊號3
we
output
1
“ssram” 寫入允許訊號。
f_reset
output
1
“flash” 內部狀態重設。
f_addr
output
22
“flash” 位址排線。
f_data
input
16
“flash” 資料排線。

 
2.功能說明
    此模組主要是要將存取於快閃記憶體裡800*480大小的背景圖片依序寫入靜態隨機存取記憶體裡。下圖為快閃記憶體讀取時的波形圖:
在開始進行讀取前會先將[f_reset]拉至低電位確保其內部的狀態機回到讀取狀態,且須注意雖然其不需要時脈控制,但其位址改變後其資料是在一小段延遲後才會出現的,不過由於我們使用的時脈為2.5MHz,故可視為即時出現。
    關於靜態隨機存取記憶體的波形,請見靜態隨機存取記憶體寫入模組寫入方式為逐行依序寫入。
 
3.程式說明
   此處使用有限狀態機(finite state machine)實現所需的波形輸出,由[start]作為開始訊號,並在回到閒置狀態時將[finish]拉為高電位。其中各種對記憶體的控制用訊號皆是以狀態[step]為依據來做變換。
各狀態功能及動作如下:

0
開始狀態,並在此時「重設」快閃記憶體。
1
等待快閃記憶體。
2
靜態隨機存取記憶體開始讀入位址。
3
等待靜態隨機存取記憶體。
4
[Y]值不變下改變[X]值依序寫入整行。
5
檢查[Y]值是否為結束位置,若否更改[Y]值後回到狀態4
6
閒置狀態。此時[finish]轉為高電位。

 
3.11靜態隨機存取記憶體讀取模組(ssram_re.v)
介面:

名稱
類型
位元數
功能
clk
input
1
模組運作用時脈。(40Mhz)
X
input
10
讀取起始X位置。
Y
input
9
讀取起始Y位置。
sig
input
1
讀取回復起始訊號。
data
output
16
輸出從“ssram”讀得之訊號。
s_addr
output
19
“ssram”位址線。
s_data
input
32
“ssram”資料輸入線。
adsc
output
1
“ssram” 位址移動控制訊號,新位址讀入。
adsp
output
1
“ssram” 位址移動控制訊號,起始位置讀入。
adv
output
1
“ssram” 位址移動控制訊號,位址移動。
ce1
output
1
“ssram” 晶片啟動訊號1
ce3
output
1
“ssram” 晶片啟動訊號3
oe
output
1
“ssram” 輸出允許訊號。

 
功能說明:
    此模組的功能是用於將“ssram”中的資料讀出,運作方式為當[sig]為高電位時將狀態[step]回復到0,重新開始讀取。否則便以12個時脈唯一週期的方式來連續運作。一週期讀取出來的資料為{[Y][X]}值到{[Y][X]+7}共八單位(每單位16位元)依序讀出。有關於讀取時和所需要的靜態隨機存取記憶體相關波形,請見下圖:
其中各參數的輸出是依據[step]的值來改變。有關於波形代表的涵義,請見靜態隨機存取記憶體之datasheet: “ 61VPS_LPS-51236A_102418A.pdf”
 
程式說明:
    此處是以有限狀態機的方式來實現上述動作,其各狀態功能如下:

0
週期起始。
1
“ssram”初始位址寫入。
2~9
“ssram”資料輸出。
10~11
閒置狀態,並於最後回到狀態0

 
3.12靜態隨機存取記憶體寫入模組(ssram_wr.v)
介面:

名稱
類型
位元數
功能
clk
input
1
模組運作時脈。(2.5Mhz)
call
input
1
模組開始訊號。
done
output
1
模組結束訊號。
face1_X
input
40
X座標組1
face1_Y
input
36
Y座標組1
face2_X
input
40
X座標組1
face2_Y
input
36
Y座標組1
face3_X
input
40
X座標組1
face3_Y
input
36
Y座標組1
s_addr
output
19
位址排線。
s_data
output
32
資料排線。
adsc
output
1
位址移動控制訊號,新位址讀入。
adsp
output
1
位址移動控制訊號,起始位置讀入。
adv
output
1
位址移動控制訊號,位址移動。
ce1
output
1
晶片啟動訊號1
ce3
output
1
晶片啟動訊號3
we
output
1
寫入允許訊號。

 
功能說明:
    本模組主要是用於將外界傳來的座標點資料,轉為一整個四邊形的平面並寫入靜態隨機存取記憶體中。其中傳進來的資料為四個點,實際寫入方法為由每面的邊12逐行寫到邊34,由有限狀態機完成。
 
          
其中傳進來的座標其相對位置會依其原始立方體在螢幕中的位置而有所不同(如圖),因此在實作程式時將會依據此部分而特別進行處理。
    關於靜態隨機存取記憶體的輸出波形,依據其“datasheet”所言,開始後其輸出波形因如下圖(黑線部分),但此處爲了減化有限狀態機的狀態,我們在開始寫入後便將[adsc]持續以低電位輸出(紅線部分),如此便不用在寫入暫停後重新輸出位址起始波形。
 
程式說明:
    程式共分為三部份,第一部份為座標點的重分類,第二部份為座標點相對位置資訊的處理,第三部份為實際對靜態隨機存取記憶體進行波形輸出的有限狀態機。其中第一部份為優先進行,第二、三部份為同時進行。
 
第一部份: 座標點的重分
  
    原始座標點組[face1_X]等,為一由四個10位元X座標組成之40位元排線,分別代表四邊型的四個點其順序為原立方體編號的由小到大。此處要將其轉為如右圖三個四邊型的編號順序。相對應如下:

原變數名稱
新變數名稱
原變數名稱
新變數名稱
f1_X1
face1_X[39:30]
f2_Y1
face2_Y[35:27]
f1_X2
face1_X[29:20]
f2_Y2
face2_Y[26:18]
f1_X3
face1_X[19:10]
f2_Y3
face2_Y[17:9]
f1_X4
face1_X[9:0]
f2_Y4
face2_Y[8:0]
f1_Y1
face1_Y[35:27]
f3_X1
face3_X[29:20]
f1_Y2
face1_Y[26:18]
f3_X2
face3_X[9:0]
f1_Y3
face1_Y[17:9]
f3_X3
face3_X[39:30]
f1_Y4
face1_Y[8:0]
f3_X4
face3_X[19:10]
f2_X1
face2_X[39:30]
f3_Y1
face3_Y[26:18]
f2_X2
face2_X[29:20]
f3_Y2
face3_Y[8:0]
f2_X3
face2_X[19:10]
f3_Y3
face3_Y[35:27]
f2_X4
face2_X[9:0]
f3_Y4
face3_Y[17:9]

 
第二部份:起始結束點邊資訊
    黑色&藍色四邊形,非平行邊斜率的計算。此部份為透過子模組“divide.v”來達成,詳見簡易除法模組
 
第三部份:有限狀態機
    此部份在每次[call]為高電位時將狀態回復到零,開始動作,並在最後一個狀態前將[done]輸出一週期的高電位表寫入完成。
控制用特殊參數:

 
addr_x
此次輸出X位址,為一20位元參數,取其整數部分輸出,後10位為小數。
addr_y
此次輸出Y位址,為一19位元參數,取其整數部分輸出,後10位為小數。
addr_x_start
輸入邊起始X值。
addr_y_start
輸入邊起始Y值。
addr_x_end
輸入邊結束X值。
addr_y_end
輸入邊結束Y值。

 
各狀態功能及動作如下:

寫入面
紅色面
0
起始狀態,輸入起始、結束值。
1
 “ssram”初次位址寫入。
2
等待“ssram”
3
“ssram”資料連續寫入,並在[addr_x]到達[addr_x_end]結束點時至狀態4
4
檢查[addr_y]是否到達結束點,若否跟新輸入邊起始結束X方向的值後回到狀態3
黑色面
5
輸入起始、結束值。
6
“ssram”初次位址寫入。
7
等待“ssram”
8
“ssram”資料連續寫入,並在[addr_x]到達[addr_x_end]結束點時至狀態9
9
檢查[addr_y]是否到達結束點,若否跟新輸入邊起始結束X方向的值後回到狀態8
藍色面
10
輸入起始、結束值。
11
“ssram”初次位址寫入。
12
等待“ssram”
13
“ssram”資料連續寫入,並在[addr_y]到達[addr_y_end]結束點時至狀態14
14
檢查[addr_x]是否到達結束點,若否跟新輸入邊起始結束Y方向的值後回到狀態13
15
閒置狀態。
16
閒置狀態,輸出完成訊號。

 
 
3.13簡易除法模組(divide.v)
介面:

名稱
類型
位元數
功能
A1
input
10
輸入被除數1
A2
input
10
輸入被除數2
B1
input
10
輸入除數1
B2
input
10
輸入除數2
ans
output
20
輸出答案。
minusA
output
1
[A1][A2]大小關係表示。1表示A1>A2
minusB
output
1
[B1][B2]大小關係表示。1表示B1>B2

 
功能說明:
    此模組是進行的計算,並將[A1][A2][B1][B2]間的大小關係以[minusA][minusB]來記錄,以方便之後判斷使用。並使[ans]轉為20位元(後面10位元表示小數)同時爲了使用上的方便和計算述速度上的考量,最後是以移位的方式(只除以)來做一個近似解。
 
程式說明:
   整體流程如下圖:
其中dA/dB是透過以dB為依據,選擇將dA寫入[ans]的第幾位元來得到的。整個組合電路大約需2μs便可得正確答案。
 
設計方法:
 
 
演算法概念 :
  

1  物理特性計算

反彈演算法與牛頓運動定律演算法
 
以下以 pseudo code 概念描述之
while(1){
 
//X,_fY_f,Z_f 代表球心空間位置
//vx,vy,vz 代表球體移動速度
//
//n0[k],n1[k],n2[k]代表球心到第 k 個偵測點的單位方向向量
//sx[k],sy[k],sz[k]代表第 k 個偵測點在空間中的位置
for( i=0 ; I < 60 ; ++i){
         sx[i] = X_f + 19 * n0[i];
         sy[i] = Y_f + 19 * n1[i];
         sz[i] = Z_f + 19 * n2[i];
         if( sx[i],sy[i],sz[i]組成的座標在反彈執行區域內  ) {
beep[i]=1;
have_beep = 1;}
else{
  beep[i]=0;
}
//N0,N1,N2 代表概念上的反射面的方向資訊
N0 = N1 = N2 = 0;
for( i = 0 ; i<60; ++i){
         N0 +=n0[i]*beep[i];
         N1 +=n1[i]*beep[i];
         N2 +=n2[i]*beep[i];
}
 
///////////////////////////////
//v_norm_x,v_norm_y,v_norm_z 代表球體速度在(N0,N1,N2)上且方向一
//致的正投影,即球體速度與概念上的反射面垂直的分量。
//v_para_x,v_para_y,v_para_z 代表球體速度與概念上的反射面平行的分
//向。
v_norm_x =abs( ((vx*N0+vy*N1+vz*N2)/(N0*N0+N1*N1+N2*N2))) *N0;
v_norm_y =abs( ((vx*N0+vy*N1+vz*N2)/(N0*N0+N1*N1+N2*N2)))*N1;
v_norm_z = abs( ((vx*N0+vy*N1+vz*N2)/(N0*N0+N1*N1+N2*N2)))*N2;
v_para_x = vx + (-v_norm_x);  
v_para_y = vy + (-v_norm_y);
v_para_z = vz + (-v_norm_z);
//new_vx,new_vy,new_vz  充當球體考慮反彈後的速度
new_vx = v_para_x * friction_ratio + (- v_norm_x * reflection_ratio);  
new_vy = v_para_y * friction_ratio + (- v_norm_y * reflection_ratio);  
new_vz = v_para_z * friction_ratio + (- v_norm_z * reflection_ratio);  
//new_x,new_y,new_z  充當球體考慮反彈後的位置
new_x =X_f+(-v_norm_x*2);
new_y =Y_f+(-v_norm_x*2);
new_z =Z_f+(-v_norm_x*2);
//意思是果斷地將球直接移出反射區域。系數”2”為一個保險用比例
 
X =( have_beep)?new_x : (X + vx);  
Y =( have_beep)?new_x : (Y + vy);  
Z =( have_beep)?new_x : (Z + vz);  
 
vx =( have_beep)?new_vx : limitation(vx + ax*ascale);  
vy =( have_beep)?new_vy : limitation(vy+ ay*ascale);  
vz =( have_beep)?new_vz : limitation(vz + az*ascale);  
//limitation 表示各方向速限,最大值為+1,最小值為-1,單位為像素
//ax 為來自加速度儀晶片的加速度資訊 ascale 為虛擬空間與實體空間加    
//速度比例校正參數
}
}
 
2.
6
v_norm_y =abs( ((vx*N0+vy*N1+vz*N2)/(N0*N0+N1*N1+N2*N2)))*N1;
v_norm_z = abs( ((vx*N0+vy*N1+vz*N2)/(N0*N0+N1*N1+N2*N2)))*N2;
v_para_x = vx + (-v_norm_x);  
v_para_y = vy + (-v_norm_y);
v_para_z = vz + (-v_norm_z);
//new_vx,new_vy,new_vz  充當球體考慮反彈後的速度
new_vx = v_para_x * friction_ratio + (- v_norm_x * reflection_ratio);  
new_vy = v_para_y * friction_ratio + (- v_norm_y * reflection_ratio);  
new_vz = v_para_z * friction_ratio + (- v_norm_z * reflection_ratio);  
//new_x,new_y,new_z  充當球體考慮反彈後的位置
new_x =X_f+(-v_norm_x*2);
new_y =Y_f+(-v_norm_x*2);
new_z =Z_f+(-v_norm_x*2);
//意思是果斷地將球直接移出反射區域。系數”2”為一個保險用比例
 
X =( have_beep)?new_x : (X + vx);  
Y =( have_beep)?new_x : (Y + vy);  
Z =( have_beep)?new_x : (Z + vz);  
 
vx =( have_beep)?new_vx : limitation(vx + ax*ascale);  
vy =( have_beep)?new_vy : limitation(vy+ ay*ascale);  
vz =( have_beep)?new_vz : limitation(vz + az*ascale);  
//limitation 表示各方向速限,最大值為+1,最小值為-1,單位為像素
//ax 為來自加速度儀晶片的加速度資訊 ascale 為虛擬空間與實體空間加    
//速度比例校正參數
}
}
 
2.2  三維轉二維演算法
在計算球運動的方式之後,需要把它轉到螢幕上去顯示,故要將其三維座標轉換
成相對應的二維座標。
        三維轉二維的做法大致上分成兩種:(1)正交投影(Orthographic projection ) (2)
透視投影(Perspective projection)。此次顯示採用的是透視投影法,如下圖所示。
將視點(perspective)和想要投影的點連線,再找到和投影平面的交點就是投影的
結果。例如:圖中 A 點投影在 Z = k 的平面上的點就是 B 點。
 
 
 
 
 
 
 
程式體現 :
 
根據設計架構,我們目前完成了硬體設計模擬方塊圖中除了CENTRAL_CONTROL以外的所有部分。也就是所有晶片的控制子單元已全部完成。
設計架構已大致清楚描述了我們程式撰寫的大略架構。包含 :
1.物理特性模組(PHYSICS)
2.加速度計模組(acc_SPI)
3.雙暫存緩衝模組(DOUBLE_BUFFER)
4. SDRAM 初始化模組(SDRAM_init)
5.LTM模組(LTM_process)(觸控面板的部分尚未納入主架構內)
6.SDRAM繪圖模組(DRAW_TO_SDRAM)
7.貼圖遮蔽控制模組(threeDTotwoD_control)
8.三為轉二維模組(threeDTotwoD)
9.靜態隨機存取記憶體模組(ssram)
10.快閃記憶體寫入靜態隨機存取記憶體模組(flashtossram)
11.靜態隨機存取記憶體讀取模組(ssram_re)
12.靜態隨機存取記憶體寫入模組(ssram_wr)
13.簡易除法模組(divide)
 
以上所有13個模組皆為verilog語法所撰寫,所體現出來的功能主要是讓LCD顯示幕上出現3D的簡單場景與一個具有物體碰撞力學特性的虛擬球體。
 
 
(Revision: 5 / 2010-09-17 23:38:12)

6. 設計特點 (Preliminary Paper)

擬真運動模擬:

本組於本次企劃中,將主要致力於有效率、高準確度的運動模擬計算的
開發。
以往關於物體運動碰撞部分的模擬,處理的方式大多是一維、或單純二
方向(水平鉛直)的計算。本次本組計畫將開發三維、全角度碰撞模式,讓使
用者對物體運動的不自然感覺降到最低。
 
直覺的操作介面:
3-D 運動加速度測量儀,很容易讓人直接聯想到任天堂遊戲機 wii 的操
作特色。彩色螢幕、觸控面板,將創造比 wii 更多元、更直覺式的互動介面。
 
物理計算核心的可擴充整合性:
本次計畫不同於以往侷限於二維或三維少數
方向上的物理模擬,將開發一個具有完整三維空間牛頓運動定律的計算核心。
此核心整合重力加速度儀,可搭配建構出像是擬真控制賽車、飛船等物件在
數位電路上的模型更臻完美,未來可於其他企劃中繼續應用。
 
簡單、不失真的 3-D 貼圖技術:
我們不需要只因為要顯示 3-D 畫面而去「再
建構」3-D 環境。但本計畫有把握實現能帶給使用者滿意的 3-D 視覺效果技
術。只要使用本企劃獨家的 multi-layer pseudo 3-D,就能輕鬆打造
出小巧但幾可亂真的 3-D 視覺效果!!
(Draft / 2010-06-30 08:05:09)

7. 總結 (Final Project Paper)

 

坦白說,本次計畫與實際體現的結果是有一段落差。

由於是首次學習verilog,我們一開始花了很多的心思在於"如何撰寫正確的verilog程式"這件事情上,也把這個習慣一直帶到後續的研究發展過程。對於altera開發平台的嵌入式CPU是直到後面才開始研究,但這時很多子模組已經撰寫完成,整個主架構又因太過龐大而一直沒有去實現改造成與嵌入式CPU相容的版本,因此在本次的作品版本中是看不到嵌入式CPU的。

另外,在一開始對於作品的想法,是想要造出一個虛擬的迷宮球。這個版本我們著重在球體物理性質的描述,因此也造成環境是一個盒子,營幕所見就像是盒子的蓋子往內看的狀況。但後來想一想,如果螢幕所見是在固定空間中的攝影機,而手動操作的盒子如果是在螢幕內的一個透明物件的話,那展示效果絕對會更加出色,這點子可惜的是沒有被及時發現。所以有機會看到我們拍的demo的話,會發現我們真的體現了一個"裝著球的盒子"。

本次參賽最大的收穫是,我們親身體會了動手寫這麼多控制模組是多麼累人的一件事。首先要看懂我們所想要控制的晶片特性,之後要針對不同溝通方式作整合的平台。當晶片愈來愈多(本次作品動用了幾乎是DE2板上的所有記憶體資源),程式也就愈來愈複雜,以致工程師沒有辦法太過專注在"創新"或"功能"這幾件事情上。

使用了SOPC作簡單測試之後,我們的思維又回到了C語言的世界,而且SOPC已經對板上諸多硬體作了幾乎是完備的整合平台,只要犧牲一點點效率就能換來功能上的專注,這是非常大的突破。不過或許也因為這次的遺憾,讓我們更加了解CPU與一般應用晶片的不同,以及SOPC整合平台的強大,縱使他有諸多操作上的限制。

真的非常謝謝Altera公司提供的硬體、軟體設備,讓我們有機會用"實作"的方式認識verilog語法。

 

PS:如果參賽文稿的編輯環境可以PDF形式繳交的話,我們組會更加感謝Altera公司!!

(Revision: 2 / 2010-09-18 00:00:00)