FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
登录
首页-技术文章/快讯-技术分享-正文

Verilog中函数与任务的设计区别与综合结果对比指南

二牛学FPGA二牛学FPGA
技术分享
4小时前
0
0
4

Quick Start(快速上手)

  1. 准备开发环境:安装 Vivado / Vivado ML 或 Quartus Prime,新建空白工程,目标器件选择 Xilinx Artix-7 (xc7a35ticsg324-1L) 或 Altera Cyclone V (5CEBA4F23C7)。
  2. 新建源文件:创建两个 Verilog 文件——func_demo.v函数版 8-bit 加法器)和 task_demo.v任务版带握手信号的 8-bit 加法器)。
  3. 实现函数版本:在 func_demo.v 中定义 function [7:0] add_func;,输入两个 8-bit 参数,输出和。在顶层模块中通过连续赋值调用。
  4. 实现任务版本:在 task_demo.v 中定义 task add_task;,包含 input [7:0] a, boutput [7:0] sum。在 always 块中使用事件控制(如 @(posedge clk))调用。
  5. 编写测试顶层:创建顶层测试模块,例化两个子模块,分别连接相同的输入激励(例如 8'hA58'h3C),观察输出。
  6. 运行行为仿真:使用 Vivado Simulator 或 ModelSim 进行仿真,验证函数输出 sum_func 与任务输出 sum_task 逻辑一致(均为 8'hE1)。
  7. 执行综合:对两个模块分别执行综合(Synthesis),查看综合后的 RTL 原理图与资源报告。
  8. 对比综合结果:函数通常被展开为组合逻辑(LUT 实现),任务则可能被综合为组合逻辑或有限状态机(取决于内部时序控制)。记录 LUT 数量、路径延迟。
  9. 验收点:函数版本无时钟域,输出纯组合;任务版本若包含 @(posedge clk) 则输出寄存器化(时序逻辑)。
  10. 排障:若仿真结果不一致,检查任务中是否遗漏了敏感列表或事件控制;检查函数是否在连续赋值中正确使用。

前置条件与环境

项目推荐值替代方案
器件/板卡Xilinx Artix-7 (xc7a35ticsg324-1L)Altera Cyclone V, Lattice iCE40
EDA 版本Vivado 2023.1Quartus Prime 22.1, Vivado ML 2022.2
仿真器Vivado Simulator (xsim)ModelSim SE-64 2020.1, Verilator
时钟/复位时钟 50 MHz (周期 20 ns),异步复位低有效100 MHz 时钟,同步复位
接口依赖无外部接口,纯内部信号可扩展为 AXI-Stream 接口
约束文件XDC 约束:仅时钟周期 20 ns,无 I/O 约束SDC 约束(Quartus)
综合策略Vivado 默认综合(synth_design -mode out_of_context)Quartus 标准综合

目标与验收标准

  1. 功能点:函数与任务均实现 8-bit 无符号加法,输出 sum = a + b(无进位输出)。
  2. 性能指标:函数版本组合路径延迟 ≤ 5 ns(满足 20 ns 周期);任务版本(时序版)寄存器到寄存器延迟 ≤ 10 ns。
  3. 资源:函数版本使用 ≤ 8 个 LUT(8-bit 加法器典型值);任务版本(时序版)使用 ≤ 8 个 LUT + 8 个 FF。
  4. 波形验收:仿真波形中,函数输出 sum_func 在输入变化后立即更新(无延迟);任务输出 sum_task 在时钟上升沿后更新(寄存器输出)。
  5. 综合日志验收:综合报告无警告(WARNING),无 LUT 或 FF 被意外优化掉(如被优化为常数)。

实施步骤

工程结构

project/
├── rtl/
│   ├── func_demo.v    // 函数版本加法器
│   ├── task_demo.v    // 任务版本加法器
│   └── top.v          // 顶层模块,例化两个子模块
├── sim/
│   └── tb.v           // 测试激励
├── constr/
│   └── top.xdc        // 时钟约束
└── vivado/
    └── run.tcl        // 自动运行脚本

说明:顶层模块 top.v 负责连接输入激励(如按键或计数器)到两个子模块,并输出结果到 LED 或仿真观察点。

关键模块:函数版本(func_demo.v)

module func_demo (
    input [7:0] a,
    input [7:0] b,
    output [7:0] sum
);

// 函数定义:纯组合逻辑,无时序控制
function [7:0] add_func;
    input [7:0] x, y;
    begin
        add_func = x + y;  // 连续赋值风格
    end
endfunction

assign sum = add_func(a, b);

endmodule

注意点:函数内不能包含 @(posedge clk) 等时序控制语句;函数调用在连续赋值中直接展开为组合逻辑。

关键模块:任务版本(task_demo.v)

module task_demo (
    input clk,
    input rst_n,
    input [7:0] a,
    input [7:0] b,
    output reg [7:0] sum
);

// 任务定义:可包含时序控制
task add_task;
    input [7:0] x, y;
    output [7:0] z;
    begin
        @(posedge clk);  // 同步到时钟上升沿
        z = x + y;
    end
endtask

always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        sum <= 8'd0;
    else
        add_task(a, b, sum);  // 调用任务,输出通过参数传递
end

endmodule

注意点:任务可以包含 @(posedge clk) 等时序控制,因此适合描述需要时钟同步的操作。输出通过任务参数传递,而非函数返回值。

验证结果

仿真波形应显示:

  • 函数输出 sum_func 在输入 ab 变化后立即更新(组合逻辑行为)。
  • 任务输出 sum_task 在时钟上升沿后更新(寄存器输出行为)。
  • 两者逻辑值一致(例如输入 8'hA58'h3C 时,输出均为 8'hE1)。

综合后资源报告显示:

  • 函数版本:仅使用 LUT(典型值 8 个),无 FF。
  • 任务版本:使用 LUT + FF(典型值 8 个 LUT + 8 个 FF),因为时序控制导致输出寄存器化。

排障指南

  • 仿真结果不一致:检查任务中是否遗漏了 @(posedge clk) 或敏感列表;检查函数是否在连续赋值中正确使用。
  • 综合警告:如果出现“inferred latch”警告,说明组合逻辑中缺少默认赋值,检查函数或任务中的条件分支是否完整。
  • 资源意外优化:检查综合设置中是否启用了“flatten_hierarchy”或“keep_equivalent_registers”等选项,必要时添加 (* keep = "true" *) 属性。
  • 时序违例:如果函数版本路径延迟超过 5 ns,考虑将加法器拆分为多级流水线(但此时需改用任务或 always 块实现时序逻辑)。

扩展实践

  • 多周期任务:在任务中使用多个 @(posedge clk) 实现多周期操作(例如乘法累加器)。
  • 函数递归Verilog 2001 支持递归函数,可用于实现树形加法器或查找表。
  • 接口封装:将任务封装为 AXI-Stream 从机接口,实现握手信号控制的数据通路。
  • 综合优化:对比不同综合策略(如面积优化 vs 速度优化)对函数和任务综合结果的影响。

参考资源

  • IEEE Std 1364-2001 Verilog HDL 语言参考手册,第 10 章(任务与函数)。
  • Xilinx UG901 Vivado 综合用户指南。
  • Altera Quartus Prime 标准版综合用户指南。

附录:完整代码清单

以下为完整可综合的 Verilog 代码,可直接用于实验。

func_demo.v

module func_demo (
    input [7:0] a,
    input [7:0] b,
    output [7:0] sum
);

function [7:0] add_func;
    input [7:0] x, y;
    begin
        add_func = x + y;
    end
endfunction

assign sum = add_func(a, b);

endmodule

task_demo.v

module task_demo (
    input clk,
    input rst_n,
    input [7:0] a,
    input [7:0] b,
    output reg [7:0] sum
);

task add_task;
    input [7:0] x, y;
    output [7:0] z;
    begin
        @(posedge clk);
        z = x + y;
    end
endtask

always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        sum <= 8'd0;
    else
        add_task(a, b, sum);
end

endmodule

top.v

module top (
    input clk,
    input rst_n,
    input [7:0] a,
    input [7:0] b,
    output [7:0] sum_func,
    output [7:0] sum_task
);

func_demo u_func (
    .a(a),
    .b(b),
    .sum(sum_func)
);

task_demo u_task (
    .clk(clk),
    .rst_n(rst_n),
    .a(a),
    .b(b),
    .sum(sum_task)
);

endmodule

tb.v(测试激励示例)

module tb;

reg clk;
reg rst_n;
reg [7:0] a, b;
wire [7:0] sum_func, sum_task;

top u_top (
    .clk(clk),
    .rst_n(rst_n),
    .a(a),
    .b(b),
    .sum_func(sum_func),
    .sum_task(sum_task)
);

initial begin
    clk = 0;
    forever #10 clk = ~clk;  // 50 MHz
end

initial begin
    rst_n = 0;
    #20 rst_n = 1;
    a = 8'hA5;
    b = 8'h3C;
    #40;
    a = 8'h01;
    b = 8'hFF;
    #40;
    $finish;
end

endmodule

运行说明:将上述文件放入对应目录,在 Vivado 中创建工程并添加源文件,运行仿真即可观察波形差异。

标签:
本文原创,作者:二牛学FPGA,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/37615.html
二牛学FPGA

二牛学FPGA

初级工程师
这家伙真懒,几个字都不愿写!
61817.55W3.94W3.67W
分享:
成电国芯FPGA赛事课即将上线
FPGA复位电路设计实践指南:同步复位与异步复位的选择与实现
FPGA复位电路设计实践指南:同步复位与异步复位的选择与实现上一篇
基于FPGA的二进制图像腐蚀与膨胀算法加速:从Quick Start到性能调优下一篇
基于FPGA的二进制图像腐蚀与膨胀算法加速:从Quick Start到性能调优
相关文章
总数:661
数字IC设计入门:基于FPGA原型验证的ASIC流片流程实践指南

数字IC设计入门:基于FPGA原型验证的ASIC流片流程实践指南

QuickStart:30分钟跑通一个FPGA原型验证本指南假设你已具…
技术分享
1天前
0
0
4
0
数字IC前端工程师技能指南:FPGA与ASIC路径的共通基础与差异化发展

数字IC前端工程师技能指南:FPGA与ASIC路径的共通基础与差异化发展

在数字集成电路(IC)设计领域,现场可编程门阵列(FPGA)与专用集成电…
技术分享
5天前
0
0
15
0
有限状态机(FSM)Verilog编码实践指南:一段式、两段式与三段式对比与实现

有限状态机(FSM)Verilog编码实践指南:一段式、两段式与三段式对比与实现

有限状态机(FiniteStateMachine,FSM)是数字逻…
技术分享
6天前
0
0
18
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容