安德鲁

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

0
阅读(2022)

对读者的假设

已经掌握:

内容

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;
	 
	// log2 constant function
	function integer log2(input integer n);
	  integer i;
	begin
	  log2 = 1;
	  for(i=0; 2**i

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

参考

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

另见

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