极化码List-Fast-SSC解码器的高效硬件排序架构设计
1. 项目概述与背景在无线通信系统的核心信道编码扮演着确保信息可靠传输的基石角色。简单来说它就像给要寄出的珍贵包裹信息加上一层层防撞泡沫冗余校验位即使运输途中遭遇颠簸信道噪声和干扰收件人也能根据泡沫的完整情况准确还原出包裹里的物品。从3G时代的Turbo码到4G广泛采用的LDPC码编码技术的每一次演进都直接推动了通信速率和可靠性的跃升。而极化码Polar Codes的出现无疑是这个领域的一个里程碑。它不仅在理论上被严格证明是首个能够达到香农极限的信道编码方案更因其结构上的优雅和可证明的优越性被正式采纳为5G增强移动宽带场景中控制信道的编码标准。极化码的解码尤其是其高性能的实现方案是将其理论优势转化为实际系统增益的关键。连续消除列表解码Successive Cancellation List, SCL算法是目前的主流选择它通过同时保留L条例如L8或16最有可能的候选解码路径极大地逼近了最大似然解码的性能有效解决了基础连续消除解码在有限码长下性能不足的问题。为了进一步提升吞吐量Fast-SSCFast Simplified Successive Cancellation算法被引入它识别并跳过了解码树中那些对应信息位全冻结或全信息位的特殊节点直接进行计算避免了大量冗余的递归操作。然而当我们试图将List-Fast-SSC算法映射到实际的硬件如ASIC或FPGA上构建一个高吞吐量、低延迟的解码器时一个看似简单却异常关键的环节成为了性能瓶颈路径度量排序。在SCL解码的每一步我们都需要从2L条扩展路径每条现有路径产生两条新路径对应比特0和1中筛选出度量值最优的L条路径予以保留。这个“筛选最优”的过程本质上就是一个对2L个数据进行排序并取前L个的问题。当L增大时传统的基于比较的排序网络如冒泡排序、归并排序的硬件化实现其比较器数量和关键路径延迟会急剧增加消耗大量的芯片面积和功耗并严重制约时钟频率的提升。因此设计一个专为List-Fast-SSC解码场景优化的高效排序架构绝非简单的算法移植而是决定整个解码器能否满足5G乃至未来6G苛刻的吞吐率与能效指标的核心硬件设计挑战。本文将深入拆解这一挑战分享从算法特性分析到硬件架构创新的完整设计思路与实现细节。2. List-Fast-SSC解码中排序问题的深度剖析要设计高效的硬件排序架构首先必须透彻理解排序操作在List-Fast-SSC解码流程中的具体行为、特点与约束。这不同于通用的软件排序库我们需要在硅片面积、时序和功耗的严格限制下完成特定模式的高频次运算。2.1 排序操作的上下文与特性在SCL解码器中每条路径都维护着一个路径度量值Path Metric, PM通常基于对数似然比LLR计算值越小代表路径越可靠。每当解码到一个信息比特或Fast-SSC中的一个特殊节点组时每条存活路径都会进行“分裂”根据当前比特判决为0或1的可能性生成两条子路径并更新其PM值。于是瞬间我们就有了2L条待选路径。排序的目标是迅速找出其中PM值最小的L条淘汰掉另外L条。这个排序问题具有几个鲜明的硬件导向特征数据规模固定且较小输入数据量固定为2L如16 32输出为前L个最小元素。这远小于通用处理器需要处理的数据集使得定制化硬件设计成为可能且必要。高频次触发排序操作并非一次性完成。在解码一个码字的过程中每次遇到信息比特或等效的信息节点都需要执行一次。对于一个长度为N1024的极化码其信息位数量K可能在500以上这意味着排序模块会被调用数百次。关键路径延迟敏感解码器的吞吐率通常由“处理一个码字所需的时间”决定。而排序操作往往是解码数据通路中最慢的环节之一。排序模块的延迟直接影响到系统所能运行的最高时钟频率从而对吞吐率产生决定性影响。比较操作密集传统排序算法如冒泡排序、插入排序需要O(L²)级别的比较器。在硬件中比较器由逻辑门如异或门、与或非门构成其数量直接影响模块的面积和功耗。2.2 传统排序网络的硬件代价分析在硬件设计中排序通常通过排序网络来实现。经典的比特onic排序网络或奇偶归并排序网络虽然结构规整、易于流水线化但其比较器数量约为 O(L log² L)。当L16时这已经是一个不小的开销。更常用的是一种基于“冒泡排序”思想的简化硬件结构一个由比较-交换单元构成的阵列。例如要对2L32个数据进行排序并取前L16个一种直观的实现是使用一个16宽度的“优胜者保持”阵列。新来的32个数据与当前阵列中的16个数据进行比较和交换经过多轮操作后阵列中保留的就是最小的16个。这种方法的问题在于为了确保结果正确需要的比较轮次多时序路径长。注意在硬件描述语言中一个“比较-交换”单元通常表现为一个条件赋值语句。如果设计为纯组合逻辑那么一个包含多级比较-交换的链式结构其逻辑深度会非常深导致建立时间过长严重限制时钟频率。如果采用时序逻辑打拍流水虽然能提高频率但会引入额外的流水线延迟可能不符合解码器整体的控制流需求。2.3 Fast-SSC引入的新考量Fast-SSC算法进一步改变了排序操作的场景。它不再对每个比特进行排序而是对一个个“节点”进行解码。一个节点可能对应多个比特。例如一个“Rate-1”节点全信息比特或一个“Rate-0”节点全冻结比特的解码不需要路径分裂因此也不需要排序。而一个“SPC”节点则需要更复杂的内部计算但最终输出到路径管理模块时仍然可能涉及多条路径的度量更新与筛选。这意味着在List-Fast-SSC解码器中排序模块的调用不再是均匀的。它会经历突发性的工作负载在解码简单节点时空闲在解码复杂节点时被密集调用。这种特性启示我们排序架构不一定需要持续运行在最高性能状态或许可以采用一种“按需启动、快速完成”的触发式设计或者其内部可以设计成支持不同数据宽度的配置以适应不同节点解码后产生的不同数量的候选路径有时可能少于2L条。3. 高效排序架构的核心设计策略针对上述分析一个面向List-Fast-SSC解码的高效排序架构不能简单地套用教科书上的排序算法。它需要从算法、数据流和电路层面进行协同优化。下面介绍几种经过实践验证的核心策略。3.1 两阶段度量排序策略这是解决硬件排序瓶颈的一个经典且有效的思路。其核心思想是将一次复杂的、大规模的排序分解为两次或多次更简单的、小规模的排序操作从而降低单次操作的硬件复杂度和延迟。第一阶段局部排序与筛选。当2L条新路径的度量值产生后我们不直接对这2L条数据进行全局排序。而是先将它们分成若干组。例如将2L32条路径分成4组每组8条。在每组内部我们用一个小型、快速的排序网络比如基于比较器树的最小值查找逻辑找出该组内度量值最小的若干条比如4条。这样我们从每组8条中选出了4条“优胜者”4组共产生16条候选路径。这个阶段淘汰掉了每组中明显较差的路径32-1616条。第二阶段全局合并排序。将第一阶段产生的16条候选路径它们来自不同组组内已部分有序输入到一个规模更小的全局排序网络中。这个网络只需要对16条数据进行排序并最终输出全局最小的L8条路径。由于输入数据量从32减少到16并且输入数据已经具备一定的有序性来自各组的前列这个全局排序网络可以设计得更简单、更快。优势分析延迟降低两个小规模排序网络的级联延迟通常远低于一个大规模排序网络的单次延迟。特别是当使用树形结构时延迟是对数级别的。面积优化多个小规模排序模块的总面积有可能小于一个大规模排序模块。因为排序网络的复杂度增长是非线性的。灵活性局部排序的组数和每组筛选出的数量可以作为设计参数进行调节以在延迟、面积和排序精度淘汰是否过于激进之间取得平衡。3.2 基于部分排序的“锦标赛”架构另一种高效的硬件排序思路是模仿体育比赛的淘汰赛制即“锦标赛排序”或“树形比较排序”。这种架构特别适合找出前L个最小或最大值而不需要完整的全排序。架构工作原理构建比较树将2L个输入数据作为叶子节点。每两个数据配对通过一个比较器决出一个“较小值”优胜者。这些优胜者进入下一轮再次两两比较。如此层层晋级最终在树根会得到一个全局最小值。提取最小值并更新树根输出的就是当前2L个数中的最小值。将其输出并记录。关键的一步是将这个最小值所在的叶子节点位置用一个“极大值”或一个无效标记替换。然后只从该叶子节点到树根路径上的比较器重新进行计算。由于树的其他分支结果未变这次重新计算的速度非常快。迭代输出前L个重复步骤2每次都能快速得到当前剩余数据中的最小值。经过L次迭代就能得到前L个最小的数据。硬件实现要点存储需要寄存器阵列来存储所有叶子节点的当前值。比较器阵列构建一个静态的、多层的比较器网络。每一层的比较器都是并行的。控制逻辑需要一个状态机来控制迭代次数并在每次输出最小值后根据索引找到对应的叶子节点并进行数据替换与路径重算。优势与挑战优势延迟确定。输出第一个最小值需要O(log(2L))的延迟后续每个最小值的输出延迟更短仅路径重算。结构规整易于流水线化。挑战需要额外的逻辑来追踪每个比较结果对应的数据索引以支持最小值替换和路径更新。当L较大时控制逻辑和互连复杂度会增加。3.3 增强型度量排序与近似排序在一些对绝对精度要求不是极端苛刻但对吞吐量和能效要求极高的场景可以考虑近似排序策略。思想我们不一定需要绝对精确的前L个最小值。如果能够以极高的概率筛选出“足够好”的L条路径对最终解码性能的影响微乎其微那么就可以大幅简化硬件。一种实现方法——阈值筛选法计算2L个路径度量的一个统计值例如平均值、中位数或某个分位数。设定一个动态阈值如平均值加上一个小的偏移量。将所有度量值低于该阈值的路径直接选出。如果选出的路径数M大于等于L则只需对这个M条路径进行排序取前L即可此时M通常只比L略大排序规模小。如果M小于L则再从剩余路径中补充。计算阈值和比较操作可以非常快速、并行地完成。另一种方法——分组量化比较将路径度量值的范围划分为几个粗粒度的区间。首先比较数据所属的区间优先从更优区间值更小的区间选取路径。只有在同一区间内的数据才需要进行精确比较。这相当于一个两级的比较过程第一级是粗略的、并行的区间判断可以快速淘汰大量数据。实操心得近似排序是一把双刃剑。在算法仿真阶段必须结合具体的极化码参数码长、码率、列表大小L和信道条件大量评估近似排序带来的误码率性能损失。通常在中等至高信噪比下性能损失可以控制在0.1dB以内这对于许多应用是可以接受的。而换来的面积和功耗收益可能是20%-30%这在移动设备芯片设计中意义重大。4. 具体硬件实现与优化技巧有了高层策略接下来需要将其转化为可综合的硬件描述语言代码。这里以两阶段排序策略为例阐述一些关键的实现细节。4.1 模块划分与接口定义一个完整的排序模块通常包含以下子模块输入缓冲单元接收来自路径度量计算单元的2L个PM值及其对应的路径标识符。局部排序单元实现第一阶段的分组筛选。可以实例化多个相同的小型排序子模块。全局排序单元实现第二阶段的最终排序。控制状态机协调数据流控制排序的开始、阶段切换和结果输出。输出寄存单元锁存最终排序选出的L条路径的PM值和路径ID并输出给路径管理模块。接口信号通常包括时钟clk、复位rst_n、数据有效输入data_valid_i、2L个PM值输入pm_i[2L-1:0]、2L个路径ID输入path_id_i[2L-1:0]、排序完成标志sort_done_o、L个PM值输出pm_o[L-1:0]以及对应的L个路径ID输出path_id_o[L-1:0]。4.2 局部排序单元的硬件实现假设采用分组策略将32个数据分为4组每组8个每组选出前4个。module local_sort_8to4 ( input wire clk, input wire rst_n, input wire [7:0] pm_in [7:0], // 8个输入PM值 input wire [PATH_ID_WIDTH-1:0] path_id_in [7:0], // 对应的8个路径ID input wire start_i, output reg [3:0] valid_o, output reg [7:0] pm_out [3:0], output reg [PATH_ID_WIDTH-1:0] path_id_out [3:0] ); // 使用寄存器存储输入和中间结果 reg [7:0] pm_reg [7:0]; reg [PATH_ID_WIDTH-1:0] id_reg [7:0]; // 比较器网络这里可以采用一个简单的排序网络例如小型冒泡排序的硬件展开。 // 为了追求速度可以展开成多级流水线。 always (posedge clk or negedge rst_n) begin if (!rst_n) begin // 初始化... end else if (start_i) begin // 第一级比较对(pm_reg[0], pm_reg[1]), (pm_reg[2], pm_reg[3])... 并行比较交换 // 第二级比较跨组比较... // ... 经过若干级固定的比较交换后前4个寄存器中存储的就是最小的4个值。 // 将结果赋值给输出端口 pm_out[0] pm_reg[0]; path_id_out[0] id_reg[0]; // ... 赋值其他3个输出 valid_o 4b1111; end else begin valid_o 4b0000; end end // 具体的比较-交换逻辑可以用组合逻辑always块或generate语句实现 // 例如一个比较-交换单元 // if (pm_a pm_b) {out_a, out_b} {pm_a, pm_b}; else {out_a, out_b} {pm_b, pm_a}; // 同时需要交换对应的path_id。 endmodule在实际实现中为了获得高频率这个8选4的排序网络通常会被完全展开成组合逻辑然后用寄存器在中间打拍形成2-3级流水线。这样每个时钟周期都能开始处理一组新数据吞吐量高。4.3 全局排序单元的硬件实现全局排序单元的输入是4个局部排序单元输出的16个候选数据。它需要从中选出最终的8个最小值。由于输入数据已经部分有序每个局部模块的输出是其输入的前4小全局排序的压力小了很多。一种高效的实现是采用“合并排序”的硬件变体。可以将16个数据视为4个有序序列每个序列4个元素然后进行多路归并。第一步两两归并。将4个序列两两配对用一个小型比较器网络如4选2分别从每对序列中选出最小的2个元素形成2个新的、更长的有序序列每个序列8个元素这里需要仔细设计以保持输出数量。更常见的做法是直接进行多路选择。第二步决赛圈选择。设计一个“前8名选择网络”。这个网络可以基于一个更大的比较器树。因为输入是16个输出是8个我们可以设计一个逻辑它不进行全排序而是能排除掉明显最大的8个。这可以通过锦标赛结构实现第一轮比较后每个“失败者”很可能但不绝对是较大的值可以结合第二轮结果进行更精确的筛选。为了简化也可以直接实例化一个优化过的16输入、8输出的排序网络。虽然规模比32输入小但仍需精心设计以减少关键路径。module global_sort_16to8 ( input wire clk, input wire rst_n, input wire [15:0] local_valid_i, // 来自4个局部模块的有效信号 input wire [7:0] pm_in [15:0], input wire [PATH_ID_WIDTH-1:0] path_id_in [15:0], output reg [7:0] pm_out [7:0], output reg [PATH_ID_WIDTH-1:0] path_id_out [7:0], output reg done_o ); // 使用一个多级的比较-交换网络。 // 可以用parameter定义网络结构用generate语句生成多层比较器。 // 例如第一层16个数据两两比较产生8个优胜者和8个失败者。 // 第二层对8个优胜者再两两比较... 同时对第一层的8个失败者之间也可能需要比较并与第二层的失败者交叉比较以确保最终得到全局前8。 // 这是一个经典的“前K名”选择网络设计问题可以使用如“双调排序前K段”或自定义的比较网络。 // 关键路径优化将多级比较用寄存器隔开形成流水线。 reg [7:0] pm_stage1 [15:0]; reg [PATH_ID_WIDTH-1:0] id_stage1 [15:0]; // stage1 logic... always (posedge clk) begin // 第一级比较结果锁存 pm_stage1 ...; id_stage1 ...; end reg [7:0] pm_stage2 [15:0]; reg [PATH_ID_WIDTH-1:0] id_stage2 [15:0]; // stage2 logic... always (posedge clk) begin // 第二级比较结果锁存 pm_stage2 ...; id_stage2 ...; end // ... 可能还需要stage3 // 最终从最后一级寄存器中提取前8个作为输出 always (posedge clk) begin pm_out[0] pm_stageN[0]; // ... done_o (current_state OUTPUT_STATE); end endmodule4.4 关键优化技巧资源复用与流水线平衡比较器复用在局部排序和全局排序中比较器是主要资源。确保比较器的位宽与PM值的位宽匹配避免不必要的资源浪费。如果PM值动态范围固定可以考虑使用饱和运算或定点数表示来减少位宽。流水线深度权衡排序模块的流水线越深能达到的最高时钟频率越高但数据从输入到输出的延迟也越大。需要与解码器其他模块如LLR计算单元、路径更新单元的流水线深度相匹配避免成为整体控制流的瓶颈。通常需要协同仿真找到吞吐率最高的平衡点。门控时钟与使能信号排序模块并非每个时钟周期都工作。在Fast-SSC解码中遇到无需排序的节点时排序模块应被关闭以节省功耗。使用时钟门控单元或数据路径使能信号来动态关闭模块内部寄存器的翻转。基于FPGA的优化如果目标平台是FPGA需要关注比较器本质上是算术比较如何映射到FPGA的查找表和专用进位链上。有时将多个小比较器合并成更宽的比较操作可能更利于FPGA综合器的优化。5. 性能评估与常见问题排查设计完成后必须进行严格的性能评估和验证。这不仅包括功能正确性更重要的是评估其时序、面积和功耗是否满足目标要求。5.1 性能评估指标功能正确性通过大量的随机测试向量与一个软件参考模型如C/C或Python实现的精确排序的结果进行比对确保在所有 corner case 下如输入数据有相等值、极端大/小值硬件输出与软件结果一致。时序性能关键路径延迟使用综合工具如Synopsys Design Compiler for ASIC, Vivado Timing Analyzer for FPGA进行静态时序分析。确保排序模块内部最长的组合逻辑路径满足目标时钟周期要求。重点关注比较器树的深度。吞吐率衡量排序模块每秒钟能处理多少组数据。如果模块是全流水线的吞吐率等于时钟频率。如果是迭代式的吞吐率 时钟频率 / 处理一组数据所需的周期数。整体解码器吞吐率将排序模块集成到完整的List-Fast-SSC解码器中在目标频率下仿真统计解码一个码字所需的总周期数从而计算出解码吞吐率如 Mbps。面积与功耗面积综合后报告的总单元面积或FPGA上的LUT、寄存器、DSP占用数量。排序模块通常是解码器中面积最大的模块之一。功耗通过仿真活动因子结合综合后的网表进行功耗分析如使用PrimeTime PX。关注动态功耗它与数据翻转率和时钟频率成正比。5.2 常见问题与调试技巧时序违例现象静态时序分析报告建立时间Setup Time违例关键路径在排序网络的深层。排查查看时序报告定位关键路径上的具体单元。通常是某一条链上的连续比较器太多。解决插入流水线寄存器在比较器网络中间插入寄存器将长组合逻辑链打断。这是最有效的方法但会增加延迟。逻辑重构检查比较器网络结构看是否有更平衡的树形结构可以替代。例如将线性比较改为二分比较树。手动布局约束对于ASIC设计可以对关键路径上的单元施加位置约束让它们靠得更近以减少线延迟。功能错误排序结果不稳定或错误。现象仿真时输出结果偶尔与参考模型不符特别是在输入数据有重复值时。排查检查比较器逻辑确保比较-交换单元在两个输入相等时有确定的、一致的行为例如保持原顺序或按索引排序。不稳定的比较会导致结果不可预测。检查数据路径与索引路径的同步在交换PM值时必须同步交换对应的路径ID。任何时钟或使能信号的不同步都会导致ID与PM值错配。仿真波形调试在出现错误的时刻抓取所有中间节点的波形与软件模型每一步的中间结果对比定位第一个出现差异的地方。功耗过高。现象功耗分析报告显示排序模块动态功耗占比异常高。排查检查活动因子。排序模块在非工作时段其输入是否还在变化内部寄存器是否还在无谓地翻转解决完善门控时钟确保在sort_enable信号无效时排序模块的时钟被有效关断。冻结输入数据当模块空闲时其输入端口应保持为常数值避免输入信号跳变引起内部组合逻辑的毛刺功耗。操作数隔离如果部分逻辑在特定阶段不需要可以插入与门将其输入置零防止信号传播。与解码器整体集成后的性能不达预期。现象排序模块单独测试性能良好但集成到解码器后整体频率上不去或吞吐率低于计算值。排查接口握手排序模块与上下游模块路径度量计算、路径管理的握手协议valid/ready是否设计正确是否存在反压导致排序模块经常停滞流水线气泡由于Fast-SSC节点类型多变排序模块的启动可能不是连续的导致流水线中出现“气泡”降低了整体效率。需要考虑是否可以通过缓冲或动态调度来平滑工作负载。内存访问冲突排序模块输出结果后路径管理模块需要读取和写入路径内存。如果内存端口有限可能成为新的瓶颈。需要分析整体数据流图。实操心得排序架构的设计是一个典型的面积-速度-功耗折衷过程。没有“最好”的方案只有“最合适”的方案。对于追求极限吞吐量的基站侧解码器可能倾向于采用深度流水线、高并行度的两阶段排序即使面积大一些。而对于功耗敏感的终端侧解码器则可能采用迭代次数稍多但面积和功耗更优的锦标赛排序或近似排序。在项目初期用高级语言如C建立可配置的排序架构模型并与解码算法仿真器集成快速评估不同排序方案对整体误码率和吞吐量的影响是避免后期硬件返工的关键步骤。