怡心湖

如何在 FPGA 中利用 DDS(直接数字频率合成)技术同时生成 C/A 码和载波,并完成两者的扩频调制。

这是一个非常经典且完美的 FPGA 数字通信(GNSS 诱骗)工程案例。在 GNSS 诱骗机中,C/A 码(1.023 MHz)​ 和 载波(1575.42 MHz)​ 并不是独立存在的,它们需要通过扩频调制(Spreading)​ 结合在一起。

FPGA 实现这一过程的黄金标准就是 DDS(直接数字频率合成)+ 并行调制。我们将使用两个独立的 NCO(数控振荡器)分别生成 C/A 码时钟和载波,然后在数字域完成 BPSK 调制。


一、系统架构总览

核心思想是:C/A 码是"开关",载波是"载体"。C/A 码控制载波的相位翻转(0° 或 180°)。

+-----------------+
                      |   C/A Code NCO  | --> [PRN ROM] --> PRN_Chip (1/0)
                      +-----------------+                |
                                                       | (BPSK Modulation)
[System Clock] --->    +-----------------+                v
                      | Carrier NCO     | --> [Sine/Cos LUT] --> Carrier_I/Q
                      +-----------------+

二、模块 1:C/A 码 NCO 与 PRN 生成

1. C/A 码 NCO 参数计算

C/A 码速率是 1.023 MHz

  • fclk​=100 MHz

  • fca​=1.023 MHz

  • N=32 bits

FCWCA​=100×1061.023×106×232​≈43,890,049

2. PRN 码生成(Gold Code)

C/A 码由两个 10 级移位寄存器(G1, G2)生成 Gold 码。

  • 存储方式:通常不在 FPGA 里实时生成移位寄存器(耗资源),而是将 1023 个码片(1 ms 的数据)预存在 Block RAM (BRAM)​ 中。

  • 寻址:C/A 码 NCO 的相位累加器高位(例如高 10 位,因为 210=1024)作为 BRAM 的地址线。

  • 输出PRN_bit,值为 10。但在 BPSK 调制中,我们需要将其转换为极性码:PRN = 1 -> +1; PRN = 0 -> -1


三、模块 2:载波 NCO 与正弦查找表

1. 载波 NCO 参数计算

GPS L1 载波频率是 1575.42 MHz

  • fcarrier​=1575.42×106 Hz

FCWCarrier​=100×1061575.42×106×232​≈67,627,206

2. 正弦/余弦查找表 (LUT)

  • 存储内容:一个周期的 sin和 cos函数值。

  • 位宽:通常使用 8 位或 10 位量化(例如 -127 到 +127)。

  • 寻址:载波 NCO 的相位累加器高位(例如高 10 位或 12 位)作为 LUT 地址。

  • 输出Carrier_ICarrier_Q(正交载波)。


四、模块 3:扩频调制(BPSK 相乘)

这是最核心的一步。GNSS 使用的是 BPSK(二进制相移键控),即:

s(t)=PRN(t)⋅Carrier(t)

在数字电路中,这就是一个简单的乘法器

时序逻辑

// 假设 PRN 已经是极性码 (-1 or +1)
// 假设 Carrier_I 是 8bit 有符号数
reg signed [8:0] modulated_i; // 输出扩频信号

always @(posedge sys_clk) begin
    if (PRN_bit_polar == 1'b1) begin
        modulated_i <= Carrier_I; // 同相
    end else begin
        modulated_i <= -Carrier_I; // 反相 (180度相位翻转)
    end
end

物理意义

  • 当 C/A 码是 1时,载波原样输出。

  • 当 C/A 码是 0时,载波乘以 -1,相当于相位翻转 180 度。

  • 由于 C/A 码速率(1.023 MHz)远低于载波(1575.42 MHz),结果是载波被"切碎"成 1.023 MHz 的片段,每一毫秒相位翻转一次。


五、完整 FPGA 实现时序图

假设系统时钟 100MHz,我们压缩时间轴来看:

Time (ns):  0   10  20  30  40  50  60  70  80  90  100 110 120 ...
Sys_Clk:    ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑

CA_NCO_Acc: [0] [1] [2] ... [42949] (Overflow at 1.023MHz rate)
PRN_Addr:   [0] [0] [0] ... [1]     (Address increments)
PRN_Bit:    [1] [1] [1] [1] [0] [0] [0] ... (Read from ROM)

Carrier_NCO:[0] [X] [2X]... (High speed counting)
Carrier_Ph: [0] [1] [2] ... [628] (Phase angle)
Carrier_Wv: _/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾\_/‾_

Modulated:  _/‾\_/‾\___/‾\___/‾\_/‾\___/‾\___/‾\...
            ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^
            CA=1   CA=1   CA=0   CA=0   CA=1   CA=1
            (No flip)(No flip)(Flip!)(Flip!)(No flip)(No flip)

六、GAN 诱骗系统的特殊集成(Slow Pull-off)

现在我们把上一问的 GAN 控制逻辑​ 融入进来。

在 GAN 诱骗系统中,我们不再使用固定的 FCW,而是使用一个可编程的 FCW 寄存器,由 CPU 根据 GAN 生成的 Δρ(t)曲线动态更新。

1. 动态 FCW 注入

reg [31:0] fcw_carrier_reg;

always @(posedge sys_clk) begin
    if (cpu_config_en) begin
        fcw_carrier_reg <= cpu_new_fcw; // CPU写入新的牵引频率控制字
    end else begin
        fcw_carrier_reg <= fcw_carrier_reg; // 保持当前牵引速度
    end
end

// NCO 使用这个寄存器作为累加步长
always @(posedge sys_clk) begin
    carrier_accumulator <= carrier_accumulator + fcw_carrier_reg;
end

2. 双通道(I/Q)输出

为了后续上变频方便,通常输出 I/Q 两路正交信号:

  • I_Channel = PRN * cos(2πf t)

  • Q_Channel = PRN * (-sin(2πf t))

这样在模拟端可以用正交调制器直接上变频到 L1 频段。


七、资源优化与工程技巧

技巧

目的

实现方法

CORDIC 算法

替代 Sine/Cosine LUT

节省 BRAM 资源,但时序稍慢,适合低速场合。

相位抖动 (Dithering)

降低杂散

在 NCO 累加器低位加随机噪声,将杂散能量扩散。

半带/内插滤波器

提高 DAC 利用率

如果 DAC 速率很高(>100MHz),可以在 NCO 后加 CIC 滤波器插值。

符号位调制

极致简化

如果 GAN 波形不需要高保真,可以直接用 PRN 码(1/-1)去异或载波相位的最高位,省去乘法器。


八、总结

此文由 怡心湖 编辑,若您觉得有益,欢迎分享转发!:首页 > 常识论 » 如何在 FPGA 中利用 DDS(直接数字频率合成)技术同时生成 C/A 码和载波,并完成两者的扩频调制。

()
分享到:

相关推荐