1:實驗說明:
對於Zedboard的用戶自定義的IP核有兩種可行的方案:
一:通過EMIO交換數據(GPIO,SPI),這個其實就是將PL的IP核看作系統的外設,在數據交互性能和效率上都有很大的缺陷。(不常用)
二:利用嚮導來製作滿足AXI協議的IP核,嚮導自動生成總線相關的代碼,做好地址譯碼邏輯,讀寫控制邏輯,並在用戶工作區生成一些寄存器。我們寫的PL邏輯通過讀寫這些寄存器和PS交互。這也是常用的方法。
Zedboard也有一些自己做好了的IP core,實驗八就是用的自帶的IP core。
本實驗就是採用第二種方法,製作一個簡單的PWM發生器。在PL端開發了這個IP核以後,先在裸跑的程序裏面調用這個IP core,測試我們的邏輯有沒有實現,這個和之前做的實驗沒有什麼區別(zedboard--zynq使用自帶外設IP讓ARM PS訪問FPGA(八),只不過這裏是我們自己寫的IP core)
PWM發生器內部只有兩個寄存器,一個是調節週期的週期寄存器,另一個是調節佔空比的佔空比寄存器,其中週期寄存器的最高位是狀態位,控制PWM波最後是否產生。
2:具體步驟
啓動PlanAhead,創建工程,Next,圖1
輸入工程名project_10,Next,圖2
Next,RTL工程 圖3
一路Next,不添加任何文件 圖4
選擇board 圖5
完成工程 圖6
PlanAhead進入工作視圖,在Project Manager中單擊那個有+的圖標(addsources),出現下圖,選擇Embedded Sources 圖7,圖8
Next 選着Create Sub-Design。 圖9
輸入名稱,這裏爲system 圖10
點擊finish 圖11
進入了XPS,提示所建立的一個zynq工程,提示是否建立bsb Wizard,選擇yes 圖12
出現下圖 圖13
點擊ok 出現 圖14
選擇next 這裏不要大意,一定要把右側的兩個東西來remove掉,我當時就是卡在這裏。,remove後出現這樣的圖 圖15
Finish,點擊finish就可以了,然後進入zynq的配置界面,Diligent公司做好了一個配置方案,可以到網上下載到配置文件。
如圖16 17 18
Hardware- Createor Import Periphera 來到歡迎界面 圖19
Next,創建新的模板(默認選擇) 圖20
Next 默認 圖21
Next命名工程 圖22
採用AXI4-Lite 圖23
Next,這裏只要 User logic master support 圖24
Next,我們要兩個寄存器,分別是佔空比寄存器和週期寄存器,圖25
Next,不做任何修改 圖26
Next,不需要仿真平臺 圖27
Next, 全選圖28
第一個選項表示生成的User Logic使用VerilogHDL
第二個選項表示同時生成一個ISE的工程,便於調試和測試Ipcore
第三個選項表示生成軟件驅動庫文件,方便在SDK裏使用Ipcore
Next,點擊finish就可以了 圖29
我們自己配置的IP核就建立好了,接下來添加剛完成的IP核,在IP Catalog裏面的USER選項中找到它 圖30
雙擊PWM_IP,出現 圖31
選擇YES, 圖32
點擊兩次ok,出現 圖33
注意一下不要粘貼外面的(如word文檔裏面的),容易出錯,輸入法選擇在英文輸入法下。
右擊pwm_ip_0,View MPD,添加PORT pwm_out=””,DIR=O,如圖34(添加在60行),保存並關閉
右擊pwm_ip_0,Brouse HDLsources,打開pwm_ip.vhd.添加代碼
1添加(138行) 將pwm_out接口設置爲模塊的輸出接口
pwm_out :out std_logic; 圖35
2添加(253行)將pwm_out接口到user_logic設備
pwm_out :out std_logic; 圖36
3添加(342)將設備的pwm_out接口和IP核的pwm_out接口連接
pwm_out =>pwm_out, 圖37
保存,退出,右擊pwm_ip_0,Brouse HDLsources,打開user_logic.v.添加代碼
1添加(58行),聲明pwm_out接口,添加pwm_out, 圖38
2添加(88行)定義pwm_out爲輸出,而且位寬爲1,添加
output pwm_out; 圖39
3接下來就是用戶實現段了,令slv_reg0爲週期寄存器,slv_reg1爲佔空比寄存器。此外我們還需要一個計數器(pwm_counter),下一個週期的開始信號(Over Period)和預輸出信號(pre_pwm_out)。
在110添加邏輯
wire ovprd;
reg [C_SLV_DWIDTH-1 :0] pwm_counter;
wire pre_pwm_out;
圖40
pwm產生器的邏輯
在124行添加邏輯 圖41
// USER logic implementation added here
always @(posedgeBus2IP_Clk)
begin
if(!Bus2IP_Resetn || ovprd ||~slv_reg1[31])
pwm_counter=32'h8000_0000;
else if(slv_reg1[31])
pwm_counter=pwm_counter+1'b1;
else pwm_counter=pwm_counter;
end
assignovprd=(pwm_counter[30:0]==slv_reg0[30:0])?1'b1:1'b0;
assignpre_pwm_out=(slv_reg1<pwm_counter)?1'b0:1'b1;
assignpwm_out=pre_pwm_out & slv_reg1[31];
保存,退出,在project菜單中選擇RescanUser Repositories,從port中可以看到我們新添加的引腳pwm_out.選擇External Ports把引腳引出去,如圖42
打開Address標籤頁,單擊右上角的GeneratedAddresses按鈕,如圖43
單擊project –>Design Rule Check,沒有報錯,關閉xps,回到PlanAhead圖44
在system.xmp文件上右擊,選擇CreateTop HDL 圖45,46
單擊Add source按鈕,選擇Add orCreate Constrains 單擊Next 圖47
單擊 Create File…選項 圖48
改文件名 圖49,finish就可以了
單擊左邊的Run Synthesis ,這裏就出錯了,如圖50,
在tcl console 按下ctrl +f 輸入error,如圖51一看是user_logic.v出錯了,<slv_reg> is not d eclared這個時候啓動xps,改正錯誤,可以看到圖41,確實是錯的,應該在128和134行爲slv_reg1,而我漏掉了1,改正,保存,退出xps,重新Run Synthesis,這裏也是尋找解決錯誤的方法。
過程結束後會彈出對話框,圖52
選擇Open Synthesized Design,會有一些警告,忽略,打開I/O Port標籤,由於以前一直用Altera,這個標籤找了一會兒(window->I/O Port),設置pwm_out的引腳,保存。圖53
選擇Select an existing file
看不到system.ucf,重啓PlanAhead,這時候就可以看到system.ucf文件的內容如下 圖54
單擊左邊的Generate Bitstream.單擊yes,完成implementation,至此硬件工程就做完了。(這個過程又點長)
在PlanAhead中,單擊File->Export->ExportHardware 圖55
建立c工程 圖56
選擇Xilinx Tools->Repositories,單擊new,找到工程路徑,圖57
在hello_bsp_0上右擊,選擇BoardSupport Package Setting ,找到drivers中得pwm_ip_0,修改Driver,圖58,如果你沒有出現估計就悲劇了。
然後我們將自設的IP核的Driver添加進來後就可以添加c代碼了。圖59
修改bug在hello_bsp_0上面有一個紅色的叉,是有一個宏沒有設置,需要手動設置這個宏,找到pwm_ip_selftest,c這個文件,C:\zedboard\project_11\project_11.srcs\sources_1\edk\system/drivers/pwm_ip_v1_00_a/src/pwm_ip_selftest.c(我的目錄在這裏)
註釋 #include "xio.h"
添加#define PWM_IP_USER_NUM_REG 2 圖60
保存,等待工程編譯結束。
出現圖61的錯誤,解決辦法。重新建立一個c工程。然後和上面的是一樣的,至於原因就不知道了。
測試
選擇Xilinx Tools->Program FPGA
在hello_world_0工程上右擊,選擇RunAs->Launch on Hardware,用示波器看波形結果是正確的,修改helloworld.c 中的佔空比可以看到不同的波形。
易出錯的地方:
第一個:在添加vhdl和verilog代碼的時候以及找錯誤的方法。
第二個是出現類似於以下的錯誤: "Building target: hello_world_0.elf Invoking: ARM gcc linker arm-xilinx-eabi-gcc -Wl,-T -Wl,../src/lscript.ld -L../../standalone_bsp_0/ps7_cortexa9_0/lib -o"hello_world_0.elf" ./src/helloworld.o ./src/platform.o -l-Wl,--start-group,-lxil,-lgcc,-lc,--end-group ../lib/gcc/arm-xilinx-eabi/4.6.1/../../../../arm-xilinx-eabi/bin/ld.exe: cannot find -l-Wl,--start-group,-lxil,-lgcc,-lc,--end-group collect2: ld returned 1 exit status make: *** [hello_world_0.elf] Error 1"解決方法就是重新新建一個c工程,(衝PlanAhead重新導入一次),原因不祥。
以上都在上面有提到過。這次是用裸跑的程序來調用IPcore,下次實驗是要爲這個IPcore開發Linux系統上的設備驅動,使得運行在Linux上的應用程序可以使用這個驅動程序與PL端進行通信,從而控制PWM的輸出。