Xilinx ZYNQ 7000+Vivado2015.2系列(二)之奇數分頻和邏輯分析儀(ILA)的使用

L707發表於2024-03-27

前言:

偶數分頻容易得到:N倍偶數分頻,可以透過由待分頻的時鐘觸發計數器計數,當計數器從0計數到N/2-1時,輸出時鐘進行翻轉,並給計數器一個復位訊號,使得下一個時鐘從零開始計數。以此迴圈下去。

奇數分頻如何得到呢?

第一部分 奇數分頻

奇數分頻方法:

N倍奇數分頻,首先進行上升沿觸發進行模N計數,

計數到(N-1)/2時輸出時鐘翻轉,同時進行下降沿觸發的模N計數,

計數到(N-1)/2時輸出時鐘翻轉時,進行輸出時鐘時鐘翻轉。

兩個佔空比非50%的n分頻時鐘相或運算,得到佔空比為50%的奇數N分頻時鐘。

或者使用“相與”,方法與上相同,只是翻轉的數值變為(N-2)/2。

三分頻的Verilog實現:

module Divider_Multiple(
	input clk_i,
	input rst_n_i,
	output div2_o,
	output div3_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] 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

assign div2_o=div2_o_r;
assign div3_o=div3_o_r0 | div3_o_r1;  //相或

endmodule

模擬:

模擬檔案:

module Divider_Multiple_tb;
    // Inputs
    reg clk_i;
    reg rst_n_i;
    // Outputs
    wire div2_o;
    wire div3_o;
    // Instantiate the Unit Under Test (UUT)
    Divider_Multiple uut (
    .clk_i(clk_i),
    .rst_n_i(rst_n_i),
    .div2_o(div2_o),
    .div3_o(div3_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

vivado模擬結果:

20170923220846085

至此,第一部分結束。

第二部分 邏輯分析儀

增加邏輯分析儀:

首先為了配合手裡的**zc702**板子,修改了一下輸入時鐘;

為了觀察分頻訊號,增加了一個2Hz的訊號,將其連線在led上,可以看見led閃爍。

邏輯分析儀的使用分三步走:

1. 在設計檔案中,在要抓取的訊號定義前新增:

<strong>(*make_debug="true"*)</strong>

2. 匯入ILA的IP核:

20170924152017463

雙擊新增的IP,在General Options裡設定探針數(訊號組數)和取樣深度(利用BRAM儲存的),在Probe Ports裡設定訊號位寬:

20170924152834955

20170924152951634

OK之後,點選Generate。

IP Source裡雙擊模板,將例化模板複製到設計檔案中,填好對應的待測訊號:

20170924153834680

3. 新增約束-->生成位元檔案-->下載-->新增觸發訊號-->抓取。

為了閱讀的連貫性,貼出修改後的程式碼:

module Divider_Multiple(
	input clk_p,
	input clk_n,
	input rst_n_i,
	output div2_o,
	output div3_o,
	output div2hz_o
);

IBUFGDS IBUFGDS_inst (
          .O(clk_i),  // Clock buffer output
          .I(clk_p),  // Diff_p clock buffer input (connect directly to top-level port)
          .IB(clk_n) // Diff_n clock buffer input (connect directly to top-level port)
       );
 (*make_debug="true"*)wire div2_o;
 (*make_debug="true"*)wire div3_o;
 (*make_debug="true"*)wire 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] 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 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}) // input wire [3:0] probe1
);

endmodule

約束檔案如下:

set_property PACKAGE_PIN D18 [get_ports {clk_p}]
set_property IOSTANDARD LVDS_25 [get_ports {clk_p}]
set_property PACKAGE_PIN C19 [get_ports {clk_n}]
set_property IOSTANDARD LVDS_25 [get_ports {clk_n}]

set_property PACKAGE_PIN G19 [get_ports {rst_n_i}] 
set_property IOSTANDARD LVCMOS18 [get_ports {rst_n_i}]
#GPIO PMOD1
set_property PACKAGE_PIN E15 [get_ports {div2_o}]
set_property IOSTANDARD LVCMOS18 [get_ports {div2_o}]
set_property PACKAGE_PIN D15 [get_ports {div3_o}]
set_property IOSTANDARD LVCMOS18 [get_ports {div3_o}]
set_property PACKAGE_PIN W17 [get_ports {div2hz_o}]
set_property IOSTANDARD LVCMOS18 [get_ports {div2hz_o}]

下載到fpga之後,邏輯分析儀的介面會自動開啟,各個區域的功能如下,先新增觸發訊號,可以右鍵點選新增,也可以點選window-->debug probe將訊號拖拽至“觸發訊號”區域:

20170924155220761

總結:

訊號運算得到新的訊號。沒有模擬就沒有發言權。

相關文章