混頻原理
混頻就是把兩個不同的頻率信號混合,得到第三個頻率。在模擬電路中經(jīng)常見到的就是把接收機接收到的高頻信號,經(jīng)過混頻變成中頻信號,再進行中頻放大,以提高接收機的靈敏度。
數(shù)字電路中最簡單的混頻便是兩個信號做乘法,可以得到它們的和頻信號與差頻信號。數(shù)字混頻在通信的調(diào)制、解調(diào)、DUC(數(shù)字上變頻)、DDC(數(shù)字下變頻)等系統(tǒng)中應(yīng)用廣泛。通常把其中一個信號稱為本振信號(local oscillator),另一個信號稱為混頻器的輸入信號。
程序設(shè)計
本文的程序設(shè)計參考自杜勇老師的書《數(shù)字濾波器的MATLAB與FPGA實現(xiàn)-Altera/Verilog版》,對其中部分設(shè)計細節(jié)做了修改。杜勇老師的這個系列共有三本書,很推薦大家購買學(xué)習(xí)。不過可能由于篇幅有限,杜勇老師在書中對設(shè)計的一些細節(jié)和思想沒有做詳細介紹,博主在本文中和大家討論討論。
程序設(shè)計系統(tǒng)時鐘5MHz,625kHz的輸入信號與625kHz的本振信號做混頻,根據(jù)混頻原理會得到1.25MHz的和頻信號與0Hz(直流),將直流濾除掉得到1.25MHz的有效信號。
設(shè)計的頂層模塊接口如下所示:
module Mixer
(
input clk, //5MHz系統(tǒng)時鐘
input rst_n, //低電平有效復(fù)位信號
input [9:0] din, //輸入信號
output [9:0] s_oc, //本振信號,625kHz
output out_valid, //NCO輸出有效信號
output [19:0] dout //混頻輸出信號
);
程序中首先生成本振信號。Quartus和Vivado中都提供了類似功能的IP核:Vivado中叫DDS(Direct Digital Synthesizers)Compiler;Quartus中叫NCO(Numerically controlled oscillators)。下面以實例化NCO為例,具體的設(shè)計方法在下文講解。
wire [9:0] oc_sin;
oc oc
(
.phi_inc_i (16'd8192), //相位增量,對應(yīng)625kHz
.clk (clk),
.reset_n (rst_n),
.clken (1'b1), //時鐘允許信號
.fsin_o (oc_sin), //本振正弦信號
.out_valid (out_valid) //輸出有效標志
);
接下來用乘法進行混頻。我們都知道計算機中有帶符號數(shù)signed和無符號數(shù)unsigned,還知道計算機經(jīng)常以二進制補碼的形式的表示帶符號數(shù)。
在FPGA設(shè)計中,不管是Altera還是Xilinx,它們的IP核幾乎都是采用二進制補碼帶符號數(shù),也有很多的ADC、DAC芯片的數(shù)據(jù)接口也采用的是二進制補碼。因此,在設(shè)計中,我們要清楚什么時候用什么數(shù)值表示法。
比如NCO的輸出為帶符號數(shù)二進制補碼,假設(shè)混頻的輸入信號也是帶符號數(shù)二進制補碼,則在整個混頻程序設(shè)計中都要保持這個數(shù)值表示方法,否則就會出錯。
在下面的方法1中,再定義一個帶符號的寄存器將輸入信號轉(zhuǎn)換為帶符號數(shù)是很有必要的:“wire signed [9:0] din_s = din;”。如果不這樣做,直接使用乘法運算符“*”,會被綜合為無符號數(shù)乘法,得到的就是錯誤的結(jié)果。
當然也可以用方法2,乘法器IP核可以選擇計算方式是“signed”還是“unsigned”,將乘法器設(shè)置為signed也可以完成正確的計算。
//----------------------------------------------------
// 乘法實現(xiàn)混頻,方法1,轉(zhuǎn)換為帶符號數(shù)后再相乘
//----------------------------------------------------
//reg signed [19:0] mult;
//wire signed [9:0] din_s = din;
//wire signed [9:0] oc_sin_s = oc_sin;
//
//always @(posedge clk or negedge rst_n)
// if (!rst_n) mult <= 20'd0;
// else mult <= din_s * oc_sin_s;
//----------------------------------------------------
// 乘法實現(xiàn)混頻,方法2,調(diào)用乘法器IP核,設(shè)置為signed
//----------------------------------------------------
wire signed [19:0] mult;
mult1 mult1_inst (
.clock ( clk ),
.dataa ( din ),
.datab ( oc_sin ),
.result ( mult )
);
接下來濾除混頻后的直流信號。由于乘法的運算結(jié)果為帶符號數(shù),接下來的計算使用到的寄存器都應(yīng)申明為signed。
需要強調(diào)的是,signed和unsigned的申明只是告訴設(shè)計的運算如何看待這個寄存器中的數(shù),并不能改變寄存器的值。比如“11”這個值,如果申明為signed,運算將其視作-1,如果申明為unsigned,運算將其視作3。因為有符號數(shù)和無符號數(shù)的運算法則是不一樣的,所以錯誤的申明會導(dǎo)致結(jié)果計算錯誤。
reg signed [19:0] m1,m2,m3,m4,m5,m6,m7;
// 5MHz/625kHz=8; 緩存連續(xù)8個點的值
always @ (posedge clk or negedge rst_n)
if (!rst_n) begin
m1 <= 20'd0; m2 <= 20'd0; m3 <= 20'd0;
m4 <= 20'd0; m5 <= 20'd0; m6 <= 20'd0; m7 <= 20'd0;
end
else begin
m1 <= mult; m2 <= m1; m3 <= m2; m4 <= m3;?
m5 <= m4; m6 <= m5; m7 <= m6;
end
wire signed [22:0] madd = mult+m1+m2+m3+m4+m5+m6+m7; //一個周期
wire signed [19:0] mean = madd[22:3]; //舍掉低3bit,相當于除8,得到
wire signed [19:0] mt = mult - mean; //濾除直流分量
assign dout = mt;
assign s_oc = oc_sin;
endmodule
上面濾除直流分量的方法并不通用,由于5Mhz的系統(tǒng)時鐘是625kHz信號的8倍,所以連續(xù)8個點的平均值便是直流分量。不過程序設(shè)計思路還是可以學(xué)習(xí),比如依次移位緩存數(shù)據(jù)、截高位做除法這些小技巧。
NCO IP核的使用
在Quartus中打開該IP核,配置界面如下。后面的Quartus版本中將IP核集成到了qsys中,配置界面略有不同,但設(shè)置的參數(shù)之類的基本一樣。
設(shè)定好相位累加器精度、角度分辨率、幅度精度、系統(tǒng)時鐘和輸出信號頻率,便可以得到一個相位增量值(phase increment value),在實例化NCO模塊時傳入的便是這個值。實際的輸出頻率和設(shè)定的頻率會存在一定誤差,下方便展示了輸出信號的頻域和時域圖形。總體來說設(shè)置比較簡單。
如果需要仿真,在生成IP核前一定要在“Set up simulation”中選中“Generate Simulation Model”和“Generate netlist”,如下圖所示。否則在導(dǎo)入ModelSim時會失敗,無法進行仿真。
DDS Compiler IP核的使用
基本配置
在Vivado中打開DDS Compiler IP核,配置界面如下:
這個IP核的配置選項更豐富,提供的功能也更強大。我這里只介紹下本設(shè)計用到的功能,其余具體信息可以參考Xilinx官方文檔pg141。
同樣設(shè)定系統(tǒng)時鐘,Parameter Selection選擇“System Parameters”,這種設(shè)計方式可以直接設(shè)置無雜散動態(tài)范圍、頻率分辨率、輸出頻率等系統(tǒng)級的參數(shù),和Quartus的NCO IP核很像。另外一種“Hardware Parameters”設(shè)計方式需要自己設(shè)定輸出數(shù)據(jù)和相移的位寬,輸出頻率、相位偏移等值需要自己計算對應(yīng)的二進制數(shù)值。這兩種設(shè)計方式向不同需求的設(shè)計者提供。
pg141中給出了總線位寬與系統(tǒng)參數(shù)之間的轉(zhuǎn)換關(guān)系公式。
相位增量和相位偏移都可以設(shè)置為可編程的“Programmable”和“Streaming”方式,本設(shè)計只需要產(chǎn)生625kHz固定頻率的本振信號,設(shè)置為“Fixed”即可(所需資源少)。在“Summary”中可以看到整個DDS系統(tǒng)的詳細信息。
位寬問題
需要提醒的是系統(tǒng)最終的實際信號位寬和總線接口位寬并不一致。IP核的位寬只會是8的倍數(shù),多余的位數(shù)會移符號為填充,如下圖所示。
更直觀的感受,看一個DDS Compiler IP核的仿真:
可以看到相移雖然有16bit的位寬,但是有效的只有低10bit,高位都是符號為。為了更好的觀察相位值,新建一個“virtual bus“,將低10bit加到bus中,如下圖所示:
可以清楚的看到相位和幅度之間的關(guān)系。
產(chǎn)生sin與cos信號
很多系統(tǒng)中需要sin和cos信號(如解調(diào)系統(tǒng)中的本振信號),在DDS中設(shè)置為“Sine and Cosine”輸出時,sin和cos信號會共用數(shù)據(jù)總線,sin使用高字節(jié),cos使用低字節(jié),格式如下:
產(chǎn)生帶有相位偏移的信號
如果需要生成帶有可調(diào)初始相位(也叫相位偏移Phase Offset)的信號,在DDS中將“Phase Offset Programmability”設(shè)置為“Streaming”,IP核端口會增加一個PHASE輸入通道,該通道數(shù)據(jù)總線的有效位寬與設(shè)置的頻率分辨率(Frequency Resolution)有關(guān),可以在Summary界面中看到位寬(Phase Width)。該數(shù)據(jù)總線與360°相位之間線性對應(yīng)。比如Phase Width為16Bits,則0對應(yīng)0°,F(xiàn)FFF對應(yīng)360°,7FFF對應(yīng)180°,以此類推。
NCO和DDS是經(jīng)常用到的IP核,在后面的“FPGA數(shù)字信號處理“系列介紹的其它系統(tǒng)中,也會經(jīng)常出現(xiàn),因此需要熟悉掌握這兩個IP核的使用。
原文標題:FPGA學(xué)習(xí)-數(shù)字信號處理數(shù)字混頻
文章出處:【微信公眾號:FPGA設(shè)計論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
FPGA
+關(guān)注
關(guān)注
1630文章
21769瀏覽量
604651 -
程序設(shè)計
+關(guān)注
關(guān)注
3文章
261瀏覽量
30419 -
數(shù)字混頻
+關(guān)注
關(guān)注
0文章
4瀏覽量
7480
原文標題:FPGA學(xué)習(xí)-數(shù)字信號處理數(shù)字混頻
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設(shè)計論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論