xilinx Vivado的使用詳細介紹(2):創建工程、添加文件、綜合、實現、管腳約束、產生比特流文件、燒寫程序、硬件驗證
Author:zhangxianhe
新建工程
打開Vivado軟件,直接在歡迎界面點擊Create New Project,或在開始菜單中選擇File - New Project即可新建工程。
點擊Next;
輸入工程名稱和路徑。
選擇默認的RTL Project選項,勾選Do not specify......(這樣可以跳過添加源文件的步驟,源文件可以后面再添加)。
直接選擇Boards,然后選擇Zedboard Zynq Evaluation and Development Kit 硬件開發包。
點擊Next,再點擊Finish,項目新建完成
添加Verilog設計文件(Design Source)
在Project Manager窗口中,右擊選擇Design Sources,在空白處或任意文件夾上右擊,選擇Add Sources。
選擇Add or Create Design Sources,點擊Next。
點擊Create File按鈕,彈出的小窗口中輸入文件名,點擊OK。
可以一次性新建或添加多個文件,最后點擊Finish。
稍后會彈出定義模塊的窗口,也就是剛剛添加的Divider_multiple文件。可以在這里設置Divider_multiple模塊的輸入輸出端口;或者直接點擊OK,稍后再自行編寫。
點擊OK后,如果彈出下面窗口直接點擊Yes。
設計文件和對應的模塊即創建完成,如下圖。
打開Divider_multiple設計文件,並把如下代碼復制進去,並保存。
module Divider_Multiple_top( input clk_i, input rst_n_i, output div2_o, output div3_o, output div4_o, output div8_o, output div2hz_o ); reg div2_o_r; always@(posedge clk_i or negedge rst_n_i) begin if(!rst_n_i) div2_o_r<=1'b0; else div2_o_r<=~div2_o_r; end reg [1:0] div_cnt1; always@(posedge clk_i or negedge rst_n_i) begin if(!rst_n_i) div_cnt1<=2'b00; else div_cnt1<=div_cnt1+1'b1; end reg div4_o_r; reg div8_o_r; always@(posedge clk_i or negedge rst_n_i) begin if(!rst_n_i) div4_o_r<=1'b0; else if(div_cnt1==2'b00 || div_cnt1==2'b10) div4_o_r<=~div4_o_r; else div4_o_r<=div4_o_r; end always@(posedge clk_i or negedge rst_n_i) begin if(!rst_n_i) div8_o_r<=1'b0; else if((~div_cnt1[0]) && (~div_cnt1[1])) div8_o_r<=~div8_o_r; else div8_o_r<=div8_o_r; end reg [1:0] pos_cnt; reg [1:0] neg_cnt; always@(posedge div2_o_r or negedge rst_n_i) begin if(!rst_n_i) pos_cnt<=2'b00; else if(pos_cnt==2'd2) pos_cnt<=2'b00; else pos_cnt<=pos_cnt+1'b1; end always@(negedge div2_o_r or negedge rst_n_i) begin if(!rst_n_i) neg_cnt<=2'b00; else if(neg_cnt==2'd2) neg_cnt<=2'b00; else neg_cnt<=neg_cnt+1'b1; end reg div3_o_r0; reg div3_o_r1; always@(posedge div2_o_r or negedge rst_n_i) begin if(!rst_n_i) div3_o_r0<=1'b0; else if(pos_cnt<2'd1) div3_o_r0<=1'b1; else div3_o_r0<=1'b0; end always@(negedge div2_o_r or negedge rst_n_i) begin if(!rst_n_i) div3_o_r1<=1'b0; else if(neg_cnt<2'd1) div3_o_r1<=1'b1; else div3_o_r1<=1'b0; end reg div2hz_o_r; reg [25:0] div2hz_cnt; always@(posedge clk_i or negedge rst_n_i) begin if(!rst_n_i) div2hz_cnt<=0; else if(div2hz_cnt<26'd50_000000) div2hz_cnt<=div2hz_cnt+1'b1; else div2hz_cnt<=0; end always@(posedge clk_i or negedge rst_n_i) begin if(!rst_n_i) div2hz_o_r<=0; else if(div2hz_cnt==26'd24_999999 || div2hz_cnt==26'd49_999999) div2hz_o_r<=~div2hz_o_r; else div2hz_o_r<=div2hz_o_r; end assign div2_o=div2_o_r; assign div3_o=div3_o_r0 | div3_o_r1; assign div4_o=div4_o_r; assign div8_o=div8_o_r; assign div2hz_o=div2hz_o_r; endmodule
添加Verilog仿真文件(Simulation Source)
操作和上一步添加Verilog設計文件基本一致,唯一的區別是選擇Add or Create Simulation Sources。新建一個名為Divider_Multiple_TB的仿真文件。
設計文件新建完成后,在Design Sources和Simulation Sources中都有,而仿真文件只會出現在Simulation Sources文件夾中。設計文件可以用於仿真,也可以用於最終燒寫進開發板,而仿真文件僅用於仿真。
雙擊打開Divider_Multiple _TB仿真文件,並把如下代碼復制進去,並保存。
module Divider_Multiple_TB; // Inputs reg clk_i; reg rst_n_i; // Outputs wire div2_o; wire div3_o; wire div4_o; wire div8_o; wire div2hz_o; // Instantiate the Unit Under Test (UUT) Divider_Multiple MyDivider_Multiple ( .clk_i(clk_i), .rst_n_i(rst_n_i), .div2_o(div2_o), .div3_o(div3_o), .div4_o(div4_o), .div8_o(div8_o), .div2hz_o(div2hz_o) ); initial begin // Initialize Inputs4 clk_i = 0; rst_n_i = 0; // Wait 100 ns for global reset to finish #96; rst_n_i=1; end always begin #5 clk_i=~clk_i; end endmodule
IO口配置(I/O Planning)/編輯約束文件(Edit Constraints Sets)
做好的模塊,在燒寫進板子之前,需要設置輸入輸出信號與板子上IO口的對應關系。
IO口設置有兩種方法,第一種是直接創建並編輯約束文件,第二種是在圖形界面進行設置。
編輯約束文件
操作和上一步添加Verilog設計文件、仿真文件基本一致,唯一的區別是選擇Add or Create Simulation Sources。新建一個名為Zedboard_pin的約束文件。
打開Zedboard_pin的約束文件,並把如下代碼復制進去。
create_clock -name clk100MHZ -period 10.0 [get_ports {clk_i}] set_property PACKAGE_PIN Y9 [get_ports {clk_i}] set_property IOSTANDARD LVCMOS33 [get_ports {clk_i}] set_property PACKAGE_PIN N15 [get_ports {rst_n_i}] set_property IOSTANDARD LVCMOS18 [get_ports {rst_n_i}] set_property PACKAGE_PIN T22 [get_ports {div2hz_o}] set_property IOSTANDARD LVCMOS33 [get_ports {div2hz_o}] set_property PACKAGE_PIN T21 [get_ports {div8_o}] set_property IOSTANDARD LVCMOS33 [get_ports {div8_o}] set_property PACKAGE_PIN U22 [get_ports {div4_o}] set_property IOSTANDARD LVCMOS33 [get_ports {div4_o}] set_property PACKAGE_PIN U21 [get_ports {div3_o}] set_property IOSTANDARD LVCMOS33 [get_ports {div3_o}] set_property PACKAGE_PIN V22 [get_ports {div2_o}] set_property IOSTANDARD LVCMOS33 [get_ports {div2_o}]
圖形界面配置管腳
在實現完成后,Open Implemented Design選項從灰色變成可點擊狀態。
點擊Open Implemented Design,即可打開Implemented Design窗口。
在I/O Ports窗口展開管腳,對於每個輸入輸出信號,在Site欄選擇對應的管腳,注意確保Fixed欄處於勾選狀態,I/O Std常選擇LVCMOS33。
設置好后,Implemented Design窗口標題欄會顯示一個*號,表示設置發生了更改。
按Ctrl+S快捷鍵保存設置,會彈出窗口如圖,提示保存constraints文件會導致綜合與實現過期。也就是說,修改了管腳分配設置后,需要重新進行綜合、實現操作。這里點擊OK。
彈出窗口,選擇Create a new file並輸入文件名,點擊OK。
此時約束文件已經自動被創建並編輯,可以打開查看。
行為仿真(Run Behavioral Simulation)
在Flow Navigator窗口中點擊Run Simulation - Run Behavioral Simulation;或者在菜單中選擇Flow - Run Simulation - Run Behavioral Simulation,即可啟動行為仿真。
稍后Behavioral Simulation窗口打開,即可看到輸出的仿真波形。
綜合(Synthesis)
綜合類似於編程中的編譯。
在Flow Navigator或Flow菜單中,選擇Synthesis - Run Synthesis;或點擊工具欄中的三角形按鈕如圖,即可開始對設計文件進行綜合。
綜合完成后,會彈出如下窗口。如果選擇第一項並點擊OK,就會啟動下一步的實現。為了方便學習,這里我們直接點擊Cancel。
綜合后時序仿真(Run Post-Synthesis Timing Simulation)
在Flow Navigator窗口中點擊Run Simulation - Run Post-Synthesis Timing Simulation;或者在菜單中選擇Flow - Run Simulation - Run Post-Synthesis Timing Simulation,即可啟動行為仿真。
觀察波形可以清晰看到綜合后仿真加入了延遲更加接近實際芯片的運行情況
執行(Implementation)
綜合完成后,需要進行實現,在Flow Navigator或Flow菜單中,選擇Synthesis - Run Implementation;或點擊工具欄中的三角形按鈕如圖,即可開始對設計文件進行綜合。實際中是在綜合后沒有錯誤直接點Run Implementation選項進行實現。
實現完成后,同樣會出現一個窗口如下。選擇第一項可以打開下一步的IO口設置界面,選擇第二項可以啟動后面要說的生成比特流操作。同樣,這里還是點擊Cancel關閉。
執行后時序仿真(Run Post-Implementation Timing Simulation)
觀察波形可以清晰看到布局布線后仿真加入了延遲這要比綜合后的時序更加接近真實的情況。
生成比特流
生成比特流文件,這個文件會被直接燒寫進板子。類似於編程中的二進制可執行文件。點擊Program and Debug->Generate Bitstream。或下圖的上面圖標即可執行生成比特流的操作。
比特流生成后顯示如下對話框,為了方便直接點擊Cancel。
燒寫程序
連接電路板並打開電源。 生成比特流,打開硬件會話並編程FPGA。
確保Micro-USB電纜連接到Zedboard的電源連接器旁邊的JTAG PROG連接器。
Zedboard需要通過位於POWER開關旁邊的J20連接一個單獨的電源。
選擇Program and Debug - Open Hardware Manager。
如果之前連接過開發板,直接點擊上方綠色欄的Open recent target即可打開;如果是第一次連接開發板,則點擊Open a new hardware target。
第一次連接開發板,點擊Open a new hardware target,點擊Next
還是點擊Next。
顯示下面窗口,稍后即可打開硬件設備。
\
由於我以前連接過開發板,所以直接連接開發板。
Hardware Manager窗口即被打開,此時處於”Unconnected”狀態。
單擊Open target,在下面出現的菜單中選擇 Auto Connect。
硬件會話狀態從“Unconnected”更改為服務器名稱,設備突出顯示。 還要注意狀態表明它沒有被編程。
打開設備后,就會在Hardware窗口顯示。右擊設備並選擇Program Device,進行Program。
或者直接點擊綠色欄的Program Device進行Program。
彈出比特流文件選擇窗口,一般直接按默認值點擊Program,即可燒寫程序到板子中。
本實驗介紹了VIVADO 的FPGA 開發流程規范。包括了程序設計、行為仿真、綜合過程、綜合后時序仿真、執行過程、執行后仿真,比特流文件生成並下載到開發板上驗證。
注意點一:
在vivado下建立工程,有以下幾種情況:1.如果沒有涉及到PS部分,可以采用基於v文件或者diagram的工程。基於v文件的工程是由一個個的verilog或vhdl或ip組成的;基於diagram的工程是先新建一個diagram,然后在diagram中添加一個個的ip。2.如果用到了PS,那只能采用基於diagram的工程。
PS和PL的關系:PS的實質就是ARM Cortex A9 MPcore,所以如果我們不使用可編程部分,我們完全可以只使用PS部分。也就是說,對於ZYNQ芯片,PS部分可以完全獨立使用,不依賴PL部分。PL部分的實質是Xilinx FPGA。在ZYNQ中,我們可以把PL看成是PS的另一個具有可重配置特點的“外設”,它可以作為PS部分的一個從設備,受ARM處理器控制。比如ARM(PS)的串口數量不夠時,以太網接口不夠時,或者需要視頻接口時都可以用PL部分擴展。當然我們也可以把PL部分看成一個不受ARM處理器控制,與ARM處理器對等的主設備,主動完成與外部芯片、接口的數據交互。更甚至PL部分也可以作為整個系統的主設備,主動從APU部分的存儲器中獲取、存儲數據,並可控制ARM處理器的運算。所以,理論上PL部分也可以像PS部分那樣獨立運行。但限制是必須使用JTAG接口對PL部分進行配置。如果沒有JTAG接口,就無法獨立運行,因為ZYNQ的PS部分和PL部分都必須依靠PS來完成芯片的初始化配置。
注意點二:
PS核與PL的IP之間通信方式只有一種,那就是通過AXI總線。AXI interconnect IP是一個功能強大的IP,它能管理多個AXI接口的IP。用戶如果用到多個AXI IP,那么只需PS將M_AXI_GP0引腳連接到AXI interconnect Ip的SO0_AXI引腳,再將AXI interconnect ip的輸出分別連接到每個AXI IP的S_AXI引腳即可,省去了多個AXI互聯的管理問題。Processor System Reset IP為其他IP提供復位信號。