多路分頻器設計
在第七節的學習中,筆者帶大家通過一個入門必學的流水燈實驗實現,快速掌握了VIVADO基於FPGA開發板的基本流程。考慮到很多初學者並沒有掌握好Vivado 下FPGA的開發流程,本章開始筆者講更加詳細地介紹基於VIVADO FPGA開發的流程規范,讓讀者掌全面掌握FPGA開發流程包括了如何仿真、綜合、執行、下載到開發板測試。
9.1 硬件圖片
本章使用到的硬件和前一章一樣:LED部分及按鈕部分
9.2 硬件原理圖
PIN腳定義:
GCLK:Y9(PL輸入時鍾)
LD0:T22
|
BTNU:T18
|
9.3 介於VIVADO的FPGA設計流程
9.4 多路分配器設計思想
FPGA輸入全局時鍾100MHZ,定義合適的分頻計數器,得到對應的時鍾。通過chipscope來抓取2分頻、3分頻(注意:對二分頻的時鍾進行3分頻)、4分頻和8分頻結果,通過板子上的LED燈,來顯示2HZ的時鍾。設計總體框圖如下所示
。
9.5時序設計
① 定義寄存器div2_o_r,檢測輸入時鍾上升沿,每次上升沿寄存器div2_o_r反轉一次,實現2分頻。
② 定義寄存器pos_cnt[1:0],neg[1:0],分別檢測div2_o_r的上升沿和下降沿,檢測到上升沿和下降沿時,兩個寄存器分別累加。計數到2’d2時,寄存器清零。另定義兩個div3_o_r0和div3_o_r1,當兩個計數器小於2’d1時,div3_o_r0和div3_o_r1均賦值為1,其他情況賦值為0。由div3_o_r0和div3_o_r1組合邏輯相或即為div2_o_r進一步進行3分頻所得的結果。
③ 定義位寬為2的寄存器div_cnt[1:0],檢測輸入時鍾上升沿,div_cnt==2’b00或2’b01,4分頻輸出寄存器div4_o_r反轉,div_cnt==2’b00時,8分頻輸出寄存器div8_o_r反轉。
④ 由於輸入時鍾100MHZ,為得到2HZ的時鍾,需要定義計數器至少100000000/1=100000000。在此定義一個26位位寬的div2hz_cnt計數器。檢測輸入時鍾上升沿,div2hz_cnt==26’d24_999999或div2hz_cnt==26’d49_999999時,2HZ輸出寄存器div2hz_o_r反轉。
9.6程序源碼
`timescale 1ns / 1ps
//-----------------------------------------------------------------------------------------------------
// Target Devices: XC7Z020-FGG484
// Tool versions: VIVADO2015.4
// Description: Divider_Multiple
// Revision: V1.1
// Additional Comments:
//1) _i PIN input
//2) _o PIN output
//3) _n PIN active low
//4) _dg debug signal
//5) _r reg delay
//6) _s state machine
*/
//-----------------------------------------------------------------------------------------------------
module Divider_Multiple(
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;
ila_0 ila_0_0 (
.clk(clk_i), // input wire clk
.probe0(div2hz_o), // input wire [0:0] probe0
.probe1({div2_o,div3_o,div4_o,div8_o}) // input wire [3:0] probe1
);
endmodule
|
9.7行為仿真9.7.1創建多路分頻器工程
Step1:創建工程
Step2:歡迎界面直接單擊NEXT
Step3:工程名字命名為Divider_Multiple,並且設置保存的路徑,單擊NEXT
Step4:新建一個RTL 工程,並且勾選不要添加源文件,單擊NEXT
Step5:由於MIZ702和ZEDBOARD是兼容的,因此直接選擇ZEDBOARD硬件開發包作為我們MIZ702的開發包。這樣可以省去很多麻煩,達到事半功倍的目的。單擊NEXT
Step6:最后單擊Finish 完成工程的創建
9.7.2添加仿真文件
Step1:單擊Add Sources添加仿真文件
Step2:單擊Add Sources添加仿真文件
Step3:單擊 Add files 把仿真文件添加進來
Step4:單擊 Add files 把仿真文件添加進來
Step5:仿真文件源碼
module Divider_Multiple_top_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_top uut (
.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
|
Step6:單擊 Simulation Settings對仿真參數做一些設置
Step7:單擊 Simulation 設置仿真時間為1000ms
9.7.3行為級仿真
Step1:單擊 Run Simulation
Step2:計算機CPU會模擬FPGA的運行,1000ms運行來說通常需要幾分鍾時間。具體時間和CPU的配置有很大關系。
Step3:仿真結束后查看波形,為了觀察方便,右擊窗口選擇float
Step4:使用放大工具放大后觀察
Step5:使用放大工具放大后觀察
Step6:斷點觀察更多信號
1、打開divider_multiple.v文件只要是顯示紅色圓圈的位置就是可以設置斷點,單擊紅色圓圈。
2、單擊運行
3、可以看到紅色線框內有很多信號了,這些就是內部的運行信號,可以讓我們觀察程序更加仔細。
Step7:用鼠標單擊這個幾個信號,然后右擊后單擊Add To Wave Window
Step8:可以看到我們添加進來的三個寄存器變量
Step9:重新仿真 按鈕1是初始化仿真 按鈕2是仿真開始 按鈕3是仿真到設置時間
1、去掉剛才設置的斷點
2、單擊1處按鈕重新加載初始化仿真
3、設置仿真時間為1000ms
4、單擊3處按鈕
Step10:重新仿真后結果
Step11:設置觀察的數據類型
1、首先選擇一個要觀察的變量
2、右擊選擇Radix
3、假設選擇Binary以二進制形式觀察
Step12:設置好后的效果
9.8綜合 Synthesis9.8.1添加文件
Step1:把Divider_multiple.v添加進來,並且創建xdc管腳約束文件
XDC約束文件
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}]
|
9.8.2綜合並查看報告
Step1:點擊綜合按鈕
Step2:綜合完成后通過查看報告看資源的利用情況
可以看到這個工程只是利用到了很少一部分資源
9.8.3綜合時序仿真
Step1:單擊Run Simulation 選擇 Run Post-synthesis Timing Simulation
Step2:觀察波形可以清晰看到綜合后仿真加入了延遲更加接近實際芯片的運行情況
9.9執行Implementation9.9.1執行並查看報告
Step1:點擊執行按鈕
Step2:執行運行完畢后再次單擊
Step3:查看執行運行完畢后的報告,執行完成后的報告比綜合后的報告相比,是精確的分析和評估
Step4:點開Table可以看到使用的資料的具體參數
Step5:查看執行完后的時序約束報告
時序約束報告是FPGA開發中很重要的一項參數,所以必須看一下是否有違反時序約束的情況。可以看到有一些黃色的waring。在這里不會影響我們的輸出結果,因為我們這輸出並沒有做時序約束。但是如果要輸出很嚴格的時序就需要加上時序約束。
9.9.2布局布線后時序仿真
Step1:單擊Run Simulation 選擇 Run Post-Implementation Timing Simulation
Step2:觀察波形可以清晰看到布局布線后仿真加入了延遲這要比綜合后的時序更加接近真實的情況
9.10 VIVADO在線邏輯分析儀使用9.10.1 IP Catalog添加IA ip core
Step1: 單擊IP Catalog
Step2: 打開Debug & Verification > Debug ->雙擊 ILA
Step3:游標General Options設置如下
1、Number of probes 2 為設置需要觀察信號的組為2組,因為我們准備1組放觸發信號,1組放普通觀察的信號
2、Sample Data Depth 1024 設置采樣的深度,這是需要消耗FPGA的BRAM的BRAM越大可以設置的采樣深度就越大,當然編譯速度會降低。
Step4:游標Probe_Ports設置如下
Probe Port 探針類似示波器的表筆,只是這里是在FPGA內部,我們設置了Probe0用來檢查2HZ的信號,Probe1用來檢測另外4個分頻信號。
設置好后單擊OK關閉窗口
Step5: 直接單擊Generate
Step6: 可以看到ila這個邏輯分析儀的IP添加進來了
Step7:切換IP Sources游標下,然后雙擊 ila_0.veo 打開調用的接口模版
Step8:IP接口調用模版打開后,可以看到這是一個IP接口,顯然我們只要把需要被檢測的信號根據前面的設置填進去就可以了。 clk就是采樣時鍾,probe0就是2HZ信號,proble1就是其他需要被觀察的信號。
修改,並且嵌入到頂層文件中
ila_0 ila_0_0 (
.clk(clk_i), // input wire clk
.probe0(div2hz_o), // input wire [0:0] probe0
.probe1({div2_o,div3_o,div4_o,div8_o}) // input wire [3:0] probe1
);
|
9.10.2 邏輯分析儀抓取的信號
設置好邏輯分析儀,需要抓取的信號為
div2_o_r,
div3_o_r,
div3_o_r0,
div3_o_r1,
div4_o_r,
div8_o_r。
邏輯分析儀抓取的信號如下圖所示。
9.10.3 邏輯分析儀使用
區域1:設置采樣的啟動停止,和采樣的方式
區域2:設置觸發信號
區域3:被觀察的信號名字
區域4:被觀察的信號波形
區域5:觸發模式設置
區域6:觸發設置
那么我們主要使用的有1、2、3、4這個幾個區域。
9.11小結
本章全面介紹了VIVADO的FPGA開發流程規范。包括了程序設計、行為仿真、綜合過程、綜合后時序仿真、執行過程、執行后仿真、FPGA資源的利用情況分析、利用VIVADO自帶的邏輯分析儀抓取信號波形,進行分析、IAL邏輯分析儀IP的使用和設置。本章非常適合從ISE轉向VIVADO開發的工程,或者ALTERA開發轉向XILINX 開發的工程師、或者沒有FPGA開發基礎的初學者。
轉載原文出處:
http://www.osrc.cn/forum.php?mod=viewthread&tid=1350&extra=page%3D1%26filter%3Dtypeid%26typeid%3D44