题目
(此处省略图片链接)
解题思路
题目要求从信号发生器输出两路波形 A 和 B 并通过一个增益为 1 的加法器生成信号 C,我们需要做的就是从 C 中将 A'和 B'解出来。一种方法是将 C 进行傅里叶变换然后识别出两路波形分别是什么然后将频域分离出来随后进行傅里叶逆变换再输出。另一种方法是本文所使用的方法:由于题目不考虑波形的相位和峰峰值与原波形的关系,可以将输入的 C 信号进行傅里叶变换识别出两路波形的频率。由于 AB 波的峰峰值为固定的 1V,而正弦波为单音信号频谱集中,三角波有三次谐波的存在导致基波信号的峰峰值会被削弱,使得可以通过比较频谱中基波的幅值大小来识别输入的波形是三角波还是正弦波。得到两路波的波形以及频率后,就可以使用 DDS 重构出 A'和 B'波形。但重构的波形与信号发生器所出的波形不在同一个时钟上,由于不同时钟的微小差异,会使得相位差在不停的累积产生信号漂移,所以需要设计一个锁相环将生成的信号与原信号的相位锁住,移相只需要改变 ROM 表的地址即可实现。
基本框架
C 信号——>高速 ADC——>FPGA——>FIFO——>串口——>stm32——>FFT——>识别波形和频率——>串口——>DDS——>锁相环——>高速 DAC——>A',B'
代码思路
第一部分(FPGA 的 FIFO 以及串口发送接收)
1. FIFO
此处使用的 FIFO 为黑金 AX7035B 所提供的例程,其中写入速率为 1MHz(与高速 ADC 的采样频率相同),读取速率为 12.5KHz(串口的发送速率)。
assign ad9238_clk_ch0 = clk_1M;
wire wr_en,rd_en,full,empty,wr_rst_busy,rd_rst_busy;
wire [10:0] rd_data_count,wr_data_count;
reg [7:0] w_data;
localparam W_IDLE = 1;
localparam W_FIFO = 2;
localparam R_IDLE = 1;
localparam R_FIFO = 2;
reg[2:0] write_state;
reg[2:0] next_write_state;
reg[2:0] read_state;
reg[2:0] next_read_state;
wire [7:0] rx_data,tx_data;
reg tx_valid;
always@(posedge clk_1M or negedge rst) begin
if(rst == 1'b0) write_state <= W_IDLE;
else write_state <= next_write_state;
end
// ... (其余逻辑保持不变)
2. FPGA 串口发送
此处串口发送使用的也是黑金的 AX7035B 的例程(在 FIFO 中每读一个数就通过串口发送出去)。
uart_tx#( .CLK_FRE(50), .BAUD_RATE(115200) )uart_tx(
.clk(clk),
.rst_n(rst),
.tx_data(tx_data),
.tx_data_valid(tx_valid),
.tx_pin(tx_pin)
);
// ... (其余逻辑保持不变)
3. FPGA 串口接收
此处串口接收使用的也是黑金的 AX7035B 的例程(帧头为 FF 帧尾为 FE 第一个数据为第一个波的波形 第二个数据为第一个波的频率 第三个数据为第二个波的波形 第四个数据为第二个波的频率)。
module uart_rx #( parameter CLK_FRE = 50, parameter BAUD_RATE = 115200 ) (
input clk,
input rst_n,
output reg[7:0] rx_data,
output reg rx_data_valid,
input rx_data_ready,
input rx_pin
);
// ... (其余逻辑保持不变)
4. 总结
这是与 stm32 通信模块的所有代码。
module stm32_communication(
input clk, input rst, input clk_1M,
input [7:0] ADC, input rx_pin,
output reg wave1, output reg [7:0] wave1_freq,
output reg wave2, output reg [7:0] wave2_freq,
output tx_pin
);
// ... (包含 FIFO、UART 收发逻辑)
endmodule


