
简介这份文档面向通信工程、无线通信课程学习者和CDMA系统入门者聚焦扩频通信中两类核心序列——m序列与Walsh码的原理与生成方法帮助读者理解码分多址中扩频码的设计逻辑与正交性来源。压缩包内为1个doc文件约355KB集中整理了Walsh码由Hadamard矩阵重排生成的过程、64阶Walsh序列在前向链路中的信道分配与码片速率说明并附有Matlab生成函数代码涵盖Paley序、Walsh序及逆Walsh序的变换矩阵构造同时讲解m序列的线性移位寄存器结构与反馈系数、起始状态对序列的影响并延伸至Gold序列的模2加生成思路。内容还讨论了多径与小区间异步导致的实际非正交及多址干扰问题适合作为扩频序列理论学习与仿真实现的参考。目前已有636人学习下载。1. 正交的幻觉为什么 Walsh 码在纸面上完美在空口里翻车扩频序列里有两个名字几乎绕不开m 序列和 Walsh 码。前者靠线性移位寄存器滚出 2^n−1 的伪随机长周期后者靠 Hadamard 矩阵的行正交性把 64 条前向信道硬生生塞进同一段频谱。教科书给它们的评价都很漂亮——正交、低互相关、抑制多址干扰。但真正在链路预算里踩过坑的人都知道Walsh 码的正交性只在「同步」这个前提下成立一旦多径延迟到达、邻区信号异步混入那点正交性立刻打折MAI 不会归零。这个反直觉的落差恰恰是理解扩频序列设计动机的入口正交不是物理属性而是一个需要被工程条件兜住的约定。搞懂 m 序列怎么产生、Walsh 矩阵怎么从 Hadamard 矩阵重排出来、Gold 序列为什么要在 m 序列之上再叠一层才能明白 CDMA 里码分多址到底「分」的是什么。下面从生成机制一路拆到矩阵重排的源码细节。2. m 序列n 级移位寄存器如何滚出 2^n−1 的周期2.1 反馈系数决定序列起始状态只决定起点m 序列的全称是最长线性移位寄存器序列结构上就是一个 n 级移位寄存器加一条模 2 加法的反馈抽头。每个时钟沿寄存器整体左移一位最右端补入的新比特由若干级输出异或得到。这里有个容易被混淆的分工反馈系数的组合决定这条序列「是不是」m 序列、周期有多长起始状态只决定你从这条周期序列的哪个相位开始读。换句话说反馈多项式选错了再怎么换初值也滚不出最长周期。n 级寄存器最多有 2^n 种状态全零状态是吸收态异或永远得零所以理论上限是 2^n−1。能跑满这个上限的反馈抽头对应的是本原多项式。常见的实现思路是查本原多项式表而不是现场枚举——n 稍大一点枚举空间就爆炸了。# n 级 m 序列发生器taps 为本原多项式对应的反馈抽头位置1-based def m_sequence(n, taps, seed, length): state seed ((1 n) - 1) # 截断到 n 位防止初值越界 if state 0: raise ValueError(全零初值是吸收态永远输出 0) out [] for _ in range(length): out.append(state 1) # 取最低位作为输出码片 fb 0 for t in taps: # 对抽头位置做模 2 加 fb ^ (state (t - 1)) 1 state (state 1) | (fb (n - 1)) # 右移并回填反馈位 return out这段逻辑里taps就是反馈系数的位置集合seed是起始状态length控制输出长度。关键在最后一行右移之后把反馈位塞进最高位等价于「左移补反馈」的镜像写法两种写法在文献里都常见读别人代码时别被方向绕晕。state 1取的是当前最低位所以输出序列的相位和 seed 强相关——同一个本原多项式、不同 seed得到的是同一条周期序列的不同平移。2.2 自相关双值特性为什么它像噪声又不像噪声m 序列被当作伪随机噪声序列用核心依据是它的自相关函数只有两个取值零延迟处为 1归一化后其余延迟处为 −1/(2^n−1)。这个「接近零但不等于零」的旁瓣是它和理想白噪声的区别也是它在同步捕获里能用的原因——接收端滑动本地序列做相关只有对齐那一刻相关峰才陡然立起来其余位置都被压得很低。互相关方面同一本原多项式不同相位之间的互相关同样很低但不同本原多项式产生的两条 m 序列之间互相关峰值可能并不理想。这就是优选对概念的由来并非任意两条 m 序列都适合拿来做码分多址的地址码得挑互相关峰值满足门限的那一对。Gold 序列正是建立在这个前提上——取一对优选对模 2 加得到一族序列族内任意两条的互相关都受控。提示判断一条序列是不是 m 序列别只看周期长度还要验证它在一个周期内 0 和 1 的个数差 1、游程分布符合预期。周期对但统计特性不对多半是反馈抽头选成了非本原多项式。3. Walsh 码Hadamard 矩阵到 Walsh 矩阵的重排逻辑3.1 正交性来自矩阵行不来自生成公式Walsh 码的正交性根源在 Hadamard 矩阵一个由 1 和 −1 构成的方阵任意两行内积为零。直接把 Hadamard 矩阵的行拿来当扩频码其实已经正交了那为什么还要「重排」因为 Hadamard 矩阵的自然行序也叫 Paley 序下相邻行的交变次数符号翻转次数并不随行号单调增长。而实际系统关心的是「序号小的码交变次数少」——交变次数少意味着码片变化慢对载波同步误差和滤波失真更宽容。Walsh 序就是把行按交变次数重新排列让 W0 全为 1、W1 交变一次、W2 交变两次……依次递增。这个重排不是随便排的它对应一个确定的置换。源码里用三个矩阵把这条链路拆得很清楚Hp是 Paley 序矩阵Wg是 Walsh 序矩阵Hm是逆 Walsh 序矩阵Ep、Eg、Em则是记录置换关系的变换矩阵。理解这段代码的关键是看懂「用位操作算出行号映射」这件事。3.2 源码拆解位操作如何完成行号置换function X walshf1(N) N ceil(log2(N)); H hadamard(2^N); % 生成 2^N 阶 Hadamard 矩阵Paley 序 Hp zeros(2^N); Ep zeros(2^N); Wg zeros(2^N); Eg zeros(2^N); E eye(2^N); % 第一段把 H 的行按 Paley 序映射到 Hp for n 1:2^N p 0; for i 1:N p bitset(p, i, bitget(n-1, N-i1)); % 位序反转 end Hp(p1, :) H(n, :); Ep(p1, :) E(n, :); end % 第二段按交变次数规则把 Hp 重排成 Walsh 序 Wg for n 1:2^N g 0; g bitset(g, N, bitget(n-1, N)); % 最高位直接继承 for i 2:N if bitget(n-1, N-i1) 0 g bitset(g, N-i1, bitget(g, N-i2)); else g bitset(g, N-i1, 1 - bitget(g, N-i2)); end end Wg(g1, :) Hp(n, :); Eg(g1, :) Ep(n, :); end % 第三段再反转一次位序得到逆 Walsh 序 Hm for n 1:2^N m 0; for i 1:N m bitset(m, i, bitget(n-1, N-i1)); end Hm(m1, :) Wg(n, :); Em(m1, :) Eg(n, :); end X Wg; % 返回 Walsh 序矩阵第一段的bitset(p, i, bitget(n-1, N-i1))做的是位序反转把行号 n−1 的二进制位从高到低倒过来写。这一步把 Hadamard 矩阵的自然行序转成 Paley 序Ep同步记录这个置换方便后续反查「Walsh 序第 k 行对应原始第几行」。第二段是核心g的每一位由前一位更高位和当前输入位共同决定规则是「输入位为 0 则继承为 1 则取反」。这实际上是在按 Gray 码的思路累加交变次数——相邻 Walsh 序行号之间只差一个符号翻转位置所以交变次数单调递增。第三段再反转一次位序得到逆 Walsh 序Hm和Em是给需要反向映射的场景准备的。参数上N进来先被ceil(log2(N))规整成 2 的幂次所以传 64 得到 64 阶传 60 也会被抬到 64 阶。X Wg是最终返回的 Walsh 序矩阵行号从 1 开始对应 W0 到 W(2^N−1)。如果只想要矩阵不关心置换关系Ep、Eg、Em可以省掉但排查「某个 W 码对应哪条原始 Hadamard 行」时这三个矩阵就是后悔药。3.3 64 阶 Walsh 与前向信道的对应关系CDMA 前向链路用 64 阶 Walsh 序列每个 W 序列固定分配给一种前向物理信道W0 到 W63 一共 64 条码片速率 1.2288 Mc/s。这个数字不是随手定的1.2288 Mc/s 的码片速率配合 64 阶正交码正好把一条 1.25 MHz 带宽的载波切成 64 个正交子信道每个子信道承载一路低速业务或控制信息。码分多址的「分」在前向链路上分的就是这 64 条 Walsh 码——基站侧所有信道同时发射靠码的正交性在接收端解扩时彼此分离。但这里埋着第 1 章说的那个坑正交性要求所有 Walsh 码在接收端严格码片对齐。基站发出去的 64 路信号在时间上是同步的可一旦经过多径信道某条路径延迟了几个码片到达它携带的 Walsh 码和本地解扩用的 Walsh 码就不再逐位对齐内积不再为零MAI 就漏进来了。邻区信号更是完全异步正交性从源头上就不成立。所以实际系统里 Walsh 码负责的是「同小区同步信道之间的正交」跨小区和抗多径得靠别的机制兜底。4. Gold 序列为什么要在 m 序列之上再叠一层模 2 加4.1 优选对模 2 加换来的是一整族可控互相关的码单条 m 序列的互相关特性依赖优选对可选数量有限。Gold 序列的做法是取一对周期和速率相同的 m 序列优选对把其中一条循环移位后与另一条模 2 加移位量取遍一个周期就得到一族序列。族内任意两条序列的互相关峰值被限制在一个三值集合内不会随码数量增加而恶化。这个性质对码分多址至关重要——地址码数量要够多同时任意两条地址码之间的干扰要可控Gold 序列正好卡在这个平衡点上。从实现角度看Gold 序列发生器就是两个并行的 m 序列发生器加一个模 2 加法器移位量通过改变其中一条序列的初值相位来选。硬件代价比单独维护一张大码表低得多这也是它在实际系统里被广泛采用的原因之一。4.2 m 序列、Walsh、Gold 三者的分工把三者放在一起看分工其实很清楚m 序列提供长周期、类噪声的伪随机特性适合做扰码和同步Walsh 码提供严格正交的行集合适合做信道化把同一小区的多路信号分开Gold 序列提供数量足够、互相关受控的码族适合做地址码区分不同用户或不同小区。很多系统里这三者是叠加使用的——先 Walsh 信道化再加扰码扰码往往就来自 m 序列或 Gold 序列。理解这个分层比单独记住每个序列的定义有用得多。序列核心性质典型角色关键约束m 序列周期 2^n−1双值自相关扰码、同步、PN 生成反馈抽头须为本原多项式Walsh 码行间严格正交前向信道化依赖码片级同步Gold 序列族内互相关三值受控地址码、区分用户/小区需先有 m 序列优选对5. 避坑与排查扩频序列实现里最容易翻车的几处5.1 现象m 序列周期对但统计特性不对原因多半是反馈抽头选成了非本原多项式寄存器跑进了一个短循环。解决方式是拿本原多项式表核对抽头位置或者直接验证一个周期内 1 的个数是否为 2^(n−1)不对就换抽头。5.2 现象Walsh 矩阵生成后某两行内积不为零先查阶数是否被ceil(log2(N))悄悄抬过——传了非 2 的幂次矩阵维度变了行号对应关系全乱。再查重排循环里bitset的位序方向N-i1和i写反会导致置换错位矩阵看着像那么回事正交性却崩了。5.3 现象仿真里 MAI 明明该为零却压不下去检查多径模型是否引入了非整数码片延迟。只要延迟不是码片周期的整数倍Walsh 码的正交性就破了这时候该看的是接收端有没有做多用户检测或均衡而不是回头怀疑矩阵生成代码。5.4 现象Gold 序列互相关峰值超标大概率是两条源 m 序列不构成优选对。优选对的互相关峰值有明确门限随便拿两条 m 序列模 2 加族内互相关可能远超预期。换优选对或者退一步用别的码族。注意Walsh 序和逆 Walsh 序的矩阵不要混用。Wg和Hm行序不同拿Hm的行号去索引信道解扩出来的结果是错的而且错得很隐蔽——因为矩阵本身仍然正交。6. 设计取舍正交是约定不是物理定律回到最开始那个落差。Walsh 码的设计动机是在同步前提下用最小的实现代价换取信道间的完全正交——Hadamard 矩阵天然存在重排只是行序调整硬件上就是查表和异或代价极低。这个取舍成立的条件写得很清楚码片对齐。一旦条件不满足正交性不是「减弱」而是从根上不成立因为内积为零的推导每一步都依赖逐位对齐。m 序列的取舍在另一头用线性反馈换长周期和低自相关旁瓣代价是互相关特性依赖本原多项式和优选对的挑选不能随便组合。Gold 序列则是在 m 序列的基础上用「多一条移位序列加一个模 2 加法器」的代价换来一整族互相关受控的码把地址码数量的问题一次性解决。三者没有谁更先进只有各自兜住了哪一段工程约束。验证一套扩频序列实现是否可信我一般会走三步先验单条序列的周期和统计特性再验矩阵行间内积是否严格为零最后把序列丢进带多径和异步邻区的链路模型里看 MAI 的实际量级。前两步过不了是代码问题第三步过不了是模型问题两者别混为一谈。源码里那三个置换矩阵Ep、Eg、Em看着冗余真到排查行号映射对不上的时候就是唯一的后悔药——从那以后我每次改 Walsh 重排逻辑都强制把这三个矩阵打出来对一遍行号再谈性能。希望帮到你。本文还有配套的精品资源点击获取