《FPGA並行編程》讀書筆記(第一期)03_CORDIC

0. 內容回顧

上節內容量非常大,那可是小編耗時將近14個小時來呈現給大家的,大家都弄懂了嗎?這節實驗就比較少了,沒有新知識,主要是大家自己主動閱讀CORDIC算法並搞懂。本次推送附帶高亞軍老師的Vivado HLS中的數據類型章節來幫助大家理解上節的位寬優化,以及本章的數據表示。

  • 第5講 如何處理任意精度的數據類型
  • 第6講 數據類型的轉換
  • 第7講 Vivado HLS 中的複合數據類型
  • 第8講 在 Vivado HLS 中應用 C/C++ 基本運算

1. 緒論

CORDIC (Coordinate Rotation Digital Computer) 是座標旋轉數字計算機算法的簡稱,由Vloder於1959年在設計美國航空導航控制系統的過程中首先提出,主要用於解決導航系統中三角函數、反三角函數和開方等運算的實時計算問題。。它是一種數字算法, 每次運算均產生一次結果輸出。這使我們能夠根據應用需求調整算法精度;增加運算迭代次數可以得到更 精確的結果。運算精度與運算性能和佔用資源並列,是一種通用的設計評估指標。CORDIC是隻使用加法、減法、移位和查找表實現的簡單算法,這種算法在FPGA中實現效率高,在硬件算法實現中經常用到。
CORDIC算法是1950年由Jack Volder發明,它最開始是作爲數字解決方案替代模方案應用於B-58轟 炸機實時導航上,它的功能是計算旋轉角度。在那個時代用硬件實現乘法的成本是相當高的,同時 CPUs的計算能力也非常有限。因此這個算法需要有低的運算複雜度和使用簡單的運算操作。多年之後,它被應用於數學協處理器、線性系統、雷達信號處理、傅立葉變換和其它數字信號 處理算法中。現在,它廣泛應用於FPGA設計中。Vivado HLS用CODIC進行三角函數計算,同時CORDIC也是現代FPGA IP CORE庫中的標準運算模塊。

引自《FPGA並行編程》第三章 CORDIC。

本節課的實驗內容較少,主要是讀懂《FPGA並行編程》中的CORDIC算法,並利用上節課學過的一些優化方案來進行優化。小編感覺如果最初對CORDIC算法不是很熟悉的話,至少閱讀兩遍纔可以能有比較好的認識,大家在做實驗之前一定要搞懂前面的算法內容哦,後面我會說明原因的,小編就因爲沒有弄懂這個算法的機理,後面吃了不少苦頭。

小編認爲CORDIC算法的本質就是利用一些簡單的移位、查找表、加法操作,來逼近正餘弦的計算,既減少了資源的佔用,又提高了計算速度,但同時在不影響準確性的情況下犧牲了一定的精度。大家閱讀完CORDIC算法是怎麼看待的呢!歡迎在後臺與小編進行進一步的交流。
本章的重點是《FPGA並行編程》的第三章節內容!實驗僅僅是回顧。
本章的重點是《FPGA並行編程》的第三章節內容!實驗僅僅是回顧。
本章的重點是《FPGA並行編程》的第三章節內容!實驗僅僅是回顧。

2. 讀書筆記源碼說明

本章內容的源代碼見PP4FPGAS_Study_Notes_S1C03_HLS_CORDIC
工程文件組織和第二章節一致,只是把#define內容移到了.h文件當中。
工程目錄

3. 3個Solution帶您理解CORDIC算法

3.1 S1_Baseline

首先我們要做的當然是C Simulation了,小編在學習這章內容的時候,被這個仿真坑了許久,下面讓我一一道來。
我拿着從英文原版書籍的Github上下載的代碼,準備開始仿真,仿真就結果讓我百思不得其解,大家看下圖便可得知。
錯誤的仿真
得到如此的結果,真的非常尷尬。小編又重讀了一遍CORDIC算法,再看了一遍作者的代碼,才發現一行代碼少了一個正負控制的乘法。
錯誤的代碼
修改後方得到正確的結果正確的仿真結果
我在此說明這件事沒有啥意思,我認爲代碼時作者故意寫錯的,作者幾乎不可能犯下如此低級的錯誤。大家對一段代碼進行重構優化之時,瞭解其所使用的算法含義非常重要,否則連別人給你挖了個坑都不知道,到最後算法調試的時候發現結果不對,還找不到原因,這就只能怪自己了。大家別嫌我囉嗦,我就是感覺有所心得的東西基本都分享所來了,大家各取所需呀。
仿真後開始綜合,看看初始代碼的一些性能估計和資源利用率。S1報告

3.2 S2_Simple_Reconstruction

使用兩輸入複用器可以不使用sigma變量,在一定程度上減少資源的佔用,其實也沒少多少…,但是也要提起有這件事,這樣可以有意識的用到其他方面。使用兩輸入複用器最主要的目的是可以高效地實現選擇,另外我們使用CORDIC算法就是爲了減少複雜運算,因此可以使用移位來進行相應的運算。S2代碼
簡單的代碼重構,對比S1與S2發現
S2報告
DSP資源佔用消失了,而且時鐘的估計值小了很多!從這可以看出S1、S2雖然都是描述的同一個功能,但是進行代碼重構後可以使代碼的執行效率好很多。S2分析
乘法運算被移位運算代替了。S2ashr

3.3 S3_Pipeline

對該循環使用PIPELINE

#ifdef S3_Pipeline

void cordic(THETA_TYPE theta, COS_SIN_TYPE &s, COS_SIN_TYPE &c)
{
  // Set the initial vector that we will rotate
  // current_cos = I; current_sin = Q
  COS_SIN_TYPE current_cos = 0.60735;
  COS_SIN_TYPE current_sin = 0.0;

  // This loop iteratively rotates the initial vector to find the
  // sine and cosine values corresponding to the input theta angle
  for (int j = 0; j < NUM_ITERATIONS; j++) {
#pragma HLS PIPELINE
      // Multiply previous iteration by 2^(-j).  This is equivalent to
      // a right shift by j on a fixed-point number.
      COS_SIN_TYPE cos_shift = current_cos >> j;
      COS_SIN_TYPE sin_shift = current_sin >> j;

    // Determine if we are rotating by a positive or negative angle
    if(theta >= 0) {
        // Perform the rotation
        current_cos = current_cos - sin_shift;
        current_sin = current_sin + cos_shift;

        // Determine the new theta
        theta = theta - cordic_phase[j];
    }
	else {
        // Perform the rotation
        current_cos = current_cos + sin_shift;
        current_sin = current_sin - cos_shift;

        // Determine the new theta
        theta = theta + cordic_phase[j];
    }
  }

  // Set the final sine and cosine values
  s = current_sin;  c = current_cos;
}


#endif

對比綜合後的報告可以看出,程序的執行效率更高了。
S3報告
當然還可以繼續優化,因爲循環之間存在着依賴關係,需要大家手動UNROLL,來展開循環,上個章節已經講過這個內容了,大家可以嘗試優化下,我就不在這裏贅述了,顯得我太囉嗦。

4. 總結

對比上章本章內容略顯單薄,實驗內容較少,而且沒啥新內容;理論內容閱讀起來比較困難,需要多閱讀思考幾遍。實話說我對CORDIC算法的理解不是很深刻,所以本節課沒有帶了很多幹貨,也請見諒。再提一下大家要對CORDIC算法有個清晰明瞭的認識,後面還要用到這個算法呢。希望大家留言反饋,這樣可以修改不合理的地方,增加小夥伴們閱讀體驗。

原創不易,切勿剽竊!

在這裏插入圖片描述

歡迎大家關注我剛創建的微信公衆號——小白倉庫
原創經驗資料分享:包含但不僅限於FPGA、ARM、Linux、LabVIEW等軟硬件開發。目的是建立一個平臺記錄學習過的知識,並分享出來自認爲有用的與感興趣的道友相互交流進步。


Xilinx學術合作二維碼
最後要提的是,本文很多資料都是Xilinx大學計劃提供,該公衆號提供很多的權威信息、開源項目、開發板租借,強烈推薦對FPGA感興趣的道友關注——XIlinx學術合作。


注:個人精力能力有限,歡迎批評指正!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章