• 沒有找到結果。

Digital System Design Project

N/A
N/A
Protected

Academic year: 2022

Share "Digital System Design Project"

Copied!
28
0
0

加載中.... (立即查看全文)

全文

(1)

Digital System Design Project

JTAG = Jo Tone-Co Ai Group JTAG Interface SRAM Tester with C JTAG Interface SRAM Tester with C JTAG Interface SRAM Tester with C

JTAG Interface SRAM Tester with C----LCMLCMLCM LCM

Project Website: http://www.csie.ntu.edu.tw/~b94097/DSD/website/Home.html

1 Members & Working Distribution

組長:B94902061 張顯之、B94902065 余守壹 SRAM 組

小組長:B94902027 鍾政達

組員:B94902061 張顯之、B94902069 胡升鴻、B94902093 何星翰 TEST 組

小組長:B94902067 陳建男

組員:B94902080 何雨帆、B94902033 張峻華、B94902097 呂哲安、

B94902065 余守壹、B92902036 余守中 Document 組

組員:B94902032 陳縕儂、B94902071 楊逸民

(2)

2 Introduction to JTAG

JTAG 簡介

JTAG(Joint Test Action Group)是一種用來進行晶片測試的介面;它有一個統一個規格,

可以去針對各式各樣不同的記憶體晶片進行錯誤偵測來看該晶片是否運作正常。

在實做任何可能的測試演算法之前,我們必須先了解有可能發生的記憶體問題。現今,記 憶體裝置製造商會對每一批晶片進行多種後製作業的測試。就算某一批晶片有問題,這些壞掉 的晶片也不大可能會出現在你的系統中;廠商頂多就是把好的部份拿去製作較小規格的晶片。

你唯一會遇上的記憶體晶片問題就是”悲慘的失敗(Catastrophic failure)”通常可能是 因為晶片在生產後的一些實體或是電子損害所造成,或是該晶片的本質早就已經嚴重損毀。這 種錯誤不常見,有的話通常也會對晶片有很大的影響。因此我們可以合理的假設這種重大缺陷 可以被任何演算法偵測出來。

最常見的記憶體問題其實是來自於電路板。典型的電路板問題是處理器和記憶體裝置的(1) 接線問題、(2)晶片遺失、(3)不適當的插入記憶體晶片。這些問題是一個好的測試演算法應該 偵測出來的。

【電子接線問題】

電子接線問題可能是因為設計錯誤、板子生產錯誤或是生產後的破壞造成。每一條連結處 理器跟記憶體的電線都會是下列三種型態之一:位址線、資料線、控制線。位址線和資料線是 用來選擇記憶體位置跟傳輸資料用。控制線告訴記憶體裝置,當資料在傳輸時,處理器是要對 其位置進行讀還是寫。不幸的是,這些線路都有可能被接錯或是損毀(比方說短路或是根本沒 接到任何東西)如圖一所示。這會導致記憶體裝置行為不正常。資料可能會不正確(data line 錯 誤)、儲存到錯誤位址(address line)、或是根本沒有存入(control line)。

如果是資料線的問題,多個 bit 的資料可能會"stuck together"(舉例來說,不管資料已經 傳送了,2 個或 2 個以上的 bits 總是存著相同的值)。相似的有"stuck high"(always1)和"stuck low"(always 0)。只要接起一連串的設計好的資料值,可以單獨去測試每個 data pin(可設定成 0 或 1),就能夠偵測出這種問題。

如果是位址線的接線問題,兩個記憶體位置的內容可能會重疊,換句話說,寫到一個位址 的資料可能會蓋到其他位址所存取的內容。會發生這種問題是因為一個 address bit 短路或是 開路,導致記憶體裝置看到的位址和處理器所指定的不同。

控制線也是有可能短路或是開路。雖然說理論上有可能開發出針對控制線問題的偵測方 法,但是卻無法描述出一個普遍的測試。控制訊號的運算是處理器或是記憶體結構的特徵。所 幸,如果控制線發生了問題,記憶體根本就無法運作,而記憶體測試就可以偵測出這個問題。

(3)

如果你察覺到控制線有問題,最好的處理方式是在進行任何測試之前,先向板子的設計者尋求 建議。

【晶片遺失】

記憶體上某個位置根本就沒有放置晶片上去,理所當然地會導致問題產生。

【不適當晶片放置】

簡單來說,就是晶片被放置到不對的地方;比方說,一個 component 被放錯位置,接著 後面所有的晶片都因此位移,而沒有被安插在預計的地方。

【偵測方法研發】

有三種測試是必須被執行的:data bus test、address bus test 和 device test;前兩個 是測試”電子接線問題”和”不適當晶片放置”,第三個是偵測”晶片遺失”和”悲慘錯 誤”。 執行這三個測試的順序最好是 data bus test→address bus test→device test。因為 我們必須分階段來進行,只有在前一個階段正確之後,下個階段的測試才會有意義。

【Data Bus Test】

※ 測試目標:確認 processor 放什麼值在 bus 上,memory device 端讀到的是同一個值。

※ 測試方式:Walking 1’s bit,確定 data bus 的每一個 bit 都能正確的傳送 0 或 1: 這樣就 能確定 bus 沒問題。

(4)

Walking 1’s bit 傳送的資料

 00000001

 00000010

 00000100

 00001000

 00010000

 00100000

 01000000

 10000000

實作方式:把第一個 byte 寫到 bus 裡, 再從 memory device 端的 bus 讀出來 C implement:

For( pattern=1; pattern != 0 ; pattern <<= 1){

*address = pattern; //write to bus

if( *address != pattern){ //read from bus and check if equal return pattern; //把造成錯誤的 pattern 回傳

} }

【Address Bus Test】

※ 測試目標:確認每個 address pin 都能夠正確地指定我們所要求存放的位置。

※ 測試方式:(1)對每一個位址都去測(O(n))

(2)只測試 2 的次方數(power-of-2)的那些位址(O(logn)),因為 我們只要確認每根 pin 腳都能夠存取 0 和 1 即可。

測試的具體想法是:

 先在每個 2 的次方數的位址寫下某個 pattern。

 針對每個 2 的次方數的位址,寫入 inverse pattern。

 然後檢查其他的 2 的次方數的位址的值有沒有變(內容應該要維持是 pattern)。

 若變了則回傳 error。

 若沒有發現 error 則將在檢查的位址的值寫回 pattern 然後用同樣方法繼續檢查其他 2 的 次方數的位址。

【Device Test】

(5)

※ 主要要測的就是對於 memory 中的每個 bit 都可以保存 0 或是 1 的值。雖然做法相當的直 截了當,但是比前兩項需花費更多的心力(應該是因為要對每個 bit 都去測試的關係) 我們要對每個 memory location 測試兩次。在第一次的時候可以任意給值去測試,只要第 二次的值和第一次的值相反即可(如圖所示)。

但是因為可能存在 missing memory chip,所以最好選擇一個 set,像圖中的

00h~FFh("increment test"就是個簡單的 set),然後每個區塊的值都是 distinct,寫入這些區 塊以後再對每一個去讀,看看是否符合。

Offset Value Inverted 00h 00000001 11111110 01h 00000010 11111101 02h 00000011 11111100 03h 00000100 11111011

: : :

FEh 11111111 00000000 FFh 00000000 11111111

【JTAG 介面】

JTAG 是以很多個 cell 去包圍住我們想要測試的晶片,這些 cell 彼此之間互相連結,就好 像迴轉壽司一樣。JTAG 的輸入跟輸出都是 1 個 bit,這樣有助於規格化。我們一次 push 一個 bit 進去(TDI),等到每一個 bit 都到達正確位置後再同步丟掉晶片中,晶片接著會把結果輸出 給藍色的 cell,我們再去檢查是否都正確。

這些指令是由 TMS 傳給 JTAG,TCK 則是負責同步的工作。

(6)

上圖為一個 cell 的內部構造,Data In 以及 Data Out 就是 cell 之間連接的線路,Scan In 跟 Scan Out 則是和晶片連結。Mode 可以控制該 cell 的模式,看是要它把輸入直接傳給下一個 cell 還是要它確實去跑一次都可。負責控制動作的 TMS 輸入實質上是一連串的 1 與 0 字串;

這個字串會控制下圖的 state machine,讓 JTAG 執行我們要求的指令。

【JTAG 的優點】

JTAG 規定輸入輸出都是一次 1 個 bit,這使得它不受任何晶片種類的限制;也就是說,不必 因為換了不同種類的晶片,我們就必須改變 JTAG 的設計。而且,進行測試的時候可以把大量 的晶片全部串接起來,再用程式去看看有沒有問題。我們可以利用 mode 線路來讓某些 JTAG”

電線化”於是就能夠針對單一個晶片進行檢查。

(7)

【運作方式】

Test Case:PC JTAG:DE2

I.O.I(Interface of Interface):DE2 SRAM:DE2

首先,SRAM 的部份就是提供了多種不同的錯誤版本來給 Tester 進行測試;

我們需要 I.O.I.是因為在 PC 端會傳輸三種不同的資料給 DE2,最佳的情況應該是每一種資料 型態都有一條 RS-232 傳輸線負責,然而受制於器材限制,我們只好以 I.O.I.來告知 DE2 我們 目前傳送的資料是哪一種型態。首先 PC 傳送一個 byte 給 DE2,告知接下來要傳輸的 8 個 bytes 是什麼型態的資料。I.O.I.會在 clock down 的時候把資料準備好(置放到 buffer 裡面),等到 clock rise 的時候就把 buffer 的資料給 JTAG,於是 JTAG 就能夠去針對 SRAM 進行偵測;每 次都會回傳 1bit 的結果,我們再把這筆資料回傳到 PC 上去判斷它是否正確;沒有問題的話就 進行下一次的測試,反之則把錯誤訊息傳給 I.O.I.再讓 LCM 去顯示。

(8)

3 Introduction to SRAM

SRAM 實做方式 外部電線

data_bus_in:有八條線,代表欲存入的資料,共 8 bit。

data_bus_out:有八條線,代表欲輸出的資料,共 8 bit。

address:有四條線,代表欲存入的 memory 位置,共 4 bit。

gw:write enable,當 gw 為 0 的時候( 代表可以寫 ),才能將資料寫入。

oe:read enable,當 oe 為 0 的時候( 代表可以讀 ),才能將資料讀出。

內部電線

data_bus_in_signal:將 data_bus_in 接到 data_bus_in_signal。

data_bus_out_signal:將 data_bus_out 接到 data_bus_out_signal。

address_signal: 將 address 接到 address_signal。

Method of Implementation:

先宣告長度 16 的 memory array,當可以寫時,將 input data 存入 memory。當可以讀,

但不能寫時(不能同時又寫又讀),將 memory 指定位置的資料輸出到 output。

(9)

4 Introduction to Files

右圖為本組所有 VHDL 檔之層 次圖。IOI_JTAG.vhd 為總管所有 VHDL code 的 component。

IOI_JTAG.vhd 下面分兩邊:圖中右 邊為負責和電腦端及 C-LCM 溝通,

以及扮演 buffer 角色的

Echo_DE2.vhd,。左邊則是 JTAG simulation,simulation 的最上層檔 名為 TOP.vhd。下面會對每個重要的 檔案做更詳細的介紹。

-IOI_JTAG.vhd

名字中的 IOI 代表的是 interface of interface,而這個檔案主管 JTAG 到 buffer 資料,從 電腦 input 進來的 TDI、TMS 資料,以及 output 到 C-LCM 的 TDO。主要功用就是做為所有 VHDL 檔的最上層。

- JTAG Simulation

JTAG simulation 的檔案是根據 Boundary Scan Handbook (Parker) (下圖右) 做切割 的。

(10)

Top.vhd 涵蓋的是這整張圖裡面的所有 component,也就是 JTAG simulation 的最上面 層 VHDL 檔。另外,除了 TAP、IR、boundary scan register 之外,其他所有在外面的電線 和 multiplexer 也是在 TOP 中 implement 的。

下來到第二層,TAP.vhd 代表著圖中的 JTAG TAP,檔案裡面基本上就是根據 specification 中的 state machine 做 coding。因為對於 process 的性質不熟,又為了要在 JTAG

specification 指定的 rising edge 改變 state 又要改變相關 signal lines,所以一開始做了非 常多的測試,最後終於知道在一個 process 中,simulator 會把 process 中的所有指令視為同 時間執行。

IR.vhd 代表著圖中 Instruction register 的部分。我們的 instruction 共有三個 bit,裡頭 分成了 shift register 和 hold register。另外,我們也 implement 了 specification 上面說明 的 shift register 的 default 輸入值後兩碼為 01,以及 bypass command 的代碼後兩碼需為 11。

第二層的最後一個檔案:DR_SRAM_Mux.vhd,代表著這個圖中中間上方虛線中的東西。

其中 DR(data register)代表 JTAG 的 boundary scan cell,SRAM 就是本組需測試的 SRAM

(待測試的 SRAM 就需放在這個位置),而 Mux 就是在 bypass register 右邊出現的 multiplexer,需選擇要從 bypass register 讀資料還是要從 boundary scan cell 讀資料。

DR_SRAM_Mux.vhd 下面的 DR_SRAM.vhd,要負責 generate 出 SRAM 週圍的

boundary scan cell,以及控制其中的 data,每收到一個 clockDR 就繞著 SRAM 週圍移動一 格。

Bsc.vhd,代表的是一個小小的 boundary scan cell 的 component。

SRAM.vhd 則是我們所要測試的對象,而我們統一的 SRAM pin 角及 boundary scan cell 的順序如下圖。我們的 SRAM 為 8 bit、16 address SRAM。

(11)

5 Notes for Codes

RAM tester (C++ part)

此份 code 的工作就是控制 ram test 的流程,藉由 rs232 介面與 DE2 board 溝通,將 testing data 送至 JTAG interface 來進行 ram 的各項測試。

主要測試分為三部份,目標分別是對 data bus、address bus 以及 ram 本身進行正確性 的檢驗。測試的演算法如同 blahblahblah(document 組翻譯的那篇),但因為本組所使用的 模擬記憶體規格較小,加上要透過 JTAG interface 把資料送進 memory,因此這個程式的最 主要工作就是將三個 test 對 ram 的 input 及 address 轉換成 JTAG 的 TDI 序列,並指定適當 的 TMS 序列,使其能夠正確的藉由 JTAG interface 來完成我們所需要的測試工作。

三個部份的測試個別寫成三個 function,主程式執行時依序對 ram 作測試。當測試通過 時回傳成功訊息,否則回傳測試失敗的位置(bus 的第幾條線或是 ram 的第幾個 cell),假使無 法判定出錯的部份則傳回 unknown。程式另外一部分是開啟 COM 連結透過 rs232 的 port 對版子溝通,這部份的程式碼是參考數電實驗助教給的示範 code 來寫的。

撰寫這篇 code 本身遇到的問題不大,最麻煩的地方是和板子溝通時要如何協調。因為 VHDL 並不像 C++那麼方便設計,協調出一個合適的 protocol 讓兩邊都方便作業算是一開始 最重要也最花時間的工作。

Interface of Interface (IOI)

此 IOI 程式位在 DE2 上,以 VHDL 撰寫,使用 RS-232 通訊協定與位在 PC 端的 Tester 溝通,並扮演 Tester 與 DE2 上的其他元件(LCM 以及 JTAG 的 TAP)之間的溝通者。

Tester 可能傳送的資料有三種:TMS、TDI、LCM Data。Tester 所傳出的每筆資料的第 一個 Byte 的 ASCII Code 會標明此筆資料為何。IOI 中存有三塊 Buffer 分別用來儲存所收到 的上述三種不同資料。LCM 直接連到對應的 Buffer 做 Display。IOI 與 TAP 間有四條線,TCK、

TMS、TDI、TDO,當收到一組 TMS 與 TDI 之後,IOI 會將與 TAP 連接的 TCK Enable,接著 TAP 將會在每次 TCK High 時讀取分別 1 bit 的 TMS 資料,並根據其 State 決定是否讀取 1 bit 的 TDI 資料與是否回傳 1 bit 的 TDO 資料。為了簡化問題,我們假設 TAP 每此都會讀取 1 bit 的 TMS、TDI 資料,並回傳 1 bit 的 TDO 資料,故,IOI 會再 TCK Low 時將 TMS Buffer 與 TDI Buffer 內的資料 Shift 一個 Bit,將下一次 TCK High 時 TAP 要讀取的資料準備好,並且,

將前一次 TCK High 時 TAP 傳回的 TDO 以 RS-232 傳回給 PC 端的 Tester。(如果 TAP 實際上 沒有要讀 TDI 資料則 Buffer 內將會在該 bit 塞垃圾,且如果 TAP 實際上根本沒有丟 TDO 回來,

則回傳垃圾給 Tester,由 Tester 決定該 bit 是否有意義。這樣做可以簡化 IOI VHDL Code 的 設計,因每次只需很固定的對 Buffer Shift 1 bit,並回傳 1 bit 的 TDO 即可,額外的判斷則由

(12)

PC 端處理。) Error of SRAM

我們製造了七種類型的錯誤:

1. 內部 input 線路永遠連結到高電位 or 低電位,造成資料存取錯誤 做法:

將某個 input signal 的 bit 的值永遠設為 1 or 0 data_bus_in_signal(0) <= '1';

使得當我們想要將 data 儲存到某個記憶體位置時,不管外部輸入為何,那個 bit 的輸入永遠 都是 1 or 0。

2. 內部 output 線路永遠連結到高電位 or 低電位,造成資料讀取錯誤 做法:

將某個 output signal 的 bit 的值永遠設為 1 or 0 data_bus_out_signal(0) <= '1';

使得當我們想要讀取某個記憶體位置的 data 時,不管記憶體中的值為何,那個 bit 的輸出永 遠都是 1 or 0。

3. 內部 address 線路永遠連結到高電位 or 低電位,造成記憶體錯誤使用 做法:

將某個 address signal 的 bit 的值永遠設為 1 or 0:

address_signal(0) <= '0';

造成儲存時會存到錯誤的記憶體位置,而覆蓋掉原本的 data;而讀取時則會讀取到非目標位 置的 data。

4. 內部 input 線路之間的短路 做法:

data_bus_in_signal(0) <= data_bus_in(0);

data_bus_in_signal(1) <= data_bus_in(0);

將相鄰 input signal 短路。使得相鄰的兩個 bits 的值永遠一樣而造成 data 的毀損。

5. 內部 output 線路之間的短路 做法:

data_bus_out(0) <= data_bus_out_signal(0);

data_bus_out(1) <= data_bus_out_signal(0);

將相鄰 output signal 短路。使得相鄰的兩個 bits 的值永遠一樣而造成讀取 data 的錯誤。

6. 內部 address 線路之間的短路 做法:

(13)

address_signal(0) <= address(0);

address_signal(1) <= address(0);

將相鄰 address signal 短路。使得相鄰的兩個 bits 的值永遠一樣而造成讀取 data 的錯誤。

7. write enable 和 output enable 的錯誤

1) 代表 write enable 的 signal 永遠為 on。使得 memory 永遠在寫的狀態下。

2) 代表 write enable 的 signal 永遠為 off。使得 memory 永遠無法寫入。

3) 代表 output enable 的 signal 永遠為 off。使得永遠無法讀取 memory 中的資料。

Simulation Generating (C code)

看了別組報告時,發現原來可以用程式自己去產生 waveform。因此,為了測試 JTAG 寫 的對不對,就寫了一個產生 simulation 的 C Code。

檔案一覽:

wave_maker.c: 產生 Sequential test 的 waveform。後來才知道原來這樣的 test 是沒有用 的。

real_tester.c: 產生 SRAM 的特殊演算法的 waveform。最後跑 waveform 都是用這個程 式產生的。

wave_checker.c:檢查答案!給他 simulation 產生出來的檔案,和在產生 waveform 時所提 供的答案(在 tdo_ans8 裡面),然後他就會依照每個時間去比對,看看 simulation 跑出來的結果和答案一不一樣。

(14)

6 Problems

Problem of Hazard

Hazard,是一個令人頭痛的問題。以前只有在投影片上看到的東西,沒想到我真的有這 個機會在我自己的 simulation 中看到。我不太知道為什麼我那天會沒事把 functional 的 simulation 換成 timing 的。因為在做數電實驗的時候,助教只有提到 functional simulation,

因此我們之後在檢查的時候,也是用 functional simulation。有可能是那天心情特別的差的 緣故吧。以下 hazard 是在合併 JTAG 和 RS232 的 code 時發現的。

以上是一個 Functional Simulation 的圖,一切都看起來很正常。

以上是 Timing Simulation 的圖,ClockDRout 出現了一個 glitch。Clock 的線出現了這 種 glitch 是很傷的,因為其他元件會把他視為一次 rising edge。

以下會舉一個 hazard 的例子,和 TAP 的 state transition 有關。

Functional Simulation

Timing Simulation

程式碼: when DRShift => ShiftDR_signal <= '1'; Enable <= '1';

when DRExit1 => ShiftDR_signal <= '1';

(15)

以上的圖中可以看到,ClockDRout 在 rising edge 後,因為 ShiftDRmapout 往下掉了 一下,所以 ClockDRout 又往下掉了一下,然後再上來。這樣子會被視為兩次的 rising edge,

因此會吃 ClockDR 的 boundary scan cell 會多吃一次資料,因此就會有出其不意的結果。為 什麼 ShiftDRmapout 會往下掉一下下?經過一番的 debug,我們得到的結論如下。

State transition 是用 asynchronous 的方式寫的。因此,如果 state 有任何變動,就會 馬上反應在輸出上。即使 state 只是在轉換而已,轉換時間雖然不長,但是會有一小段時間,

TAP 的輸出會反應轉換時會經過的中間 state(是哪一個 state 我們太不可能知道,就是因為 state 用 binary 表示,而 NOT gate 造成的 delay,會讓在某一小段時間裡面,新的值和舊的 值同時存在)。因此我們也不知道他去了哪個 state,但是我們能確定的是,那個 state 的 ShiftDR_signal 是’0’。因此在轉換的過程時,ShiftDRmapout 就暫時是’0’了一下下,

造成了以上的 hazard。

如何解決問題?有兩個方法。第一個是把 state transition 換成 synchronous 電路。其實 我們原本的程式就已經是 synchronous 的電路了,在 TCK rising edge 時,current_state <=

next_state。但是 state transition 卻寫在另一個 process 裡面,所以更新 current_state 的 delay 為影響到。但如果我們直接把 state transition 寫在和更新 current_state 同一個 process 裡面的話,問題就很有可能可以解決。另一種解決方法是改變寫法。就是 JTAG 要求說,state transition 要在 TCK rising edge 的時候做,但是卻沒有說某一個 state 所 output 的電線要何 時更新。所以我們就在 TCK 的 falling edge 的時候把 output 電線的值設好。因此在 TCK rising edge 時,就不會有上面提到的 ShiftDRmapout 往下掉了一下下的問題了。我們最後是用這 個方法解決避開了 hazard 的問題。

但是,難道 hazard 就真的有那麼容易打敗嗎?應該沒那麼容易。我們有時候還是會有莫 名其妙 boundary scan cell 為多 shift 一格(多了一個 rising edge 的 hazard?)。SRAM 合併 時也有出問題,但 SRAM 改一改又沒事了。最後 JTAG 本身程式還有錯,相信原因還是有許 多隱形的 hazard 我們一直沒有找到吧。

Problem of Combination

在一開始要研究 JTAG specification 的時候,原本想說直接從制度制訂者:IEEE 那裡拿掉最 詳細的第一手資料。但是在上網尋找後,發現原來 IEEE 1149.1 standard 是要錢的。於是我 們只好用了網路上的入門 tutorial,以及一本從圖書館借的,介紹 JTAG 的書。原本擔心這些 非正式的 specification document 會有所遺漏,不過一路做下來發現這些看似入門的資料,

到也沒有遺漏任何的 specification 細節。

第一個 code 完的是 TAP.vhd,基本上都是跟據 specification 做 coding,但發現不知道 應該何時跟據 state 改變適當的 signal lines,這在上面介紹 TAP.vhd 時也有介紹。

(16)

更大的問題出現在合併之後。在做 TAP + IR + DR_SRAM 合併時,SRAM 出現了不正常 的運作結果。這次危機則在重新改變 SRAM 的 code 寫法時意外獲得解決。第二次 JTAG simulation 與 ECHO_DE2、IOI_JTAG 合併時,再度出現不正常的運作結果。而在實在不知道 是什麼原因引起的情況下,我們第一步先著手處理 fanout 的問題。

Fanout 在我們原的 design 中,從 TAP 連接到 boundary scan register 的 signal line 都 有 fanout 的問題,因為一次需要 drive 太多的 boundary scan register 了。在老師建議下,

我們把原本的 signal 送到 and gate 裡,再把 and gate 的 output 發散給更多的 and gate,

之後才把第二層 and gate 的 output 接到各別的 boundary scan register。以下 code 橋段。

可以我們都和 Mode 做 and,原因是因為 Quartus II 會自動做 optimization,於是所有寫例 如 ClockDR and ClockDR 的話,那個 and 會在 optimizaton 後消失,也無法達到產生 and gate 的效果。最後在走頭無路的情況下,只好和 Mode 這個電線做 and。但在這個 project 中,Mode 的值永遠是 1,所以這個 code 的邏輯會是正確的。

outputTCK <= ClockDR and Mode;

I1: for i in 0 to 7 generate

inputTCKarray(i) <= inputTCK and Mode;

outputTCKarray(i) <= outputTCK and Mode;

end generate I1;

data_bus_out_bsc :

bsc port map( sram_data_bus_out( i - 1 ), bsc_link_data_bus_out( i ), outputShiftarray(i mod 8), Mode,

outputTCKarray(i mod 8), outputUpdatearray(i mod 8), exit_data_bus_out( i - 1 ), bsc_link_data_bus_out( i - 1 ) )

(17)

Problem of IOI

1. Interface 的溝通:第一個版本是,有某個不知名的什麼,會給 IOI TCK 以及 TDI Shift 的 Signal,但後來才發現那個什麼得由 IOI 自己搞定,這樣的改版(其實等於重寫),

花了不少時間。

2. 收到完整的 TMS、TDI 之後,IOI 會將 TCK Enable,曾經一度天真的直接用個判斷 式判斷,然後直接將 TCK <= inner_tck,但後來才發現這樣做不行,一直認為 VHDL 的 <= operator 會真的將電線接過去,但後來發現,這樣做的話 TCK 會 Stick High,

推測 TCK 是存值而非接電線。最後解決的辦法是將 TCK 再多除頻一次,雖然這樣有 點治標不治本,但的確是可以正確執行的。

3. 程式內部有許多 Event Signal,而這些 Event Signal 都要各自不同的平率,為了和 System Clock 同寬,用了許多的 One-Hot,然而 One-Hot 原本是為了 Button 設 計的(0 Enable),又,IOI 這邊要在 TCK Low 時動作,但 RS-232 傳回的 Signal 是 1 Enable,而大家都要與 System Clock 的 High 對齊,這部份也花了一些時間處理。

4. 曾經一度將 RESET 接到 Switch,而忘了 Switch 和 Button 的 High Low 是相反的,

故整個程式就掛了(一直在 RESET)。這個 Bug 找了非常久,果然驗證了越愚蠢的 Bug 越難 De。

5. 因為 IOI 左接 RS-232 連 PC、右接複雜無比的 JTAG,因此非常的難做軟體 Simulation,因此往往只能先假設一邊是對的,或者接 LED 出來看燈號數節拍 Debug。

(18)

7 Waveform

JTAG 操控介紹

我們先解釋我們如何操控我們的 JTAG。

以上 write data 到 address 0100 時,oe = ‘0’,gw = ‘0’,然後 address bit 第二個 bit 是’1’,其他是’0’。然後我要寫入的值為 00001111。所以可以看到,前三次 shift 時,TMS=’0’,最後一次 shift 時,TMS = ’1’ (shift 時 TMS = ‘0’,要離開時才

TMS=’1’,但離開這一次也會 shift 一次)。

Read data 和 write data 唯一區別就是 gw = ‘1’。所以可以看到,綠色部分圈起來的,

就是 gw = ’1’。然後後面為什麼也要在 data in 那裡設 00001111?因為這樣能夠確保 SRAM 在 gw = ’0’到 gw = ‘1’的轉換中,不會因為 delay,使得同一個位置,吃到不同 的 data in。

最後 Data output 的部分,我們會 shift 8 次,而在最後四次 shift 的時候,JTAG shift 出 了四個’1’,這就代表 data out 的 boundary scan cell 吃到了 00001111。也表示我們成 功的將值寫入 SRAM 了。

(19)

錯誤 SRAM 的 waveform 介紹

以下的部分,我們會拿許多錯誤的 SRAM 去跑 simulation,看看 tester 是否能夠抓出 SRAM 的錯誤。不過在拿錯誤的 waveform 出來之前,先介紹一下,測試的步驟為何。

1. 用 C 程式(real_tester.c)產生出 waveform 檔。

2. 拿去 Quartus II 裡面跑 functional simulation。

3. 將以下跑出來的結果上傳工作站。

4. 用 wave_checker.c 去撿查答案是否正確。程式會說哪一個時間點 simulation 的值和正確 答案不一樣。我們由時間點就能判斷出哪一個 SRAM 是在做哪一種 test 發現了錯誤。。

(20)

現在,我們就拿幾個錯誤的 SRAM 吧!

解釋一下後面會用到的變數。data_bus_in_signal 是接到 SRAM 的 data in 的線。

data_bus_out_signal 是從 SRAM 的 data out 接出來的。address_signal 是接到 SRAM 的 address bus 的。

Data Bus Test

註: write_board(addr, value)

read_board(addr, 理論上應該讀到的答案) for (i = 0; i < INTEGER_BIT; i++) {

write_board(0, 1 << i);

read_board(0, 1 << i);

}

(21)

當我把 data_bus_in 的第零個 bit 永遠設成’0’時,那麼當我寫入 00000001 時,最後 寫入 SRAM 的值是 00000000。所以 output 時,值就是 00000000,然後就被 tester 抓出錯 誤了。

當我把 data_bus_in 的第五個 bit 設成永遠是’1’時,那我寫入 00000000 時,SRAM 讀到的值是 00100000。因此在 output 時,第五個 bit 就會是’1’,然後錯誤就被 tester 抓出來了。

當我把 data_bus_out 的第三個 bit 設成永遠是’0’時,那我寫入 00001000 時,SRAM 讀到的值是 00001000。但 output 時會輸出 00000000,然後錯誤就被 tester 抓出來了。

(22)

當我把 data_bus_in 的第三個 bit 接到第四個 bit 時,那我寫入 00010000 時,SRAM 讀 到的值是 00000000,因為 data_bus_in 的第三個 bit 是’0’。所以 output 時輸出 00000000,錯誤就被 tester 抓出來了。

當我把 data_bus_out 的第五個 bit 接到第六個 bit,那我寫入 01000000 時,SRAM 讀 到的值是 01000000。但 output 時,因為 data_bus_out 的第五個 bit 是’0’。所以 output 時輸出 00000000,錯誤就被 tester 抓出來了。

(23)

Address Bus Test

pattern 是 00001111 的話,cpattern = ~pattern = 11110000

Address bus第二個bit永遠是0,所以當我想寫入0010這個位置時,其實是寫到0000。

而我想讀0010這個位置時,也會讀到0000。而經過了上面的code第三行write_board(0, cpattern);後,0000的值被改成anti-pattern了。所以當我想讀0010時,讀出來的會是錯誤的 資料。但是理論上錯誤的資料應該是11110000,但是上面的waveform卻是00000000,所以 這裡也有點問題。

把 address bus 的第二個 bit 接到第三個 bit。這樣子當我想在 1000 寫入資料時,其實 for (i = 0; i < ADDRESS_BIT; i++)

write_board(1 << i, pattern);

write_board(0, cpattern);

for (i = 0; i < ADDRESS_BIT; i++) read_board(1 << i, pattern);

(24)

是寫到了 0000 這個位置去了。所以當 0000 寫了 anti-pattern 之後,再從 1000(其實是 0000)

讀資料時,就會讀到 anti-pattern ,因此錯誤就被 tester 給找出來了。而且這次的 output 就對了,他的確是 output 出 anti-pattern 來了。

很慘的錯誤

最後一種錯誤就是很慘的錯誤。簡單講,oe 不管怎樣,都沒辦法把 SRAM 的值讀出來。

這種情況下,tester 會說全部都錯了。因此這時候,看 waveform 也看不太出什麼就是了。

(25)

8 Feedback

余守壹

從十月初抽題目,到一月初報告,DSD project 陪伴了我們三個月。從一開始的懵懂,第 一次 status report 所見到的曙光,第二次 status report 受到的刺激,和最後上台報告,這段 路程,回首來看,真是漫長呀。在這三個月的時光中,我們每個組員,都曾為了這 project 傷 過腦筋,而因此也有了成長。

第一次 status report 前,仔細看了我們的題目。JTAG Interface SRAM/SDRAM/NOR Flash Tester with C-LCM。這是我們的題目,一長串的火星文。那天晚上,花了不少時間,

查了 wiki,查了 google,終於成功的把我們的題目斷句了。隔天的 status report 結束後,

老師對於我們的 report 還滿滿意的。當時很高興,我們朝著正確的方向踏出了第一步。

我們的 project 可以簡單拆成兩部分。一部份是 SRAM 組,另一部份是 Tester 組。而因 為我是被分到 Tester coding 組的,因此後面的心得都會是以 Tester coding 組為主。

第二次 status report 和第一次 status report 中間隔了一個月。許多其他組,就在這個段 時間中,將 project 幾乎完成了。但我們的進展,最後在老師眼中,說是一個禮拜的進展。被 老師念,可能感覺不太好。不過危機就是轉機,Tester 組也因此正式動工了。

Tester 組中又可分為”Tester 本身”和”JTAG SRAM”兩部分。”Tester 本身”的演算 法在第二次 status report 前就已經整理完畢,所以剩下的部分就是把程式寫出來。

”JTAG SRAM”組比較麻煩一點,首要的是把 JTAG 的 specification 讀懂。這是一件非 常麻煩,鬱悶的作業。因為既然老師的題目中,就已經提到,要用 JTAG Interface 來實作這 個 Tester,而 JTAG standard 已經由 IEEE 1149.1 定出來了,我們的目標,就是要 follow 這 個標準。但是 follow 這個標準是有難度的。舉例來說,JTAG 就有規定,TDO outputs on falling edge,TDI inputs on rising clock edge 等等。我們沒有什麼可以自由發揮的空間,只好乖乖 照做。有時候我們會覺得為什麼要如此規定,反而很不直覺,容易造成 hazard。想要去尋找 答案,但卻遇到網路上的 specification 沒有寫得很清楚,IEEE 1149.1 standard 本身又要錢 的情況下,我們只好自己想辦法了。這也是個我們最後 project 沒寫出來的其中一個原因吧。

JTAG specification 最主要是由守中學長和我在讀,而之後再教其他 tester coding 組的 組員。JTAG specification 本身的 learning curve 還蠻高的,也因此導致了另一個 project 沒 寫出來的主要原因。就是別人很想幫忙,但是卻幫不上忙。這是我的錯,我和守中學長花了不 少時間在 debug JTAG 的 code。而 debug 越久,我們對於 code 本身越熟悉,但是卻讓其他 人越難加入我們的行列。而一直只顧衝 debug 的我,最後也嘗了自己做了錯誤決定的苦頭。

這是 team project,team 的意思就是大家要一起做,不是自己一個人做完就好了。如果因為 自己做不完,拖累了整個 team,那這是誰的錯呢?即使溝通是很花時間的,但是到後來,真 的需要一起 debug 時,就會看出效果來了。短視近利的我,當時,沒有看出來。

(26)

分工本身,也是一個很難的問題。一開始大家都對題目不太熟悉,無法準確的看出如何切 塊比較恰當。因此在分工的時候,把兩個人分配去寫”Tester 本身”我覺得還可以。但是三個 人去寫”JTAG SRAM”我覺得是蠻不夠的。因為這部分範圍非常的大,我們寫了差不多七百 多行的 VHDL 程式。而且又是 VHDL 初學的我們,寫起程式來真的是還頗生疏的。而且學 VHDL 的時候又沒有學他底層是如何 implement 的。我花了不少時間,和學長討論,才知道為什麼 兩個 process 不能同時控制一條電線。在這種情況下寫 VHDL,其中會隱藏多少 bug 是很難 估算的,不過想必一定很多。而且 VHDL 的 debugging 比 C 麻煩許多,因此可能花了一個晚 上,一個 bug 也沒挑出來。我爸爸晚上來載我的時候,都會問說 bug 找到了沒有。通常我的 答案都是沒有…雖然這樣看似很沒實質進展,但是無形中,卻是有不少進展吧?而且又如我前 面說的,自己衝的太前面,讓其他組員很難幫忙 debug,就讓這些 bug 更難解決了。雖然說 人多一點一起寫比較好,但是人太多,也會容易造成有冗員的情況。因此分工真的是一件非常 非常困難的事情呀!我猜,資深的工程師,會變成 project 的 leader,就是因為,他分工可以 分的很好吧。

十二月底,我一度以為我把我這邊的 bug 找完了。自己寫了一個 C 程式去產生 simulation 來測測看自己的 JTAG 對不對。我怎麼測的呢?用 Sequential 的方法去測的。就是在 0000 塞值,然後再讀出來看看值對不對,再去 0001 塞值…依此類推。產生 simulation 也花了不少 時間,最後很開心的發現,simulation 的結果是正確的。當時,我很開心的以為我寫完 JTAG 了。當時沒有想清楚,我們之所以需要一個特殊演算法來測試 SRAM 對不對,就是因為用前 面提到的笨方法是沒辦法找到所有 SRAM 的問題的!唉,只可惜,我想到這東西時,已經太 晚了。所以最後在合併的時候,就出了一大堆問題。

以前就有點體會,合併許多人寫的程式是很花時間的,但是沒有實戰經驗,沒有深刻的體 會。不過這次我就有了。到了合併的時候,發現 JTAG 的 TAP 會去神秘的 state,而且怎麼按 都跳不出來。經過一番調查後(一番調查花了十幾個小時吧),終於找到原來是一直陪伴我們 的 hazard 在搞怪。在老師上課的時候有聽過 hazard 這個東西,一個邏輯上永遠是 false 的電 路,可以因為 NOT gate 的 delay,而會有一小段時間是 true。當時如果沒有自己無聊把 functional simulation 改成 timing simulation,就應該永遠不會發現這個問題吧。所以說找 到這個問題,應該算是很幸運吧。為什麼合併之後才出現這個問題?應該是因為合併之前,剛 好,那個 hazard 沒有影響的我們的電路,但是一當線路改了,delay 的時間也改了,hazard 也就因此而出現了。

總之,這次 project,收穫很多吧。許多收穫,也是很難用言語道盡的。最後報告結束時,

聽到老師的評語,讓我很欣慰。Project 有沒有做出來不是重點,重點是,我們真的有動手去 做。謝謝全體組員的努力,也謝謝老師。

(27)

余守中

還記得在分配 final project,看著個組組長辛苦的猜拳決定誰能拿到看起來比較「簡單」

時,真是想不到中間的過程能如此的精采有趣。第一次有那麼多組員的 project,第一次拿到 所謂工業級的 project,回想起來的確還蠻特別的。

在第一次進度回報之前,和另外一位組員,花了一個晚上討論找資料,終於慢慢對本組的 題目有了一定程度的了解。接下來,開始研究 JTAG specification 的時候,因為無法從 IEEE 拿到資料,我和同一位組員從圖書館借了書,加上之前就有的網路資源,開始研究 JTAG 運作 的細節。這個 specification 比想像中的簡單,規定其實沒有很多,不過可因為沒有拿到真正 的 specification,所以都不是很了解規定為什麼要這樣,我們最多能做到的,就是提出一些 沒有人能幫我們證的理論。為了要了解 TAP 裡頭的 state machine,及配合 TDI、TDO 資料 的傳輸時間的運作細節,我們花了非常多的時間。常常在我們自以建立了一個 JTAG 的運作 model 後,才發現會違反 specification 裡面的某一個規定。這時候,只好重新調整檢視我們 的 model,找出我們是否對 JTAG 運作的某些部份誤解了。

經過一個多星期,我們終於能解釋手上 document 的所有 JTAG 細節,這時才約了一個 時間,把我們已知的講解給組上的其他人。講解給大家,只花了兩個小時,把其他人快速的從 只有模糊概念,變成了解大部份運作細節,能開始分工寫 code。兩個人一個禮拜近十個小時 反覆的思考及討論,就這樣傳給了大家。我覺得了解 specification 這部份的經驗非常的難得,

不在於我們知道了真相,而在於推理真相的過程:一個一個的 specification、幾張圖、幾句 話,我們能不能建立一個 JTAG 的 model,如果這個 model 會觸犯到一個 specification,則 只好重新再想一個。也因為有了這個經驗,我們能比只花了兩三個小時了解 JTAG 運作真相的 人對 specification 有更深一層的了解。

另外,第一次在那麼大的組,我覺得分工更是一門藝術,而分工難免會有些不平均,所以 組員們的主動幫忙也扮演著舉足輕重的腳色。事後看起來,我覺得分工進行的不算非常理想,

問題還是出在於無法有效的把更多人力投入在某一個環節的 debug,以致於大家有實力、有 意願幫忙,卻無法在 debug 的路上多走幾步。從這個經驗我也學到,當參與的 project 越大,

個人能力的重要性會大幅下降,而分配、溝通的重要性大幅上升,重要到攸關 project 能不能 做出最後成果。

Hazard 的部份,我覺得我們在兩天內做的 debugging 和調整還蠻可觀也蠻多的,只可 惜最後結果不如人意。

最後,這次 project,沒有做出一個可以運作的成品,讓我覺得蠻可惜的,但學到非常多 難得且寶貴的經驗,這些經驗都是受用無窮的!

(28)

張峻華

分工的時候,要將工作切的乾淨又恰到好處並不容易,舉例來說,有些東西可以放在 PC 用 C 處理,也可以拿到 DE2 上用 VHDL 處理,當然用 C 處理是比較容易的,但也得在開始動 工之後才能漸漸發現哪些東西用 VHDL 很難處理,接著再一次討論,重新定 Interface,因此 並不是說一開始分好的工就真的會持續到最後的。

合併的過程中,雖說理論上只要各自的部分都 OK 了,合起來就應該能正確執行。但實際 上卻是,當合起來不Work的時候,根本不知道誰有問題,而且程式很多段的時候,很難Debug。

因為分工,大家對自己負責的部份會有相當程度的了解,但是當有 Bug 要開始討論可能 的問題的時候,得先花一些時間了解別組的在做些什麼,才能進入其他人的邏輯之中,進而思 考可能的問題與解決辦法。

VHDL 跟高階程式語言或者組合語言相比,思考方式上有頗大的差異,而且最重要的是,

他真的很難 Debug,硬體又很喜歡鬧彆扭。

常常在撰寫的過程中絕得自己想得很對,但跑出來就不是那麼一回事,就覺得一定是硬體 的錯或者 IDE 的錯,但事實證明,凡 Bug 必有因,其實都是自己的錯。

參考文獻

相關文件

另外, 以後我們要談的 decomposition theorem, 都是將一個 vector space 拆解成一些 subspaces 的 internal direct sum, 我們不會再去談 external direct sum,

然而另一方面,蒙古人的統治,相對其他文化而

她寫道,當我們在生活中最想做的事情也是我們的義務時,最能 感受到 Ikigai 。關於 Ikigai ,感受就是最誠實的,如果我們知道如何

• 人生在世的一個主要課題,便是了解事物間的 因果關係以及行為對周圍造成的影響,從而學

最佳解裡面如果沒有greedy choice的話, 則想辦法 把最佳解裡面的一些東西和greedy choice互換. 結 果發現這個新解跟greedy choice一樣好

結 果發現這個新解跟greedy choice一樣好(也是一個 最佳解) 或者發現這個新解更好(矛盾, 所以最佳解

結 果發現這個新解跟 greedy choice 一樣好 ( 也是一個 最佳解 ) 或者發現這個新解更好 ( 矛盾 , 所以最佳 解裡面不可能沒有 greedy choice)... 證明

結 果發現這個新解跟greedy choice一樣好 (也是一個 最佳解) 或者發現這個新解更好 (矛盾, 所以最佳解 裡面不可能沒有greedy