Altifigence Academy

31 / 37 · 概念

乘加流水线与数据对齐

按寄存器边界划分运算,使数据、valid 与辅助操作数属于同一事务。

从计算表达式划分为两个阶段

先修知识:signed 算术、非阻塞非阻塞赋值 时序 RTL 中以 <= 表示的赋值。先计算右侧,再预约更新,使同一边沿的各寄存器能够依据旧状态计算。了解更多赋值、setupsetup 捕获时钟边沿之前,输入数据必须保持稳定的最短时间。违反建立时间就无法保证存储结果。了解更多 条件与 valid 信号。

设每个输入事务包含 signed 八位 a、b,以及 signed 十六位 c,结果为下式。这是独立处理每个事务的乘加,而不是累加器。

y=a×b+cy=a\times b+c

八位乘法的精确结果需要十六位。再加 c 时,若先按十六位计算再扩宽,就无法恢复已丢失的高位。必须先把两个操作数都符号扩展为十七位,再相加。

第一级同时存储乘积与 c,第二级将同一事务的两个值相加。若不延迟 c,就会错误地把上一事务的乘积与当前事务的 c 混合。

SystemVerilog
module multiply_add_pipeline (
    input  logic               clk, rst, in_valid,
    input  logic signed [7:0]  a, b,
    input  logic signed [15:0] c,
    output logic               out_valid,
    output logic signed [16:0] y
);
    logic v1;
    logic signed [15:0] p1, c1;
    logic signed [16:0] p_ext, c_ext;
    assign p_ext = {p1[15], p1};
    assign c_ext = {c1[15], c1};

    always_ff @(posedge clk) begin
        if (rst) begin
            v1        <= 1'b0;
            out_valid <= 1'b0;
        end else begin
            v1        <= in_valid;
            out_valid <= v1;
            if (in_valid) begin
                p1 <= a * b;
                c1 <= c;
            end
            if (v1) y <= p_ext + c_ext;
        end
    end
endmodule

本接口假设每个边沿都能接收输入,接收方也始终能接收输出。out_valid=0 时不比较 y。即使不复位复位 将状态恢复为规定初值的控制。必须同时规定其同步或异步性质,以及相对于其他控制的优先级。了解更多数据寄存器寄存器 存储多位状态的电路。本课程中的同步寄存器在时钟边沿存储指定输入。了解更多,只要初始化 valid,就能区分不应使用的数据。

区分“两级”与观察时刻

下表在每个边沿接受输入,并记录紧接边沿之后的寄存器状态。A、B 表示不同事务。

边沿接受的输入第一级输出寄存器
E0AA 的乘积与 cinvalid
E1BB 的乘积与 cA 的结果,valid
E2无invalidB 的结果,valid
E3无invalidinvalid

A 的结果在 E1 之后准备好。同一时钟下的后级电路在 E2 采样它,因此从输入接受 E0 到输出接收 E2 是两个周期。解释延迟时,不要混淆输出寄存器变化时刻与后级接收时刻。

每列记录一个上升沿上升沿 时钟从 0 变为 1 的瞬间。它不同于表示整个 CLK=1 区间的电平。了解更多的观察结果。输入取自边沿前,名称带 after 的状态取自更新后。列的排列表示采样顺序,并非描绘物理传播延迟传播延迟 从输入变化到输出稳定为正确值所需的时间。逻辑表达式等价与时间特性是两回事。了解更多。事务为 A=(2,3,10)、B=(4,5,100)。第一级同时存储乘积与 c,下一边沿将上一阶段的对应值相加。破折号表示 invalid 区间。

乘积与 c 必须属于同一事务
查看波形数据
波形数据:每个字符表示一个区间,点表示保持前一状态,p 表示一个时钟周期。
信号波形总线值
edge2345E0 → E1 → E2 → E3
accepted234.A → B → -
product1 after234.6 → 20 → -
c1 after234.10 → 100 → -
y after2345- → 16 → 120 → -
out_valid after01.0

划分流水线能快多少?

考虑一个简化模型:乘法延迟 3.2ns,加法延迟 1.1ns,寄存器开销 0.2ns。这些数值只是计算假设。

Tone≥3.2+1.1+0.2=4.5 nsT_{\mathrm{one}}\ge3.2+1.1+0.2=4.5\ \mathrm{ns}
Tpipe≥max⁡(3.2,1.1)+0.2=3.4 nsT_{\mathrm{pipe}}\ge\max(3.2,1.1)+0.2=3.4\ \mathrm{ns}

最大频率上界由约 222MHz 变为约 294MHz。两级不保证吞吐率翻倍;周期由最慢一级与寄存器开销决定,实际结果还取决于综合、布局与约束。

按事务验证

接受输入时,将整数参考模型的 a×b+c 放入队列。在接收到输出 valid 的边沿,弹出队首预期值并比较。插入 in_valid=0 区间,检查空泡是否与数据一起移动。每个事务大幅改变 c 的模式,容易暴露延迟遗漏。

延伸阅读:MIT OpenCourseWare — Performance Measures

自己试试

连续施加事务 A=(a=3,b=-4,c=10)、B=(a=2,b=5,c=100)。求正确输出顺序,以及不延迟 c、直接加当前输入 c 时,A 可能产生的错误结果。

阅读解释

正确结果为 A:-12+10=-2;B:10+100=110。若 A 的乘积位于第二级时,当前 c 已是 B 的 100,就会得到 88。即使 valid 延迟正确,操作数未对齐也无法避免这个错误。

你的选择适用于此浏览器,可随时在页脚更改。