[文档].艾米电子 在综合中使用函数,Verilog

对读者的假设

已经掌握:

内容

1 概述

在Verilog的模块里,有些表达式也许会出现很多次。为了不重复输入这些代码,我们可以把常用的这部分抽象为一个routine,模块内的function可以实现这一点。Verilog的函数有一个或多个的输入参数,仅返回单值。在综合期间,函数被展开,以映射为相应的硬件。因此,出于综合的考虑,函数应该保持简单,可以当作一些复杂表达式的缩略写法。函数的基本写法如下:

module . . .
. . .
// function defined within module
function [result_type] [func_id] ([input_arg]);
begin
  [statement]
end
endfunction
. . .
endmodule

函数需要被定义在function和endfunction限定词内部。可选的[result_type]指定返回值得数据类型,常选用带范围的reg或integer类型。[input_arg]被用来声明输入的参数,[func_id]被用来指定函数的名称。函数通过表达式来返回的结果,如

[func_id] = ... ;

2 范例

在二进制计数器那一节,我们讨论了模-m计数器。有两个参数:M,指定计数的范围为[0, M-1];N,指定M个数需要多少位宽来存储,其值为大于或等于log2(M)的整数。N的值不应该一个独立的参数,一个更好的做法定义一个局部常量,然后在模块内部计算它的值。通过使用函数可以实现,修改后的代码如下:

module mod_m_bin_counter
#(parameter M=10) // mod-M
(
  // global clock and asyn reset
  input clk,
  input rst_n,
  // counter interface
  output max_tick,
  output min_tick,
  output [N-1:0] q
);

// signal declaration
localparam N = log2(M); // number of bits in counter
reg [N-1:0] r_reg;
wire [N-1:0] r_next;

// body
// register
always@(posedge clk, negedge rst_n)
  if(!rst_n)
    r_reg <= 0;
  else
    r_reg <= r_next;
   
// next-state logic
assign r_next = (r_reg == (M-1)) ? 0 : r_reg + 1'b1;
//output logic
assign q = r_reg;
assign max_tick = (r_reg == (M-1)) ? 1'b1 : 1'b0;
assign min_tick = (r_reg == 0) ? 1'b1 : 1'b0;

// log2 constant function
function integer log2(input integer n);
  integer i;
begin
  log2 = 1;
  for(i=0; 2**i<n; i = i + 1)
    log2 = i + 1;
end
endfunction
                
endmodule

定义在模块内的函数log2(),用于求取局部变量N的值。由于在综合之前的预处理中,函数已执行计算;因此函数将不引用任何物理电路。

参考

1 Pong P. Chu.FPGA Prototyping By Verilog Examples: Xilinx Spartan-3 Version.Wiley

另见

[与艾米一起学FPGA/SOPC].[逻辑实验文档连载计划]

 安德鲁® / CC BY 2.5     FPGA Run!
原文地址:https://www.cnblogs.com/yuphone/p/1903743.html