generate/genvar, for loop and procdural (always/initial) blo

R

Riad KACED

Guest
Dear Community,

I'm fairly new to Verilog and I'm already hitting some hurdles using
the 'genvar' statement.
I have written 2 verilog modules, both of them are using for loops.
though the for loop index is required to be genvar when used out of
always/initial block.
This is my example:

1. The loop index is genvar, the compile fails otherwise:

module rkXor (xout, xin1, xin2);
parameter width = 4;
output [1:width] xout;
input [1:width] xin1, xin2;
genvar i;
for ( i = 1; i <= width; i=i+1 )
assign xout = xin1 ^ xin2;
endmodule

2. The loop index is integer, the compile would complain otherwise:

module clock1(clock);
parameter period = 20;
parameter nbBits = 4;
output [0:nbBits-1] clock;
reg [0:nbBits-1] clock;
integer i,j;
initial begin
for (i = 0; i < nbBits; i=i+1) begin: loop1
clock = 0;
end
end
always
begin
for (j = 0; j < nbBits; j=j+1) begin: loop2
#(period/2) clock[j] = 1;
#(period/2) clock[j] = 0;
end
end
endmodule

Can someone shed some light on this please ? i.e. why the loop is
behaving differently when used in the always/initial bloc ?

Thank you very much in advance,
Regards,
Riad.
 
On Nov 4, 2:46 pm, Riad KACED <riad.ka...@gmail.com> wrote:
Dear Community,

I'm fairly new to Verilog and I'm already hitting some hurdles using
the 'genvar' statement.
I have written 2 verilog modules, both of them are using for loops.
though the for loop index is required to be genvar when used out of
always/initial block.
This is my example:

1. The loop index is genvar, the compile fails otherwise:

module rkXor (xout, xin1, xin2);
  parameter width = 4;
  output [1:width] xout;
  input [1:width] xin1, xin2;
  genvar i;
  for ( i = 1; i <= width; i=i+1 )
      assign  xout = xin1 ^ xin2;
endmodule

2. The loop index is integer, the compile would complain otherwise:

module clock1(clock);
  parameter period = 20;
  parameter nbBits = 4;
  output [0:nbBits-1] clock;
  reg [0:nbBits-1] clock;
  integer i,j;
  initial begin
    for (i = 0; i < nbBits; i=i+1) begin: loop1
      clock = 0;
    end
  end
  always
  begin
    for (j = 0; j < nbBits; j=j+1) begin: loop2
      #(period/2) clock[j] = 1;
      #(period/2) clock[j] = 0;
    end
  end
endmodule

Can someone shed some light on this please ? i.e. why the loop is
behaving differently when used in the always/initial bloc ?

Thank you very much in advance,
Regards,
Riad.

Welcome to verilog. Your life will be much easier if you get into the
habit of thinking like how the hardware works as opposed to writing
"code" in software. Your first module is better written as:

module rkXor #(parameter WIDTH = 4) (xout, xin1, xin2);
output [WIDTH-1:0] xout;
input [WIDTH-1:0] xin1, xin2;

assign xout[WIDTH-1:0] = xin1[WIDTH-1:0] ^ xin2[WIDTH-1:0];
endmodule

The conventional notation for signals, register is MSB:LSB. And we
start from 0.

Others can correct me, but I think I've only ever used genvar in
generate/endgenerate blocks where I want to instantiate the same
modules with different bit-selects of a signals. Because you didn't
use generate/endgenerate block the compile failed. In this case, there
isn't a need to use it. Verilog is very good in understanding "bits"
provided you specify them.

You should spend some time understanding how the "assign" statement
works. I like to think of it as continuous evaluation. An event is
scheduled to update the output when the inputs change.

In your second case, you can declare clock as reg [3:0] clock. Then,
to initialize it to 0 at t=0 of simulation,

initial begin
clock[3:0] = 4'b0000;


Initial blocks execute only once at the beginning of simulation.
Always blocks execute each time the specified condition is true. I
prefer to specify the sensitivity list or use always @(*). A better
way might be to use the verilog mode for Emacs and use always @(/
*AUTOSENSE*/) and let the mode generate the sensitivity list for you.
You should look into that.

One way to generate a clock is as follows:

// generate clock
reg clk;
parameter CLOCK_PERIOD = 10;
initial
clk <= 1'b0;
always #(CLOCK_PERIOD/2) clk = ~clk;

Hope this helps.
 
On Nov 4, 2:46 pm, Riad KACED <riad.ka...@gmail.com> wrote:
Dear Community,

I'm fairly new to Verilog and I'm already hitting some hurdles using
the 'genvar' statement.
I have written 2 verilog modules, both of them are using for loops.
though the for loop index is required to be genvar when used out of
always/initial block.
This is my example:

1. The loop index is genvar, the compile fails otherwise:

module rkXor (xout, xin1, xin2);
  parameter width = 4;
  output [1:width] xout;
  input [1:width] xin1, xin2;
  genvar i;
  for ( i = 1; i <= width; i=i+1 )
      assign  xout = xin1 ^ xin2;
endmodule


I'm surprised that this compiles as shown. What compiler are
you running? I would assume you needed a generate statement
like:
generate
genvar i;
for ( i = 1; i <= width; i=i+1 ) begin : BLOCK_NAME
assign xout = xin1 ^ xin2;
end
endgenerate

That is unless you take the other suggestion of coding it
without a loop.

2. The loop index is integer, the compile would complain otherwise:

module clock1(clock);
  parameter period = 20;
  parameter nbBits = 4;
  output [0:nbBits-1] clock;
  reg [0:nbBits-1] clock;
  integer i,j;
  initial begin
    for (i = 0; i < nbBits; i=i+1) begin: loop1
      clock = 0;
    end
  end
  always
  begin
    for (j = 0; j < nbBits; j=j+1) begin: loop2
      #(period/2) clock[j] = 1;
      #(period/2) clock[j] = 0;
    end
  end
endmodule

Can someone shed some light on this please ? i.e. why the loop is
behaving differently when used in the always/initial bloc ?

Thank you very much in advance,
Regards,
Riad.

There's a very good reference book from Doulos called the
Verilog Golden Reference Guide. It describes how the
generate works and how loops inside a generate statement
are different from loops in a procedural block.

Regards,
Gabor
 
Hi Pallv,

Thank you very much indeed for your prompt answer.
Well, your comments are very interesting. They don't help me that much
with understanding my problem though.

Both modules I have provided did not use any generate/endgenerate.
Though, one module has worked not the other. the generate/endgenerate
is not required as far as I understand. In fact, I have just read the
following from the Verilog-D IEEE Std 1364-2005 doc (Page 181):

"The keywords generate and endgenerate may be used in a module to
define a generate region. A generate region is a textual span in the
module description where generate constructs may appear. Use of
generate regions is optional. There is no semantic difference in the
module when a generate region is used. A parser may choose to
recognize the generate region to produce different error messages for
misused generate construct keywords ..."
Besides, I'm rather a user of Verilog-AMS where the generate is an
obsolete statement that is left for legacy reasons. This is another
story, I'm just interested in Verilog-D right here.

My guess is that a the for loop behaves differently when in a
procedural bloc like initial/always. That's what I'm trying to
understand.
Anyway, thanks for your advice on the other bits of my code.

Cheers,
Riad.
 
Hi Gabor,

My code compiles, yes it does. One of the compilers I have run was
Cadence's ncvlog
Thanks for the reference, I'll try to get hold of it ...

Thanks for your help too !
Cheers,
Riad.
 
On Nov 4, 4:10 pm, Riad KACED <riad.ka...@gmail.com> wrote:
Well, your comments are very interesting. They don't help me that much
with understanding my problem though.
Hi Riad,

Looks like I did not understand your question. Sorry.

Kind regards.
 
Hi Palav,

Although it didn't really answer my question, your comments are still
very valuable and I'm very grateful for it !
Looking forward for some more people to comment this item !

Cheers,
Riad.
 
On Nov 5, 2:12 pm, Riad KACED <riad.ka...@gmail.com> wrote:
Although it didn't really answer my question, your comments are still
very valuable and I'm very grateful for it !
Looking forward for some more people to comment this item !
I think what you're missing is the distinction between code that's
"executed" at compile/elaboration time and code that runs at
simulation time (or run time). Obviously, I'm just talking about
simulation here; synthesis also has compile/elaboration time, but
doesn't support initial blocks, so I assume you're interested in
simulation at this point.

Side note: I apologize for lumping compilation and elaboration
together. They're technically different stages, one following the
other, but I don't have the differences at the tip of my brain right
now. They might be discussed in your simulator manual and should be in
the LRM. Reading up on them will help you here.

Generate statements are handled at compile/elaboration time. Your
first example is a generate-for and, being handled at comp/elab time,
it's a useful shorthand for putting down multiple module
instantiations, continuous assigns, or even whole sequential blocks (I
think), with some reference (bit, bit range, array location) varying
with the genvar. Essentially, generate-for statements are to save you
potentially lots of typing, but in theory you could unroll the loop
yourself because the loop count must be known in advance. You're using
it to create more code or structures that will go through compile/
elaboration and then simulation.

Your second example has two sequential blocks containing for loops.
These are not generate-for statements, they're sequential for
statements (I guess you'd call them that). As such, these are handled
at simulation time, and while I hate to put it this way, you can think
of them like a for loop in C -- that is, they can have a variable loop
count, the loop can be interrupted, etc., but most important, you're
not creating new structures, you're running a block of code multiple
times.

As others have mentioned, your generate-for to create multiple 1-bit
assignments is better (and more efficiently) replaced by a single
multi-bit assign, and there are better styles for clock generators.
Personally, I still like this one from Janick Bergeron's _Writing
Testbenches_, 1st ed.:

reg clk;
initial
forever begin
#(period/2) clk = 1'b0;
#(period/2) clk = 1'b1;
end

Clock events at time 0 used to cause problems though the simulation
vendors have cleaned those up. I still like delaying the first posedge
clk though. Makes it easier to see what happens on the first clock in
waves.

-cb
 
On Nov 6, 11:01 am, Chris Briggs <ch...@engim.com> wrote:

[snip]

. . . there are better styles for clock generators.
Personally, I still like this one from Janick Bergeron's _Writing
Testbenches_, 1st ed.:

reg clk;
initial
   forever begin
      #(period/2) clk = 1'b0;
      #(period/2) clk = 1'b1;
   end

Clock events at time 0 used to cause problems though the simulation
vendors have cleaned those up. I still like delaying the first posedge
clk though. Makes it easier to see what happens on the first clock in
waves.

-cb
That's pretty useful, thanks. No edge at time zero but X-0
edge at period/2 is still a "negedge" event consistent with
the clock's operation. I've been using the Xilinx GUI to
generate a quick starter for testbenches, but they always
fill in all the module inputs in an initial block starting
at time zero. Not a problem for rising edge only clocks
when setting the initial to 0. Of course the Xilinx stuff
has other start-up issues like their semi-hidden GSR net
that resets all their structural models (but not your
behavioral code) for the first 100 ns of the simulation.

Most of my behavioral code is written with asynchronous
reset, so what happens on the first clock isn't so important.
However I do remember having some headaches with the falling
edge event at time zero due to the initial statement. I always
thought that "initial" was for initial conditions - i.e.
everything is assumed to start from there, but of course
the LRM says otherwise, i.e. everything is X until initialized
and that X to whatever transition is an event.

Regards,
Gabor
 
Gabor wrote:
everything is X until initialized
and that X to whatever transition is an event.
Yes, but be very afraid.... Since 2001 you have been
able to initialize module-level variables:

module foo;
reg clock = 0;
always #5 clock = ~clock;
...

But that reg-initialization is, by definition, exactly
equivalent to

reg clock;
initial clock = 0;

with the semantics that Gabor indicated - clock is
initially X but is changed to 0 as one of the many
things that happens at time 0. This is, of course,
a fine way to get lots of unpleasant races.

In SystemVerilog-2005, the meaning of that initialization
was redefined to be like a VHDL signal initialization:
the reg had that value since before the Big Bang, and
has no value-change event at time 0. With the soon-to-
happen merging of Verilog and SystemVerilog, this will
be the generally mandated behaviour.

It happens that most simulator vendors, trying to give
customers roughly what they expect, have implemented
register-initializers in such a way that there will be
no noticeable difference when the new rules kick in.
The de-facto behaviour is one of the legal orderings
of the Verilog code anyway, so the change will not be
disruptive. But it's as well to be very, very cautious
about what happens around time 0 and, as far as possible,
make your design and testbench completely immune to
time-0 races. Easier said than done :-(
--
Jonathan Bromley
 
Hi Guys,

Thank you all for your time and very valuable comments on my query !
Very much appreciated,

Riad.
 

Welcome to EDABoard.com

Sponsor

Back
Top