NCO IF 数字中频实现verilog
- 简介 Description
- Application
- verilog IF实现
- Ending
简介 Description
NCO 是numerically controlled oscillator 三个单词的缩写,数控振荡器。与其相对应的模拟电路中还有 VCO ,voltage controlled oscillator 压控振荡器。VCO主要应用在模拟电路锁相环中,而NCO主要应用在数字信号处理上(DSP)和 DDS 数字信号合成。
我这里所说的DSP是广义的,不单单包括 DSP芯片,还包括FPGA等具备DSP功能的芯片。在最新的各种通信仪器,如雷达、软件无线电SDR,测量仪器仪表,如矢量网络分析仪(VNA, 我曾经业余自制过一个版本VNA用来测量天线,和各种射频器件,可查看我其它的blog)、频谱分析仪等都有专门DSP模块,其中FPGA是主要实现方式,在对信号进行处理,如做FFT、信号分离I Q路信号都用的了NCO。
说白了,NCO就是数字计数器,然后maping出相位和幅度。
Application
求同频(与中频信号相同)信号的幅度和相位, 下面就提取IQ路信号进行说明使用,其实原理跟模拟电路一样。
假设输入信号 f i n f_{in} fin
输 入 信 号 : f i n = x ∗ s i n ( t w + △ ) 输入信号:{f_{in}= x*sin( tw+△)} 输入信号:fin=x∗sin(tw+△) x是信号幅度,△是信号相位。就是我们想要计算得到大的值
中频信号 f I , f Q f_I,f_Q fI,fQ
中 频 信 号 I : f I = s i n ( t w ) 中频信号I:{f_{I}=sin(tw)}\qquad 中频信号I:fI=sin(tw) 中 频 信 号 Q : f Q = s i n ( t w + φ ) 中频信号Q:{f_{Q}=sin(tw+φ)} 中频信号Q:fQ=sin(tw+φ)这里的 φ = 1 2 π φ=\frac{1}{2}π φ=21π,幅度都假设为1,方便计算
f i n f_{in} fin与I Q中频混频。
I 路 : f i I = f I ∗ f i n = x ∗ s i n ( t w + △ ) ∗ s i n ( t w ) I路 :{f_{iI}= f_I*f_{in}= x*sin( tw+△)*sin(tw)}\qquad \qquad \qquad \qquad I路:fiI=fI∗fin=x∗sin(tw+△)∗sin(tw) Q 路 : f i Q = f Q ∗ f i n = x ∗ s i n ( t w + △ ) ∗ s i n ( t w + φ ) φ = 1 2 π Q路 :{f_{iQ}= f_Q*f_{in}=x*sin(tw+△)}*sin(tw+φ) \qquad φ=\frac{1}{2}π Q路:fiQ=fQ∗fin=x∗sin(tw+△)∗sin(tw+φ)φ=21π
把上面的公式根据积化和差
I 路 : f i I = − 1 2 x ∗ c o s ( 2 t w + △ ) − 1 2 x ∗ c o s ( △ ) I路 :{f_{iI}= -\frac {1}{2} x*cos( 2tw+△) - \frac {1}{2}x*cos(△)}\qquad \qquad \qquad \qquad \qquad I路:fiI=−21x∗cos(2tw+△)−21x∗cos(△) Q 路 : f i Q = − 1 2 x ∗ c o s ( 2 t w + △ + φ ) − 1 2 x ∗ c o s ( △ − φ ) ( φ = 1 2 π ) Q路 :{f_{iQ}=-\frac {1}{2}x*cos(2tw+△+φ)}-\frac {1}{2}x*cos(△ - φ) \qquad (φ=\frac{1}{2}π) Q路:fiQ=−21x∗cos(2tw+△+φ)−21x∗cos(△−φ)(φ=21π)
由上面的公式可以看出:混频之后每一路信号就分变为 直流和交流叠加的信号,就 I 路 I路 I路而言,交流信号是 − 1 2 x ∗ c o s ( 2 t w + △ ) -\frac {1}{2} x*cos( 2tw+△) −21x∗cos(2tw+△), 直流信号是 − 1 2 x ∗ c o s ( △ − φ ) -\frac {1}{2}x*cos(△ - φ) −21x∗cos(△−φ)。因为 ( φ = 1 2 π ) (φ=\frac{1}{2}π) (φ=21π), − 1 2 x ∗ c o s ( △ − φ ) → 1 2 x ∗ s i n ( △ ) -\frac {1}{2}x*cos(△ - φ) \to\frac {1}{2}x*sin(△) −21x∗cos(△−φ)→21x∗sin(△) 可得Q路
Q 路 : f i Q = − 1 2 x ∗ s i n ( 2 t w + △ ) + 1 2 x ∗ s i n ( △ ) Q路 :{f_{iQ}=-\frac {1}{2}x*sin(2tw+△)}+\frac {1}{2}x*sin(△ ) Q路:fiQ=−21x∗sin(2tw+△)+21x∗sin(△)
做累加 s u m ( I ) = ∑ t = 0 T − 1 [ − 1 2 x ∗ c o s ( 2 t w + △ ) − 1 2 x ∗ c o s ( △ ) ] T = N ∗ F R E Q s a m p l i n g F R E Q i f sum(I)=\displaystyle \sum_{t=0}^{T-1} [-\frac {1}{2} x*cos( 2tw+△) - \frac {1}{2}x*cos(△)] \qquad T = \frac {N *FREQ_{sampling}}{FREQ_{if}} sum(I)=t=0∑T−1[−21x∗cos(2tw+△)−21x∗cos(△)]T=FREQifN∗FREQsampling s u m ( I ) = − T ∗ 1 2 x ∗ c o s ( △ ) sum(I)= -T* \frac {1}{2}x*cos(△)\qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad sum(I)=−T∗21x∗cos(△)
s u m ( Q ) = ∑ t = 0 T − 1 [ − 1 2 x ∗ s i n ( 2 t w + △ ) + 1 2 x ∗ s i n ( △ ) ] T = N ∗ F R E Q s a m p l i n g F R E Q i f sum(Q)=\displaystyle \sum_{t=0}^{T-1} [-\frac {1}{2} x*sin( 2tw+△) + \frac {1}{2}x*sin(△)] \qquad T = \frac {N *FREQ_{sampling}}{FREQ_{if}} sum(Q)=t=0∑T−1[−21x∗sin(2tw+△)+21x∗sin(△)]T=FREQifN∗FREQsampling s u m ( Q ) = T ∗ 1 2 x ∗ s i n ( △ ) sum(Q)= T* \frac {1}{2}x*sin(△)\qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad sum(Q)=T∗21x∗sin(△)
到此为止我们可以求出相位 △ = a r c t a n ( T ∗ 1 2 x ∗ s i n ( △ ) T ∗ 1 2 x ∗ c o s ( △ ) ) → a r c t a n ( − s u m ( I ) s u m ( Q ) ) △ = arctan(\frac{ T* \frac {1}{2}x*sin(△)}{T* \frac {1}{2}x*cos(△)}) \to arctan(-\frac {sum(I)}{sum(Q)}) △=arctan(T∗21x∗cos(△)T∗21x∗sin(△))→arctan(−sum(Q)sum(I))
得到相位就能求出幅度 x x x 的值了。
x = 1 T 2 ∗ s u m ( Q ) s i n ( △ ) x =\frac{1}{T} \frac{2*sum(Q)}{sin(△)} x=T1sin(△)2∗sum(Q)
verilog IF实现
module NCO_2MHZ
#(
parameter THRESHOLD = 8'd23,//40 - 1,CLK=48MHz
QUADRATURE_START = 8'd6 // 40*1/4 - 1
)
(input RST,input CLK,output PHASE_START, //if sin = 0, output a pulseoutput [7:0] SIN_COUNTER,output [7:0] COS_COUNTER,output signed [11:0] SIN_VALUE,output signed [11:0] COS_VALUE);reg [7:0] SinCountorReg;
reg [7:0] CosCountorReg;
reg [11:0] SinVlaue[THRESHOLD:0];initial begin
SinVlaue[0] = 12'd0;
SinVlaue[1] = 12'd530;
SinVlaue[2] = 12'd1024;
SinVlaue[3] = 12'd1447;
SinVlaue[4] = 12'd1773;
SinVlaue[5] = 12'd1977;
SinVlaue[6] = 12'd2047;
SinVlaue[7] = 12'd1977;
SinVlaue[8] = 12'd1773;
SinVlaue[9] = 12'd1447;
SinVlaue[10] = 12'd1024;
SinVlaue[11] = 12'd530;
SinVlaue[12] = 12'd0;
SinVlaue[13] = -12'd530;
SinVlaue[14] = -12'd1024;
SinVlaue[15] = -12'd1447;
SinVlaue[16] = -12'd1773;
SinVlaue[17] = -12'd1977;
SinVlaue[18] = -12'd2047;
SinVlaue[19] = -12'd1977;
SinVlaue[20] = -12'd1773;
SinVlaue[21] = -12'd1447;
SinVlaue[22] = -12'd1024;
SinVlaue[23] = -12'd530;endalways@(posedge CLK,negedge RST)
beginif(!RST)beginSinCountorReg = 0;CosCountorReg = QUADRATURE_START;endelsebeginif(SinCountorReg == THRESHOLD)begin SinCountorReg = 0;endelsebeginSinCountorReg = SinCountorReg + 8'd1;endif(CosCountorReg == THRESHOLD)beginCosCountorReg =0;endelsebeginCosCountorReg = CosCountorReg + 8'd1;endend end
assign SIN_COUNTER = SinCountorReg;
assign COS_COUNTER = CosCountorReg;
assign SIN_VALUE = SinVlaue[SinCountorReg];
assign COS_VALUE = SinVlaue[CosCountorReg];
endmodule
Ending
上面的NCO是我的VNA中FPGA中使用的代码。由于水平有限,只能暂时提供verilog的代码了。其原理还是很简单的。
当然这个NCO
parameter THRESHOLD = 8'd23,//40 - 1,CLK=48MHz
QUADRATURE_START = 8'd6 // 40*1/4 - 1
修改这两个值就能修改IF 的频率。当然你也以设置为reg 类型,外部可编程(SDR和DDS就是这样应用的)。ram maping 部分我用的12bits 的输出值。对我的项目来说可能够用了。