
1. 从“正交”说起为什么通信系统需要码片序列如果你接触过CDMA码分多址技术或者研究过扩频通信那么“码片序列”这个词一定不陌生。它听起来有点技术化但背后的核心思想其实非常直观如何在同一个频段、同一段时间里让多个用户同时说话并且彼此互不干扰这就像在一个嘈杂的房间里如何让多组人同时交谈而每组人只能听懂自己同伴的话。答案的关键就在于“正交”。正交是一个数学概念在这里可以简单理解为“互不干扰”。两个正交的序列它们的内积一种特定的运算为零。在通信中这意味着即使两个信号叠加在一起传输接收方只要用对应的正交序列去“解码”就能完美地分离出自己想要的信息而将其他用户的信号视为噪声消除掉。这个用于区分用户、承载信息的正交序列就是“码片序列”。那么如何系统地生成大量性能优良的正交码片序列呢这就引出了两个强大的数学工具沃尔什函数和哈达玛矩阵。它们不是通信工程师的凭空发明而是从数学宝库中借来的利器为现代无线通信的多址接入奠定了坚实的理论基础。很多人可能知道要用它们但未必清楚为什么是它们以及它们之间精妙的联系与差异。今天我们就抛开教科书式的定义从工程实现的视角深入拆解码片序列、沃尔什函数与哈达玛矩阵的原理、生成方法、实际应用中的坑点以及如何在你自己的仿真或项目中灵活运用它们。2. 沃尔什函数在时域上定义的正交波形首先我们得明确一点沃尔什函数是一组在时域上定义的、取值仅为1和-1的完备正交函数集。它最初由数学家沃尔什提出后来被通信领域广泛采用特别是在早期的CDMA标准如IS-95中作为前向信道的扩频码。2.1 核心思想基于过零点序列的构建沃尔什函数的定义方式有很多最直观的一种是基于“过零点序列”或“拉德马赫函数”的乘积来构建。拉德马赫函数R(k, t)是一组在区间[0, 1)内定义的、类似方波的函数其过零点位置由参数k决定。第n个沃尔什函数WAL(n, t)可以通过一组拉德马赫函数的乘积来生成WAL(n, t) ∏ R(k_i, t)其中n的二进制表示中为1的位对应的k_i被选中进行乘积。例如n6的二进制是110那么WAL(6, t) R(2, t) * R(1, t)。这个定义保证了生成的函数在[0,1)区间内是正交的。注意这里的“正交”是指函数在连续时间域上的积分正交。但在数字通信中我们处理的是离散序列。因此我们需要对WAL(n, t)在一个周期内进行等间隔采样得到离散的沃尔什序列。采样点数通常是2的幂次如64、128、256这样才能保证采样后的离散序列仍然保持正交性。2.2 离散沃尔什序列的生成与性质假设我们生成一个长度为N8的沃尔什序列集。我们可以通过哈达玛矩阵下一节会详细讲的行或列来获得但这里我们先理解其本身的性质。一个长度为8的沃尔什序列集包含8个序列每个序列由8个码片chip组成每个码片取值是1或-1。例如W0 [1, 1, 1, 1, 1, 1, 1, 1]W1 [1, 1, 1, 1, -1, -1, -1, -1]W2 [1, 1, -1, -1, 1, 1, -1, -1]W3 [1, 1, -1, -1, -1, -1, 1, 1]... 以此类推。关键性质正交性任意两个不同序列的对应码片相乘再求和即内积为0。例如sum(W0 * W1) 0。双极性取值为1和-1非常适合用BPSK二进制相移键控调制实现简单。平衡性大部分沃尔什序列除了全1的W0中1和-1的个数相等。这个性质有利于信号的直流平衡。自相关与互相关在同步CDMA中所有用户的码片序列对齐沃尔什序列的互相关为零这是理想情况。但它的非周期自相关和互相关性能并不好这意味着在异步CDMA或存在多径时延的场景下干扰会比较大。这是沃尔什码的一个重要局限。2.3 实操心得沃尔什序列的索引与顺序陷阱在仿真或实际编程中一个常见的坑是沃尔什序列的索引n和顺序。不同的文献、不同的代码库如MATLAB的walsh函数、一些开源项目可能采用不同的排序方式。主要有两种按沃尔什序Walsh Order或称为序列序Sequence Order这是基于过零点数量或格雷码顺序排列的看起来“不规则”。按哈达玛序Hadamard Order这是按对应的哈达玛矩阵的行顺序排列的看起来非常规整像我们上面举的例子。如果你在仿真中使用了沃尔什码但结果不对首先应该检查你生成的序列顺序是否与接收端预期的顺序一致。一个可靠的方法是始终使用哈达玛矩阵来生成你需要的沃尔什序列集并明确记录你使用的是哪一行或哪一列。在MATLAB中hadamard(8)生成8阶哈达玛矩阵其每一行除去第一行全1的就可以作为一组沃尔什序列。这避免了顺序混乱的问题。3. 哈达玛矩阵系统化生成正交码的“母体”如果说沃尔什函数提供了理论定义那么哈达玛矩阵就是工程上批量生成正交码片序列的“流水线”。它是一个方阵元素仅为1和-1并且任意两行或两列都是相互正交的。3.1 递归构造法从1阶开始无限扩展哈达玛矩阵的构造非常优美它遵循一个简单的递归公式H(1) [1] H(2) [ 1, 1; 1, -1 ] H(2N) [ H(N), H(N); H(N), -H(N) ]这个公式意味着只要你有了一个N阶的哈达玛矩阵H(N)你就可以通过“复制和取反”的方式轻松构造出2N阶的哈达玛矩阵H(2N)。这为生成任意2的幂次长度的正交序列集提供了极其高效的算法。为什么是2的幂次因为递归构造法天然生成的是2^k阶的矩阵。在通信中序列长度扩频因子通常也选择为2的幂次以便于数字信号处理如使用FFT和系统设计。3.2 哈达玛矩阵与沃尔什序列的关系这是一个核心点规范排序的沃尔什序列集等价于哈达玛矩阵的行或列集合。具体来说将N阶哈达玛矩阵的每一行看作一个长度为N的序列这N个序列就构成了一组正交的沃尔什序列。通常我们会把第一行全1序列对应W0保留作为导频或同步信道其他行分配给不同的用户或信道。因此在工程实践中我们几乎总是通过生成哈达玛矩阵来获得沃尔什序列因为算法简单、确定且易于实现。3.3 代码实现与验证这里提供一个Python示例演示如何通过递归法生成哈达玛矩阵并验证其正交性。import numpy as np def hadamard_matrix(n): 递归生成n阶哈达玛矩阵n必须是2的幂次。 if n 1: return np.array([[1]]) else: h hadamard_matrix(n // 2) return np.block([[h, h], [h, -h]]) # 生成8阶哈达玛矩阵 N 8 H hadamard_matrix(N) print(8阶哈达玛矩阵 H8:) print(H) # 验证正交性任意两行内积为0除了自相关 orthogonal True for i in range(N): for j in range(i1, N): inner_product np.dot(H[i], H[j]) if inner_product ! 0: print(f行{i}和行{j}不正交内积为{inner_product}) orthogonal False if orthogonal: print(所有不同行之间正交性验证通过) # 取第2行和第3行作为两个用户的码片序列索引从0开始 user1_code H[1] # 对应沃尔什序列W1 user2_code H[2] # 对应沃尔什序列W2 print(f\n用户1码片序列: {user1_code}) print(f用户2码片序列: {user2_code}) print(f两序列内积: {np.dot(user1_code, user2_code)})运行这段代码你会看到输出内积为0直观地验证了正交性。在实际的通信系统仿真中这个矩阵的每一行就是你分配给不同逻辑信道的扩频码。4. 深入原理相关性与多址干扰的博弈理解了如何生成这些序列后我们必须深入其核心性能指标相关性。这直接决定了系统抗干扰能力的强弱。4.1 周期相关性与非周期相关性周期互相关当两个序列完全同步即起始点对齐时计算它们在一个周期长度内的内积。对于沃尔什序列来自哈达玛矩阵在完全同步时周期互相关严格为零。这是同步CDMA如IS-95的前向链路的理论基础。基站可以精确控制发给所有用户的信号时间从而利用这一理想特性。非周期互相关当两个序列存在相对时延不同步时计算它们的内积。此时沃尔什序列的非周期互相关值不再为零而且可能会出现较大的峰值。在异步CDMA如反向链路各用户终端发射时间难以绝对同步或多径环境中这就会产生多址干扰MAI。下表对比了理想同步和异步情况下的区别场景序列同步状态互相关特性对系统的影响典型应用场景理想同步严格对齐周期互相关为零无多址干扰容量理论可达上限蜂窝网络下行链路基站到手机、卫星通信下行异步/多径存在时延差非周期互相关非零有峰值产生多址干扰限制系统容量和性能蜂窝网络上行链路手机到基站、Ad-hoc网络4.2 沃尔什码的局限性远近效应与 scrambling正因为沃尔什码的非周期相关性能不佳所以在实际的CDMA系统如CDMA2000、WCDMA中很少单独使用沃尔什码作为唯一的扩频码。它的主要局限在于远近效应敏感如果有一个距离基站很近的用户信号很强而另一个距离远的用户信号很弱即使它们的沃尔什码正交由于非完美同步和多径强信号会对弱信号造成严重的干扰。沃尔什码自身无法抑制这种干扰。序列数量有限长度为N的沃尔什码只能提供N个正交序列。在用户数很多时需要很长的序列这会降低数据速率因为扩频因子变大了。解决方案加扰Scrambling为了解决上述问题现代CDMA系统采用了“正交扩频 伪随机加扰”的两级结构。正交扩频Channelization使用沃尔什码或OVSF码其本质是哈达玛矩阵的另一种排序。这一步的目的是在同一个基站下区分不同的物理信道例如同一个用户的不同业务信道、控制信道、导频信道。因为基站可以控制这些信道的同步所以正交性得以保持。伪随机加扰Scrambling在正交扩频之后再用一个周期很长的伪随机噪声PN序列进行逐码片相乘或异或。这个PN序列是伪随机的具有优良的非周期自相关和互相关特性。加扰的目的有两个 a)区分不同的小区或基站每个基站使用不同相位的PN序列这样即使使用相同的沃尔什码集手机也能区分信号来自哪个基站。 b)将干扰白化将其他用户尤其是其他小区用户的信号干扰近似为白噪声从而抑制远近效应。因为长PN码的互相关特性比沃尔什码好得多。所以完整的扩频过程是用户数据 - 沃尔什码正交扩频区分信道 - 长PN码加扰区分小区/用户抗干扰。5. 超越通信沃尔什-哈达玛变换的应用沃尔什函数和哈达玛矩阵的价值远不止于生成码片序列。它们对应的数学变换——沃尔什-哈达玛变换WHT在信号处理、图像压缩、加密等领域也有广泛应用。5.1 沃尔什-哈达玛变换的本质离散沃尔什-哈达玛变换是傅里叶变换的一种“简化版”。傅里叶变换的基函数是正弦和余弦复指数而WHT的基函数就是沃尔什序列1和-1的方波。因此WHT计算的是信号在一组方波基函数上的投影。其变换矩阵就是哈达玛矩阵或按沃尔什序排列的矩阵。对于一个长度为N2的幂次的离散信号x其WHT变换系数y可以通过矩阵乘法计算y H * x可能需要除以归一化因子sqrt(N)。由于H矩阵的元素只有1和-1这个变换只需要加法和减法不需要乘法计算速度极快。5.2 在图像压缩中的实战案例JPEG XR的基石一个著名的应用是微软的JPEG XR扩展范围图像编码标准。它核心的变换环节就使用了双哈达玛变换。为什么用哈达玛变换计算效率极高相比于JPEG使用的离散余弦变换DCT需要浮点乘加运算哈达玛变换只有加减法在硬件实现上成本极低速度极快特别适合移动设备和实时处理。能量集中虽然能量集中效果不如DCT但对于图像的高频和边缘信息哈达玛变换仍有不错的表现。JPEG XR通过巧妙的编码结构如色彩转换、预测、量化弥补了其压缩效率上的微小差距。无损实现由于变换系数都是整数哈达玛变换可以完全无损地实现这对于需要精确重构的医疗图像或档案存储非常重要。在JPEG XR中的具体步骤简化版将图像分成小块例如4x4。对每个4x4块应用二维哈达玛变换先行变换再列变换或者使用4x4的哈达玛核矩阵。对变换后的系数进行量化和熵编码。你可以用Python简单体验一下import numpy as np from scipy.linalg import hadamard import matplotlib.pyplot as plt # 生成一个简单的4x4图像块这里用随机整数模拟 np.random.seed(42) image_block np.random.randint(0, 256, (4, 4), dtypenp.int16) print(原始4x4图像块像素值:) print(image_block) # 生成4阶哈达玛矩阵 H4 hadamard(4) # scipy的hadamard函数直接返回哈达玛矩阵 # 计算二维WHT: Y H * X * H H是对称的 # 注意为了得到标准变换通常需要除以N这里N4。但JPEG XR中可能有自己的归一化处理。 wht_coeffs H4 image_block H4 print(\n二维沃尔什-哈达玛变换系数:) print(wht_coeffs) # 逆变换忽略量化 X_recon (1/N^2) * H * Y * H image_reconstructed (H4 wht_coeffs H4) / 16 # 因为 H * H N*I 所以逆变换是 H * Y * H / N^2 print(\n逆变换重建的图像块应等于原始块:) print(image_reconstructed.astype(np.int16)) print(f重建误差最大绝对差: {np.max(np.abs(image_block - image_reconstructed))})这个例子展示了WHT变换的可逆性。在实际压缩中wht_coeffs中的许多高频系数值很小经过量化后会变成0从而实现了数据压缩。5.3 在加密与编码中的角色由于哈达玛矩阵的行沃尔什序列具有良好的正交性和伪随机外观它们也被用于一些加密和编码方案中。正交编码在需要抗干扰传输的场合直接将信息比特映射到不同的沃尔什序列上。接收端通过相关器检测哪个序列被发送从而解码信息。这提供了固有的差错检测能力因为非法的序列组合相关性低。作为伪随机序列的组成部分一些复杂的伪随机序列如Gold序列、Kasami序列的生成会用到哈达玛矩阵或与之相关的m序列。6. 工程选型与避坑指南当你需要在项目中使用正交码或相关变换时如何选择以下是一些实战经验。6.1 通信系统OVSF码 vs. 沃尔什码在3G/4G的扩频系统中你更常听到的是OVSF正交可变扩频因子码而不是沃尔什码。它们是什么关系本质相同OVSF码的码树本质上就是通过哈达玛矩阵的递归构造法生成的。码树上的每一个分支节点对应一个哈达玛矩阵的行序列。关键区别在于“可变因子”沃尔什码集通常指固定长度N的所有序列。而OVSF码强调码树结构它允许在同一系统中同时使用不同长度即不同扩频因子的码并且保证这些不同长度的码之间仍然正交只要一个码不是另一个码的祖先节点。这提供了巨大的灵活性可以动态地为不同速率要求的业务分配不同扩频因子的码从而更高效地利用带宽。选型建议如果你的系统是固定速率、固定扩频因子的同步CDMA仿真直接使用哈达玛矩阵的行作为沃尔什码简单有效。如果你的系统需要模拟可变速率业务如WCDMA或者需要动态分配信道化码那么你必须实现一个OVSF码树的管理算法包括码的分配、释放和正交性检查。6.2 信号处理何时选择WHT而非FFT沃尔什-哈达玛变换WHT和快速傅里叶变换FFT是两种不同的分析工具。FFT基于正弦波擅长分析周期性、连续变化的信号能提供精确的频率和相位信息。适用于音频分析、通信解调、振动分析等。WHT基于方波擅长分析跃变、方波类的信号或者当你只关心信号的过零点、电平跳变模式时。计算速度是最大优势。选型决策矩阵考量维度优先选择FFT优先选择WHT信号特性连续变化富含正弦分量方波、脉冲、开关信号所需信息精确频率、相位、频谱跃变位置、序列模式、能量在方波基上的分布计算资源充足有硬件乘法器极其有限嵌入式、MCU需要避免乘法应用场景音频处理、无线通信、频谱分析二进制图像处理、简单加密、低功耗传感器信号处理、JPEG XR类编码实时性要求一般极高一个典型的WHT应用场景在低功耗物联网节点上传感器产生的是开关量或低速数字信号。你需要快速检测信号的特定模式例如一个特定的脉冲序列。使用WHT将一小段信号转换到沃尔什域然后与预先存储的模式模板系数进行简单比较只需加减法可以实现极低功耗的模式识别。6.3 常见陷阱与调试技巧归一化问题在使用哈达玛矩阵进行变换时一定要注意归一化。正向变换通常为y (1/sqrt(N)) * H * x以保证变换是正交的即H^T * H N * I。逆变换则为x (1/sqrt(N)) * H * y。如果忘记归一化虽然可逆但能量关系会出错在压缩或滤波应用中会导致问题。序列同步在通信仿真中如果你用沃尔什码做异步CDMA仿真性能很差是正常的这不是bug是特性。务必加入PN加扰环节并考虑使用更复杂的多用户检测算法如干扰消除来提升性能。生成矩阵的差异scipy.linalg.hadamard(n)生成的是规范形式的哈达玛矩阵第一行和第一列全为1。但有些数学定义或通信标准可能使用其他排列方式例如按格雷码序。务必查阅你所遵循的标准文档确认所需的序列顺序。在存疑时自己实现递归生成函数并固定下来是最可靠的。复数扩展以上讨论的都是实数值1/-1的序列和矩阵。在复数调制如QPSK系统中有时会使用复正交码如4相序列。沃尔什-哈达玛矩阵可以通过H j*H等方式扩展到复数域但其正交性和相关性需要重新评估。7. 从理论到实现一个简单的CDMA链路仿真框架最后我们整合所有知识点搭建一个极简的同步CDMA下行链路仿真框架看看沃尔什码如何在实际中工作。仿真场景一个基站同时向3个用户发送不同的二进制数据。使用长度为8的沃尔什码区分用户。信道理想无噪声、无时延。import numpy as np def generate_data(num_users, num_bits): 为每个用户生成随机的二进制数据0/1。 return np.random.randint(0, 2, (num_users, num_bits)) def bpsk_modulate(bits): BPSK调制0 - 1, 1 - -1。 return 2 * bits - 1 def spread(symbols, spreading_codes): 扩频每个用户的每个符号乘以整个码片序列。 num_users, num_symbols symbols.shape spreading_factor spreading_codes.shape[1] spreaded_signals np.zeros((num_users, num_symbols * spreading_factor)) for u in range(num_users): # 将每个符号重复 spreading_factor 次然后与扩频码逐元素相乘 # 更高效的做法使用外积 (np.outer) for s in range(num_symbols): spreaded_signals[u, s*spreading_factor:(s1)*spreading_factor] symbols[u, s] * spreading_codes[u] return spreaded_signals def combine_signals(spreaded_signals): 在基站端将所有用户的扩频信号叠加功率假设相同。 return np.sum(spreaded_signals, axis0) def despread(received_signal, spreading_codes, spreading_factor): 解扩用每个用户的扩频码与接收信号进行相关运算。 num_users spreading_codes.shape[0] num_symbols len(received_signal) // spreading_factor recovered_symbols np.zeros((num_users, num_symbols)) for u in range(num_users): code spreading_codes[u] for s in range(num_symbols): segment received_signal[s*spreading_factor:(s1)*spreading_factor] # 相关运算点积后除以扩频因子归一化 correlation np.dot(segment, code) / spreading_factor recovered_symbols[u, s] correlation return recovered_symbols def bpsk_demodulate(symbols): BPSK解调正数 - 0, 负数 - 1。 return (symbols 0).astype(int) # 主仿真流程 # 1. 参数设置 num_users 3 num_bits 10 spreading_factor 8 # 扩频因子沃尔什码长度 # 2. 生成哈达玛矩阵作为扩频码集取前num_users行跳过全1的第一行 H hadamard(spreading_factor) # 通常第一行全1的W0用作导频这里我们取第1,2,3行索引0,1,2给三个用户 spreading_codes H[:num_users] # 形状 (3, 8) print(f使用的扩频码沃尔什序列:\n{spreading_codes}) # 3. 生成用户数据 original_bits generate_data(num_users, num_bits) print(f\n原始发送比特:\n用户1: {original_bits[0]}) print(f用户2: {original_bits[1]}) print(f用户3: {original_bits[2]}) # 4. BPSK调制 symbols bpsk_modulate(original_bits) # 5. 扩频 spreaded_signals spread(symbols, spreading_codes) # 6. 信号合成基站发射 combined_signal combine_signals(spreaded_signals) print(f\n合成后的发射信号前20个码片: {combined_signal[:20]}) # 7. 信道传输此处理想无噪声 received_signal combined_signal # 8. 每个用户解扩 recovered_symbols despread(received_signal, spreading_codes, spreading_factor) # 9. BPSK解调 recovered_bits bpsk_demodulate(recovered_symbols) # 10. 验证误码 print(f\n恢复的比特:) for u in range(num_users): print(f用户{u1}: {recovered_bits[u]}) error_count np.sum(original_bits[u] ! recovered_bits[u]) print(f 误比特数: {error_count})运行这个仿真你会看到在理想同步且无噪声的情况下三个用户的比特被完美地恢复出来误码数为0。这直观地演示了沃尔什码在同步CDMA中的核心作用通过正交性在混合信号中无串扰地分离出各自的数据。你可以尝试修改这个仿真加入高斯白噪声观察误码率随信噪比的变化。让用户的发射功率不同模拟远近效应你会发现即使同步由于功率不同在解扩相关运算后强用户对弱用户的“干扰”会以非零相关值的形式体现但实际上在理想正交下不会这是因为我们假设了完美同步。加入微小时延后干扰就会出现。将沃尔什码替换为随机序列对比性能。你会发现没有正交性的随机序列在同步情况下无法分离用户解扩后全是干扰。通过这个从理论到代码的完整旅程你应该对码片序列、沃尔什函数和哈达玛矩阵不再是停留在概念层面而是真正理解了它们从哪里来、为什么有效、在工程中如何实现以及最重要的——它们的局限性和适用的边界。这些知识是深入理解现代扩频通信、多址技术乃至一些特定信号处理应用的基石。下次当你看到相关协议或算法时希望你能一眼认出这些老朋友并清楚它们正在扮演什么角色。