寫在前面
數據手冊
博客首頁
花了幾個小時瞭解並寫了這篇博客,不得不說的是瞭解的還是皮毛而已,但盡力寫的詳細點,這比較適合新手,老手可以忽略繁瑣的部分。
注:學習交流使用!
正文
本文來自於一個CSDN博友的求助,由於我以前也沒做過,因此抽了點時間,參考數據手冊PG141以及各大互聯網資源,簡單寫了下這篇博文,僅供參考 。
設計要求
- 生成4種基本波形,例如正弦波,方波等,波形形狀和參數自定;
- 輸出4中基本波形的任意疊加結果,供16種波形可供選擇;
雖然要求這麼多,但本篇博文僅僅提供基礎操作,其他的可以自行實現。
IP核配置
定製輸出數據位寬
這裏的輸出數據指的是輸出的波形數據,其位寬相關參數介紹如下:
可見,輸出數據寬度和SFDR以及Noise Shaping有關,你可先不必知道Noise Shaping和SFDR是什麼?只需要暫時知道在IP覈定制時需要選擇即可,如果Noise Shaping選擇了None and Dithering,則輸出數據寬度爲:
如果爲Taylor:
而Spurious Free Dynamic Range (SFDR)翻譯爲無雜散動態範圍,和輸出數據寬度以內部總線寬度以及各種實現策略有關;
假設我需求的數據寬度爲10位,Noise Shaping選爲None,則SFDR爲60,輸入IP定製頁面:
查看輸出是否爲10bit:
定製相位位寬(或頻率分辨率)
根據數據手冊對頻率分辨率的描述:
頻率分辨率:以赫茲爲單位指定,指定最小頻率分辨率,用於確定相位累加器使用的相位寬度及其相關的相位增量(PINC)和相位偏移(POFF)值。較小的值可提供較高的頻率分辨率,並且需要較大的累加器。較大的值會減少硬件資源。根據噪聲整形的選擇,可以增加相位寬度,並且頻率分辨率高於指定的分辨率。對於光柵化模式(rasterized mode),頻率分辨率由系統時鐘、通道數和所選模數固定。
從這段描述,我們得出信息,頻率分辨率可以用來控制相位位寬。
如果操作模式選擇標準模式,如下IP 覈定制頁面:
頻率分辨率可以這樣計算:
我們先給定需求的相位寬度,又已知系統頻率值,根據公式就可以算出頻率分辨率;將頻率分辨率代入IP覈定制頁面,即可自動得到相位寬度。
其實從上式也可以直接推出相位寬度:
本例我們的系統頻率爲100MHz,如果想要相位寬度爲16位,則頻率 分辨率爲:
在IP覈定制頁面,如下圖,我們輸入頻率分辨率的值:
查看相位寬度爲16位:
上面選擇的是標準模式,如果選擇另一種模式呢?
Rasterized Mode of Operation:光柵化操作模式;
我們可以根據下面公式得到頻率分辨率,但和相位寬度沒有直接關係,爲了知識完整性,簡介如下:
在IP覈定制頁面提現如下:
輸出頻率
本示例選擇的是單通道,也即通道數爲1,因此輸出頻率也只能選擇一個:
輸出頻率值也不是隨便選擇的,而是有其範圍的,例如我輸入105MHz,則通過不了:
提示超出範圍,範圍爲(0,100).
輸出正餘弦選擇以及數據格式
可以在IP覈定制頁面選擇輸出正弦還是餘弦還或者是都輸出:
本示例選擇輸出正餘弦,由於輸出採用的是axi總線,因此輸出數據位於M_AXIS_DATA_TDATA中,那麼正餘弦輸出結果是如何組合成M_AXIS_DATA_TDATA的呢?
數據手冊給出解釋:
輸出DATA通道TDATA結構將正弦和餘弦輸出字段符號擴展到下一個字節邊界,然後以最低有效部分的餘弦進行連接,以創建m_axis_data_tdata。如果僅選擇正弦或餘弦之一,則將其符號擴展並放入m_axis_data_tdata的最低有效部分。
下圖顯示了這三種配置的TDATA的內部結構。正交輸出,僅餘弦和僅正弦。例如,在圖中顯示了11位輸出,符號擴展到16位。 <<<表示符號擴展名:
因此我們可以這麼認爲,由於存在擴展符號位的關係,我們可以提取低一半的數據爲COS,高一半的數據未SIN。
其他設置
有了上面的定製參數,輸出波形是沒有問題了,至於其他的定製參數,本文選擇默認:
點擊OK,等待IP覈定制完成。
電路設計
本示例設計十分簡單,就是單純例化下IP核:
複製例化模板:
給出設計文件:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Reborn Lee
// Module Name: waveform_gen
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Reborn Lee
// Module Name: waveform_gen
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module waveform_gen(
input i_clk,
output o_data_valid,
output [31 : 0] o_data,
output o_phase_valid,
output [15 : 0] o_phase
);
dds_compiler_0 inst_dds (
.aclk(i_clk), // input wire aclk
.m_axis_data_tvalid(o_data_valid), // output wire m_axis_data_tvalid
.m_axis_data_tdata(o_data), // output wire [31 : 0] m_axis_data_tdata
.m_axis_phase_tvalid(o_phase_valid), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata(o_phase) // output wire [15 : 0] m_axis_phase_tdata
);
endmodule
行爲仿真
仿真程序也僅僅例化設計文件,設計下系統頻率即可:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Reborn Lee
// Create Date: 2020/06/03 17:25:26
// Module Name: waveform_gen_tb
//////////////////////////////////////////////////////////////////////////////////
module waveform_gen_tb(
);
reg clk;
wire o_data_valid;
wire [15 : 0] o_data;
wire o_phase_valid;
wire [31 : 0] o_phase;
initial begin
clk = 0;
forever begin
# 5 clk = ~clk;
end
end
waveform_gen inst_waveform_gen
(
.i_clk (clk),
.o_data_valid (o_data_valid),
.o_data (o_data),
.o_phase_valid (o_phase_valid),
.o_phase (o_phase)
);
endmodule
執行行爲仿真:
注意,仿真時間可以在此確定:
仿真波形:
正餘弦拆開:
選擇高16位作爲sin。
下面選擇有符號數顯示:
同時選擇模擬顯示:
之後你會發現正餘弦顯示波形相對於整體太平坦,以致於看起來像是直線,這是因爲顯示範圍太大了導致的:
改下顯示的座標幅度範圍:
顯示正常了。
就這樣吧,提供了基本操作,更多的原理以及實現,舉一反三吧!