pipeline code

On Fri, 22 Apr 2011 16:57:03 +0100, Chris Hinsley
<chris.hinsley@gmail.com> wrote:

always @( posedge clk_i )
if( en_i )
shift_regs <= { shift_regs, d_i };

assign q_o = shift_regs[ ( DEPTH - 1 ) * WIDTH +: WIDTH ];

Are you relying on the compiler to just discard the top part of the
composite value ?
Yes, that's completely legitimate and well-defined. Some lint
tools may complain about it as a possible user error, but it's
the mandated behaviour. If you don't like it, widen the target
to the right width:

reg [WIDTH-1:0] discarded;
...
{discarded, shift_regs} <= {shift_regs, d_i};

And then weep at the synthesis warnings saying that
register "discarded" is redundant and has been eliminated!

That might be OK, but again, I'm not keen on trusting the
compilers to do this correctly. Is this a garenteed action ?
Yes. Copying a wide expression to a narrow target in Verilog
reliably throws away any surplus MSBs. Of course this is a
two-edged sword, and care is needed. But it's well-defined
and all tools support it correctly.

Widening of narrow expressions when written to a wider target
is a little more complicated, but again it's well-defined
and in simple cases you can just do...
it
reg [3:0] src;
reg [5:0] dst;
...
dst <= src;

and the upper 2 bits of dst will reliably be zero.
--
Jonathan Bromley
 
On 22/04/11 18:07, Jonathan Bromley wrote:
On Fri, 22 Apr 2011 16:47:23 +0100, Chris Hinsley wrote:

I just naturally did i++, coming from C++. It means exactly the same thing ?

It was added in SystemVerilog, and has the same meaning as in C.

I believe that some tools still don't support the use of ++/--
in an expression (you know, the usual a[i++] thing). But they
are fine as simple increment operators, equivalent to +=1 (also
supported in SystemVerilog but not in classic Verilog).

The syntax of Verilog bears many superficial resemblances to
C, but it's foolhardy to extrapolate without checking the
consequences. The existence of X values and arbitrary
bit-width expressions makes things distinctly different
in Verilog, and there are other pinch-points too.
I'm sure Jonathan knows this, but it caught me out on first encounter -
i++ is equivalent to a blocking assignment, so if you try and write a
counter

always_ff @(posedge clk)
if (reset)
count <= 0;
else
count++;

it will "all end in tears" (or more specifically you'll probably get a
synthesis warning about mixing blocking and non-blocking assignments to
the same variable).

With the for loop, SystemVerilog also allows the loop variable to be local,

for (int i = 0; i< 10; i++)

So if you're committed to SV, you can hide i from the outside world;
which does have a superficial resemblance to C++.


regards
Alan

--
Alan Fitch
 
On Sat, 23 Apr 2011 10:08:56 +0100, Alan Fitch wrote:

i++ is equivalent to a blocking assignment, so if you
try and write a counter

always_ff @(posedge clk)
if (reset)
count <= 0;
else
count++;

it will "all end in tears" (or more specifically you'll probably get a
synthesis warning about mixing blocking and non-blocking assignments to
the same variable).
Right; all the assignment operators (+=, -= etc) are blocking too.
Which dramatically limits their usefulness for RTL coding!

I recall a frivolous conversation a few years ago, almost
certainly overheard by Alan in the same office, along the
lines of "couldn't you add nonblocking assignment
operators like <+= or <-=" and then deciding that was
going to be a really, really bad idea given that
we already have operators <<= and <<<=.

With the for loop, SystemVerilog also allows the loop variable to be local,

for (int i = 0; i< 10; i++)

So if you're committed to SV, you can hide i from the outside world;
which does have a superficial resemblance to C++.
Or even, dare one say it, to VHDL!
--
Jonathan Bromley
 
In article <ued3r6hj0o152iavnv4nireip9g2tb16qt@4ax.com>,
Jonathan Bromley <spam@oxfordbromley.plus.com> wrote:
On Fri, 22 Apr 2011 16:57:03 +0100, Chris Hinsley
chris.hinsley@gmail.com> wrote:

always @( posedge clk_i )
if( en_i )
shift_regs <= { shift_regs, d_i };

assign q_o = shift_regs[ ( DEPTH - 1 ) * WIDTH +: WIDTH ];

Are you relying on the compiler to just discard the top part of the
composite value ?

Yes, that's completely legitimate and well-defined. Some lint
tools may complain about it as a possible user error, but it's
the mandated behaviour. If you don't like it, widen the target
to the right width:

reg [WIDTH-1:0] discarded;
...
{discarded, shift_regs} <= {shift_regs, d_i};

And then weep at the synthesis warnings saying that
register "discarded" is redundant and has been eliminated!

That might be OK, but again, I'm not keen on trusting the
compilers to do this correctly. Is this a garenteed action ?

Yes. Copying a wide expression to a narrow target in Verilog
reliably throws away any surplus MSBs. Of course this is a
two-edged sword, and care is needed. But it's well-defined
and all tools support it correctly.

Widening of narrow expressions when written to a wider target
is a little more complicated, but again it's well-defined
and in simple cases you can just do...
it
reg [3:0] src;
reg [5:0] dst;
...
dst <= src;

and the upper 2 bits of dst will reliably be zero.
Chris, I tend to be very careful with sizes of things in my designs.
Port sizes must explicity match everywhere, just about all my
constants are sized, being very careful when mixing
algebraic operations with logical operations, etc..

But I rely on these two behaviours in verilog (wide expression to
narrow target, and the reverse) SOO much. As Jonathan indicates -
it's well defined, and the tools will do the correct thing.
Whenever I run some sort of lint tool, I just need
to turn these type of checks completely off.

--Mark
 

Welcome to EDABoard.com

Sponsor

Back
Top