1. 程式人生 > 其它 >FPGA邏輯分析儀

FPGA邏輯分析儀

FPGA邏輯分析儀  

作為工程專業的學生,​​我們經常發現自己正在使用各種通訊協議或需要特定的波形。但是,可以輸出特定功能或分析通訊的實驗室裝置通常很昂貴。因此,我們的專案為學生提供了機會,使他們能夠以很少的成本購買這種工具。通過使用fpga,我們能夠實時解碼通訊,同時還允許來自HPS的軟體配置。

概述

該專案包括兩個主要部分:FPGA和HPS。FPGA負責在可變數量的數字輸入通道上取樣資料。FPGA在硬體上執行SPI和I2C的解碼,並且還能夠記錄訊號的上升沿和下降沿以重建原始波形。HPS負責執行基於python的GUI,該GUI通過從SRAM和環形緩衝區讀取資料來繪製取樣資料。GUI還允許對fpga中使用的分析器模組進行軟體配置。


高階設計

專案原理

該專案的靈感來自模擬發現產品,以及我們對能夠分析數字邏輯和輸出波形的多功能工具的渴望。在當今時代,準確而可靠的工具通常非常昂貴。因此,在需要進行許多設定的教室和實驗室中,這種昂貴的工具不是可行的選擇。因此,學生常常沒有適當地解碼邏輯的手段,這可能會導致除錯過程中的挫敗感。因此,我們的小組希望建立一種工具,該工具對於實驗室而言既具有成本效益,又對學生有用。我們想出的解決方案是使用SoC / FPGA來實現這種工具。在設計專案時,我們做出的決定之一是使解碼塊具有可標記性。這意味著我們可以選擇在硬體編譯之前需要多少塊。這樣一來,無論學生使用什麼SoC / FPGA系統,他們都可以使用我們的專案,因為他們可以自定義模組的數量,以使用系統所擁有的邏輯空間。對於該專案的GUI部分,我們選擇對應用程式進行x轉發。這使學生可以從自己的裝置執行我們的應用程式,而無需安裝python或GUI中使用的其他各種軟體包。對於該專案的GUI部分,我們選擇對應用程式進行x轉發。這使學生可以從自己的裝置執行我們的應用程式,而無需安裝python或GUI中使用的其他各種軟體包。對於該專案的GUI部分,我們選擇對應用程式進行x轉發。這使學生可以從自己的裝置執行我們的應用程式,而無需安裝python或GUI中使用的其他各種軟體包。

邏輯結構

該專案分為三個主要部分:硬體邏輯分析器/任意函式生成器,軟體GUI和PIC32,其生成一系列測試輸入。硬體讀取和解碼數字輸入以及輸出任意功能,並由HPS上以Python執行的GUI控制,該GUI可以配置硬體並向用戶顯示輸出。為了視覺化有用的輸入,PIC32生成PWM,I2C和SPI輸入。

硬體/軟體權衡

我們在設計中進行了各種權衡。我們認為,最大的地方應該是匯流排協議解碼發生的地方。我們選擇在硬體中對SPI和I2C進行解碼,因為可以通過將SPI事務編碼為資料來實現節省儲存空間。這確實增加了設計的複雜性,因為它更容易在軟體中實現。此外,我們失去了靈活性,因為現在新的匯流排協議支援需要硬體修改,這比軟體更改要大得多。

此外,我們選擇使用Python作為GUI語言,而不是C語言。儘管這確實需要花費更多的精力來設定軟體包(甚至需要我們完全切換作業系統),但它極大地提高了我們迭代GUI的速度。設計。我們還為Python付出了效能成本,因為它是一種解釋型語言,它將比C慢得多。

程式/硬體設計

計劃詳情

圖形使用者介面


為了處理解碼資料的顯示,我們選擇實現在HPS上執行的基於python的GUI。之所以做出此決定,是因為我們將VGA輸出的DAC用於任意函式發生器。因此,不能通過FPGA處理GUI。此外,由於我們小組的成員已經具有使用它的經驗,因此我們選擇將GUI作為python整合的tkinter庫的基礎。GUI本身是觀察已解碼資料以及配置硬體交叉開關和解碼塊的主要方法。下圖顯示了我們GUI的主視窗。

設定檔

GUI的主要功能之一是能夠從軟體重新配置硬體交叉開關的功能。這使我們能夠重新分配引腳輸入,解碼器模組功能和觸發條件,而無需重新編譯硬體本身。下圖顯示瞭解碼器塊配置選單之一的示例。可以看出,第一行允許重新配置解碼塊的功能。這使我們能夠更改硬體正在動態解碼的協議。這樣,使用者無需硬體重新編譯就可以從解碼GPIO切換到SPI或I2C。此外,我們還可以即時設定觸發條件,從而可以檢視嘗試在不同事件上觸發的結果。

實際上,從軟體配置fpga分為兩個階段。這樣做的原因是,在將更改傳送到fpga之前,一次可以配置多個塊。第一步是在上述選單中選擇所需的設定。選擇所需的設定後,選擇“儲存”按鈕將在GUI類變數中設定相應的位。這顯示在下面的程式碼中。

def save(decode_type, decoder_num, pin1, pin2, pin3, pin4, trig, trigCond, trigMask):
    #We call .get() after each variable to obtain their integer forms 
    #This is because tkinter wdigets use tkinter variables which must be converted 
    gui.block_cfg[decoder_num] = decode_type.get()
    print(gui.block_cfg[0])
    if (decoder_num == 0):
        gui.block1_pins[0] = pin1.get();
        gui.block1_pins[1] = pin2.get();
        gui.block1_pins[2] = pin3.get();
        gui.block1_pins[3] = pin4.get();
        gui.triggers   [0] = trig.get();
        gui.trig_cond      = int(trigCond.get(),16);
        gui.trig_mask      = int(trigMask.get(),16);
    #trig_cond and trig_mask are tk.StringVars and must be casted to int using base 16

儲存功能與每個解碼器塊選單相關,並且對於該塊是唯一的。相應地配置了塊之後,按在完整GUI圖片中看到的藍色箭頭按鈕會將每個塊的配置傳送到fpga。這樣做的程式碼如下所示。由於set_pin_configs函式的輸入是一個數組,因此我們將每個模組的引腳配置連線到一個數組中,然後將其傳送到fpga。

def set_configs():
    pins_config = [] 
    pins_config.extend(gui.block1_pins)
    pins_config.extend(gui.block2_pins)
    pins_config.extend(gui.block3_pins)
    pins_config.extend(gui.block4_pins)
    h.set_pin_configs(pins_config)
    h.set_trigger_ (gui.triggers [0],gui.triggers [1],
                     gui.triggers [2],gui.triggers [3],
                     gui.trig_mask,gui.trig_cond)
    h.set_block_configs(gui.block_cfg [0],gui.block_cfg [1],gui.block_cfg [2],
                         gui.block_cfg [3],gui.block_cfg [4])
   

繪圖

可以說,GUI的最重要特徵是能夠對解碼後的資料進行圖形處理。為了支援此功能,我們使用了適用於python的matplotlib庫。每個解碼器模組最多可分配4個子圖,每個引腳一個。為了能夠在從SRAM和環形緩衝區讀取取樣資料時更新每個圖,我們使用matplotlib的動畫功能。這使我們可以在設定的時間間隔內為每個系列的子圖呼叫繪圖功能。要實際從硬體讀取資料,我們使用自定義的硬體/軟體介面。下面顯示瞭如何完成此操作的示例。可以看出,我們使用介面的get_trigger_status()函式來讀取32位觸發狀態值。該值的MSB告訴我們是否已觸發。接下來的2位描述了觸發了哪些解碼塊,最後下面的29位是SRAM的觸發地址。如果已觸發,則從觸發地址開始從SRAM讀取資料,並繼續進行500個取樣。如果未觸發,則從SRAM讀取地址0到500。

trig_status = h.get_trigger_status()
trigger = bin(trig_status[0])
trigger_int = int(trigger,2)
check = int(trigger,2)
if(check != 0): #if it is 0, we did not trigger, and so the return value is 0
	status =  bitslice(trigger_int, 31, 31)
	status_block =  bitslice(trigger_int, 29, 30)
	trig_addr = bitslice(trigger_int, 0, 28)
else:
	status = 0
	status_block = 0
	trig_addr = 0
if (status and (status_block == 0)):
	samples = h.read_samples(trig_addr, 500)
else:
	samples = h.read_samples(0, 500)
			

還需要注意的是我們暫停和開始繪製取樣資料的能力。這些操作繫結到在整體GUI圖片中看到的開始和暫停按鈕。實現這一點非常簡單,因為我們使用了全域性暫停變數,然後將其封裝在繪圖函式中。單擊“暫停”或“開始”按鈕將更改此全域性值。此外,通過使用內建的matplotlib工具欄,使用者可以放大單個圖,儲存每個圖以供將來分析,還可以調整每個圖的設定,而無需重新啟動GUI。函式生成

GUI的最後一個方面是能夠通過繪製波形來建立波形波形。儘管在許多情況下不一定有用,但這使我們能夠確認函式發生器是否正常工作。在我們報告的結果部分中可以看到一個例子。按下GUI右上角的三個圖形按鈕之一,可以繪製要通過三個函式發生器之一顯示的波形。為了繪製波形,我們使用pygame庫。該庫允許我們繪製一條線,當完成繪製時,將返回其座標。然後,這些結果將在我們的硬體/軟體介面中使用,以告訴函式生成器要建立什麼。如果我們繪製一個x值的y值超過一個y的波形,則將較大的y值用於函式生成。

GUI效能和X轉發

GUI的整體效能仍然需要做一些工作,其中有幾個因素在起作用。第一個因素是所使用的python庫。為了繪製資料圖,我們選擇使用matplotlib庫。但是,這是一個相當繁重的庫,這給處理器增加了很大的工作量,尤其是當我們需要一次繪製多個圖時。由於板載處理器是一個簡單的微控制器,因此通常會將MCU推向極限。這可以從以下事實中看出:僅啟動GUI時,我們的處理器使用率就躍升至近100%。
GUI的效能問題中的另一個重要因素是x轉發。如前所述,我們選擇使用x-forwarding來使我們專案的使用者能夠執行我們的GUI和硬體設定,而無需在自己的計算機上安裝python或其軟體包。但是,此方法的缺點是,由於X11固有的設計缺陷,x-forwading的效能下降幅度很大。X11不會將螢幕傳送到使用者計算機,而是將顯示指令傳送到本地X11伺服器,然後該伺服器用來在使用者本地計算機上重新建立螢幕。這必須在每次更改/重新整理顯示時發生。由於本地計算機不知道需要更新什麼,並且遠端伺服器也不知道客戶端需要什麼,這導致傳送大量冗餘資料。在我們的GUI使用的動畫圖形或影象的情況下尤其如此。實際上,在測試中,我們能夠發現圖形更新和暫停之間的效能顯著下降。
展望未來,我們可能會尋找matplotlib的替代方案。提高效能的潛在解決方案之一是在滾動文字框中以字串形式輸出解碼後的通訊結果。這仍將使使用者瞭解通過其通訊線路傳送的訊息,同時消除了matplotlib的開銷。最有可能的是,我們會根據使用者的系統規格為使用者提供選擇使用哪種選項。

硬體細節

分析儀模組設計


分析器模組是模組化和可配置的硬體,可以執行數字輸入的所有采集和解碼。它具有4個輸入,並能夠解碼SPI和I2C,並具有模組化介面,可輕鬆支援更多協議。此外,它能夠記錄引腳上的任何上升沿和下降沿,從而可以完全重建所有數字訊號。該塊可在執行時重新配置,這意味著GUI可以修改交叉開關連線,解碼型別和觸發條件,而無需重新編譯硬體。

解碼

該模組支援解碼I2C或SPI,或僅記錄每個輸入的上升沿和下降沿以完全重建給定的數字訊號。每個解碼器從輸入交叉開關接收輸入,該輸入交叉開關能夠將四個外部輸入中的任何一個重新對映到解碼器的引腳。解碼器需要知道哪個引腳是時鐘,資料或特定協議的任何其他重要訊號。輸入交叉開關允許使用者以他們喜歡的任何方式插入訊號,並且使用軟體介面,他們可以讓硬體知道他們如何連線訊號,而不是強迫使用者為特定訊號使用特定的引腳。

解碼SPI

SPI解碼器相對簡單。當CS線被拉低時,交易開始。在CS較低的情況下,解碼器將在SCK的每個上升沿從MOSI和MISO移入新值。當CS變高時,如果解碼器感覺到整個事務已發生,則SPI值將被髮送到分析器模組。這意味著解碼器將丟棄未傳送完整8位的事務,以避免誤識別格式錯誤的事務。下面顯示了ModelSim中的一個示例。

上面的ModelSim快照顯示了在兩個不同的SPI事務下解碼器的行為。第一個事務在MOSI和MISO線上均顯示0xFF。我們可以看到,內部“ miso_value”和“ mosi_value”訊號隨著SCK的每個上升沿而更新。當我們到達事務結束時,這兩個訊號都代表通過匯流排傳送的值。當CS拉高時,兩個miso和mosi值將打包到一個稱為“ acquire_data”的結果中,併發出“ acquire_val”訊號,以使分析器模組知道它應獲取此解碼器的資料。同樣,另一個SPI事務將緊隨其後,這一次是在MOSI和MISO線上傳送0xAA和0x55。就像之前的交易一樣,“ mosi_value”和“ miso_value”的值會隨著位的到達而更新,

解碼I2C

與SPI相比,解碼I2C的簡單性略差一些。I2C事務包括四個主要部分:START條件,8位資料,ACK / NACK(可能是STOP條件)。該解碼器跟蹤開始是否是重複開始,8位資料,是否存在NACK或ACK以及是否聲明瞭STOP。

以上來自ModelSim的波形顯示了一個示例I2C傳送0xFF並帶有起始和ACK的示例。隨著SCL的上升沿在總線上計時新值,我們可以看到“ current_byte_id”從0增加到7。在整個事務處理過程中,將緩慢構造位元組值,從而將0xFF值返回給分析器塊。從朝向圖片按鈕的訊號中,我們可以看到在各個位置確定了START,ACK和STOP條件。

     

觸發方式

觸發單元可以被配置為在許多不同的事件上觸發。它可以在任何輸入的任何上升沿或下降沿上觸發,或在其中一個解碼器中遮蔽了交易值。例如,這意味著可以在以下情況下觸發:

  • 在任何上升沿
  • 在引腳1的下降沿或引腳2和3的上升沿
  • 通過SPI傳送0x42時
  • 當I2C事務的前四位為1時

由於觸發器單元支援掩碼和條件,因此潛在觸發器的集合非常大。另外,由於觸發單元的配置與總體塊配置不同,因此有可能解碼一個協議並在上升/下降沿或什至在另一協議上觸發。

分析儀團塊設計

我們的設計允許衝壓出許多分析儀模組。實施該模組化設計是為了使我們的設計能夠在各種硬體平臺上執行,並且解碼器通道的數量能夠根據目標裝置上的可用硬體進行擴充套件。我們將分析器塊的分組稱為“塊”,下圖試圖說明該模組的各個元件。

可變數量的分析器模組都連線到迴圈仲裁器。每個分析器模組都試圖將樣本寫入共享的SRAM。該仲裁程式來自康奈爾大學ECE 4750和ECE 5745課程提供的vc庫。仲裁器接收請求的位向量,這些請求是請求訪問共享資源的實體,在這種情況下,共享資源是共享的SRAM。這些塊僅在內部緩衝區中有等待寫入的資料時才斷言其請求。迴圈仲裁器將以迴圈方式接受請求,嘗試儘可能公平,同時確保在給定的週期內僅授予一個分析器塊寫入SRAM的許可權。

延遲不敏感的通訊

由於我們的分析器模組將在不可知的時間產生結果(因為資料直接對應於外部輸入),因此我們認為可以容忍資料快速爆發的對延遲不敏感的介面是最合適的。所有分析器模組共享一個公共SRAM,並將其樣本資料寫入其中。這是為了確保最大的記憶體利用率(劃分為多個SRAM可能非常浪費)並降低軟體複雜性。下圖顯示了我們如何構造介面。

對於每個環形緩衝區,相應的“環形緩衝區管理器”將跟蹤其相關的元資料。每個環形緩衝區都有一個讀指標和一個寫指標,其中讀指標描述讀取器在緩衝區中的位置,寫指標描述寫入器在哪裡。如果寫指標在讀指標後面,則有寫空間。如果寫指標位於讀指標,則緩衝區已滿,我們無法寫。讀指標有類似的邏輯。如果讀取指標在寫入指標的前面,那麼我們可以讀取,但是如果讀取指標在讀取指標的後面,則緩衝區為空,我們無法讀取。環形緩衝區管理器的角色是將環形緩衝區偽裝成無限的記憶體字串,以方便讀取器和寫入器邏輯使用。

函式發生器設計

函式發生器實現使用板載3通道DAC,該DAC用於驅動VGA訊號的R,G和B分量。相反,我們將每個通道用作8位DAC通道以生成任意功能。每個通道都有一個SRAM,其中包含要輸出的點。SRAM由軟體控制,每個函式發生器週期都從SRAM中讀取一個新樣本,並輸出到DAC上。函式發生器還具有一個預分頻器,可用於調整從SRAM讀取樣本的速率。這樣一來,使用者就不會鎖定FPGA時鐘的取樣率,並且他們可以選擇任意的預分頻器值來減慢時鐘速度。SRAM可通過軟體編寫,並且可通過GUI輕鬆控制。

     

PIC32實際測試

為了測試邏輯分析儀的解碼能力,我們決定最好使用PIC32生成真實世界的波形。感謝Bruce教授,我們能夠使用ECE4760的PIC32板和PIC微型棒使該專案的這一部分相對簡單。為了測試正確的功能,我們需要各種GPIO訊號,SPI和I2C的波形。PIC輸出了4個GPIO訊號,所有佔空比和週期都不同。對於SPI,PIC充當主裝置,並反覆從0-255傳輸值並減慢它的速度。對於I2C協議,由於在使用PIC32上的I2C外設時遇到了一些問題,因此最終導致了特定值的位撞擊。

我們使用以下程式碼將PIC32轉換為從模式:

// Open SPI Channel 2 as master (@500 kHz) 8 bit mode
SpiChnOpen(spiChn, SPI_OPEN_ON | SPI_OPEN_MODE8 | SPI_OPEN_MSTEN | SPI_OPEN_CKE_REV , spiClkDiv);

// SDO2 (MOSI) is in PPS output group 2, could be connected to RB5 which is pin 14
PPSOutput(2, RPB5, SDO2); 
PPSInput(3,  SDI2, RPB13); // RBP13 --> SDI2
PPSInput(3, SS2, RPA3);    // RPA3  --> Chip select
                

SPI的中斷服務程式程式碼:

// CS low to start transaction
mPORTBClearBits(BIT_4); // start transaction
// test for ready
while (TxBufFullSPI2());
// write to spi2
WriteSPI2(count++); //send values 0-255
// test for done
while (SPI2STATbits.SPIBUSY); // wait for end of transaction
// CS high to end transaction
mPORTBSetBits(BIT_4);

結果

邏輯分析儀取樣

在最終設計中,我們建立了一個16通道數字邏輯分析儀(可以輕鬆新增更多通道)。每個樣本都具有以下內容之一:4個輸入中的每個輸入的上升/下降沿,一個SPI事務,一個I2C事務。樣品帶有時間戳,並標有采樣時間和取樣塊。我們的46位時間戳沒有溢位問題,我們可以非常準確地跟蹤取樣時間。在此實現中,總取樣位寬為64位。但是,硬體解碼可以節省大量資料。例如,如果我們使用四個連續取樣通道以20 MHz對SPI進行取樣,則我們將以(20 * 4)100 Mbps的速率產生資料。但是,如果我們以硬體解碼SPI事務,並假設平均SPI通道最多在50%的時間產生事務,

我們已經能夠記錄4個GPIO通道,1個SPI通道和1個I2C,其中每個GPIO通道以大約500 kHz的頻率切換,並且SPI和I2C通道的傳輸速度與PIC32可以傳輸的速度一樣快(@ 20Mhz和100kHz,分別)。有關此結果的螢幕截圖,請參見視訊和GUI部分。
任意函式發生器

我們的設計還支援包含3通道任意函式發生器。有一些預置模式,例如三角波和方波,但是我們還包括繪製波形並在DAC輸出上重新建立波形的功能。如下所示。繪製的波形在頂部,相應的輸出顯示在其下方。

結論

期望與現實

我們對該專案的結果感到非常滿意。儘管我們能夠在HPS上執行一個功能齊全的GUI,但由於X-Forwarding速度較慢,尤其是嵌入式HPS核心的計算能力相對較弱,我們不得不做出一些妥協。我們不能使用許多我們想要的圖形庫,並且GUI的響應時間比我們期望的要少。但是總的來說,我們對該專案感到非常滿意,並認為該專案完全符合我們最初設定的最初目標。
法律和智慧財產權注意事項

為了產生這個專案,我們使用了Altera通過其Quartus IDE提供的各種FPGA IP。我們不打算分發或出售此軟體或硬體。除非在檔案頭或此報告中另有說明,否則所有其他程式碼都是我們自己的。我們使用了ECE 4750中釋出的一些庫程式碼,並引用了此程式碼的用法。但是,由於我們尚未獲得將其公開發布的明確許可,因此我們從公開發布中忽略了這一點。

附錄

小組批准此報告以將其包含在課程網站中。該小組批准將視訊收錄到課程youtube頻道中。

Verilog程式碼

在下面可以找到我們專案的帶註釋的Verilog程式碼。

這裡​people.ece.cornell.edu/land/courses/ece5760/FinalProjects/s2019/amv64_jbc262_nas256/amv64_jbc262_nas256/amv64_jbc262_nas256/code/hw.zip




QSys螢幕截圖


我們的QSys配置的螢幕快照可以在此處此處

此處找到​people.ece.cornell.edu/land/courses/ece5760/FinalProjects/s2019/amv64_jbc262_nas256/amv64_jbc262_nas256/amv64_jbc262_nas256/img/qsys3.png



C程式碼

可以在此處找到我們專案的帶有註釋的PIC32 C程式碼。


任務分配

儘管該專案的絕大部分工作是共同努力,但Nick大多專注於硬體實現,Julia專注於PIC32測試平臺,而Anthony專注於Python GUI。這種故障使我們可以並行工作,並且比以前的工作效率更高。
參考

資料表

PIC32MX​people.ece.cornell.edu/land/courses/ece4760/PIC32/Microchip_stuff/2xx_datasheet.pdf Cyclone V器件資料表​www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/cyclone-v/cv_51002.pdf

原理圖

程式碼參考

Index of /land/courses/ece4760/PIC32/PLIB_examples/plib_examples/spi/master_slave​people.ece.cornell.edu/land/courses/ece4760/PIC32/PLIB_examples/plib_examples/spi/master_slave/ Index of /land/courses/ece4760/PIC32/PLIB_examples/plib_examples/i2c/i2c_master​people.ece.cornell.edu/land/courses/ece4760/PIC32/PLIB_examples/plib_examples/i2c/i2c_master/