%% 参数设置
clear all; close all; clc;
Fs = 5e9; % 采样率 5 GHz
fc = 1e9; % 载波频率 1 GHz
bw = 5e6; % 信号带宽 5 MHz
duration = 20e-6; % 信号持续时间 20 μs
t = 0:1/Fs:duration-1/Fs;
%% 生成QPSK调制信号
fprintf('生成QPSK调制信号...\n');
symbol_rate = bw/2; % 符号率 2.5 MHz
sps = floor(Fs/symbol_rate); % 每符号采样点数
num_symbols = ceil(length(t)/sps);
data = randi([0 3], 1, num_symbols); % QPSK数据
modulated = pskmod(data, 4, pi/4); % QPSK调制
% 升余弦滤波
rolloff = 0.35;
filt = rcosdesign(rolloff, 6, sps);
baseband = upfirdn(modulated, filt, sps, 1);
baseband = baseband(1:length(t));
%% 上变频
fprintf('上变频到RF...\n');
carrier = exp(1i*2*pi*fc*t);
rf_signal = real(baseband .* carrier);
%% 添加噪声
fprintf('添加噪声...\n');
noise_power = 0.01 * var(rf_signal);
rf_signal = rf_signal + sqrt(noise_power)*randn(size(rf_signal));
%% 定点量化 (16位有符号)
fprintf('定点量化...\n');
nbits = 16;
max_val = 2^(nbits-1)-1;
rf_signal_normalized = rf_signal / max(abs(rf_signal));
rf_fixed = round(rf_signal_normalized * max_val);
rf_fixed(rf_fixed > max_val) = max_val;
rf_fixed(rf_fixed < -max_val) = -max_val;
%% 重组为16路并行数据
fprintf('重组为16路并行数据...\n');
num_samples = length(rf_fixed);
if mod(num_samples, 16) ~= 0
rf_fixed = [rf_fixed, zeros(1, 16 - mod(num_samples, 16))];
num_samples = length(rf_fixed);
end
parallel_data = reshape(rf_fixed, 16, []);
num_blocks = size(parallel_data, 2);
%% ===================== 并行混频模块实现 =====================
fprintf('\n===== 开始并行混频处理 =====\n');
tic;
% NCO参数计算
nco_phase_step = 2*pi*fc/(Fs/16); % 每路相位增量
nco_initial_phase = 2*pi*fc*(0:15)/Fs; % 16路初始相位
% 初始化混频输出
mixed_data = complex(zeros(16, num_blocks)); % 复数类型
% 并行混频处理
for block_idx = 1:num_blocks
samples = parallel_data(:, block_idx);
% 计算每个通道的NCO相位
time_offset = (block_idx-1)*16; % 时间偏移
current_phase = nco_initial_phase + time_offset*nco_phase_step;
% 生成NCO载波
nco_carrier = exp(-1i * current_phase);
% 混频处理
mixed_data(:, block_idx) = double(samples) .* nco_carrier.';
end
% 重组为串行数据
mixed_serial = reshape(mixed_data, 1, []);
mixer_time = toc;
fprintf('并行混频处理完成! 耗时: %.4f 秒\n', mixer_time);
%% ===================== 混频模块性能指标 =====================
fprintf('\n===== 混频模块性能指标 =====\n');
% 计算资源消耗
num_multipliers = 16; % 并行混频器数量
total_mult_ops = num_blocks * 16; % 总乘法操作数
fprintf('并行混频器数量: %d\n', num_multipliers);
fprintf('每时钟周期乘法操作: %d\n', num_multipliers);
fprintf('总乘法操作数: %d\n', total_mult_ops);
fprintf('处理速率: %.2f MSPS\n', length(mixed_serial)/mixer_time/1e6);
% 计算信号质量
expected_bb = baseband(1:length(mixed_serial)); % 期望的基带信号
error = mixed_serial - expected_bb;
snr = 10*log10(mean(abs(expected_bb).^2) / mean(abs(error).^2));
fprintf('混频后信号SNR: %.2f dB\n', snr);
%% ===================== 16倍并行多相抽取器 =====================
fprintf('\n===== 开始16倍并行多相抽取 =====\n');
tic;
% 设计抗混叠滤波器(截止频率156.25 MHz)
cutoff_freq = 0.9 * (Fs/16/2); % 140.625 MHz (留裕量)
filter_order = 255; % FIR滤波器阶数
h = fir1(filter_order, cutoff_freq/(Fs/2));
% 多相分解(16个子滤波器)
num_taps = length(h);
if mod(num_taps, 16) ~= 0
h = [h, zeros(1, 16 - mod(num_taps,16))]; % 补零对齐
end
poly_phase = reshape(h, 16, []); % 16x(L/16) 多相系数矩阵
L_poly = size(poly_phase, 2); % 每个多相分支的抽头数
% 初始化历史缓冲区(存储前L-1个样本)
hist_buffer = complex(zeros(16, L_poly-1)); % 复数缓冲区
% 处理每个数据块
decimated_output = complex(zeros(1, num_blocks)); % 抽取后输出
for block_idx = 1:num_blocks
% 当前块数据 + 历史缓冲区
current_block = mixed_data(:, block_idx);
full_block = [hist_buffer, current_block]; % 16xL_poly
% 多相滤波(16路并行乘加)
poly_out = zeros(16, 1); % 存储每路输出
for i = 1:16
poly_out(i) = sum(poly_phase(i, :) .* full_block(i, :));
end
% 输出抽取结果(16:1)
decimated_output(block_idx) = sum(poly_out);
% 更新历史缓冲区(移除最旧数据)
hist_buffer = full_block(:, 2:end);
end
% 计算新采样率
Fs_new = Fs / 16; % 312.5 MHz
decimator_time = toc;
fprintf('并行多相抽取完成! 耗时: %.4f 秒\n', decimator_time);
fprintf('输出采样率: %.1f MHz\n', Fs_new/1e6);
%% ===== 多相抽取器性能指标 =====
fprintf('\n===== 多相抽取器性能指标 =====\n');
% 资源消耗
num_mult_blocks = 16 * L_poly; % 每块乘法器数量
total_mult_ops_dec = num_blocks * num_mult_blocks;
fprintf('每块乘法操作: %d\n', num_mult_blocks);
fprintf('总乘法操作数: %d\n', total_mult_ops_dec);
fprintf('处理速率: %.2f MSPS\n', length(decimated_output)/decimator_time/1e6);
% 信号质量分析
expected_bb_dec = resample(baseband, 1, 16, 1024); % 理想抽取结果
min_len = min(length(decimated_output), length(expected_bb_dec));
error_dec = decimated_output(1:min_len) - expected_bb_dec(1:min_len);
snr_dec = 10*log10(mean(abs(expected_bb_dec(1:min_len)).^2) / mean(abs(error_dec).^2));
fprintf('抽取后信号SNR: %.2f dB\n', snr_dec);
%% ===================== 频谱分析 =====================
% 1. 原始信号频谱
figure('Name', '原始信号频谱', 'Position', [50, 50, 800, 400], 'NumberTitle', 'off');
N_fft = 2^nextpow2(num_samples);
f_axis = (-N_fft/2:N_fft/2-1)*(Fs/N_fft);
spectrum = fftshift(abs(fft(rf_fixed, N_fft)));
plot(f_axis/1e9, 20*log10(spectrum/max(spectrum)));
title('原始信号频谱 (5 GHz 采样率)');
xlabel('频率 (GHz)');
ylabel('幅度 (dB)');
xlim([0, 2.5]); grid on;
% 2. 混频后基带信号频谱
figure('Name', '混频后基带信号频谱', 'Position', [100, 100, 800, 400], 'NumberTitle', 'off');
N_fft_mixed = 2^nextpow2(length(mixed_serial));
f_axis_mixed = (-N_fft_mixed/2:N_fft_mixed/2-1)*(Fs/N_fft_mixed);
spectrum_mixed = fftshift(abs(fft(mixed_serial, N_fft_mixed)));
plot(f_axis_mixed/1e6, 20*log10(spectrum_mixed/max(spectrum_mixed)));
title('混频后基带信号频谱 (5 GHz 采样率)');
xlabel('频率 (MHz)');
ylabel('幅度 (dB)');
xlim([-20, 20]); grid on;
% 3. 抽取后基带信号频谱
figure('Name', '抽取后基带信号频谱', 'Position', [200, 200, 800, 400], 'NumberTitle', 'off');
N_fft_dec = 2^nextpow2(length(decimated_output));
f_axis_dec = (-N_fft_dec/2:N_fft_dec/2-1)*(Fs_new/N_fft_dec);
spectrum_dec = fftshift(abs(fft(decimated_output, N_fft_dec)));
plot(f_axis_dec/1e6, 20*log10(spectrum_dec/max(spectrum_dec)));
title(sprintf('抽取后基带信号频谱 (%.1f MHz 采样率)', Fs_new/1e6));
xlabel('频率 (MHz)');
ylabel('幅度 (dB)');
xlim([-10, 10]); grid on;
% 4. 混频前后时域对比
figure('Name', '混频前后信号对比', 'Position', [150, 150, 1000, 600], 'NumberTitle', 'off');
subplot(2,1,1);
plot(real(baseband(1:200))), hold on;
plot(real(mixed_serial(1:200)));
title('混频前后信号实部对比');
xlabel('样本索引');
ylabel('幅度');
legend('原始基带', '混频输出');
grid on;
subplot(2,1,2);
plot(imag(baseband(1:200))), hold on;
plot(imag(mixed_serial(1:200)));
title('混频前后信号虚部对比');
xlabel('样本索引');
ylabel('幅度');
legend('原始基带', '混频输出');
grid on;
% 5. 抽取前后时域对比
figure('Name', '抽取前后信号对比', 'Position', [250, 250, 1000, 600], 'NumberTitle', 'off');
subplot(2,1,1);
t_orig = (0:length(baseband)-1)/Fs;
t_dec = (0:length(decimated_output)-1)/Fs_new;
plot(t_orig(1:200)*1e6, real(baseband(1:200))), hold on;
stem(t_dec(1:ceil(200/16))*1e6, real(decimated_output(1:ceil(200/16))));
title('抽取前后信号实部对比');
xlabel('时间 (\mus)');
ylabel('幅度');
legend('原始基带', '抽取输出');
grid on;
subplot(2,1,2);
plot(t_orig(1:200)*1e6, imag(baseband(1:200))), hold on;
stem(t_dec(1:ceil(200/16))*1e6, imag(decimated_output(1:ceil(200/16))));
title('抽取前后信号虚部对比');
xlabel('时间 (\mus)');
ylabel('幅度');
legend('原始基带', '抽取输出');
grid on;
%% 保存结果
save('parallel_mixer_decimator_results.mat', 'mixed_serial', 'decimated_output', ...
'mixer_time', 'decimator_time', 'num_multipliers', 'snr', 'snr_dec', 'Fs_new');
fprintf('\n处理完成! 结果已保存。\n'); 详细解释这段代码,此代码适用的范围,梳理代码DDC的框架,以此代码为核心写写一篇期刊论文该如何进行