From: Clifford E. Cummings (cliffc@europa.com)
Date: Fri Aug 08 1997 - 08:57:49 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{1b0}},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 + 1b1;
assign next_pop_ctr = (pop_ctr == depth-1) ? 0 : pop_ctr + 1b1;
always @ (posedge clk)
if(reset){full,empty} <= #1 2b01;
else if(push && !pop)
{full,empty} <= #1 {(next_push_ctr == pop_ctr),1b0};
else if(!push && pop)
{full,empty} <= #1 {1b0,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 common:
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 syntax 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.
------------------------
BTF Meeting - May, 1997
generate - endgenerate can only exist at the module scope - passed
5-2-1(abstain)
(opposing - no new keywords should be introduced)
genvar - the generate for-loop -
should be declared passed 6-0-2(abstain)
new keyword genvar required ) 6-1-1(abstain)
(opposing - no new keywords should be introduced)
<Karen leaves>
genvar is local to the generate-scope 7-0-0
for, if-then-else, case 7-0-0
The following 4-4 (the committee needs to think about this - it may pass on
the next vote)
named-block loops not required
use the instance name with . seperators between indexes
Leaning towards top.mx8.1.2.5
<p>//********************************************************************//
// 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:41 PDT
and
sponsored by Boyd Technology, Inc.