Simulink仿真卷积码与BPSK在AWGN信道下的性能分析 简介本资源是一套基于MATLAB/Simulink实现的卷积码编译码与BPSK调制联合通信系统仿真方案面向通信工程专业本科生、数字通信初学者及MATLAB实践者解决前向纠错编码与数字调制协同建模、性能评估等核心学习难点。压缩包共2个文件14KB含1个主控脚本juanjima.m用于参数配置与BER统计1个完整Simulink模型juanji.slx已集成卷积编码器、BPSK调制/解调、AWGN信道及Viterbi解码模块支持信噪比扫描与误码率曲线自动生成。已有525人学习下载可直接运行复现典型卷积码如约束长度3、码率1/2在BPSK系统下的抗噪性能配套模型结构清晰、模块标注完整便于理解编码逻辑、调制映射关系及解码路径选择机制是掌握通信链路级仿真实践的高效入门范例。1. 项目缘起从理论到仿真的必经之路在通信工程的学习和研发中我们经常会接触到各种信道编码技术卷积码无疑是其中经典且重要的一员。教科书上关于生成多项式、状态转移图、维特比算法的推导清晰严谨但公式和框图终究是“纸上谈兵”。一个编码方案到底能带来多大的性能提升在真实的噪声环境下它的误码率曲线究竟如何这些问题仅靠理论计算往往难以获得直观且令人信服的答案。这就是仿真工作的价值所在。它搭建了一座从理论到实践的桥梁让我们能在计算机上构建一个可控、可观测的“虚拟实验室”。对于卷积码编译码系统尤其是结合了BPSK调制在加性高斯白噪声信道下的性能仿真是通信系统入门和深造的经典实验。通过MATLAB特别是其强大的图形化建模环境Simulink我们可以像搭积木一样将编码器、调制器、信道、解调器、译码器这些模块连接起来直观地观察信号在系统中的流动与变换并最终通过蒙特卡洛方法统计出系统的误码性能。我最初接触这个仿真时也走过不少弯路。比如Simulink中卷积码模块的参数该如何与理论对应BPSK调制后的信号功率如何归一化AWGN信道的信噪比Eb/No到底该加在哪个环节仿真时间步长和帧长设置不当可能导致仿真效率极低甚至结果错误。这篇文章我就结合多次实操的经验手把手带你用Simulink搭建一个完整的卷积码以常用的(2,1,3)码为例编译码及BPSK调制仿真系统并深入剖析每一个环节的设置要点和背后的原理让你不仅能“跑通”仿真更能“吃透”仿真。2. 系统蓝图与Simulink建模核心思想在打开Simulink之前我们必须先在脑子里勾勒出整个系统的框图。一个完整的数字通信系统仿真链路通常包括信源、信道编码、调制、信道、解调、信道译码、信宿以及性能评估模块。我们的仿真目标就是对比经过卷积码编码和未经编码的原始数据在相同信道条件下误码率随信噪比变化的曲线从而直观地看到编码带来的“编码增益”。Simulink建模的核心思想是“数据流驱动”。每个模块都有输入端口和输出端口数据信号从信源开始按照连接线的方向依次流经各个处理模块最终到达信宿或显示、记录模块。仿真的过程就是Simulink求解器按照我们设定的时间步长一步步计算每个模块在接收到输入数据后所产生的输出数据。理解这一点至关重要因为它决定了模块的采样时间、信号维度的匹配以及缓存处理等细节。我们的系统具体蓝图如下信源 (Bernoulli Binary Generator)产生随机的二进制比特流。卷积编码器 (Convolutional Encoder)对信源比特流进行编码产生码率更高的编码比特流。BPSK调制器 (BPSK Modulator Baseband)将二进制比特0/1映射为基带符号1/-1。AWGN信道 (AWGN Channel)对调制后的信号添加加性高斯白噪声模拟实际信道损伤。BPSK解调器 (BPSK Demodulator Baseband)对含噪信号进行硬判决或软判决恢复出二进制比特流对于硬判决或软信息对于软判决。维特比译码器 (Viterbi Decoder)利用解调器输出的比特流或软信息根据卷积码的约束关系最大似然地译码出原始信息比特。误码率计算 (Error Rate Calculation)对比译码器输出的比特与信源原始比特计算误码率。显示与工作区记录 (Display To Workspace)实时显示误码率并将数据保存到MATLAB工作区用于后续绘图分析。同时为了进行对比我们需要一个并行的、不经过编码的“参考支路”。这条支路从信源直接连接到BPSK调制然后经过相同的信道和解调最后与原始信源比特进行误码率计算。这样我们就能在同一张图上画出“未编码BPSK”和“卷积码BPSK”两条性能曲线。3. 模块详解与关键参数配置打开Simulink新建一个模型。我们从库浏览器中拖拽所需的模块。这里的关键不是拖进来而是如何正确配置它们。下面我逐一拆解。3.1 信源Bernoulli Binary Generator这个模块在Communications Toolbox / Sources路径下。它生成独立的、服从伯努利分布的二进制随机序列。Probability of a zero通常设置为0.5以保证信源等概信息熵最大。Initial seed随机数种子。这是一个非常重要的参数为了进行公平的对比“编码支路”和“未编码支路”必须使用完全相同的随机信源序列。因此你需要为两个信源模块设置相同的种子值比如12345。如果种子不同两条支路比较的就是不同的数据结果没有意义。Sample time采样时间决定了每个比特的持续时间。对于基带仿真我们通常关心的是符号/比特的个数而不是绝对时间。可以设为1表示每个仿真时间步输出一个比特。更关键的是**Samples per frame**。Samples per frame每帧的样本数。这是提高仿真效率的关键Simulink处理帧数据比处理标量数据快得多。我们将它设置为一个较大的数比如1000或10000。这意味着模块每次会输出一个长度为1000的比特向量而不是一个一个地输出比特。后续所有模块都需要支持帧处理并注意帧长度的传递。3.2 卷积编码器Convolutional Encoder该模块位于Communications Toolbox / Error Detection and Correction / Convolutional。Trellis structure网格结构。这是定义卷积码的核心参数。它必须是一个MATLAB的poly2trellis函数生成的结构体。例如对于码率1/2约束长度K3生成多项式为g1 [1 1 1],g2 [1 0 1]八进制表示为7, 5的卷积码我们需要在MATLAB命令行先定义trellis poly2trellis(3, [7 5]);然后在模块参数框里填入trellis。poly2trellis的第一个参数是约束长度第二个参数是生成多项式矩阵。这一步是将教科书上的生成多项式转化为Simulink能识别的内部结构。Operation mode操作模式。选择Continuous。在连续模式下编码器会在每一帧结束时保持其内部状态寄存器内容并在下一帧开始时继续使用该状态。这对于处理长数据流是必要的。如果选择Truncated或Terminated则每帧独立编码会引入额外的尾比特开销或状态重置在性能仿真中通常不这么用。Reset port通常不勾选。我们不需要在仿真中间重置编码器状态。注意编码器的输入是信源产生的帧如1000个信息比特输出则是1000 * (1/码率) 2000个编码比特的帧。帧结构被保持。3.3 BPSK调制与解调器两者均在Communications Toolbox / Modulation / Digital Baseband Modulation / PM下BPSK是相移键控的一种特例。调制器 (BPSK Modulator Baseband)Phase offset (rad)相位偏移通常设为0。Output data type输出数据类型。选择double以保证计算精度。它简单地将输入比特0映射为1比特1映射为-1。解调器 (BPSK Demodulator Baseband)Phase offset (rad)必须与调制器一致设为0。Decision type判决类型。这是影响性能的关键Hard decision硬判决。直接根据接收信号的符号正或负判决为0或1。输入是double型的实数值输出是0/1比特。这种方式会丢失信道可靠性信息。Approximate log-likelihood ratio近似对数似然比软判决。输出不再是0/1而是一个double型的软信息值其绝对值大小反映了判决的可靠程度值越大越可靠。维特比译码器如果接收软信息可以获得约2-3dB的额外增益。因此如果我们要连接软判决维特比译码器这里必须选择此项。Variance source方差来源。当选择软判决时需要指定噪声方差。通常选择Dialog parameter然后在Noise variance中填入一个值。这里有个大坑这个方差应该是信道噪声的方差即N0/2双边功率谱密度的一半。但在我们的链路中这个值最好通过计算动态传入而不是写死。一个常见的做法是先不填在模型中用其他方式计算后输入。关于信号功率归一化BPSK调制后符号能量Es通常被归一化为1。因为对于比特01和比特1-1其能量都是(1)^2 1和(-1)^2 1。因此平均符号能量Es 1。由于码率R k/n 1/2那么每信息比特的能量Eb Es / R 2。这个关系在设置AWGN信道参数时会用到。3.4 AWGN信道模块路径Communications Toolbox / Channels / AWGN Channel。这是仿真的核心也是参数最容易出错的地方。Mode模式。选择Signal to noise ratio (Eb/No)。这是我们最常用的方式直接指定每信息比特的能量与噪声功率谱密度的比值。Eb/No (dB)信噪比。这是我们仿真时要扫描的变量。比如我们可以从0:1:10逐个仿真。在模型中我们可以先设一个初始值如5。更优雅的方式是使用MATLAB工作区变量例如在模型初始化脚本中定义EbNo_dB 5;然后在这里填入EbNo_dB。Number of bits per symbol每个符号的比特数。对于BPSK这里是1。注意这个参数是用于计算Es/No的。模块内部会根据Es/No Eb/No 10*log10(bits per symbol)来换算。因为我们用的是Eb/No模式且BPSK下bits per symbol1所以Es/No Eb/No。但如果用了其他调制如QPSKbits per symbol2这里就需要改。Input signal power (watts)输入信号功率。这里要填1。为什么因为我们的BPSK调制器输出的符号能量Es已经归一化为1即平均功率为1。模块会根据这个功率和指定的Eb/No值计算出需要添加的噪声功率。Symbol period (s)符号周期。在基带等效仿真中这个参数不影响噪声功率的计算因为噪声功率谱密度N0是通过Eb/No和Eb推导的。通常设为1即可。Complex noise复噪声。对于实信号的BPSK取消勾选添加实噪声。对于QPSK等复信号则需要勾选。重要计算原理假设我们设置Eb/No 5 dB输入信号功率Es 1。模块内部会进行以下计算将Eb/No (dB)转换为线性值EbNo_lin 10^(5/10) ≈ 3.1623。计算每信息比特能量Eb。由于我们给了Es1且bits per symbol1对于编码支路Eb Es / R 1 / 0.5 2线性值。但请注意AWGN模块并不知道编码码率R。它默认Eb Es / (bits per symbol)。因此在编码支路如果我们希望噪声功率是基于Eb每信息比特能量计算的我们需要手动调整Input signal power。一个更通用的方法是始终让AWGN模块工作于Es/No模式并自己计算Es/No。更推荐的做法将Mode改为Signal to noise ratio (Es/No)。然后对于未编码支路Es/No (dB) Eb/No (dB)。对于编码支路Es/No (dB) Eb/No (dB) 10*log10(1/R)。其中R是码率1/210*log10(1/0.5)3 dB。这意味着在相同的Eb/No下编码支路的Es/No要高3dB因为它的符号承载了更少的信息比特能量需要分摊到两个编码符号上。这样设置两个支路的AWGN信道模块的Input signal power都可以设为1BPSK符号功率逻辑更清晰。3.5 维特比译码器Viterbi Decoder模块路径Communications Toolbox / Error Detection and Correction / Convolutional。Trellis structure必须与编码器的网格结构完全相同填入同一个trellis变量。Decision type判决类型。必须与BPSK解调器的输出匹配如果解调器是Hard decision这里选Unquantized实际上对于硬判决的0/1输入Unquantized和Hard Decision都可以但Unquantized更通用。如果解调器是Approximate log-likelihood ratio软输出这里必须选Soft Decision并指定Number of soft decision bits例如3或8。这个参数决定了软信息的量化精度。位数越多性能越接近理论值但计算量也越大。通常3位就能获得大部分软判决增益。Soft input port当Decision type选Soft Decision时此端口出现。需要将解调器输出的软信息实数值转换到译码器期望的整数输入范围。通常需要一个增益模块来调整。例如对于3比特软判决输入范围是0-7。假设解调器输出LLR值正数对应比特0负数对应比特1且绝对值大小表示可靠性。我们可以通过一个线性变换y (LLR * 缩放因子 偏移量)然后取整将其映射到0-7。缩放因子的设置需要一些经验或理论计算。Traceback depth回溯深度。这是维特比算法的一个重要参数通常设为约束长度的5到10倍。对于K3的卷积码设为32或35是一个典型值。深度太浅会影响译码性能太深则增加延迟和存储开销但性能提升有限。Operation mode操作模式。与编码器对应选择Continuous。Reset port通常不勾选。3.6 误码率计算器Error Rate Calculation模块路径Communications Toolbox / Comm Sinks(旧版本) 或Communications Toolbox / Statistics。Receive delay接收延迟。对于维特比译码器由于存在回溯深度其输出相对于输入有固定的延迟Traceback depth个符号。这个参数必须正确设置否则误码率计算会对齐错误的比特延迟值等于译码器的回溯深度Traceback depth。例如如果回溯深度是35那么这里就填35。对于未编码支路延迟为0。Computation delay计算延迟。通常设为0表示从第一个数据开始比较。Output data选择Port这样它会输出一个三维向量[Ber, ErrCount, TotalBits]到示波器或工作区。Stop simulation可以设置当总比特数达到某个值或错误数达到某个值时停止仿真以节省时间。3.7 系统同步与帧处理这是Simulink建模中极易出错的地方。由于我们使用了帧处理必须确保整个链路上信号的帧长度和采样时间保持一致。信源产生N个比特的帧。编码器输入N帧输出N/R帧。帧长度变了但输出仍是一个帧。调制器输入N/R个比特的帧输出N/R个符号的帧。帧长度不变。AWGN信道输入N/R个符号的帧输出同样长度的帧。解调器输入N/R个符号的帧输出N/R个比特硬判决或软信息的帧。译码器输入N/R个比特/软信息的帧输出N个比特的帧。帧长度恢复。误码率计算将译码器输出的帧有延迟与信源原始帧经过相应延迟对齐比较。关键检查点使用Simulink的Signal Dimensions和Sample Time Colors显示功能在菜单栏Display下。确保连接线旁边显示的数字帧长度符合预期并且没有出现不匹配的错误提示。确保整个链路是单一的采样时间通常显示为一种颜色没有意外的多速率转换问题。4. 模型搭建、仿真脚本与性能曲线绘制4.1 完整Simulink模型搭建根据上述模块和说明搭建如下图所示的双支路对比模型。图中应清晰显示两条并行的链路上方为卷积码编码支路下方为未编码参考支路。两个信源使用相同的Initial seed。两个AWGN信道模块均设置为Es/No模式其中编码支路的Es/No值通过一个加法器EbNo_dB 10*log10(1/R)输入。误码率计算器的输出连接到Display模块以便实时查看同时也通过To Workspace模块命名为BER_Coded和BER_Uncoded将数据保存到MATLAB工作区。此处为模型结构描述实际操作中需在Simulink中搭建[信源 Bernoulli] - [卷积编码器] - [BPSK调制] - [AWGN信道 (Es/No EbNo3dB)] - [BPSK解调 (软输出)] - [增益/量化] - [维特比译码器 (软判决)] - [误码率计算 (DelayTrDepth)] | 原始信源比特 --------------------------------------------------------------------------------------------------------------- [延迟对齐] - [误码率计算 (Delay0)] | [信源 Bernoulli (同种子)] - [BPSK调制] - [AWGN信道 (Es/No EbNo)] - [BPSK解调 (硬判决)] - [误码率计算 (Delay0)]4.2 编写MATLAB仿真脚本我们不会在Simulink界面手动更改Eb/No值跑很多次。最佳实践是编写一个MATLAB脚本用循环来自动化这个过程。% 初始化参数 clear; close all; EbNo_dB_range 0:1:10; % 信噪比扫描范围 numFrames 1000; % 每个信噪比下仿真的帧数 frameSize 1000; % 每帧的信息比特数与信源模块设置一致 R 1/2; % 卷积码码率 tracebackDepth 35; % 与Viterbi译码器设置一致 % 定义卷积码网格结构 trellis poly2trellis(3, [7 5]); % 预置数组存储结果 BER_Coded zeros(length(EbNo_dB_range), 1); BER_Uncoded zeros(length(EbNo_dB_range), 1); % 加载Simulink模型假设模型已保存为ConvCode_BPSK.slx model ConvCode_BPSK; load_system(model); % 设置模型参数帧大小、网格结构、回溯深度等 set_param([model /Bernoulli Binary Generator], SamplesPerFrame, num2str(frameSize)); set_param([model /Convolutional Encoder], TrellisStructure, trellis); set_param([model /Viterbi Decoder], TrellisStructure, trellis, TracebackDepth, num2str(tracebackDepth)); % 设置误码率计算器的延迟 set_param([model /Error Rate Calculation_Coded], ReceiveDelay, num2str(tracebackDepth)); % 循环仿真每个信噪比点 for idx 1:length(EbNo_dB_range) EbNo_dB EbNo_dB_range(idx); fprintf(Simulating at Eb/No %.1f dB...\n, EbNo_dB); % 计算编码支路所需的 Es/No (dB) EsNo_dB_Coded EbNo_dB 10*log10(1/R); % 对于R1/2加3dB % 将信噪比参数设置到模型工作区 % 方法1使用set_param直接设置模块参数如果模块参数对话框里填的是变量名 % 方法2使用Simulink.SimulationInput对象更现代、灵活 simIn Simulink.SimulationInput(model); simIn simIn.setVariable(EbNo_dB, EbNo_dB, Workspace, model); simIn simIn.setVariable(EsNo_dB_Coded, EsNo_dB_Coded, Workspace, model); % 设置仿真停止时间。由于使用帧处理我们可以按帧数来停止。 % 总比特数 numFrames * frameSize 仿真时间可以设得足够大或使用Stop模块。 % 这里假设模型内通过一个计数器当误码率计算器累计的TotalBits达到目标值时触发Stop。 % 更简单的方式设置一个固定的仿真时间保证能跑完足够多的帧。 simTime numFrames * frameSize * 1e-3; % 一个粗略估计实际需调整 simIn simIn.setModelParameter(StopTime, num2str(simTime)); % 运行仿真 simOut sim(simIn); % 从仿真输出中提取误码率数据 % 假设To Workspace模块输出的变量名是BER_Coded_Data和BER_Uncoded_Data % 它们是一个Nx3的矩阵最后一行的第一个元素就是平均误码率。 dataCoded simOut.get(BER_Coded_Data); dataUncoded simOut.get(BER_Uncoded_Data); if ~isempty(dataCoded) BER_Coded(idx) dataCoded(end, 1); % 取最终的平均BER end if ~isempty(dataUncoded) BER_Uncoded(idx) dataUncoded(end, 1); end % 如果误码率已经很低例如1e-6可以提前跳到下一个点节省时间 if BER_Coded(idx) 1e-6 BER_Uncoded(idx) 1e-6 fprintf( BER very low, moving on.\n); end end % 仿真结束关闭模型不保存 close_system(model, 0); % 绘制性能曲线 figure; semilogy(EbNo_dB_range, BER_Uncoded, b-o, LineWidth, 1.5, DisplayName, Uncoded BPSK); hold on; semilogy(EbNo_dB_range, BER_Coded, r-s, LineWidth, 1.5, DisplayName, (2,1,3) Convolutional Code BPSK); grid on; xlabel(Eb/No (dB)); ylabel(Bit Error Rate (BER)); title(Performance of Convolutional Code over AWGN Channel); legend(Location, best); % 可以添加理论曲线作为参考例如未编码BPSK的理论BER为0.5*erfc(sqrt(EbNo_lin)) EbNo_lin 10.^(EbNo_dB_range/10); theory_BER_uncoded 0.5 * erfc(sqrt(EbNo_lin)); semilogy(EbNo_dB_range, theory_BER_uncoded, k--, DisplayName, Theory (Uncoded BPSK)); hold off;4.3 结果分析与解读运行上述脚本后你会得到一张误码率曲线图。理想情况下你应该看到未编码BPSK曲线与理论曲线基本吻合在高信噪比区域误码率随信噪比提升而急剧下降。卷积码BPSK曲线在低信噪比区域由于编码引入了冗余码率1/2有效信息速率减半在相同的Eb/No下其性能可能比未编码系统更差这称为“编码开销”或“门限效应”。但当信噪比超过某个“交叉点”后编码系统的性能将显著优于未编码系统两条曲线之间的垂直距离在同一误码率水平下就是编码增益。对于(2,1,3)软判决维特比译码在BER1e-5处编码增益大约在4-5 dB左右。如果曲线出现异常比如编码性能比未编码还差很多或者曲线非常平缓请按以下步骤排查检查信源同步确保两个支路的信源使用了相同的随机种子。检查AWGN信道设置确认Es/No的计算是否正确特别是编码支路是否加了10*log10(1/R)。检查译码器延迟误码率计算器中的Receive delay是否等于维特比译码器的Traceback depth。这是最常见的错误之一会导致比特错位误码率接近0.5。检查软判决链路如果使用软判决确认BPSK解调器输出的是Approximate LLR维特比译码器设置为Soft Decision并且软信息到整数输入的映射增益模块是否合理。一个简单的测试方法是暂时改用硬判决看性能是否恢复正常趋势。检查帧长度传递使用信号维度显示确保整个链路中没有意外的标量/向量转换或帧长度不匹配。增加仿真量对于低误码率如1e-5的点需要仿真足够多的比特通常要求错误比特数100才能得到统计上可靠的结果。增加numFrames或frameSize。5. 进阶探讨与性能优化5.1 硬判决 vs. 软判决前面的配置我们使用了软判决。你可以轻松地在模型中修改BPSK解调器和维特比译码器的设置将其改为硬判决链路。重新运行仿真后对比两条曲线你会清晰地看到软判决带来的额外增益大约2-3 dB。这是牺牲一定计算复杂度需要处理多比特软信息换取的性能提升在实际系统设计中需要权衡。5.2 约束长度与码率的影响尝试修改卷积码的网格结构。例如将约束长度从3改为5或7生成多项式也需要相应改变例如poly2trellis(5, [23 35])代表一个经典的(2,1,5)码。重新仿真你会发现性能提升更长的约束长度意味着更复杂的网格和更强的纠错能力在中等至高信噪比下性能更好。译码复杂度飙升维特比译码器的状态数呈2^(K-1)增长K5时有16个状态K7时有64个状态。译码延迟和计算量大幅增加。门限效应更复杂的码可能在低信噪比时性能更差。你也可以尝试其他码率如2/3或3/4的穿孔卷积码。这需要在编码器和译码器中配置穿孔模式。穿孔码在保持近似纠错能力的同时提高了频谱效率是实际通信标准如Wi-Fi LTE中的常用技术。5.3 仿真加速技巧蒙特卡洛仿真非常耗时尤其是跑低误码率点。以下是一些加速技巧并行计算如果拥有Parallel Computing Toolbox可以使用parfor循环并行仿真不同的信噪比点。变步长仿真在低信噪比区域高误码率不需要仿真太多比特就能得到稳定结果。可以写一个自适应循环当错误比特数达到一定数量如200就停止该点的仿真。在高信噪比区域则需要设定一个最大仿真比特数上限避免单点仿真时间过长。使用sim函数的加速模式sim函数有Accelerator或Rapid Accelerator模式可以显著提升仿真速度尤其是在模型结构固定、仅参数变化时。简化模型关闭所有不必要的显示模块如Scope将Display模块的更新频率调低使用To Workspace保存数据而非实时显示。5.4 从Simulink到实际实现的思考Simulink仿真完美地验证了算法原理和系统性能。但要将它转化为实际的硬件如FPGA或软件如嵌入式C代码还需要考虑定点量化仿真中使用double浮点数而硬件中必须使用定点数。需要分析每个模块尤其是软判决解调和维特比算法中的路径度量计算所需的字长和动态范围进行定点化设计并评估量化带来的性能损失。时序与流水线Simulink是数据流模型而硬件设计是时钟驱动的。需要将帧数据流拆解为连续的时钟周期操作并插入流水线寄存器以提高吞吐量。资源与功耗维特比译码器尤其是软判决、长约束长度的译码器是资源消耗大户。需要权衡性能、资源和功耗。通过这个完整的Simulink仿真项目你不仅掌握了卷积码性能评估的工具和方法更建立了一套从理论分析、建模仿真到结果验证的完整工程思维流程。下次当你看到一篇论文中的性能曲线时你完全可以自己动手用Simulink复现甚至优化它。本文还有配套的精品资源点击获取