Verilog Generate可以实现批量的信号定义与赋值、模块例化
对于相关器(Correlator)电路,它对两个输入信号在一定窗口范围内进行乘积,然后对积进行叠加作为输出。如果需要低延时的相关器输出,就需要将每一个采样值作为被乘数(根据实际需要的过采样率来决定抽头个数)。一般这样的相关器会消耗更多的资源。
相关器实现的结构如图:
要实现这样的相关器,一种可行的做法是用MATLAB/C程序,产生期望的大量的格式化代码保存在.v文件,然后用`include把这段代码放到需要的地方(比如wire声明,reg声明,assign赋值,always里面<=赋值)。注意在工程中,将这些.v文件作为头文件而不是设计文件来管理(否则编译器认为语法出错)。这样做的缺点是:每一段代码需要用一个.v文件保存,而且每次进行代码修改都需要运行MATLAB/C程序。
Verilog有generate结构可以实现上述的“代码堆叠”操作。
上面的结构图中有3个地方可以generate:1、d1信号的采样移位。2、d2信号的采样移位。3、乘法器组。
模块的关键参数:1、N=30,为移位寄存器的阶数。2、每一级移位寄存器是5-bit Signed乘法器。3、din_shift_reg是二位数组的定义形式,即reg signed[4:0] din_shift_reg[29:0]。
给出移位寄存器的generate实现:
//*** Shift Operation genvar ite_din; generate for(ite_din=0; ite_din<N; ite_din=ite_din+1)begin: din_op // 记得for结构需要用begin开头,并且为generate结构加标识符,如din_op always@(posedge ts_sam_clk)begin if(!rst_n)begin din_shift_reg[ite_din] <= 5'd0; end else begin if((N-1) == ite_din)begin din_shift_reg[ite_din] <= din; // New Data In-Buff end else begin din_shift_reg[ite_din] <= din_shift_reg[ite_din+1]; // Shift Operation end end end end // 记得for结构需要end结尾 endgenerate
给出乘法器的generate实现:
//*** Generate Multiplier genvar ite_mult; generate for(ite_mult=0; ite_mult<N; ite_mult=ite_mult+1)begin: mult_op mult_s5 mult_s5_inst( .clock(ts_sam_clk), .dataa(din_shift_reg[ite_mult]), .datab(local_reg[ite_mult]), .result(prod[ite_mult]) ); end endgenerate
说明和一些理解:generate结构将其内部的结构例化/生成多次,各个结构的参数可以通过genvar进行配置。
等效的结构图: