3.1 Namuru跟踪模块分析

\qquad 在参考设计AGRS_GP_1的SOPC系统中,以自定义外设组件形式集成了一个GNSS基带模块(数字化硬件),并为它生成了一个名为gnss_bdmod的实例。运行在NIOS II CPU中的导航软件通过参考名称gnss_bdmod与它(组件实例)进行交互,达到存取基带I/O数据和控制基带信号逻辑的目的。

\qquad HD-GP接收机的GNSS基带模块是以Namuru接收机跟踪模块的开源代码为基础开发的,继承和扩展了Namuru跟踪模块的架构和接口,特点是增加了支持BDS系统和双系统以及输出1PPS时标的功能。本文主要分析开源Namuru跟踪模块的架构和接口,重点讨论它的时基模块和跟踪通道。开源Namuru跟踪模块可以从网络下载,本文参考的代码由UNSW的Peter Mumford发布,最终修改年份为 2007年。

3.1.1 总体描述

\qquad Namuru跟踪模块最初用VHDL开发,开发工具使用Mentor Graphics的ModelSim软件包,后来使用Altera的Quartus package软件包,Verilog版也已完成开发。下面介绍Verilog版的Namuru GPS跟踪模块。

\qquad Namuru跟踪模块的设计目标是为运行在一台微处理器上的导航固件提供GPS L1信号跟踪和观测量服务。Namuru跟踪模块非常适合将位置功能集成到具有FPGA芯片的设备中。FPGA解决方案固有的灵活性在GNSS不断变化的环境中提供了优势,并便于特定应用程序的修改。

\qquad 如图3-1所示,Namuru跟踪模块由一个主模块和三个子功能块组成:12个完全相同的跟踪通道、一个时基模块、以及一个寄存器和地址译码功能块。主模块(gps_baseband)的任务是:

  1. 提供接收工作时钟(clk)和数字中频(IF)的接口;
  2. 生成时基模块实例,使用工作时钟(clk)和采样时钟(s_clk)(包含在IF信号中)导出总线和跟踪通道处理所需的各种时序信号,包括:一个中断信号(accum_int)和一个观测量锁存信号(TIC);
  3. 生成和管理12个跟踪通道(实例),为每个通道提供的功能包括:引入数字中频信号、时序信号、以及控制信号,控制参数更新,转储相干累积值和自然观测量,等等;
  4. 提供与(跟踪模块)控制器进行数据交换的总线接口,包括:一个中断信号(accum_int)、一组寄存器以及相应的地址译码和读/写功能。寄存器类型包括:控制寄存器、状态寄存器、以及通道寄存器。控制器通过向控制寄存器写入数据来控制跟踪模块,通过读取状态寄存器来获取系统处理状态,通过读取各通道寄存器来获取跟踪GPS信号的数据、以及形成伪距和解码导航数据位的观测量,以及通过向各通道的参数控制寄存器写入数据来控制它的信号生成和跟踪。

图3-1 Namuru基带模块顶层架构图

图3-1 Namuru基带模块顶层架构图(s_clk与后文中的sample_clk为同一信号)

\qquad 跟踪模块作为内存映射的外围设备连接到处理器。在测试系统中,这是一个NiosII软核处理器,连接过程用Quartus软件中的SOPC Builder来完成。

\qquad 跟踪模块占用256个地址空间,每个地址对应一个预定义类型和功能的寄存器,不过地址空间存在许多备用插槽。所有寄存器都为32-位宽,并非每个寄存器都使用了全部32-位。

\qquad 寄存器类型包括:控制寄存器、(系统)状态寄存器、以及通道寄存器。控制器通过向控制寄存器写入数据来控制相干模块,通过读取状态寄存器来获取系统处理状态,通过读取各通道寄存器来获取跟踪GPS信号和解码导航数据位的数据、以及合成伪距的自然观测量,以及通过向各通道的参数控制寄存器写入数据来控制它的信号产生和信号跟踪。

\qquad 有关寄存器地址和功能的具体说明参见文档“Namuru FPGA GPS tracking module”。

\qquad 至此,我们已经初步了解了Namuru跟踪模块的顶层架构和基本工作方式,现在可以参照图3-1所示的基带模块基本架构以及图3-2给出的跟踪通道一般框图,对单个跟踪通道的信号处理回路做出一般描述了,我们假定这个处理回路最终能够捕获和稳定跟踪到卫星信号。

  1. 进入跟踪通道的卫星信号(IF)与本地复现的卫星信号进行相干(剥离载波和码信号),参见图3-2中的Carrier strip和Code strip功能块;
  2. 相干值在每个采样点上累积(累积时间跨度不小于一个码信号周期),形成相干累积值并转储,转储动作由转储使能信号(dump_enable)触发,参见图3-2中的Accumulate & dump功能块;
  3. 转储使能信号由码生成器(Code gen)在一个码信号起点/终点发出,严格做到这一点是获得准确自然观测量的基础;由此,转储周期(dump cycle)通常为一个码信号周期的整数倍,即n-ms (GPST);
  4. 为了让控制器及时取得相干累积值,主模块以一个不大于(标称)转储周期的间隔,向控制器发出一个中断,称为累积中断(accum_int),参见图3-1;
  5. 控制器在响应这个累积中断期间,读取跟踪通道的相干累积值,进行决策计算,并将结果参数反馈给跟踪模块;如果控制器确认已经捕获和跟踪到了卫星信号,还会使用相干累积值解码导航数据位,参见图3-1和图3-2;
  6. 跟踪通道在主模块控制下更新参数,从随后一个合适时间点开始,使用它们生成本地复现信号,参见图3-1和图3-2;
  7. 信号处理回到步骤(1)。

图3-2 单个跟踪通道的一般框图

图3-2 单个跟踪通道的一般框图

\qquad 在上面这个信号处理回路中,有两个预先确定的时间常数:(标称)转储周期和累积中断间隔,它们分别对应模块中实际定义的转储信号(dump)(图3-2)和累积中断信号(accum_int)(图3-1)。我们已经提到过,为了不丢失累积数据,累积中断间隔应选择得不大于(标称)转储周期,通常将它选为比后者小,以及尽量让后者除以它所得结果的有效小数位多些。

\qquad 这里有一个问题:由于每颗卫星相对接收机天线的距离不同,从卫星上按1-ms对齐发出的码信号,到达接收机天线时不再对齐,因此在码信号起点/终点时发出的转储信号,对于不同跟踪通道是不同时的。问题的解决方法之一是为每个跟踪通道的转储信号定义一个累积中断,于是12个跟踪通道需要定义12个不同的累积中断。很明显,这种解决方法过于草率,不实用;对跟踪模块而言,难以确定和保证12个累积中断间的时序关系而不丢失累积数据;对运行在任何微处理器中的控制器而言,即便响应以均匀时间间隔(对于C/A码信号,约为40~80μs)发出的12个累积中断,也是一个巨大挑战。

\qquad 对此,Namuru跟踪模块的解决方法是:

  1. 首先,定义一个为所有跟踪通道服务的累积中断,它按固定时间间隔发出中断信号;
  2. 其次,在主模块中使用一个寄存器(称为NEW_DATA寄存器),跟踪所有跟踪通道的转储信号状态,每一位与一个跟踪通道相对应;
  3. 当一个跟踪通道有等待读取的新数据时,NEW_DATA寄存器的相应位被置为1,这发生在这个跟踪通道的、与码信号起点/终点对齐的转储信号(dump)出现时;
  4. 控制器在响应一个累积中断期间,读取NEW_DATA寄存器,检查每个跟踪通道的状态位,如果状态位为1,则进一步读取它的相干累积值;
  5. 这个寄存器在读取后被清除,由主模块保证。

\qquad 接下来,我们讨论Namuru跟踪模块为导航固件提供观测量服务的机制。观测量是特定于跟踪通道的,只有跟踪通道进入了稳定跟踪状态,它们对于位置求解才有效。

\qquad 参见图3-2。在一个跟踪通道中,码生成器(Code gen)和码NCO (Code NCO)维持了合成伪距观测量所需的码相位信息,它们能将这些自然观测量的模糊度解析到一个码信号周期(一个历元)(对于C/A码,为1-ms)。在Namuru跟踪模块实现中,出于时序保证、代码效率和封装的考虑,通过与控制器配合,在每个跟踪通道中维持了一个历元计数器(Epoch Counter),将自然观测量的模糊度解析到了一个导航位对应的历元数(对于C/A码,为20个历元,即20-ms)。

\qquad 参见图3-1~3.2。为了获得所有跟踪通道在同一接收机时间上的自然观测量,Namuru跟踪模块设计了一个TIC时序信号。TIC信号由时基模块产生,按固定间隔发出,并被引入每个跟踪通道。每个跟踪通道在TIC信号上升沿将历元计数和码相位锁存到相应寄存器中。TIC信号间隔通常由接收机的每秒定位解最大值决定,典型值为10 ~ 1000 ms,因此一般比累积中断间隔至少大一个量级。

\qquad 与dump信号一样,需要设计一种机制,通知控制器出现了TIC信号。这里的情形简单些,因为dump信号有12个,而TIC信号只有1个,且TIC信号间隔一般更大,因而通知机制既可使用中断技术,也可使用状态存储技术,Namuru跟踪模块使用了后者:

  1. 在主模块中,用一个寄存器(称为STATUS寄存器)中的一位(称为TIC状态位)保持对TIC信号状态的跟踪;如果该寄存器在上次读取之后出现了一个TIC,这一位被置为1;
  2. 控制器在响应一个累积中断时,读取该寄存器,检查其中的TIC状态位,如果该位为1,则进一步读取所有(处于稳定跟踪状态的)跟踪通道的自然观测量;
  3. TIC状态位在STATUS寄存器读取后被清除,由主模块保证。

\qquad 至此,我们对Namuru跟踪模块的工作原理,就深入到跟踪通道模块架构这一层次而言,基本上完成了。在结束这个总体描述之前,还要讨论一个问题:跟踪模块的输入信号中已经有了一个(数字中频)采样时钟,为什么还需要一个工作时钟(clk)?如何确定这个工作时钟的频率?

\qquad 如果我们使用一个工作时钟,首先为了提供半码片信号,它的频率至少应等于码信号频率的两倍(对于C/A-码为2.048 Mhz,对于P-码为20.48 Mhz)。其次,工作时钟频率不应低于采样时钟频率,在相关运算之前,任何低于所需最小值(通常是主瓣占用的带宽)的带宽减小都将截断自相关峰值,从而导致更大的距离测量噪声。最后,为便于时基模块导出和管理时序信号,通常将工作时钟频率选择为采样时钟频率的2到6倍。

3.1.2 时基模块

\qquad 在Namuru跟踪模块中,时基模块(time_base)用工作时钟clk和采样时钟sample_clk导出处理所需的时序信号,包括tic_enable和accum_enable,参见图3-3。时序信号tic_enable对应前一小节中的观测量锁存信号TIC,accum_enable对应前一小节中的累积中断信号accum_int。时基模块导出的另两个重要时序信号为pre_tic_enable和accum_sample_enable。这些信号都同步于clk上升沿,选通脉冲宽度都为1个clk周期。

图3-3 时基模块输入/输出信号

图3-3 时基模块输入/输出信号

1、累积中断信号(accum_enable)

\qquad accum_enable为一中断信号,控制相关模块中累积器(accumulator)与控制器之间的数据传递,缺省周期为500.00μs。这个周期可以通过写入PROG_ACCUM_INT寄存器来改变,但写入的值必须小于1-ms,以保证累积数据不会被覆盖或丢失。

2、采样工作信号(accum_sample_enable)

\qquad 信号accum_sample_enable从基本时钟clk和采样时钟sample_clk导出,为一同步于工作时钟clk上升沿的采样工作时钟。

3、观测量锁存脉冲(tic_enable)

\qquad tic_enable为一内部计数脉冲,缺省周期为0.1s。它用于在相同瞬间锁存所有12个通道的自然观测量(Epoch count, Code phase, Code DCO phase, Carrier DCO phase, Carrier cycle count)。它的周期随后可以被改变,方法是将周期值写入PROG_TIC寄存器。

4、观测量预锁存脉冲(pre_tic_enable)

\qquad pre_tic_enable也为一内部计数脉冲,与tic_enable的周期相同,但脉冲比tic_enable早选通1个clk周期。pre_tic_enable只用于码NCO模块(code_nco),目的是比tic _enable早1个clk时钟锁存模块中的码NCO相位(code_nco_phase),以此与那些对齐于tic _enable的自然观测量在时序上一致。

3.1.3 跟踪通道(功能和代码)

\qquad 在Namuru跟踪模块中,一个跟踪通道由主模块(tracking_channel)和以下子模块构成:

  • 2个载波混频器(carrier_mixer),
  • 1个载波数控振荡器(carrier_nco),
  • 1个码数控振荡器(code_nco),
  • 1个码产生器(code_gen),
  • 1个历元计数器(epoch_counter),
  • 6个累积器(accumulator)。

为优化存储和运行效率,没有将码混频器实现为独立子模块,而是将其编程在累积器(accumulator)模块中。

1、主模块

\qquad Namuru跟踪通道的主模块(tracking_channel)电路十分简单,唯一作用是用导线将输入/输出信号以及这些子模块连接起来,参见下面的图3-4和Verilog代码(tracking_channel.v)。

图3-4 跟踪通道数字电路

图3-4 跟踪通道数字电路(只显示了1个累积器)

\qquad 这里按照图3-4中的信号流向,再次概述跟踪通道的信号处理:

  1. 进入通道的中频采样数据(if_sign, if_mag),在载波混频器(carrier_mixer)中与载波数控振荡器(carrier_nco)产生的本地载波信号(carrier_sign, carrier_mag)相混频,得到剥离了载波的中频信号(mix_sign, mix_mag);
  2. 码数控振荡器(code_nco)产生半码片使能信号(hc_enable)并传到码产生器(code_gen)中;
  3. 码产生器(code_gen)产生C/A码超前(early)、即时(prompt)、滞后(late)码片和转储使能信号(dump_enable);
  4. 在不同累积器(accumulator)中,在采样脉冲accum_sample_enable的作用下,剥离了载波的中频信号(carrier_mix_sign, carrier_mix_mag)分别与当前C/A码的early、prompt、late码片进行相关计算,结果加到各自的累加器中。图中只显示了同相即时码累加器(accumulator:ip),没有显示其余累加器(accumulator:ie, accumulator:il, accumulator:qp, accumulator:ie, accumulator:il);
  5. 在每个C/A码周期结束时触发的dump_enable脉冲作用下,转储累加器数据。

2、载波NCO

\qquad 载波NCO (carrier_nco),以基本时钟clk频率钟控,目标是合成在载波混频器(carrier_mixer)中将输入信号转换为基带所需的本地复现信号(i_sign, i_mag, q_sign, q_mag)。并且,为了将多普勒偏移和参考频率误差的影响考虑在内,必须能将它的产生频率调整为偏离其标称值。

\qquad 载波NCO的频率受控于频率控制字f_control。f_control一旦改变,立即起作用,从而引起载波NCO信号的变化。f_control长度为29-bit,需要如此精细分辨率是为了NCO保持与卫星信号相位一致有足够长数据。.

\qquad 载波NCO复现的载波是由8-级相位组成的伪正弦波形。NCO频率为

                f = fControl * Clk / 2^N

其中:

  f = the required carrier wave frequency
  Clk = the system clock (= 40MHz)
  N = 30 (bit width of the phase accumulator)
  fControl = the 29 bit (unsigned) control word。

\qquad 为I 分支和Q分支产生的波形类似于

                Phase   :  0  1  2  3  4  5  6  7 
                 --------------------------------- 
                    I: -1 +1 +2 +2 +1 -1 -2 -2 
                    Q: +2 +2 +1 -1 -2 -2 -1 +1 

\qquad 对(Namuru接收机中使用的)GP2015射频芯片而言,标称中心频率为:

  f = the required carrier wave frequency
  Clk = the system clock (= 40MHz)
  N = 30 (bit width of the phase accumulator)
  fControl = the 29 bit (unsigned) control word。

分辨率为:

  fControl increment value = 0.037252902 Hz

换句话说,使用这个NCO,37mHz是载波频率的最小可能变化值。

\qquad 载波相位和载波整周计数在tic_enable上被锁存到32-bit寄存器carrier_val中。载波相位为累加寄存器(accum_reg)的高10-bits。整周计数为最近两个tic_enables信号之间的载波整周数。这两个值被组合到carrier_val中,位9:0为载波相位,位31:10为整周计数。

3、码NCO

\qquad 码NCO (code_nco)类似于载波NCO (carrier_nco),也以基本时钟clk频率钟控,用于合成以2倍C/A码速率驱动码产生器(code_ gen)所需的振荡器。

\qquad 码NCO产生半码片使能信号(hc_enable)。这个信号驱动C/A码产生器(标称频率为1.023MHz)。应用代码必须使用复现的C/A码将频率调节为对齐进入的信号,其中需要考虑到时钟误差(TCXO频率误差)和多普勒频移。

\qquad 码NCO的频率受控于频率控制字f_control。f_control一旦改变,立即起作用,从而引起码NCO信号的变化。f_control长度为28-bit,需要如此精细分辨率是为了NCO保持与卫星信号相位一致有足够长数据。.

\qquad 码NCO的频率为

  f = fControl * Clk / 2^N

其中:

  f = the required frequency
  N = 29 (bit width of the phase accumulator) 
  clk = the system clock (= 40MHz) 
  fControl = the 28 bit (unsigned) control word 

\qquad 为了产生频率为f的C/A码,这个NCO必须设置以2f运行,因此

 code_frequency = 0.5 * fControl * clk/2^N

对于一个clk = 40 MHz的系统时钟:

  fControl = code_frequency * 2^29 / 20[Mhz]

对于code_frequency = 1.023MHz

  fControl = 0x1A30552

\qquad 码NCO在tic_enable信号上提供精细码相位值(10- bit)。需要注意的是:全码片使能信号(fc_enable)在code_gen模块产生,且与半码片使能信号(hc_enable)不对齐,fc_enable总是比(最靠近自己的)hc_enable信号晚一个时钟周期,进一步分析参见后面的“信号时序分析”。C/A码的码片边界对齐的是fc_enable,而不是hc_enable。这意味从产生hc_enable的code_nco中取得的精细码相位将早一个时钟周期。考虑到这一点,使能信号pre_tic_enable被用于锁定码NCO相位。

4、载波混频器

\qquad 载波混频器(carrier_mixer)将载波NCO(carrier_nco)的本地复现信号乘以中频原始数据产生一个基带信号。

\qquad 中频原始数据和本地复现载波都为2-bit量。每个量都有一个符号位和一个幅值位。输入信号中的if_mag代表数值1和3,carrier_mag代表数值1和2。混频后的幅值mix_mag为表示1,2,3,6的3-bit量;混频后的符号位mix_sign,0代表负,1代表正。

\qquad 下面是真值表:

if_mag        | 0 0 1 1 | 
carrier_mag   | 0 1 0 1 | 
output bit: 
              0 | 1 0 1 0 | = not carrier_mag 
 
              1 | 0 1 1 1 | = if_mag or carrier_mag 
              2 | 0 0 0 1 | = if_mag and carrier_mag 
----------------|---------| 
     value      | 1 2 3 6 | 

3*2 = (11*10)b = (110)b
3*1 = (11*01)b = (011)b
1*2 = (01*10)b = (010)b
1*1 = (01*01)b = (001)b

 if_sign       | 0 0 1 1 |  (0 = -ve, 1 = +ve) 
 carrier sign  | 0 1 0 1 | 
 output sign: 
               | 1 0 0 1 |  = not( if_sign xor carrier_sign ) 

5、码产生器

\qquad 码产生器(code_gen)在码NCO (code_nco)输出的2倍C/A码速率脉冲驱动下,产生三个C/A码信号序列:超前、即时、滞后(early, prompt, late),它们之间相差半个码片。

\qquad 为码产生器选择指定卫星所对应的C/A码,通过改变模块输入信号prn_key来设置,即通过控制器将卫星PRN初始相位值写入PRN_KEY寄存器来设置。码产生器还提供了一种以1/2码片为单位滑动C/A码的机制,通过改变模块输入信号code_slew来完成,即通过控制器将要滑动的1/2码片数写入CODE_SLEW寄存器来设置。

\qquad 在每个即时码序列结束时,产生一个dump_enable信号,用于锁存累加数据,以便信号跟踪软件使用。每个通道是单独锁存的,因为接收的卫星信号不相互同相。

\qquad C/A码相位(半码片计数)在tic_enable信号上被锁存到11-bit寄存器code_phase中。半码片计数范围为0到2045。码NCO (code_nco)提供了精细码相位code_nco_phase。需要注意的是:在码片滑动期间,code_phase观测量是无效的。

\qquad 对码产生器(code_gen)模块功能和代码实现的进一步分析参见后面的“码产生器剖析”。

6、累积器

\qquad 在累积器(accumulator)中,合并了三项任务:

\qquad (1) 码混频器:将经过载波信号剥离之后的信号(carrier_mix_sign, carrier_mix_mag)与C/A码信号(code) 相乘。

\qquad 信号carrier_mix_sign提供符号位:0为负,1为正.;信号carrier_mix_mag的3个幅值位代表1,2,3,6。code的0或1分别表示-1和1。信号carrier_mix和code相乘的幅值就是carrier_mix_mag,符号由carrier_mix sign和code之积决定:

code                0 0 1 1 
carrier_mix_sign    0 1 0 1 
                    ------- 
result              1 0 0 1  (0 for -ve, 1 for +ve) 

if (code == carrier_mix_sign) result = 1
else result = 0

\qquad (2) 累积器:在1个C/A码序列的完整码周期上(标称1ms)对6个独立的相关结果进行积分。

\qquad (3) 转储:每个通道有6个独立的16-位累加器。在C/A码产生器输出的DUMP信号作用下,将6个积分结果转储在这些累加器之中。它们分别代表在积分周期上I和O信号与超前、即时、滞后码的相关值。在这些寄存器上没有重写保护机制,因此数据必须在下一个DUMP之前被读取。

7、历元计数器

\qquad 历元计数器(epoch_counter)模块用两个计数器跟踪1秒间隔中的C/A码周数:1ms历元计数器(周计数器cycle_count)和20ms历元计数器(或位计数器bit_count)。1ms历元计数器(通过计数dump_enable脉冲)对每1ms出现的C/A码周期从0到19计数。这允许对导航电文中每20ms出现的位边界进行跟踪。每当这个计数器翻转时,20ms历元计数器加1。20ms历元计数器从0计数到49,允许跟踪电文的帧边界。

\qquad 1ms历元计数器为5-bit宽,20ms历元计数器为6-bit宽。这些值在每个tic_enable上被锁存到epoch寄存器中,其瞬时值可以从epoch_check寄存器中获得,以帮助寻找电文位翻转。这些值可以用模块输入信号epoch_load来加载,以便将它们与卫星数据流同步,方法是将预加载值写入EPOCH_LOAD寄存器。

3.1.4 跟踪通道(进一步讨论)

\qquad 本小节将对跟踪通道的以下重要功能的实现予以具体讨论:

  • 信号时序:分析其中重要的时序信号和时序关系;
  • 码产生器:对码产生器的功能进行分解和分析。

1、信号时序关系

\qquad 在Namuru跟踪通道中,驱使本地复现信号与进入通道的GPS信号在载波和C/A码频率上一致、相位上对齐的任务,分别由载波振荡器(carrier_nco)和码振荡器(code_nco) + 码产生器(code_gen)完成。在产生本地载波信号序列的carrier_nco中,信号时序关系比较简单。而在产生本地C/A码片序列的模块code_nco+code_gen中,由于涉及导出和对齐多个信号,时序关系比较复杂。两个因素造成了这一情形:

  • 第一,为了获得卫星信号的准确发射时间 ,对于本地复现的C/A码信号而言,不仅要求频率一致、相位对齐,而且要求时间对准,即要求准确记录产生一个C/A码片序列的开始(时刻)。为此,需要我们定义和使用一个使能脉冲,当它选通时,触发一个新C/A码片序列的产生。后面要讨论的信号dump_enable就是这样的脉冲,在稳定跟踪状态下,它的上升沿刚好对准卫星C/A码片序列的开始发射时刻,而后者与GPST 的1-ms起点是对准的。
  • 第二,为了满足跟踪算法要求,在每个clk时钟上,不仅需要C/A码产生器提供即时码片(prompt),而且需要它提供超前码片(early)和滞后码片(late),由此加大了产生C/A码、移动C/A码片、对齐时序信号的设计难度。尽管如此,通过定义两个使能脉冲,一个用于触发C/A码片序列产生,一个用于移动即时、超前、滞后码片(三元组),以及将它们与使能脉冲dump_enable相配合,就能实现满足功能要求的时序关系。后面要讨论的信号fc_enable和hc_enable就是这样两个脉冲。

由此可见,只要对一个C/A码片序列的开始和结束时间边界予以明确定义,以及对有关信号在此边界前后若干个clk时钟脉冲上要完成的任务予以明确指定,就应能清晰显现和可靠把握它们之间的时序关系。我们下面以此为切入点进行讨论。

\qquad 首先,约定使用以下记号:

  • 用cXXXX代表一个全码片序列中的第XXXX个码片(XXXX为1到1023之间的一个4位10-进制整数);
  • 用[cXXXX cYYYY cZZZZ]代表半码片三元组[L P E]的当前值,其中[L P E]为[Late Prompt Early]的缩写。

\qquad 于是,一个全码片序列从开始到结束相继为c0001. c0002, ……, c1022, c1023,在称为全码片使能脉冲(fc_enable)的作用下,以C/A码信号速率从一个码片移动到下一个码片;而一个半码片三元组[L P E]序列从开始到结束相继为[c1023 c0001 c0001], [c0001 c0001 c0002], [c0001 c0002 c0002], ……, [c1022 c1023 c1023], [c1023 c1023 c0001],在称为半码片使能脉冲(hc_enable)的作用下,以2倍C/A码信号速率从一个三元组移动到下一个三元组。在时间上,这两个序列元素之间应保持以下对应关系:

两个三元组序列元素间的对应关系
\qquad 假设fc_enable脉冲由hc_enable脉冲导出,则对C/A码片序列边界(附近)的信号时序可以做出如图3-5所示的设计:

  • 第1行clk为工作时钟信号;
  • 第2行hc_enable为半码片使能信号,由clk以2倍C/A码信号速率导出,其使能脉冲宽度为1个clk周期;
  • 第3行fc_enable为全码片使能信号,由hc_enable以C/A码信号速率导出(每两个hc_enable导出一个fc_enable),其使能脉冲宽度为1个clk周期,落后导出它的那个hc_enable一个1个clk周期;
  • 第4行[L P E]为半码片三元组序列;一个C/A码片序列的边界由半码片三元组序列的开始和结束元素决定,即[L P E] = [c1023 c0001 c0001]代表从边界开始的元素,[L P E] = [c1023 c1023 c0001] 代表结束于边界的元素;
  • 在时序上,一个(C/A码片序列的)边界选择为与一个fc_enable脉冲的上升沿重合,因此它的前后分别为一hc_enable脉冲和一fc_enable脉冲,我们将它们所对应的clk时钟脉冲分别记为clk_hc和clk_dump;
  • 第5行ca_code代表C/A码产生器产生的码片;ca_code在每个fc_enable脉冲作用下移动1个码片,它在边界上的值为c0002,也就是说,相比于三元组开始元素([c1023 c0001 c0001]),它的开始元素(c0001)超前一个fc_enable信号周期;
  • 在第4行中,两个相继半码片三元组[L P E]状态的转移可以用一个3-位长度的移位寄存器(比如shft_reg)实现:移位操作在选通hc_enable的clk时钟周期上进行(比如shft_reg[2:1] <= shft_reg[1:0], shft_reg[0] <= ca_cod),状态转移在下个clk时钟周期内完成。例如:在边界前后,从状态[c1023 c1023 c0001]到状态[c1023 c0001 c0001]的转移在clk_dump时钟周期内完成;
  • 第6行dump_enable为转储使能信号;时钟周期clk_dump十分关键,应尽可能在这个周期内完成(上个C/A码周期的)累积数据转储和累积寄存器清零。为此,需要在clk_hc周期上,导出一个传送到相应模块的转储使能信号(dump_enable),让后者在clk_dump周期上完成这些处理;
  • clk_dump为一临界时钟周期,如果一个采样工作脉冲 (accum_sample_enable)与一个转储使能脉冲(dump_enable)同时出现,则需要舍弃那个采样数据。
    图3-5 C/A码片序列结束/开始边界(附近)的信号时序关系
    图3-5 C/A码片序列结束/开始边界(附近)的信号时序关系

\qquad 接着,我们参考图3-4给出的(跟踪通道中的)信号流向,以及前面给出的码振荡器(code_nco)和码产生器(code_gen)的Verilog代码,来看看:在Namuru跟踪通道中,C/A码片序列边界上的信号时序关系如何以及如何保证?

\qquad 在C/A码片序列产生中,码振荡器(code_nco)导出半码片使能脉冲(hc_enable),在码产生器(code_gen)中:

  • 全码片使能脉冲(fc_enable)由hc_enable脉冲导出(每两个hc_enable导出一个fc_enable);
  • 当前C/A码片(ca_code)在每个fc_enable脉冲作用下移动1个码片(在下个时钟clk上开始有效);
  • 码移位寄存器(shft_reg)在每个hc_enable脉冲作用下移动1位,即shft_reg(2:1) <= shft_reg(1:0), shft_reg(0) <= ca_code;对应于shft_reg的新[L P E]在下个时钟clk上开始有效;
  • 转储使能脉冲(dump_enable)由hc_enable信号在每个C/A码片序列边界导出,在稳定跟踪状态下(code_slew=0):
    • 在选通hc_enable的那个clk(对应图3-5中的clk_hc)上,fc_enable<=1,dump_enable <= 1,[L P E]为[c1023 c1023 c0001];
    • 在下个clk上(对应图3-5中的clk_dump),
      • dump_enable信号起作用,转储之前累积的1个C/A码周期的数据,并清零累积寄存器;
      • [L P E]变为[c1023 c0001 c0001],标志1个新C/A码片序列的开始;
    • 在下2个clk上,
      • ca_code移动一个码片, ca_code = c0002;
      • 在accum_sample_enable信号作用下,开始累积新C/A码周期的数据。

\qquad 由此,这个过程导出的重要时序信号为:

  • hc_enable:半码片使能脉冲
  • fc_enable:全码片使能脉冲
  • dump_enable:累积转储脉冲

此外,还生成了以下自然观测量:

  • code_nco_phase:码NCO相位
  • code_phase:码相位

\qquad 本小节随后内容对这些时序信号及其关系在Namuru模块中的实现进行总结,并对本地C/A码序列产生进行仿真。对码产生器(code_gen)的深入剖析放在随后小节(“码产生器剖析”)中。

(1) 在模块code_nco中

  • 在复位信号(rstn)作用下,code_nco_phase和hc_enable被清零,由此标志新复现C/A码信号序列的开始;
  • 在每个时钟脉冲clk作用下,码相位累加器(accum_sum)递增一个频率控制字(f_control)大小;
  • 当码相位累加器(accum_sum)进位时,产生一个半码片使能(hc_enable)脉冲(2倍于C/A码速率);
  • 在tic_enable信号作用下,码NCO相位被保存到寄存器code_nco_phase中,这个相位值从最近一次hc_enable信号使能后开始计数。

(2) 在模块code_gen中

  • 在正常情况下(code_slew=0),每出现2个hc_enable脉冲,导出1个fc_enable(全码片使能)脉冲,且fc_enable滞后导出它的那个hc_enable脉冲1个clk时钟;
  • C/A码(ca_code)在每个fc_enable脉冲作用下移动1个码片(在下个时钟clk上开始有效);
  • 码移位寄存器(shft_reg)在每个hc_enable脉冲作用下移动1位,即shft_reg(2:1) <= shft_reg(1:0), shft_reg(0) <= ca_code;生成的新[L P E]在下个时钟clk上开始有效;
  • 在每个C/A码片序列结束时所对应的那个hc_enable脉冲(对应图3-5中的clk_hc)上,产生一个累积转储脉冲(dump_enable<=1)和一个全码片使能脉冲(fc_enable<=1),这是code_slew = 0时的情况;如果code_slew ≠ 0,则dump_enable有可能不与一个fc_enable对齐,因为code_slew的单位为半码片。
  • 在tic_enable信号作用下,码相位被保存到寄存器code_phase中,这个相位值从最近一次累积转储脉冲(dump_enable)开始对半码片进行计数。

(3) 时序仿真

\qquad 图3-6显示了仿真本地C/A码片序列产生过程所获得的时序信号波形,对应于一个跟踪通道启动一段时间中的情形,反映了时钟信号clk、复位脉冲rstn、半码片使能脉冲hc_enable、全码片使能脉冲fc_enable、累积转储脉冲dump_enable、以及当前C/A码片ca_code之间的时序关系。参考前面关于码产生器的分析以及给出的码产生器代码(code_gen.v)。

  • 光标1指向最后1个复位脉冲(rstn)结束处,这时通道中所有寄存器复位为缺省值;
  • 光标2指向第1个全码片使能脉冲(fc_enable)结束处:
    • 这个fc_enable出现在第2个hc_enable之后,二者脉冲宽度都为1个clk周期,出现时间相差1个clk周期;
    • ca_code这时移动到了下一个码片。
  • 光标3指向第2个全码片使能脉冲(fc_enable)和累积转储脉冲(dump_enable)结束处:
    • fc_enable、dump_enable出现在第4个hc_enable之后;
    • ca_code在此移动到了下一个码片。

图3-6 本地C/A码片序列产生过程中的时序信号仿真图

图3-6 本地C/A码片序列产生过程中的时序信号仿真图

2、码产生器剖析

\qquad 对C/A码产生器(code_gen)的模块代码按功能分解如下,之后分别进行讨论:

  • 码振荡器(code_nco)产生C/A码的半码片使能脉冲(hc_enable),本模块接收hc_enable脉冲;
  • 参照半码片使能脉冲hc_enable,产生全码片使能脉冲fc_enable(参见代码分析“产生全码片使能脉冲”);
  • 在fc_enable作用下,移动C/A码片(ca_code)(参见代码分析“移动C/A码片”);
  • 在hc_enable作用下,按2倍码片速率将C/A码片(ca_code)移入移位寄存器(shft_reg),从而产生early、prompt和late码片(参见代码分析“移动相干码片三元组”);
  • 在每个C/A码片序列结束时,产生累积数据转储使能脉冲 (dump_enable)(参见代码分析“产生转储使能脉冲”)。

(1) 产生全码片使能脉冲

// The full-chip enable generator (Ignore code_slew)
// 这个处理以hc_enable一半的速率产生fc_enable信号。
/*----------------------
 1. hc_enable, fc_enable脉冲选通宽度为1个clk周期;
 2. fc_enable比hc_enable滞后1个clk周期。
----------------------*/
always @ (posedge clk) 
begin 
	if (prn_key_enable) 
	begin 
		hc_count1 <= 0; 
		fc_enable <= 0; 
	end 
	else 
		begin  
		if (hc_enable) 
		begin 
			if (hc_count1 == 1) 
			begin 
				hc_count1 <= 0; 
				fc_enable <= 1; // create fc_enable pulse 
			end 
			else 
				hc_count1 <= hc_count1 + 1; // increment count 
		end 
		else 
			fc_enable <= 0; 
	end 
end

(2) 移动C/A码片

// The G1 shift register 
/*----------------------
 1. ca_code在fc_enable上移动1个码片。
----------------------*/
always @ (posedge clk) 
begin 
	if (prn_key_enable) // set up shift register 
	begin 
		g1_q <= 0; 
		g1 <= 10'b1111111111; 
	end 
	else if (fc_enable) // run 
	begin 
		g1_q <= g1[0]; 
		g1 <= {(g1[7] ^ g1[0]), g1[9:1]}; 
	end 
end 

// The G2 shift register 
//---------------------- 
always @ (posedge clk) 
begin 
	if (prn_key_enable) // set up shift register 
	begin 
		g2_q <= 0; 
		g2 <= prn_key; 
	end 
	else if (fc_enable) // run 
	begin 
		g2_q <= g2[0]; 
		g2 <= {(g2[8] ^ g2[7] ^ g2[4] ^ g2[2] ^ g2[1] ^ g2[0]), g2[9:1]}; 
	end 
end

assign ca_code = g1_q ^ g2_q;

(3) 移动相干码片三元组

// chip spreader: shift register for generating early, prompt and late chips 
//-------------------------------------------------------------------------- 
// Half a chip separates the early and prompt, and prompt and late codes. 
always @ (posedge clk)
begin
	if (prn_key_enable) //clear register;
		shft_reg <= 0;
	else if (hc_enable) //make shifting here;
		shft_reg <= {shft_reg[1:0], ca_code};
end
assign srq = shft_reg;   

// assign the early, prompt and late chips, one half chip apart 
assign early = srq[0]; 
assign prompt = srq[1]; 
assign late = srq[2];

(4) 产生转储使能脉冲

// The dump_enable generator (Ignore code_slew)
/*----------------------
参见时序图3-7:
1. 在最大半码片计数值max_count2上,半码片计数器hc_count2<=0, 它在下一个clk上有效;
2. 在(随后的)第1个hc_enable到来前,hc_count2=0:
l	ca_code = c1023,[L P E]为[c1021 c1022 c1022];
3. 在(随后的)第1个hc_enable到来时,hc_count2<=1:
l	fc_enable为0,[L P E]仍为[c1021 c1022 c1022];
l	在下1个clk上, [L P E]变为[c1022 c1022 c1023];
4. 第2个hc_enable到来时,hc_count2<=2:
l	fc_enable<=1,[L P E]仍为[c1022 c1022 c1023];
l	在下1个clk上, [L P E]变为[c1022 c1023 c1023];
l	在下2个clk上,ca_code移动一个码片, ca_code = c0001;
5. 第3个hc_enable到来时,hc_count2<=3:
l	fc_enable为0,[L P E]仍为[c1022 c1023 c1023];
l	在下1个clk上, [L P E]变为[c1023 c1023 c0001];
6. 第4个hc_enable到来时,hc_count2<=4(hc_count2在这个clk上的值为3):
l	fc_enable<=1,dump_enable <= 1,[L P E]仍为[c1023 c1023 c0001];
l	在下一个clk上:
n	dump_enable信号起作用,转储(此前)1个C/A码周期的累积数据;
n	[L P E]变为[c1023 c0001 c0001],1个新C/A码周期开始;
l	在下2个clk上,ca_code移动一个码片, ca_code = c0002。
----------------------*/
always @ (posedge clk) 
begin 
	if (prn_key_enable) 
	begin 
		dump_enable <= 0; 
		hc_count2 <= 0; 
		slew_trigger <= 0; 
		max_count2 <= 2045; // normal half-chip count in one C/A cycle 
	end 
	else if (hc_enable) 
	begin 
		hc_count2 <= hc_count2 + 1; 
		if (hc_count2 == 3)//dump) 
			dump_enable <= 1; 
		else if (hc_count2 == max_count2) 
			hc_count2 <= 0; 
		else if (hc_count2 == 1)  // signals the arrival of the first hc_enable 
			begin 
				if (slew_flag) // slew delay 
				begin 
					slew_trigger <= 1; 
					max_count2 <= 2045 + code_slew; 
				end 
				else 
					max_count2 <= 2045; 
			end 
	end 
	else 
	begin 
		dump_enable <= 0; 
		slew_trigger <= 0; 
	end 

end 

图3-7 转储使能脉冲产生器时序图

图3-7 转储使能脉冲产生器时序图

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值