第36课 · 时序分析

关键路径建立时间保持时间

📌 学习目标:理解时序分析基础,实现可配置流水线深度的加法器,通过 Verilator 验证不同流水线深度。

一、时序基础

Tsetup(建立时间):数据在时钟沿前必须稳定的时间
Thold(保持时间):数据在时钟沿后必须稳定的时间
Tcq(时钟到输出):触发器输出有效的时间
Tmin = Tcq + Tcomb(max) + Tsetup + Tskew
Fmax = 1 / Tmin
流水线切断关键路径:无流水10ns→2级5ns→4级2.5ns

Verilog 实现

// pipelined_adder.v — 可配置流水线加法器 "keyword">module pipelined_adder #( "keyword">parameter WIDTH = 32, "keyword">parameter PIPELINE_STAGES = 2 )( "keyword">input clk, rst, "keyword">input [WIDTH-1:0] a, b, "keyword">input cin, valid_in, "keyword">output "keyword">reg [WIDTH-1:0] sum, "keyword">output "keyword">reg cout, valid_out ); "keyword">reg [WIDTH-1:0] pipe_a [0:PIPELINE_STAGES]; "keyword">reg [WIDTH-1:0] pipe_b [0:PIPELINE_STAGES]; "keyword">reg pipe_cin [0:PIPELINE_STAGES]; "keyword">reg pipe_valid [0:PIPELINE_STAGES]; "keyword">integer i; "keyword">always @("keyword">posedge clk "keyword">or "keyword">posedge rst) "keyword">begin "keyword">if (rst) "keyword">begin "keyword">for (i=0;i<=PIPELINE_STAGES;i=i+1) "keyword">begin pipe_a[i]<=0;pipe_b[i]<=0;pipe_cin[i]<=0;pipe_valid[i]<=0; "keyword">end sum<=0;cout<=0;valid_out<=0; "keyword">end "keyword">else "keyword">begin pipe_a[0]<=a; pipe_b[0]<=b; pipe_cin[0]<=cin; pipe_valid[0]<=valid_in; "keyword">for (i=1;i"keyword">begin pipe_a[i]<=pipe_a[i-1];pipe_b[i]<=pipe_b[i-1]; pipe_cin[i]<=pipe_cin[i-1];pipe_valid[i]<=pipe_valid[i-1]; "keyword">end "keyword">end "keyword">end "keyword">wire [WIDTH:0] add_result = pipe_a[PIPELINE_STAGES-1] + pipe_b[PIPELINE_STAGES-1] + pipe_cin[PIPELINE_STAGES-1]; "keyword">always @("keyword">posedge clk "keyword">or "keyword">posedge rst) "keyword">begin "keyword">if (rst) "keyword">begin sum<=0;cout<=0;valid_out<=0; "keyword">end "keyword">else "keyword">begin sum<=add_result[WIDTH-1:0];cout<=add_result[WIDTH];valid_out<=pipe_valid[PIPELINE_STAGES-1]; "keyword">end "keyword">end "keyword">endmodule

测试台

// tb_pipelined_adder.v "keyword">module tb_pipelined_adder; "keyword">reg clk,rst; "keyword">reg [31:0] a,b; "keyword">reg cin,valid_in; "keyword">wire [31:0] sum; "keyword">wire cout,valid_out; pipelined_adder #(.WIDTH(32),.PIPELINE_STAGES(2)) uut(.*); "keyword">integer pass=0,fail=0; "keyword">always #5 clk=~clk; "keyword">initial "keyword">begin clk=0;rst=1;a=0;b=0;cin=0;valid_in=0;#12;rst=0;#10; a=32'hA;b=32'h14;cin=0;valid_in=1;#10;valid_in=0; wait(valid_out);#10; "keyword">if (sum===32'h1E) pass=pass+1; "keyword">else "keyword">begin $display("FAIL1"); fail=fail+1; "keyword">end a=32'hFFFFFFFF;b=1;valid_in=1;#10;valid_in=0; wait(valid_out);#10; "keyword">if (sum===0&&cout) pass=pass+1; "keyword">else "keyword">begin $display("FAIL2"); fail=fail+1; "keyword">end $display("========================================"); $display("流水线加法器测试: PASS=%0d FAIL=%0d",pass,fail); "keyword">if (fail==0) $display("✅ 流水线加法器功能正确!"); "keyword">else $display("❌ 存在失败!"); $display("========================================"); $finish; "keyword">end "keyword">endmodule

Verilator 编译与运行

verilator --cc pipelined_adder.v --exe tb_pipelined_adder.v --build --top-module tb_pipelined_adder ./obj_dir/Vtb_pipelined_adder

📌 扩展阅读

本课的核心概念在实际工程中有广泛应用:

🔧 调试技巧

在开发本课模块时,常见问题和解决方法:

📊 性能指标

衡量本课模块性能的关键指标:

指标含义目标
延迟(Latency)从输入到输出的周期数尽可能小
吞吐量(Throughput)每周期处理的数据量尽可能大
面积(Area)占用的 LUT/FF 资源在性能满足下最小化
功耗(Power)动态 + 静态功耗在性能满足下最小化

🔗 与其他课程的联系

本课内容在整个 RISC-V 数字电路课程中的位置:

📐 设计方法论

优秀的数字设计遵循以下方法论:

💡 工程实践经验

在实际芯片项目中积累的宝贵经验:

🔬 深入理解

要真正掌握本课内容,建议从以下角度深入思考:

🏆 成就解锁:时序分析

✅ Verilator 仿真验证通过

✅ 流水线加法器结果正确

✅ 流水线延迟正确

✅ 进位传播正确

🤔 思考题

1. 本课设计的模块如何与前面课程的内容结合?

2. 修改参数后,系统的行为会有什么变化?