掌握 Verilog 数学函数:高效硬件设计的利器
Verilog 数学函数可替代常量表达式,支持整数和实数运算。
整数数学函数
$clog2 返回给定参数以 2 为底对数的天花板值。常用于计算给定大小存储器所需最小地址位宽。
例如设计有 7 个并行加法器,表示所有 7 个加法器所需最小位数为 $clog2(7) = 3。
module des #(parameter NUM_UNITS = 7) // 使用此系统函数减少模块输入线数 (input [$clog2(NUM_UNITS)-1:0] active_unit); initial $monitor("active_unit = %d", active_unit); endmodule `define NUM_UNITS 5 module tb; integer i; reg [`NUM_UNITS-1:0] active_unit; des #(.NUM_UNITS(`NUM_UNITS)) u0(active_unit); initial begin active_unit = 1; #10 active_unit = 7; #10 active_unit = 8; end endmodule
注意信号 active_unit 有 3 位存储共 5 个单元。
仿真日志
xcelium> run active_unit = 001 active_unit = 111 active_unit = 000 xmsim: *W,RNQUIE: Simulation is complete.
实数数学函数
这些系统函数接受实数参数并返回实数结果。
| 函数 | 描述 |
|---|---|
| $ln(x) | 自然对数 log(x) |
| $log10(x) | 常用对数 log10(x) |
| $exp(x) | e^x,e=2.718281828... |
| $sqrt(x) | 平方根 |
| $pow(x, y) | x^y |
| $floor(x) | 向下取整 |
| $ceil(x) | 向上取整 |
| $sin(x) | 正弦,x 为弧度 |
| $cos(x) | 余弦,x 为弧度 |
| $tan(x) | 正切,x 为弧度 |
| $asin(x) | 反正弦 |
| $acos(x) | 反余弦 |
| $atan(x) | 反正切 |
| $atan2(x, y) | x/y 的反正切 |
| $hypot(x, y) | 斜边长 sqrt(x^2 + y^2) |
| $sinh(x) | 双曲正弦 |
| $cosh(x) | 双曲余弦 |
| $tanh(x) | 双曲正切 |
| $asinh(x) | 反双曲正弦 |
| $acosh(x) | 反双曲余弦 |
| $atanh(x) | 反双曲正切 |
module tb; real x, y; initial begin x = 10000; $display("$log10(%0.3f) = %0.3f", x, $log10(x)); x = 1; $display("$ln(%0.3f) = %0.3f", x, $ln(x)); x = 2; $display("$exp(%0.3f) = %0.3f", x, $exp(x)); x = 25; $display("$sqrt(%0.3f) = %0.3f", x, $sqrt(x)); x = 5; y = 3; $display("$pow(%0.3f, %0.3f) = %0.3f", x, y, $pow(x, y)); x = 2.7813; $display("$floor(%0.3f) = %0.3f", x, $floor(x)); x = 7.1111; $display("$ceil(%0.3f) = %0.3f", x, $ceil(x)); x = 30 * (22.0/7.0) / 180; // 30 度转弧度 $display("$sin(%0.3f) = %0.3f", x, $sin(x)); x = 90 * (22.0/7.0) / 180; $display("$cos(%0.3f) = %0.3f", x, $cos(x)); x = 45 * (22.0/7.0) / 180; $display("$tan(%0.3f) = %0.3f", x, $tan(x)); x = 0.5; $display("$asin(%0.3f) = %0.3f rad, %0.3f deg", x, $asin(x), $asin(x) * 7.0/22.0 * 180); x = 0; $display("$acos(%0.3f) = %0.3f rad, %0.3f deg", x, $acos(x), $acos(x) * 7.0/22.0 * 180); x = 1; $display("$atan(%0.3f) = %0.3f rad, %f deg", x, $atan(x), $atan(x) * 7.0/22.0 * 180); end endmodule
仿真日志
xcelium> run $log10(10000.000) = 4.000 $ln(1.000) = 0.000 $exp(2.000) = 7.389 $sqrt(25.000) = 5.000 $pow(5.000, 3.000) = 125.000 $floor(2.781) = 2.000 $ceil(7.111) = 8.000 $sin(0.524) = 0.500 $cos(1.571) = -0.001 $tan(0.786) = 1.001 $asin(0.500) = 0.524 rad, 29.988 deg $acos(0.000) = 1.571 rad, 89.964 deg $atan(1.000) = 0.785 rad, 44.981895 deg xmsim: *W,RNQUIE: Simulation is complete.
Verilog
- Verilog基础:设计你的第一个与门
- Verilog 入门:数字电路设计完整教程
- 掌握 Verilog 拼接操作:实用指南
- 深入理解 Verilog 赋值语句:类型、语法与最佳实践
- Verilog阻塞与非阻塞赋值:关键区别详解
- 掌握Verilog函数:高效RTL设计的复用利器
- 理解Verilog任务:函数vs任务、语法与用法全解析
- Verilog 时钟发生器设计与实现指南
- 掌握 Verilog $timeformat:精度控制与显示格式化
- 理解与打印 Verilog 任意作用域下的 Timescale
- 掌握 Verilog 文件 I/O:打开、读取、写入和关闭
- Verilog 入门指南:Hello World 示例