当前位置: 首页 > news >正文

FPGA学习笔记——Verilog中可综合和常见的不可综合的系统函数

目录

一、 明确可综合的系统函数

(1)$signed() 和 $unsigned()

(2)$bits()

 二、 在特定条件下可综合的函数

(1)$clog2()

三、 绝对不可综合的系统函数(常见)

(1)显示与输出函数 ($display, $write, $monitor)

(2)文件输入输出函数 ($fopen, $fdisplay, $fclose)

(3)仿真控制与中断函数 ($stop, $finish)

(4)时间函数 ($time, $realtime)

(5)随机数生成函数 ($random, $urandom)

可综合的系统函数非常少,

只有极少数系统函数被主流综合工具(如 Synopsys Design Compiler, Cadence Genus, Xilinx Vivado, Intel Quartus)支持,因为它们有明确的、可直接映射到硬件逻辑的含义。


一、 明确可综合的系统函数

(1)$signed() 和 $unsigned()

功能:执行数据类型的转换(解释),而不是值的转换。它告诉综合工具将某个线网或变量视为有符号数或无符号数。

综合结果:不会生成任何额外的逻辑电路。它只是一个“注解”,会影响综合工具对算术运算(如比较、加法、乘法)的优化方式。

示例:

module signed_arithmetic (input  wire [7:0]  unsigned_a, unsigned_b, // 无符号输入output wire [7:0]  unsigned_sum,           // 无符号输出output wire [7:0]  signed_sum             // 有符号输出
);// 示例 1A: 将有符号数转换为无符号数(通常不需要显式转换,但演示用法)
assign unsigned_sum = $unsigned($signed(unsigned_a) + $signed(unsigned_b));// 示例 1B: 执行有符号加法并与无符号加法对比
// 关键区别:有符号加法会进行符号扩展,影响进位和结果解释
wire [8:0] signed_extended_sum; // 需要额外一位防止有符号溢出
assign signed_extended_sum = $signed(unsigned_a) + $signed(unsigned_b);
assign signed_sum = signed_extended_sum[7:0]; // 取低8位endmodule

(2)$bits()

功能:返回一个变量或数据类型的位置宽度。

综合结果:综合工具会在编译时预先计算这个值,并将其作为一个常数。它常用于定义参数化的代码。

示例:

module parameterized_shifter #(parameter TYPE = logic [15:0] // 默认数据类型为16位向量
)(input  wire TYPE data_in,input  wire [$clog2($bits(data_in)):0] shift_amount, // 自动计算移位位数宽度output wire TYPE data_out
);// 根据输入数据的位宽进行动态移位
// $bits(data_in)在编译时会被替换为常量(如16)
assign data_out = data_in << shift_amount;endmodule

 二、 在特定条件下可综合的函数

(1)$clog2()

功能:计算一个数的以2为底的对数并向上取整。常用于根据深度计算地址总线的宽度。

综合条件必须在编译时其参数是已知的常数。

示例:

module inferred_rom #(parameter DATA_WIDTH = 8,   // 数据位宽parameter DEPTH       = 1024 // ROM深度(单元数)
)(input  wire [$clog2(DEPTH)-1:0] addr, // 地址线宽度自动计算:10位 (clog2(1024)=10)output reg  [DATA_WIDTH-1:0]    dout
);// 使用二维数组推断ROM
reg [DATA_WIDTH-1:0] memory [0:DEPTH-1];// 使用$readmemh初始化ROM(此initial块在FPGA综合中通常被支持)
initial begin$readmemh("rom_init_data.hex", memory);
endalways @(*) begindout = memory[addr];
endendmodule

三、 绝对不可综合的系统函数(常见)

(1)显示与输出函数 ($display$write$monitor)

用途:在仿真时向控制台打印信息。

module trying_to_print (input  wire        clk,input  wire [7:0]  data_in,output reg  [7:0]  data_out
);always @(posedge clk) begindata_out <= data_in;// 绝对不可综合!硬件没有"屏幕"或"控制台"来显示文字。$display("Time=%0t: data_in=%h, data_out=%h", $time, data_in, data_out);// 同样不可综合$monitor("data_in changed to %h", data_in);
endendmodule

(2)文件输入输出函数 ($fopen$fdisplay$fclose)

用途:在仿真时向文件写入数据。

module fake_file_writer (input  wire        clk,input  wire        valid,input  wire [31:0] data
);integer log_file;initial begin// 不可综合!硬件无法在"上电"时执行"打开文件"操作。log_file = $fopen("output_log.txt", "w");if (!log_file) $finish;
endalways @(posedge clk) beginif (valid) begin// 不可综合!硬件没有文件系统接口来写入数据。$fdisplay(log_file, "Cycle: %0t, Data: %h", $time, data);end
end// 同样不可综合
final $fclose(log_file);endmodule

(3)仿真控制与中断函数 ($stop$finish)

用途:控制仿真过程的暂停和结束。

module dangerous_control (input  wire        clk,input  wire        error_condition
);reg [3:0] counter = 0;always @(posedge clk) begincounter <= counter + 1;if (error_condition) begin// 不可综合!硬件不能"暂停"或"结束"自己的运行。$display("Error occurred at counter = %d", counter);$stop; // 暂停仿真// 或者 $finish; // 结束仿真end
endendmodule

(4)时间函数 ($time$realtime)

用途:获取当前的仿真时间。

module timing_check (input  wire        clk,input  wire        signal_a,input  wire        signal_b
);real setup_time;always @(posedge clk) begin// 不可综合!硬件没有"绝对仿真时间"的概念。if (signal_a && !signal_b) beginsetup_time = $realtime;$display("Setup time started at %t", setup_time);endif (!signal_a && signal_b) begin$display("Setup time was: %t ns", $realtime - setup_time);end
endendmodule

(5)随机数生成函数 ($random$urandom)

用途:在仿真时生成随机测试激励。

module random_generator (input  wire        clk,input  wire        enable,output reg  [7:0]  random_output
);always @(posedge clk) beginif (enable) begin// 不可综合!这会产生非确定性的逻辑。random_output = $random % 256; // 生成0-255的随机数// SystemVerilog版本,同样不可综合// random_output = $urandom_range(0, 255);end
endendmodule

以上就是Verilog中可综合和不可综合的系统函数。(如果有错误,还请大家指出来,谢谢!)

http://www.dtcms.com/a/353028.html

相关文章:

  • 数据结构:从堆中删除元素 (Deleting from a Heap)
  • 使用Spring Boot和EasyExcel导出Excel文件,并在前端使用Axios进行请求
  • linux-优化命令
  • Linux笔记11——shell编程基础-5
  • 使用appium对安卓(使用夜神模拟器)运行自动化测试
  • 解释器模式及优化
  • HIVE的Window functions窗口函数【二】
  • flume监控文件写入 Kafka 实战:解耦应用与消息队列的最佳实践
  • 性能测试-jmeter实战6
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(21):文法+单词第7回3
  • 学习嵌入式的第二十八天——线程
  • 趣味学Rust基础篇(变量与可变性)
  • RCLAMP0504M.TBT电子元器件Semtech 低电容、四通道TVS二极管阵
  • Web漏洞
  • More Effective C++条款12:理解抛出一个异常与传递一个参数或调用一个虚函数间的差异
  • 火焰传感器讲解
  • 函数指针的简化
  • 毕业项目推荐:27-基于yolov8/yolov5/yolo11的电塔缺陷检测识别系统(Python+卷积神经网络)
  • MCP模型库深度解析:AI智能体工具调用生态的多元化与规模化发展
  • SciPy科学计算与应用:SciPy图像处理入门-掌握scipy.ndimage模块
  • 1 vs 10000:如何用AI智能体与自动化系统,重构传统销售客户管理上限?
  • 从高层 PyTorch 到中层 CUDA Kernel 到底层硬件 Tensor Core
  • fortran notes[2]
  • More Effective C++ 条款11:禁止异常流出析构函数之外
  • 自学嵌入式第二十九天:Linux系统编程-线程
  • 零后端、零配置:用 AI 编程工具「Cursor」15 分钟上线「Vue3 留言墙」
  • 从“找不到”到“秒上手”:金仓文档系统重构记
  • 深度学习-----详解MNIST手写数字数据集的神经网络实现过程
  • Linux系统使用ADB同时连接多个Android设备
  • 一、Mac(M1)本地通过docker安装Dify