隨著開源的MCU源代碼越來越多,也逐漸的影響著嵌入式系統開發的思路,出現了兩種以前不常見的設計思路。第一,原本需要購買一顆MCU芯片的設計,現在直接考慮購買一顆帶有MCU硬核的FPGA(如ZYNQ系列FPGA)替代,既有MCU的功能,又有接口可編程的能力,更加的靈活;第二種思路是設計中原本需要寫復雜控制邏輯的Verilog模塊,現在直接考慮替換為一顆或者多顆開源的MCU IP核,反正這些MCU都是驗證過沒問題的,并且占用資源很小,同時可編程也帶來了功能改變的靈活性,何樂而不為呢!
(分兩次介紹上述第一種應用的兩種不同應用場景實例,帶操作系統和不帶操作系統來控制LED燈的應用。)
“龍芯杯”競賽的影響和設計水平不斷提升
隨著中興華為事件的不斷發酵,集成電路行業恰似長頸鹿的脖子一樣被一雙無形的手給緊緊的卡住了。之所以稱之為長頸鹿的脖子,是因為集成電路行業擁有很長的產業鏈,而在這個產業鏈上我們卻處處都弱,拿長頸鹿又細又長的脖子來形容再恰當不過了。
國內各種IC設計競賽、EDA設計競賽也越來越多,但筆者認為,最具有代表性最能反映一所高校在校學生數字IC設計水平的也就是“龍芯杯”CPU設計競賽。“龍芯杯”MIPS CPU設計已經舉行三屆了,參賽的隊伍水平也在不斷的提高,一個大三本科生設計一顆帶有4發射亂序處理、分支預測等功能且能跑Linux操作的CPU核已經不是什么問題,并且FPGA驗證的主頻已經超過了120MHz,凸顯了FPGA時序優化能力的提升。隨著RISC-V等開源CPU的不斷發展,相信國內在CPU設計能力上的差距正在加速縮小,被ARM和INTEL卡脖子的時代可能快要結束了。
從參賽的規模上來看,也在不斷的擴大。今年又新加入了不少高校,像北京郵電大學、河北大學等。龍芯杯競賽至少反映了這些高校在CPU設計方向的課程設置已經沒有問題,設計CPU需要眾多課程的支撐,《計算機組成原理》、《編譯原理》、《操作系統》及FPGA設計開發等相關課程,相對而言,國內絕大多數高校雖然有相關的課程,可如果找到有能力設計CPU的學生組隊參賽的高校卻不多。
以下介紹ZYNQ系列FPGA如何使用。以下內容作者是殷建飛。
部分硬件設計中需要CPU完成對電路寄存器的配置,為了完成Zedboard對FPGA上部分寄存器的配置功能,可以在PS單元(處理器系統)上運行裸機程序(無操作系統支持)完成和PL單元(FPGA部分)的數據交互功能,此時PS單元更像單片機開發;另一種方法是PS單元運行Linux操作系統,通過驅動程序和應用程序完成對硬件寄存器的讀寫操作,并且Linux有著完整的網絡協議棧支持,后續可拓展性更強,可以更好的發揮ZYNQ這種異構架構芯片的性能。主要分為兩部分,分別闡述Zedboard中FPGA和處理器互聯總線與硬件設計和Zedboard處理器系統上嵌入式Linux的移植與通過驅動和應用程序簡單配置FPGA寄存器的實現。本文主要介紹不帶操作系統的情況。
PS與PL接口設計和硬件設計
PS與PL交互可以通過ZYNQ系統內的高速總線來完成,ZYNQ內包含AXI4標準總線、AXI-Lite輕型總線和AXI-Stream流式總線。其中AXI4標準總線支持有地址、猝發和連續的傳輸,可以用于大容量數據的傳輸;而AXI-Lite總線則是一個輕量級的地址映射單次傳輸接口,占用更少的邏輯資源;AXI4-Stream是面向數據流的無地址的傳輸,更適合承載視頻流等流式數據。綜上,因為本次實驗硬件設計較為簡單,數據傳輸量較小,因此選用AXI輕型總線作為PS單元與PL單元交互接口。
(1)自定義IP封裝
VIVADO中提供了多種AXI總線接口的IP核,例如DMA IP中使用AXI-lite用來完成CPU配置DMA引擎的寄存器,而AXI標準總線用來完成DMA引擎面向內存地址映射的搬運數據。但是官方的IP核應用不夠靈活,這里我們可以封裝自己的IP并在其中加入需要的邏輯處理。
打開任意一個VIVADO工程,選擇Tools中的Creatand Package New IP選項,點擊next前進。
選擇建立一個AXI4的外設選項
進行IP命名和版本的選擇,另外需要選定工程路徑,這是稍后建 立IP時VIVADO會新建立的工程路徑。
在接口選項中,選擇一個AXI-lite的Slave接口,數據位寬為 32位,寄存器數量為4,這里我們不需要太多的寄存器。當然在面對更復雜的應用時,可以添加更多的AXI總線通道。
選擇Edit IP,此時VIVADO會打開一個新的工程。當然,也可以選擇將IP添加到庫,然后在工程中搜索添加該IP核,然后重新選中該IP選擇Edit in IP Packager,VIVADO同樣會打開一個新工程修改之前的IP。
在上述新工程中,可以看到工程的組織目錄led_v1_1_S00_AXI才是我們創建的總線接口模塊,而led_v1頂層模塊只是添加了對總線接口的例化而已。那么VIVADO建立的IP為什么要新封裝一層例化呢?我們用另一個多個AXI通道的工程來看一下,當IP需要多個AXI通道時,我們發現頂層例化了多個AXI總線通道,我們可以方便的設計和添加.v文件來完成多個數據通道之間的數據傳輸和總線控制。
(2)AXI-Lite協議分析
下面我們對AXI-Lite總線協議進行簡單分析,AXI總線共5個數據通道,分別是寫地址通道、寫數據通道、寫響應通道和讀地址通道、讀數據通道。AXI采用握手信號機制,當發送數據一端發送valid信號,而接受信號一端發送ready信號,當valid和ready同時有效時數據完成一次傳輸。
首先來看寫數據接口,寫數據需要寫數據地址通道先發送地址,然后寫數據通道發送數據,slave端接受完成后通過寫響應通道告訴master端。
上述代碼完成了slave端寫地址通道的響應,slave端在上電復位后保持awreday信號為低電平,當master發出awvalid信號時,slave端將寫地址通道上的地址數據存入寄存器,并將awready信號拉高一個時鐘周期,完成一次寫地址通道的傳輸過程。
對于寫數據通道而言,其數據傳輸過程和寫地址通道的傳輸過程很類似,slave端上電復位后將wready信號拉低,在master將wvalid信號拉高后,slave端將數據存入寄存器同時將wready信號拉高一個周期,完成一次寫數據通道傳輸過程。
寫操作由于是從master傳輸數據到slave,因此需要slave返回一個正確的響應信號給master來告訴master我已經正確收到數據,這就是寫響應通道。由于寫響應通道數據是從slave端向master端,因此由master端發出ready信號,slave端上電復位后拉低valid信號,在檢測到master端的ready信號后將valid信號和bresp回應信號一同發送到總線上完成寫響應傳輸過程。一個完整的寫交易過程完成。
通過上述代碼,讀者可能會困惑寫地址通道和寫數據通道為什么綁定到一起了呢?難道AXI-Lite總線的寫地址通道和寫數據通道數據傳輸必須同時發生嗎?我們參考了XILINX的xapp1168中關于AXI總線設計的工程,發現在它的master端設計中,寫地址通道和寫數據通道的傳輸是由同一個信號觸發的。也就是說master端總是先準備好寫地址通道和寫數據通道的數據后,然后同時傳輸要寫入的地址和要寫入的數據。因此,在slave端,保持相同的設計就可以獲得最優的性能。這也是上述代碼中為何寫地址通道獲取數據時也要求寫數據通道(wvalid)信號也有效。
通過上述設計,通過寫數據通道和寫地址通道獲取到了CPU想要寫入的地址和數據,下一步就要將數據寫入對應寄存器。由于我們選擇了4個寄存器,在代碼中已經由VIVADO為我們自動生成了4個slave寄存器。4個寄存器共需要2位地址線來進行尋址,由于slave是掛在ARM 處理器外部的,當處理器調用函數寫外設的寄存器,如果不做偏移,那么數據就會寫入寄存器0,因此地址axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]決定了將數據寫入哪個寄存器。ADDR_LSB是由數據位寬決定的,DDR數據位寬為字節,所以地址線最低位對應8位數據,對于32位位寬的數據,我們必須進行32位對齊,所以地址偏移從32/4+1位開始。OPT_MEM_ADDR_BITS則決定了偏移范圍有多大,兩位的位寬就足以尋址4個寄存器,一次本工程中OPT_MEM_ADDR_BITS是1,地址位寬是[1:0]共二位,如果8個寄存器就需要三位,那么OPT_MEM_ADDR_BITS就需要定義為2。
下面的代碼實現了根據偏移地址將數據寫入對應寄存器的操作。
假設slave基地址0x43c00000,當我們調用Xil_Out32(0x43C00000,Value)寫的就是slv_reg0的值,此時axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]即axi_awaddr[3:2]為2’b00,如果地址偏移4位,Xil_Out32(0x43C00000+4,Value),此時寫入slv_reg1寄存器,同時axi_awaddr[3:2]為2’b01.
上面分析了寫通道的數據傳輸,接下來分析讀數據通道
讀地址通道和讀數據通道的傳輸不可能同時進行,master端通過握手信號將讀地址寫入slave端,slave準備數據然后通過握手信號返回數據給master。
Slave上電復位后將讀地址通道arready信號拉低,master需要讀數據時將地址發送到讀地址通道的araddr信號線上,同時拉高arvalid信號,發起一次讀地址發送,slave端檢測到arvalid信號有效,鎖存araddr數據,并拉高arready信號完成讀地址接受過程。slave根據ardddr的偏移獲取對應寄存器的數據,然后在讀數據通道上主動發起一次數據傳輸,即將數據置入rdata并拉高讀地址通道的rvalid信號,等待master接受數據并返回rready信號有效后完成讀數據傳輸。
因為Zedboard開發板有8位led燈,所以我們設計一個8位寬的wire型線連接到寄存器0的低8位即可。
需要注意在頂層文件中添加該端口。
至此,我們自定義的IP就設計完成了,我們重新封裝該IP核。
首先點擊各項的藍色感嘆號,vivado會自動更改IP的一些信息。全部消失后就可以進行IP封裝。
選擇重新封裝選項進行封裝,封裝完成后VIVADO工程會自動關閉。
將封裝好的IP添加到庫目錄,在任意VIVADO工程中選擇IP Catalog選項,選中USER Repository選項,右鍵選中Add Repositor,選中我們之前建立IP時選擇的目錄。添加完成。
(3)硬件工程設計
本次實驗基于VIVADO2017.4版本進行硬件設計,建立VIVADO工程并選用Zedboard開發板(這樣后面的部分接口可以使用VIVADO默認配置)
新建block design,添加zynq processing_system,然后點擊Run BlockAutomation進行硬件板卡信息填充。運行完成后可以看到ZYNQ系統以及配置好了DDR內存和串口設置。
如果你使用其他板卡,那么要根據外設的位置和內存型號進行設置,這里進行簡單介紹。
PS-PL配置選項用于打開PS單元和PL單元之前的互聯總線,PS單元中面向PL單元的有4個GP接口。也就是兩個AXI-Lite主端口和兩個AXI-Lite從端口,以及4個高速的HP接口。由于我們需要CPU配置FPGA,因此啟用一個GP主端口。
配置IO選項用于關閉和打開ZYNQ的外設部分的配置,由于ZYNQ可靈活配置,因此需要選擇和板卡相對應的外設位置,選擇Zedboard的好處在于可以利用VIVADO中預設的板卡信息進行自動設置。
需要注意的是,這部分I/O口為ZYNQ的MIO,而PL部分的為EMIO。
另外,想要成功啟動linux至少需要一個TTC外設。
時鐘配置選項用于管理PS單元和PL單元的時鐘,包括內存頻率和CPU主頻信息,I/O口頻率設置。另外PS部分可以向PL部分提供最多4個時鐘,這里僅開啟一個100M的時鐘。
DDR配置選項選擇正確的內存型號即可,這里仍然使用Zedboard的默認配置即可。較為重要的是下面的中斷選項,可以選擇打開PS和PL之間的中斷開關,因為本次工程暫時沒有用到,所以不再贅述。
點擊OK保存對處理器系統的配置,繼續添加IP,搜索我們之前定制的IP,發現led V1版本的自定義IP核,點擊添加。
添加完成后將led端口引出,可以使用快捷鍵Ctrl+T,或者使用右鍵菜單也可以完成。我們將剩余的AXI標準端口使用VIVADO的自動連線功能完成連接。點擊Run Connection Automation,勾選所有IP,完成后發現VIVADO為我們自動添加了一個AXI交換矩陣和復位模塊。
頂層模塊如圖,保存。
我們在工程管理中選中創建的Block Design,選中生成HDL
VIVADO會將處理器系統和IP部件生成Verilog文件。在工程中添加約束文件,加入對LED[7:0]的管教約束。
set_property PACKAGE_PIN T22 [get_ports {LED[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED[0]}] set_property PACKAGE_PIN T21 [get_ports {LED[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED[1]}] set_property PACKAGE_PIN U22 [get_ports {LED[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED[2]}] set_property PACKAGE_PIN U21 [get_ports {LED[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED[3]}] set_property PACKAGE_PIN V22 [get_ports {LED[4]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED[4]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED[5]}] set_property PACKAGE_PIN W22 [get_ports {LED[5]}] set_property PACKAGE_PIN U19 [get_ports {LED[6]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED[6]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED[7]}] set_property PACKAGE_PIN U14 [get_ports {LED[7]}]
然后就可以生成比特流了。
硬件設計部分的工作在這里就完成了,我們需要記錄外設在ARM處理器系統上掛載的地址,這樣才能使用軟件寫入和讀取其數據。在VIVAOD中Address Edit選項卡中可以編輯外設地址,這里我們保持默認,并記錄。
在完成硬件設計部分后,我們可以簡單的運行一個裸機程序來檢驗一下我們的映射關系是否正確。首先在VIVADO中將生成的比特流導出到SDK。
選擇File,Export->ExportHardware,而后選擇File->Lunch SDK,選擇本地路徑(這樣會包含硬件比特流)。
(4)裸機程序驗證
在SDK下,已經包含對應工程的硬件平臺和板級支持包,點擊File -> New -> Application project建立一個新的SDK工程。
建立工程名稱,選擇裸機,C語言開發,班級支持包默認。Next,選擇HelloWord模板。我們在main函數中做簡單修改:
#include #include "xparameters.h" #include "sleep.h" #include "xil_io.h" int main() { int i = 1; while(1) { for(i=0;i < 8;i++) { Xil_Out32(0x43c00000, 1<
通過上述程序,我們講一個8位循環的數據寫入寄存器0中,由于寄存0的低8位連接到了LED燈,因此會有流水燈的效果。
函數 Xil_Out32(0x43c00000,1<
在軟件工程上右鍵選擇Run As -> runconfigurations
選擇對應的比特流,選中燒寫FPGA和復位系統,點擊run,可以看到燒寫完成后開發板成功點亮流水燈。
編輯:hfy
-
cpu
+關注
關注
68文章
10854瀏覽量
211587 -
IC設計
+關注
關注
38文章
1295瀏覽量
103918 -
操作系統
+關注
關注
37文章
6801瀏覽量
123285 -
EDA設計
+關注
關注
1文章
47瀏覽量
13682
發布評論請先 登錄
相關推薦
評論