FPGA圖像處理基本技巧
5 人贊了文章
代碼在這:https://github.com/becomequantum/Kryon
演算法演示動畫:https://www.bilibili.com/video/av26067000
Verilog是一種思維方式
先來談一下怎樣才能學好Verilog這個問題。有人說學Verilog很難,好像比C語言還要難學。有一定難度是真的,但並沒有比別的語言更難學。我們剛開始學C語言的時候也覺得C語言很難,直到我們把思維方式轉變過來了,把微機原理學好了,能模擬CPU的運行方式來思考問題了,就會發現C語言也沒那麼難了。所以這裡面存在一個思維方式的轉換的過程。這對於學Verilog來說也是一樣的,只不過Verilog比C語言還要更加底層,我們只掌握了CPU的思維模式還不行,還需要再往下學一層「硬體電路的思維模式」,才能更好的掌握硬體編程語言。
我對學習的一個經驗總結就是,如果你想要很好的掌握某一個層面的知識技能,那就必須要往下再學一個更基礎的層面。比如C語言是軟體層面的,理論上你不知道CPU的工作原理也能編程。但要成為高手也還是必須對更下層的微機原理、編譯原理等有深入的了解。再往下一層,也就是數字電路層,對於軟體編程來說已經不太重要了。但要學好Verilog,則又必須再往下學好數字電路這一層。也就是要了解什麼是時序電路,組合電路,RTL,什麼是觸發器的建立時間和保持時間等這些重要概念。至於觸發器是由什麼樣的門電路構成的,邏輯門的版圖又是怎麼畫的,這樣更底層的知識其實對學Verilog來說也不太重要,但要是學晶元設計,這些又很重要。
總的來說現在會硬體編程的人才少是因為之前微電子專業培養的人太少了。而計算機專業的想來用FPGA那自然會覺得Verilog難學,因為他們可能沒學過數字電路這些基礎知識,或者學過也早忘了。所以如果現在想學硬體編程,而以前也沒有學過數字電路的基礎,那就先得補充點基礎知識,再通過實踐訓練,也能很快掌握。Verilog沒有比C更難,能學好C的肯定也能學好Verilog。但這需要你再進行一次思維方式的轉換和訓練。如果你直接把寫C語言的方式套用來寫Verilog上,那就是大錯特錯了,它們不是同一個層面的。
多實踐,表掉進概念的坑
剛開始學Verilog的時候可能會發現有些概念很難理解。比如Verilog和VHDL有什麼區別?阻塞賦值和非阻塞賦值有什麼區別?什麼是可綜合和不可綜合?
初學時可能看了很多書和文章卻還是搞不清楚這些概念。其實要弄明白這些概念的關鍵不是去調研看別人的解釋,而是要自己去實踐。網上寫文章解釋這些概念的人未必自己就搞的很清楚。比如Verilog和VHDL我就認為它們之間只是形式上有些區別,一個簡潔一點一個啰嗦一些,本質上沒啥區別,換湯不換藥。能看懂Verilog去看VHDL也沒問題,我還干過手動把VHDL改為Verilog的事情,也就是複製粘貼然後改改關鍵字並刪掉一些東西就行了。能這樣就改過來說明它們之間就只有形式上的區別。網上的那些說它們之間區別的帖子,把它們之間的區別說的似乎有很大,但我覺得這些都是在瞎扯。
阻塞賦值和非阻塞賦值。呵呵,我也不知道當初發明硬體建模語言的人為啥要整出這樣一些讓人費解的術語。要知道,有些學術術語如果用大白話說實際上是很簡單的,那些搞研究的人估計是為了故作高深,所以要發明一些新的讓人看不懂的術語來顯得自己好像水平很高。所以大家千萬不要被術語給唬住了。為啥要用阻塞和非阻塞這兩個術語來描述對組合邏輯電路和觸發器的模擬,這個我也不明白。我只知道=和<=在Verilog中是如何使用的。=是用在always@(*)塊和assign語句中寫組合邏輯電路的。<=只用在always@(posedge clk)塊中用來寫寄存器。always@(*)和assign之間沒啥區別,都生成組合邏輯電路。只是有時組合邏輯比較複雜,用assign語句一句話寫不完時會用always@(*)。區別就是always@(*)塊中被賦值的信號要被定義成reg,而assign中被賦值的信號則必須是wire,但它們卻都是生成組合邏輯電路。這就是Verilog一點不嚴謹的地方。不過這也沒啥大問題,就是容易把初學者搞糊塗。有人喜歡把組合電路和時序電路在代碼中分開來寫,比如在always@(*)中寫NextState = 一堆組合邏輯,然後再在always@(posedge clk)中只寫 State <=NextState。不過我嫌這樣寫羅索,所以在我寫的代碼中就只會出現always@(posedge clk) 和assign。
可綜合和不可綜合可以直接理解為,可綜合的就是用來寫實際電路模塊的,不可綜合就是用來寫模擬測試激勵的。可綜合的就是前面說的always@(posedge clk),always@(*),assign,再加上function塊這幾種語句。function塊是用來描述純組合電路的,是可綜合的。比如你要在代碼中經常用到求最大值這個功能,就可以寫一個function [:] Max;。initial,task,for循環,#n延時,repeat(n)@等這些都只會在寫測試激勵時出現,是不可綜合的。可綜合的和不可綜合的語句都能在測試激勵中寫。這樣一說不就很清楚了。
必須了解圖像處理演算法的實現細節
現在調用OpenCV或Matlab中現成的圖像處理函數就可以做圖像處理。但這樣只能說你會用這些圖像處理演算法,並不能說你會寫圖像處理演算法。因為這些演算法具體是怎麼處理圖像數據的,怎樣進行計算的你並不知道。要想用FPGA做圖像處理,首先你得先會寫圖像處理演算法,不管你用什麼語言寫,關鍵是不能直接調用現成的函數,而是要自己能寫出一個像素、一個像素點的處理過程。然後還需要知道你寫的圖像處理演算法中,哪些是適合用FPGA來進行處理的。或者說用FPGA進行圖像處理,和進行各種計算的優勢到底再哪裡。如果發現的確可以用FPGA加速,再來進行FPGA編程實現。
關於FPGA的優勢到底在哪裡,可以參考我在知乎上的這個回答:《FPGA圖像處理的前景如何?》。和以下這兩篇文章:《FPGA,你為什麼這麼牛?》《專訪 | UIUC陳德銘教授:「萬能晶元」FPGA與深度學習》。
FPGA做圖像處理的技巧都在Block Ram的使用上
FPGA的最大優勢就是能對數據進行並行流水線處理。而實現這一點的關鍵就是要用FPGA內部的Block Ram對數據進行邊緩存邊處理。注意,進行流水線處理是用不到DDR的,DDR沒有Ram那麼高的實時性,只能用來緩存大量數據。要知道FPGA接的DDR速度和容量是遠沒有CPU上接的DDR快的。所以要發揮FPGA並行流水線處理的優勢,其所用的演算法也必須並行流水線化。把CPU上的演算法照搬到FPGA中,然後接個DDR當內存,這樣的做法並不能發揮FPGA的優勢。FPGA的優勢是並行流水線。那什麼樣的演算法可以並行流水線化呢?簡單的說只需要順序讀取數據進行處理的演算法都可以。比如像圖像處理中用NxN的運算元進行濾波,取邊緣,膨脹腐蝕等。這些都是很適合用FPGA進行處理的。有些演算法看似不是順序讀取數據的,但改造一下之後也可以。比如連通域識別,具體可見我的另一篇文章《FPGA實現的連通域識別演算法升級》。
那麼用FPGA進行NxN的運算元法圖像處理具體是怎樣實現的呢?以3x3的運算元為例,3x3的運算元要同時取3行的數據,所以先要用FPGA裡面的Block Ram緩存上兩行的數據。當這一行數據來的時候同時去讀取Ram里緩存的上兩行數據,並把這3行數據一起移入3x3的移位寄存器中,然後對這3x3個寄存器中的值進行你所需要的運算元運算。之後再把這新一行的數據存回Ram中,原先最上面的那一行數據就被覆蓋丟棄了。簡單的說流程就是這樣的,N行的運算元只需要緩存N-1行數據。Block Ram是FPGA里最重要的資源,所以能省則省。
具體如何寫大家可以去參考我開源的代碼,其實也沒有多複雜,代碼並不長。LineBuffer.v這個模塊是負責控制Block Ram讀寫的,它並沒有把Block Ram模塊包含進去,是因為Block Ram是需要你自己用ISE或Vivado根據你的演算法需要來生成的。OperatorNxN.v這個模塊包含了LineBuffer.v和Block Ram模塊,負責把數據移入移位寄存器並進行運算元的計算。
這個Ram就相當於數組,在軟體編程中我們獲取數組中的數據只要寫個A[n]數據就來了,不需要關心任何細節問題。但在Verilog硬體編程中,數據是怎麼寫入Ram中的,然後又是怎麼讀出來的都需要你去描述,這裡面關鍵要處理的就是Ram的讀寫時序問題。所以在Verilog代碼中,進行運算元計算的這塊代碼看起來是和C語言中的差不多的。Verilog中多的就是對Ram的讀寫操作和移位寄存這塊。要想用FPGA進行圖像處理,要學會的也就是這些操作。
這幾個代碼大家新建個工程把它們添加進去,並自己生成同樣大小的Block Ram就能跑模擬了,測試激勵和測試用的文本圖像文件都有。生成Block Ram時要注意選True Dual Port Ram,寬度和深度和我的代碼中標註的一樣。輸出不需要用寄存器緩存,ISE中默認沒有勾選,Vivado中勾上了,要去掉。注意FPGA中的Block Ram是有最小單位的,Xilinx 6系中是9k,7系中是18k,這就意味著如果你在7系中生成一個18x1025或19x1024的Ram就要消耗兩個18K的Block Ram模塊。所以生成時要注意看最後的報告,告訴你到底用了多少塊。
所以也就這麼幾個不長的代碼就把FPGA進行圖像處理的基本技巧都包括了,沒有多麼的複雜。用這幾個看似簡單的模塊進行組合,能實現的功能還是挺多的。
知乎問答:
(二維碼自動識別)https://www.zhihu.com/zhi/people/995213768317665280?qrcode=1
推薦閱讀:
※思騰合力將於 7/20 舉辦 DGX 人工智慧專場研討會
※【飛天存儲服務月報】2018年6月刊
※你以為勞斯萊斯是家豪車品牌,但它還是浪漫紳士有情懷的科技公司
※小程序的崛起
※通用處理器的發展(CISC->RISC->???)