NCO IF 数字中频实现verilog
简介 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 pulse
output [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;
end
always@(posedge CLK,negedge RST)
begin
if(!RST)
begin
SinCountorReg = 0;
CosCountorReg = QUADRATURE_START;
end
else
begin
if(SinCountorReg == THRESHOLD)
begin
SinCountorReg = 0;
end
else
begin
SinCountorReg = SinCountorReg + 8'd1;
end
if(CosCountorReg == THRESHOLD)
begin
CosCountorReg =0;
end
else
begin
CosCountorReg = CosCountorReg + 8'd1;
end
end
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 的输出值。对我的项目来说可能够用了。