宋桓公

【技术分享】谈谈verilog例化

0
阅读(6147)

      昨天在altera的一篇官方文档上看到一段程序,代码如下:

 

   1:  //Top-level module
   2:  module TEST_NO(A,B,Clock,Reset,Sel,AddSub,Z,Overflow);
   3:    parameter n=16;
   4:    input [n-1:0]A,B;
   5:    input Clock,Reset,Sel,AddSub;
   6:    output [n-1:0]Z;
   7:    output Overflow;
   8:    reg SelR,AddSubR,Overflow;
   9:    reg [n-1:0]Areg,Breg,Zreg;
  10:    wire [n-1:0]G,H,M,Z;
  11:    wire carryout,over_flow;
  12:    
  13:  //Define combinational logic circuit
  14:    assign H=Breg^{n{AddSubR}};
  15:    mux2to1 multiplexer(Areg,Z,SelR,G);
  16:    defparam multiplexer.k=n;
  17:        
  18:    adderk nbit_adder(AddSubR,G,H,M,carryout);
  19:    defparam nbit_adder.k=n;
  20:    assign over_flow=carryout^G[n-1]^H[n-1]^M[n-1];
  21:    assign Z=Zreg;
  22:    
  23:    
  24:  //Define flip-flops and registers
  25:    always @(posedge Reset or posedge Clock)
  26:      if(Reset==1)
  27:      begin
  28:        Areg<=0;
  29:        Breg<=0;
  30:        Zreg<=0;
  31:        SelR<=0;
  32:        AddSubR<=0;
  33:        Overflow<=0;
  34:      end
  35:      else
  36:      begin
  37:        Areg<=A;
  38:        Breg<=B;
  39:        Zreg<=M;
  40:        SelR<=Sel;
  41:        AddSubR<=AddSub;
  42:        Overflow<=over_flow;
  43:      end
  44:  endmodule
  45:   
  46:  //k-bit 2-to-1 multiplexer
  47:  module mux2to1(V,W,Sel,F);
  48:    parameter k=8;
  49:    input [k-1:0]V,W;
  50:    input Sel;
  51:    output [k-1:0]F;
  52:    reg [k-1:0]F;
  53:    
  54:    always @(V or W or Sel)
  55:      if(Sel==0)
  56:        F=V;
  57:      else
  58:        F=W;
  59:  endmodule
  60:   
  61:  //k-bit adder
  62:  module adderk(carryin,X,Y,S,carryout);
  63:    parameter k=3;
  64:    input carryin;
  65:    input [k-1:0]X,Y;
  66:    output [k-1:0]S;
  67:    output carryout;
  68:    reg [k-1:0]S;
  69:    reg carryout;
  70:    
  71:    always @(X or Y or carryin)
  72:      {carryout,S}=X+Y+carryin;
  73:       
  74:  endmodule

       从第46行往下,是两个module ,一个叫mux2to1,一个叫adderk;15行和18行分别例化了它们:

       mux2to1 multiplexer(Areg,Z,SelR,G);

       adderk nbit_adder(AddSubR,G,H,M,carryout);

       这种例化,和我平时用的不太一样,平时的话:

       mux2to1        multiplexer
                              (    
                                   .Areg(Areg), 
                                   .Z(Z),  
                                   .SelR(SelR), 
                                   .G(G)
                              );

     他这种例化方法叫做顺序例化,虽然简洁但是,顺序必须是和原模块的引脚顺序一样。当然本文的重点并不是顺序例化。

我们在顺序例化的下面紧接着有一句:defparam multiplexer.k=n; 这句话是干什么用的呢?

     首先,multiplexer就是模块mux2to1的例化名,n就是一个parameter等于16,那k是什么?multiplexer.k是个什么意思?

我们定位到mux2to1原模块,发现k就是mux2to1模块内部的一个parameter且等于8。且k是与引脚的位宽相关联的——input [k-1:0]V,W;

也就是说模块引脚的weikuan是8,可是我们观察RTL视图发现:

image

引脚的位宽不是8而是16。导致这个结果的原因就是:defparam multiplexer.k=n;这句话的意思就是从新定义这个模块的k的值为n,即16。我感觉这个方法挺不错的,增加了例化的灵活性。

总结:

      我们可以将自己的模块定义添加某些parameter,并且可将parameter关联上某些值,比如上述程序中的引脚的位宽。然后通过defparam multiplexer.参数名,这种语法来例化出不同的模块,是不是很赞呢。