Subject: BTF - B01 - Verilog Generate

From: Clifford E. Cummings (cliffc@europa.com)
Date: Fri May 02 1997 - 07:32:41 PDT


Subject: BTF - B01 - Verilog Generate

Behavioral Task Force - Enhancement Request
Assigned Enhancement Request Number: B01
Enhancement Name (Description): Verilog Generate
Date Submitted: 960227
Requestor: IVC96 (Cliff Cummings)
Status: RO
Is enhancement intended to be synthesizable?: Yes

To improve Verilog modeling capability

Proposal: Add for-loop, if-else and case generate capabilities to
Verilog.

LRM wording: TBD

NOTE: Consideration is being given to adding generate/endgenerate
keywords but Kurt Baty and I believe the additional keywords just add
extra verbosity to the proposed construct. Some Verilog users prefer
adding the generate keywords to make the context more obvious.

BNF addition: Below is a possible proposal for changes/additions to the
BNF, followed by a usage example (BNF and example courtesy of Kurt
Baty).

//-----------------------------------------------------------------
// Possible syntax changes to IEEE Standard 1364-1995, pg. 136
// - adds generated_instantiation to module_item
//-----------------------------------------------------------------

module_declaration ::=
        module_keyword [# list_of_parameters] module_identifier
        [list_of_ports]; {module_item} endmodule

list_of_parameters ::= (parameter [, parameter])

module_item ::=
<add>
        | generated_instantiation

<p>//-----------------------------------------------------------------
// Possible additions to the IEEE Standard 1364-1995
// - adds Generate Construct Syntax
//-----------------------------------------------------------------

generate_instantiation ::= constant_loop_statement |
                           constant_conditional_statement |
                           constant_case_statement

//-----------------------------------------------------------------
// Generate "for-loop" (similar to VHDL generate "for-loop")
//-----------------------------------------------------------------
constant_loop_statement ::= for (constant_reg_assignment;
        constant_expression; constant_reg_assignment)
        begin : generateted_identifier {module_item} end

//-----------------------------------------------------------------
// Generate "if-else" (better than simple VHDL generate "if")
//-----------------------------------------------------------------
constant_conditional_statement ::= if (constant_expression)
        module_item_or_null [else module_item_or_null]

//-----------------------------------------------------------------
// Generate "case" (not available in VHDL!)
//-----------------------------------------------------------------
constant_case_statement ::= case (constant_expression)
        constant_case_item {constant_case_item} endcase

constant_case_item ::= constant_expression{, constant_expression} :
        module_item_or_null | default [:] module_item_or_null

//-----------------------------------------------------------------
// Generate Example:
//-----------------------------------------------------------------
module #(width, depth) example_fifo (dout, full, empty, din,
                                     clk, reset, push, pop);

  parameter width = 16, depth = 16;
  parameter counter_width = clogb2(depth);
  //-----------------------------------------------------------------
  // The above parameter definition requires a constant function.
  // This would require another enhancement to the LRM
  //-----------------------------------------------------------------

  output [width-1 :0] dout;
  output full, empty;
  input [width-1 :0] din;
  input clk, reset, push, pop;

  wire [width*depth-1 :0] fbit;
  wire [depth-1 :0] decoded_push;
  wire [counter_width-1:0] next_push_ctr, next_pop_ctr;
  reg [counter_width-1:0] push_ctr, pop_ctr;
  reg full, empty;

  //-----------------------------------------------------------------
  // nested for-loops to "generate"
  // fifo_row[i].bit_in_row[j].fifo_bit_reg instances
  // NOTE: the named block-names are part of the hierarchical
  // reference for the generated instances
  //-----------------------------------------------------------------
  for (i=0; i<depth; i=i+1) begin: fifo_row
    for (j=0; j<width; j=j+1) begin: bit_in_row
      fifo_bit_reg fbr (clk, reset, decoded_push[i],
                        din[j], fbit[i*width+j]);
    end
  end

  assign decoded_push = {{depth{1'b0}},push} << push_ctr;

  always @(posedge clk)
    if(reset) push_ctr <= #1 0;
    else if(push) push_ctr <= #1 next_push_ctr;

  always @(posedge clk)
    if(reset) pop_ctr <= #1 0;
    else if(pop) pop_ctr <= #1 next_pop_ctr;

  assign next_push_ctr = (push_ctr == depth-1) ? 0 : push_ctr + 1'b1;
  assign next_pop_ctr = (pop_ctr == depth-1) ? 0 : pop_ctr + 1'b1;

  always @ (posedge clk)
    if(reset){full,empty} <= #1 2'b01;
    else if(push && !pop)
      {full,empty} <= #1 {(next_push_ctr == pop_ctr),1'b0};
    else if(!push && pop)
      {full,empty} <= #1 {1'b0,push_ctr == next_pop_ctr)};

  DW01_mux_any #(depth*width,counter_width,width)
               doutmux(fbit, pop_ctr, dout);

endmodule

===== Notes from meeting held at IVC 3/31/97-4/2/97 =====

//-----------------------------------------------------------------
// Generate Example:
//-----------------------------------------------------------------
module #(width, depth) example_fifo (dout, full, empty, din,
                                     clk, reset, push, pop);

  parameter width = 16, depth = 16;
  parameter counter_width = clogb2(depth);
  //-----------------------------------------------------------------
  // The above parameter definition requires a constant function.
  // This would require another enhancement to the LRM
  //-----------------------------------------------------------------
  
  output [width-1 :0] dout;
  output full, empty;
  input [width-1 :0] din;
  input clk, reset, push, pop;

  wire [width*depth-1 :0] fbit;
  wire [depth-1 :0] decoded_push;
  wire [counter_width-1:0] next_push_ctr, next_pop_ctr;
  reg [counter_width-1:0] push_ctr, pop_ctr;
  reg full, empty;

  //-----------------------------------------------------------------
  // nested for-loops to "generate"
  // i[0].j[2].fbr instances // default
  // fifo_row[0].bit_in_row[2].fbr instances
  // adder1.i[0].j[2].fbr
  // NOTE: the named block-names are part of the hierarchical
  // reference for the generated instances
  //-----------------------------------------------------------------

wire a[depth-1:0][width-1:0];
integer i, j;
    for (i=0; i<depth; i=i+1) begin
      for (j=0; j<width; j=j+1) begin
        if (j%3 == 0) begin
          fifo_bit_reg fbr (clk, reset, decoded_push[i],
                            din[j], fbit[i*width+j]);
          and foo(decoded_push[i], a[i][j]);
          not f1(a[i][j], din[j]);
        end
      end
    end

<p>wire a[depth-1:0][width-1:0];
generate (`generate?)
  genvar i, j; (`genvar)
    for (i=0; i<depth; i=i+1) begin
      for (j=0; j<width; j=j+1) begin
        if (j%3 == 0) begin
          fifo_bit_reg fbr (clk, reset, decoded_push[i],
                            din[j], fbit[i*width+j]);
          and foo(decoded_push[i], a[i][j]);
          not f1(a[i][j], din[j]);
        end
      end
    end
endgenerate

generate
  genvar fifo_row, bit_in_row;
  for (fifo_row=0; fifo_row<depth; fifo_row=fifo_row+1)
    for (bit_in_row=0; bit_in_row<width; bit_in_row=bit_in_row+1)
      fifo_bit_reg fbr (clk, reset, decoded_push[fifo_row],
                      din[bit_in_row], fbit[fifo_row*width+bit_in_row]);
endgenerate

  //-----------------------------------------------------------------
  // nested for-loops to "generate"
  // adder1.i[0].j[2].fbr instances // default
  // fifo_row[0].bit_in_row[2].fbr instances
  // NOTE: the named block-names are part of the hierarchical
  // reference for the generated instances
  //-----------------------------------------------------------------
generate: adder1
  genvar i, j;
  for (i=0; i<depth; i=i+1) begin
    for (j=0; j<width; j=j+1) begin: bit_in_row1
      fifo_bit_reg fbr (clk, reset, decoded_push[i],
                        din[j], fbit[i*width+j]);
    end
    for (j=0; j<width; j=j+1) begin: bit_in_row2
      fifo_bit_reg fbr (clk, reset, decoded_push[i],
                        din[j], fbit[i*width+j]);
    end
  end
endgenerate

  //-----------------------------------------------------------------
  // nested for-loops to "generate"
  // fifo_row[0].bit_in_row[2].fbr instances
  // NOTE: the named block-names are part of the hierarchical
  // reference for the generated instances
  //-----------------------------------------------------------------
integer i, j;
  for (i=0; i<depth; i=i+1) begin: fifo_row
    for (j=0; j<width; j=j+1) begin: bit_in_row
      fifo_bit_reg fbr (clk, reset, decoded_push[i],
                        din[j], fbit[i*width+j]);
    end
  end

<p><p>issue to discuss: generate case - multiple matches?

From: Steve Meyer <sjmeyer@crl.com>
Date: Wed, 30 Apr 1997 00:15:12 -0700 (PDT)

I have been working on implementing the new generate feature (also
arrays of instances) and I have some suggestions.

1) I think other new keywords besides case, for, and if are needed because
overloading the non generator keywords makes error recovery during parsing
and beginner use very difficult. The following bad syntax is quite comon:
instead of "initial for [something] end" wrong "for [something] end" is coded.
        
I would like to see new keywords such as gencase, genfor, genif preferably
surrounded by generate and endgenerate. I believe the slightly wordy pascal
like Verilog synatax is seen as a positive feature. Error recovery is hard
enough in Verilog because constructs are allowed to span file boundaries so
overloading such common keywords will prevent thorough syntax checking when
errors occur.

2) I think the "preprocessor" nature of generate should be explicitly
defined, i.e. constant bit selects are separated by a separator "_" with an
option for the user to select another string. String must contain legal
identifier characters. This will insure that users will know exactly how to
name generated names for hierarchical references. Same rule should, in my
view, be defined for arrays of instances.

3) Arrays of instances (and primitives) should be kept but the standard
should explicitly not allow them in generate constructs. Rationale is the
two different features allow the same capability. One easier to code but
less powerful, and another harder to use but more powerful.
//********************************************************************//
// Cliff Cummings E-mail: cliffc@europa.com //
// Sunburst Design Phone: 503-579-6362 / FAX: 503-579-7631 //
// 15870 SW Breccia Dr., Beaverton, OR 97007 //
// //
// Verilog & Synthesis Training / On-Site Training //
// Verilog, VHDL, Synopsys, LMG, FPGA, Consulting and Contracting //
//********************************************************************//



This archive was generated by hypermail 2.1.4 : Mon Jul 08 2002 - 12:54:42 PDT and
sponsored by Boyd Technology, Inc.