# DigitalLockInAmplifier **Repository Path**: aheck/DigitalLockInAmplifier ## Basic Information - **Project Name**: DigitalLockInAmplifier - **Description**: Verilog实现数字锁相放大器。 - **Primary Language**: Verilog - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 11 - **Forks**: 5 - **Created**: 2023-11-05 - **Last Updated**: 2025-08-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 锁相放大器 锁相放大器(Lock-in Amplifier)是一种用于提取微小信号的测量仪器。它的主要特点是能够通过参考信号对输入信号进行同步检测,并且具有很强的抗干扰能力。 锁相放大器的工作原理是基于相位敏感检测技术。它将输入信号与一个参考信号进行乘法运算,使得输入信号与参考信号同频率同相位。然后,通过低通滤波器对乘积信号进行滤波,从而获得输入信号的幅度和相位信息。锁相放大器可以有效地抑制输入信号中的噪声和干扰,提高信号的信噪比。 ## 原理 输入信号可以定义为 $$S_t = A_I \sin( \omega t + \varphi) + \text{Noise}(t)$$ 参考信号为 $$S_{R1}(t) = A_R \sin ( \omega t + \delta)$$ $$S_{R2}(t) = A_R \cos ( \omega t + \delta)$$ 相乘后,得到 $$S_{PSD1}(t) = \frac {1}{2} A_I A_R \cos (\varphi - \delta) + \text{Noise}(t)A_R\sin(\omega t + \delta)-\frac {1}{2} A_I A_R \cos (2\omega t + \varphi + \delta)$$ $$S_{PSD2}(t) = \frac {1}{2} A_I A_R \sin (\varphi - \delta) + \text{Noise}(t)A_R\cos(\omega t + \delta)+\frac {1}{2} A_I A_R \sin (2\omega t + \varphi + \delta)$$ 经过低通滤波器滤波后($A$为最终增益),两个信号的直流分量为 $$ S_{o1} = \frac {1}{2} A_I A \cos (\varphi - \delta)$$ $$ S_{o2} = \frac {1}{2} A_I A \sin (\varphi - \delta)$$ 可得幅度为: $$ A_I = \frac{2 \sqrt {S_{o1}^2+S_{o2}^2}}{A} $$ 可得相对相位为: $$ \theta = \varphi - \delta = \tan^{-1} \frac{S_{o2}}{S_{o1}} $$ # 结构说明 ## 文件目录 ``` |-image |-rtl |-sim |-tb ``` rtl目录存放verilog代码。tb目录存放采用iic传输方式的testbench文件。sim目录存放python脚本。 ## 数据通路 数据通路采用axi-stream接口。可自行根据自身使用的adc编写其它协议例如iic/spi转axi-stream的rtl代码。 |Name | Description | |---------|---------| |S_TDATA | axi-stream总线数据接口 | |S_TVALID | axi-stream总线valid信号 | |S_TREADY | axi-stream总线ready信号 | |S_TSTRB | axi-stream总线片选信号 | |S_TLAST | axi-stream总线last信号,本设计为连续无间断数据流,本信号无效 | ## 控制通路 控制通路支持iic/axi lite的方式读写控制寄存器。具体切换可在rtl/dlia_define.v文件中,切换**AXI_LITE_SLAVE**和**IIC_SLAVE**两个宏的方式更改控制通路传输方式。 ### AXI4 lite接口 本设备只提供AXI4 lite总线低5位的接口,具体内存地址可自定义 |Name | Description | |---------|---------| | AWVALID | 写地址通道valid信号 | | AWREADY | 写地址通道ready信号 | | AWPROT | 本设计无用 | | AWADDRESS | 写地址地址 | | WVALID | 写数据通道valid信号 | | WREADY | 写数据通道ready信号 | | WDATA | 写数据地址 | | WSTRB | 写数据字节片选信号 | | BVALID | 写响应通道valid信号 | | BREADY | 写响应通道ready信号 | | BRESP | 写响应信号 | | ARVALID | 读地址通道valid信号 | | ARREADY | 读地址通道ready信号 | | ARPROT | 本设计无用 | | ARADDRESS | 读地址地址 | | RVALID | 读数据通道valid信号 | | RREADY | 读数据通道ready信号 | | RDATA | 读数据通道数据信号 | | RRESP | 读数据通道读响应信号 | ### IIC通信 锁相放大器的7位设备地址为0x6C,寄存器地址为8位,寄存器有32位数据位。 |Name | Description | |---------|---------| | SCL | IIC的SCL接口 | | SDA | IIC的SDA接口 | ![I2C通信](./image/I2C.png) ### 寄存器 支持的读写寄存器如下图: | 寄存器名字 | AXI lite地址 | IIC地址 | 类型 | 描述 | |------|--------|---------|------|--| | start | 0x00 | 0x00 | 控制寄存器 | 32位任意一位为1,锁相放大器开始工作 | | meas_signal_freq | 0x04 | 0x01 | 控制寄存器 |待测信号的频率 | | sample_freq | 0x08 | 0x02 | 控制寄存器 | 待测信号的采样频率 | | output_cos | 0x0C | 0x03 | 只读寄存器 | 待测信号与余弦信号调制、滤波后的值 | | output_sin | 0x10 | 0x04 | 只读寄存器 | 待测信号与正弦信号调制、滤波后的值 | | ref_cos | 0x14 | 0x05 | 只读寄存器 | [15:0]为参考余弦信号 | | ref_sin | 0x18 | 0x06 | 只读寄存器 | [15:0]为参考正弦信号 | ### 启动流程 1. 往meas_signal_freq寄存器(0x01)写入待测信号的频率 2. 往sample_freq寄存器(0x02)写入待测信号的采样频率 3. 往start寄存器(0x00)写入非零数据,启动锁相放大器 4. axi stream端接收数据 7. 重复4步骤 ### 信号增益 16位输入信号与16位参考信号相乘,参考信号的幅度为$2^{14}-1$,相乘后的信号为32位,随后进入IIR滤波器。IIR滤波器的直流增益为1倍。因此最后的实际增益为: $$A = A_R = (2^{14}-1) = 16383$$ ### 待测信号计算 幅度为: $$ A_I = \frac{2 \sqrt {S_{o1}^2+S_{o2}^2}}{16383} $$ 相对相位为: $$ \theta = \varphi - \delta = \tan^{-1} \frac{S_{o2}}{S_{o1}} $$ ### 实际案例 首先假设采样频率为40MHz,待测信号的频率为300kHz,待测信号幅度为5000。待测信号混有幅度为10000频率为310kHz的干扰信号1和幅度为15000频率为500kHz的干扰信号2。 ![信号](./image/signal2.png) 那么需要使用I2C协议先往寄存器0x01写入40_000_000,往0x02写入300_000。之后再往0x00写入0x0001,启动锁相放大器。 下图为IIC启动的时序图,设备地址为0x1101100。 ![I2C通信](./image/I2CW1.png) 仿真的cos通道输出信号幅度为$39897101$,sin通道输出信号幅度为$-10734411$ ![I2C通信](./image/example1.png) 则按照公式得知待测信号频率为$\dfrac{2 \sqrt {39897101^2+(-10734411)^2}}{16383}=5044$, 待测信号相对相位为$\theta = \varphi - \delta = \tan^{-1} \dfrac{39897101}{-10734411} = -0.42 \pi$, 与收集脚本的信息一致,预测值在$5000$上下震荡,幅度为$5000 \pm 100$。 可以添加均值滤波(rtl部分无均值滤波)减小误差。可以观察到均值滤波后的值误差不超过0.3%: ![脚本](./image/script.png) ### 自动化测试 需要环境:iverilog、python #### 使用python脚本生成测试txt文件 打开tb文件夹的signal_generate.py,可以设置采样点数量、采样频率、待测频率等参数。 点击generate.bat运行后在本地生成txt信号文件。 #### 仿真 双击sim文件夹的sim.bat就可以开始仿真。 可以观察到两个通道的值以及预测值 ## RTL设计 架构图设计: ![数据通路](./image/arch.drawio.svg) DDS为32位流水线,PSD使用基4-booth乘法器,IIR滤波器的latency为1。 ### 待测频率转fword模块设计 $$\text{fword} = \frac{2^N\cdot f_{\text{dds}}}{f_{\text{sample}}}$$ 其中$N$是相位累加器的位数,$f_{\text{dds}}$是待测频率,$f_{\text{sample}}$是采样频率。 ### 滤波器设计 1阶IIR滤波器,采用的传输函数形式如下: $$H(z) = \dfrac{1}{2^{N}-(2^{N} -1 ) z^{-1}}$$ 假如采样频率为40Mhz,待测信号频率为300kHZ,当$N = 16$时,锁相放大器的$Q$值大约为$6000$(带通滤波器的$Q$通常在$10^2$左右)。如果追求更高的$Q$,可以提升$N$的大小,这可能会带来更长的等待时间。 本设计取$N=16$,即 $$H(z) = \dfrac{1}{2^{16}-(2^{16} -1 ) z^{-1}}$$ 可以通过移位加减进行乘除上的优化: ``` dout_temp <= ((dout_d1 <<< 16) - dout_d1 + din )>>> 16; ``` 频率响应如下: ![数据通路](./image/iir_freq_resp.png) 在40Mhz的采样频率下,可以达到9.7Hz的截止频率。 ## 资源占用与静态时序 综合的FPGA型号为:xc7a35tfgg484-2 ![资源占用](./image/uu.png) 200M时钟频率下的建立时间阈值和保持时间阈值 ![静态时序](./image/jt.png)