Parameterised width assignments

  • Thread starter mjl296@hotmail.com
  • Start date
M

mjl296@hotmail.com

Guest
Hi Guys,

Assigning values to signals of parameterisable width has always bugged
me. Assigning all zeros and all ones is easy, but assigning a given
value is a pain.

------------------------------------
parameter SIZE = 8;

// These assignments are fine
wire [SIZE-1:0] all_zeros = {SIZE{1'b0}};
wire [SIZE-1:0] all_ones = {SIZE{1'b1}};

// This one is messy
wire [SIZE-1:0] one = {{SIZE-1{1'b0}, 1'b1};

// Sadly, the following doesn't work
// wire [SIZE-1:0] one = SIZE'd1;
------------------------------------

Is there a better way?

Thanks,

Mark
 
On 4 May, 11:43, "mjl...@hotmail.com" <mjl...@hotmail.com> wrote:
Hi Guys,

Assigning values to signals of parameterisable width has always bugged
me. Assigning all zeros and all ones is easy, but assigning a given
value is a pain.

------------------------------------
parameter SIZE = 8;

// These assignments are fine
wire [SIZE-1:0] all_zeros = {SIZE{1'b0}};
wire [SIZE-1:0] all_ones = {SIZE{1'b1}};

// This one is messy
wire [SIZE-1:0] one = {{SIZE-1{1'b0}, 1'b1};

// Sadly, the following doesn't work
// wire [SIZE-1:0] one = SIZE'd1;
------------------------------------

Is there a better way?

Thanks,

Mark
I should have mentioned of course that you can do this...

wire [SIZE-1:0] one = 1;

But this only works if SIZE < 33 and causes a warning in most tools.
 
On 4 May 2007 03:57:18 -0700,
<mjl296@hotmail.com> wrote:


I should have mentioned of course that you can do this...

wire [SIZE-1:0] one = 1;

But this only works if SIZE < 33 and causes a warning in most tools.
What makes you think it works only for <=32 bits? Verilog's
copy rules are straightforward: if you copy a narrow value into
a wider target, it is reliably zero-extended or sign-extended
into the target. The choice of zero- or sign-extension is
determined by the signedness of the right-hand-side expression,
and can easily be controlled using the $[un]signed() conversions
if you need (or prefer) to be explicit. Note that the integer
values 1, -1 are signed expressions, whereas the sized-literal
values 'd1, -'d1 are unsigned expressions.

Similarly, wider values are copied into narrow targets by
simple truncation - throw away the unused most-significant
bits.

Synthesis tools tend to give warnings for size mismatches
across a copy, but simulators are required to do the
widening/truncation I've just described.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
On Fri, 04 May 2007 12:34:43 +0100, Jonathan Bromley
<jonathan.bromley@MYCOMPANY.com> wrote:

What makes you think it works only for <=32 bits? Verilog's
copy rules are straightforward: if you copy a narrow value into
a wider target, it is reliably zero-extended or sign-extended
into the target.
And x and z are also extended, of course, though only to 32 bits for
V-1995.

Evan
 
On Fri, 04 May 2007 14:51:06 +0100,
Evan Lavelle <nospam@nospam.com> wrote:

On Fri, 04 May 2007 12:34:43 +0100, Jonathan Bromley
jonathan.bromley@MYCOMPANY.com> wrote:

What makes you think it works only for <=32 bits? Verilog's
copy rules are straightforward: if you copy a narrow value into
a wider target, it is reliably zero-extended or sign-extended
into the target.

And x and z are also extended, of course, though only to 32 bits for
V-1995.
Hmmm.... I was quite careful to say "copy"; the business about x/z
extension (and its V-95 32-bit limit) is nothing to do with
copying, but instead relates to the way a literal number is
padded to create a sized constant value. However, Evan is
absolutely right that I should have mentioned it. So,
here goes...

Apologies for the following rather prolix post. Experience
has shown that it is rather a good idea to be pedantic about
this stuff. I suspect Steven Sharp could do a better and
more concise job, but I'll try anyway.

In my previous post I correctly (I think) described the rules
about **copying** a Verilog value into a target. This copy
operation happens when you do an assignment (obviously), and
also in a few other situations implicitly - for example, when
you pass an argument value to a function or task.

What I DIDN'T describe was the way the value itself gets
constructed, and how many bits that value has. That is,
in fact, a two-stage process.

Stage 1 applies only if you write a literal value like
"1", or "'d5", or "7'bx". The value has a width -
in the case of 7'bx it's obviously 7 bits, in the
other cases it's perhaps less obvious. The literal
number "1" or "5" or "x" somehow needs to fill that
width. The rules say (in fairly honest paraphrase)
- if the written literal begins with x or z, then
the literal is padded to the right width by adding
further copies of the corresponding x or z bit on
the left - so, for example, 7'bx really means
7'bxxxxxxx;
- if the written literal does NOT begin with x or z,
then it's zero-padded to preserve its numeric value.

So Stage 1 gets us a literal (constant) bit-pattern
of the width we specified.

Stage 2 applies when you do an assignment. The
right-hand side of the assignment - even if it's simply
a constant - is, in fact, an expression. That expression
must be evaluated in context, and (within limits) it's the
context that determines its bit width. For an assignment,
the bit-width is the wider of the left-hand-side target
and the right-hand-side expression. So, for example,

wire [7:0] a = 4'd3;

Stage 1 gives us 4'b0011 on the right. Stage 2 says
"ah yes, but that expression needs to be evaluated in
8-bit context" and so the value 4'b0011 is widened again.
The widening rules now are exactly those I described in
my earlier post - zero-extend or sign-extend depending on
whether the right-hand side is signed or unsigned.

In Verilog-95, Stage 1 was completely independent of Stage 2.
Consequently, in the (classic) example

wire [63:0] a = 'bz;

Stage 1 says: The literal 'bz has the default width for
an integer, 32 bits; so "z" gets extended to 32'bzz....zz.
Stage 2 says: Expression context is 64 bits, so right-hand
side gets further widened to 64 bits with zero padding,
giving 64'h00000000zzzzzzzz.

In Verilog >= 2001, the rules were slightly changed so that
unsized literals such as 'bz also learn their (literal)
width from context; so the literal-widening rules give
us 64'hzzzzzzzzzzzzzzzz, which doesn't need further
widening and therefore gives the sensible result.

Whenever I try to write something like this about
Verilog, I remember why the tedious, schoolmasterly but
totally straightforward rules of VHDL always come as
such a relief after a bout of Verilog coding :)
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
On 4 May, 15:51, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
On Fri, 04 May 2007 14:51:06 +0100,

Evan Lavelle <nos...@nospam.com> wrote:
On Fri, 04 May 2007 12:34:43 +0100, Jonathan Bromley
jonathan.brom...@MYCOMPANY.com> wrote:

What makes you think it works only for <=32 bits? Verilog's
copy rules are straightforward: if you copy a narrow value into
a wider target, it is reliably zero-extended or sign-extended
into the target.

And x and z are also extended, of course, though only to 32 bits for
V-1995.

Hmmm.... I was quite careful to say "copy"; the business about x/z
extension (and its V-95 32-bit limit) is nothing to do with
copying, but instead relates to the way a literal number is
padded to create a sized constant value. However, Evan is
absolutely right that I should have mentioned it. So,
here goes...

Apologies for the following rather prolix post. Experience
has shown that it is rather a good idea to be pedantic about
this stuff. I suspect Steven Sharp could do a better and
more concise job, but I'll try anyway.

In my previous post I correctly (I think) described the rules
about **copying** a Verilog value into a target. This copy
operation happens when you do an assignment (obviously), and
also in a few other situations implicitly - for example, when
you pass an argument value to a function or task.

What I DIDN'T describe was the way the value itself gets
constructed, and how many bits that value has. That is,
in fact, a two-stage process.

Stage 1 applies only if you write a literal value like
"1", or "'d5", or "7'bx". The value has a width -
in the case of 7'bx it's obviously 7 bits, in the
other cases it's perhaps less obvious. The literal
number "1" or "5" or "x" somehow needs to fill that
width. The rules say (in fairly honest paraphrase)
- if the written literal begins with x or z, then
the literal is padded to the right width by adding
further copies of the corresponding x or z bit on
the left - so, for example, 7'bx really means
7'bxxxxxxx;
- if the written literal does NOT begin with x or z,
then it's zero-padded to preserve its numeric value.

So Stage 1 gets us a literal (constant) bit-pattern
of the width we specified.

Stage 2 applies when you do an assignment. The
right-hand side of the assignment - even if it's simply
a constant - is, in fact, an expression. That expression
must be evaluated in context, and (within limits) it's the
context that determines its bit width. For an assignment,
the bit-width is the wider of the left-hand-side target
and the right-hand-side expression. So, for example,

wire [7:0] a = 4'd3;

Stage 1 gives us 4'b0011 on the right. Stage 2 says
"ah yes, but that expression needs to be evaluated in
8-bit context" and so the value 4'b0011 is widened again.
The widening rules now are exactly those I described in
my earlier post - zero-extend or sign-extend depending on
whether the right-hand side is signed or unsigned.

In Verilog-95, Stage 1 was completely independent of Stage 2.
Consequently, in the (classic) example

wire [63:0] a = 'bz;

Stage 1 says: The literal 'bz has the default width for
an integer, 32 bits; so "z" gets extended to 32'bzz....zz.
Stage 2 says: Expression context is 64 bits, so right-hand
side gets further widened to 64 bits with zero padding,
giving 64'h00000000zzzzzzzz.

In Verilog >= 2001, the rules were slightly changed so that
unsized literals such as 'bz also learn their (literal)
width from context; so the literal-widening rules give
us 64'hzzzzzzzzzzzzzzzz, which doesn't need further
widening and therefore gives the sensible result.

Whenever I try to write something like this about
Verilog, I remember why the tedious, schoolmasterly but
totally straightforward rules of VHDL always come as
such a relief after a bout of Verilog coding :)
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Thanks guys for the excellent answers. My understanding of what
happened in this case was completely wrong (for Jonathan's benefit, I
was trained by the other guys).

So considering the following parameterisable counter...

parameter WIDTH=99;
reg [WIDTH-1:0] counter;

always @(posedge clk or negedge reset_n)
begin
if(!reset_n)
begin
counter <= 0; // or indeed {WIDTH{1'b0}}
end
else
begin
counter <= counter + 1; // or indeed counter + 1'b1
end
end

This code will simulate and synthesise correctly for all WIDTH>0.
Synthesis warnings may be produced due to widths not matching but
these are best ignored or switched off in this case, as there is no
sensible notation for producing a signal of value 1 and of width
WIDTH. Is this correct?

Thanks,

Mark
 
On 8 May 2007 07:50:28 -0700, "mjl296@hotmail.com"
<mjl296@hotmail.com> wrote:


So considering the following parameterisable counter...

parameter WIDTH=99;
reg [WIDTH-1:0] counter;

always @(posedge clk or negedge reset_n)
begin
if(!reset_n)
begin
counter <= 0; // or indeed {WIDTH{1'b0}}
end
else
begin
counter <= counter + 1; // or indeed counter + 1'b1
end
end

This code will simulate and synthesise correctly for all WIDTH>0.
Synthesis warnings may be produced due to widths not matching but
these are best ignored or switched off in this case, as there is no
sensible notation for producing a signal of value 1 and of width
WIDTH. Is this correct?
As I understand it, yes.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 

Welcome to EDABoard.com

Sponsor

Back
Top