3. CORDIC流水线结构设计

任务目标

在迭代式CORDIC中,每次旋转依赖上一次结果,需N个时钟周期才能完成一次向量旋转,吞吐率仅为1/N。本案例设计并实现一个8级流水线CORDIC,每个时钟周期可启动一次新的旋转计算,从而将吞吐率提升至1(即每个时钟周期输出一个结果),并给出与迭代结构的性能对比方法。

设计思路

流水线CORDIC将迭代运算中的每一级旋转固化为独立的组合逻辑级,级间用寄存器暂存中间结果(包括旋转角度余量z和旋转方向判定所需的y符号)。每一级只需执行一次移位加/减法,方向由上一级寄存的y符号决定。由于各级并行工作,不同输入向量处于不同流水级,因此每个时钟周期均可接收新输入并输出一个已完成8次旋转的结果。

关键完整代码

module cordic_pipeline #(
    parameter DW = 16,          // 数据位宽
    parameter N  = 8            // 流水级数(迭代次数)
)(
    input  wire clk,
    input  wire rst_n,
    input  wire [DW-1:0] x_in,
    input  wire [DW-1:0] y_in,
    input  wire [DW-1:0] z_in,  // 目标角度(弧度×2^14,范围[-π/2, π/2])
    output reg  [DW-1:0] x_out,
    output reg  [DW-1:0] y_out,
    output reg  [DW-1:0] z_out
);
    // 反正切常数表(弧度×2^14):atan(2^(-i)),i=0..7
    localparam signed [DW-1:0] ATAN_TABLE [0:N-1] = '{
        16'd51472,  // atan(1)   ≈ 0.7854
        16'd30386,  // atan(0.5) ≈ 0.4636
        16'd16055,  // atan(0.25)≈ 0.2450
        16'd8150,   // atan(0.125)≈0.1244
        16'd4091,   // atan(0.0625)≈0.0624
        16'd2047,   // atan(0.03125)≈0.0312
        16'd1024,   // atan(0.015625)≈0.0156
        16'd512     // atan(0.0078125)≈0.0078
    };

    // 各级流水线寄存器
    reg signed [DW-1:0] x_stage [0:N];
    reg signed [DW-1:0] y_stage [0:N];
    reg signed [DW-1:0] z_stage [0:N];

    integer i;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (i = 0; i <= N; i = i + 1) begin
                x_stage[i] <= 0;
                y_stage[i] <= 0;
                z_stage[i] <= 0;
            end
        end else begin
            // 输入级
            x_stage[0] <= x_in;
            y_stage[0] <= y_in;
            z_stage[0] <= z_in;

            // 流水线各级:第i级执行第i次旋转(i=0..N-1)
            for (i = 0; i < N; i = i + 1) begin
                if (y_stage[i][DW-1] == 1'b0) begin  // y≥0,顺时针旋转
                    x_stage[i+1] <= x_stage[i] + (y_stage[i] >>> i);
                    y_stage[i+1] <= y_stage[i] - (x_stage[i] >>> i);
                    z_stage[i+1] <= z_stage[i] - ATAN_TABLE[i];
                end else begin                        // y<0,逆时针旋转
                    x_stage[i+1] <= x_stage[i] - (y_stage[i] >>> i);
                    y_stage[i+1] <= y_stage[i] + (x_stage[i] >>> i);
                    z_stage[i+1] <= z_stage[i] + ATAN_TABLE[i];
                end
            end

            // 输出级
            x_out <= x_stage[N];
            y_out <= y_stage[N];
            z_out <= z_stage[N];
        end
    end
endmodule

测试平台与性能对比

// 流水线CORDIC测试平台(节选)
module tb_cordic_pipeline;
    reg clk = 0, rst_n = 0;
    reg signed [15:0] x_in, y_in, z_in;
    wire signed [15:0] x_out, y_out, z_out;
    integer cycle_count;
    real x_real, y_real, angle_real;

    cordic_pipeline dut(.*);
    always #5 clk = ~clk;

    initial begin
        // 复位
        #20 rst_n = 1;
        // 输入向量 (x,y) = (10000, 5000),旋转角度 0(仅做向量模式)
        x_in = 16'sd10000; y_in = 16'sd5000; z_in = 0;
        cycle_count = 0;

        // 连续输入8个不同向量,观察输出间隔
        repeat (8) begin
            @(posedge clk);
            x_in <= x_in + 16'sd100;  // 改变输入以观察吞吐
            y_in <= y_in - 16'sd50;
            cycle_count = cycle_count + 1;
        end

        // 等待流水线排空
        repeat (10) @(posedge clk);
        $display("吞吐率验证:每周期输入1个向量,输出连续有效");
        $finish;
    end

    // 计算输出模长与输入模长比值(应接近CORDIC增益1.6467)
    always @(posedge clk) begin
        if (rst_n) begin
            x_real = $itor(x_out) / 16384.0;
            y_real = $itor(y_out) / 16384.0;
            angle_real = $itor(z_out) / 16384.0;
            $display("t=%0t x_out=%0d y_out=%0d z_out=%0d 模长比=%0.4f",
                     $time, x_out, y_out, z_out,
                     $sqrt(x_real*x_real + y_real*y_real) / 
                     ($sqrt(10000.0*10000.0 + 5000.0*5000.0)/16384.0));
        end
    end
endmodule

运行与验证方法

  1. 仿真运行:使用Vivado/ModelSim/Verilator运行上述测试平台。输入向量为(10000, 5000),z_in=0(向量模式)。
  2. 功能正确性判定:观察输出模长与输入模长之比,应在1.6467±0.02范围内(8级迭代的理论增益为∏√(1+2^(-2i))≈1.6467)。z_out应趋近于0(表示旋转完成)。
  3. 吞吐率对比:将本模块与迭代式CORDIC(单次计算需N个时钟)对比——在测试平台中统计:从第一个输入有效到第一个输出有效的时钟周期数(流水线延迟=N=8),以及连续两个输出之间的间隔(应为1个时钟周期)。迭代结构连续输出间隔为N个时钟周期。

性能对比要点

指标迭代结构流水线结构
延迟(首输出)N个周期N个周期
吞吐率(连续输出间隔)N个周期/结果1个周期/结果
资源消耗1级迭代逻辑复用N级迭代逻辑并行
适用场景资源受限、低速率高速连续数据流

验证结论:当测试平台连续输入向量且每个时钟周期均有效时,流水线CORDIC每个时钟周期输出一个有效结果,而迭代结构需要等待N个周期才能完成当前向量才能接收下一个。本设计以N倍逻辑资源换取N倍吞吐率提升,适用于雷达信号处理、OFDM同步等连续高速旋转场景。