Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > Variable vs. Signal on indexing

Reply
Thread Tools

Variable vs. Signal on indexing

 
 
ALuPin@web.de
Guest
Posts: n/a
 
      01-16-2007
Hi newsgroup,

I have the two following approaches in combinational processes:

SIGNAL ls_idx : integer RANGE 0 TO 127;
SIGNAL ls_wlist_copy_cache_q : std_logic_vector(63 DOWNTO 0);
SIGNAL ls_rlist_cache_q : std_logic_vector(63 DOWNTO 0);
SIGNAL ls_ba_checked_wlistc, ls_ba_checked_rlist : std_logic_vector(1
DOWNTO 0);
SIGNAL ls_pos_col_in_cache : std_logic_vector(5 DOWNTO 0);

1. approach:

CHECKCACHES_comb: PROCESS(ls_check_w_wc_r_list, ls_pos_col_in_cache,
ls_wlist_copy_cache_q,
ls_rlist_cache_q, ls_idx)
VARIABLE idx : integer RANGE 0 TO 127;
BEGIN
ls_ba_checked_wlistc <= "00";
ls_ba_checked_rlist <= "00";

IF ls_check_w_wc_r_list='1' THEN
idx := 2 * to_integer(unsigned(ls_pos_col_in_cache)) - 1;

ls_ba_checked_wlistc <= ls_wlist_copy_cache_q(idx DOWNTO idx-1);
ls_ba_checked_rlist <= ls_rlist_cache_q(idx DOWNTO idx-1);
ls_idx <= idx;

END IF;
END PROCESS CHECKCACHES_comb;

2. approach:

CHECKCACHES_comb: PROCESS(ls_check_w_wc_r_list, ls_pos_col_in_cache,
ls_wlist_copy_cache_q,
ls_rlist_cache_q, ls_idx)
BEGIN
ls_ba_checked_wlistc <= "00";
ls_ba_checked_rlist <= "00";
ls_idx <= 0;

IF ls_check_w_wc_r_list='1' THEN
ls_idx <= 2 * to_integer(unsigned(ls_pos_col_in_cache)) - 1;

ls_ba_checked_wlistc <= ls_wlist_copy_cache_q(ls_idx DOWNTO
ls_idx-1);
ls_ba_checked_rlist <= ls_rlist_cache_q(ls_idx DOWNTO ls_idx-1);


END IF;
END PROCESS CHECKCACHES_comb;

When using the second approach I get the following fatal error when
performing functional simulation
(with ModelsimDesigner 6.1f):


# ** Fatal: (vsim-3471) Slice range (0 downto -1) does not belong to
the prefix index range (63 downto 0).


Note that the signal "ls_pos_col_in_cache" NEVER gets "000000" when
"ls_check_w_wc_r_list"
is active.
So where is the difference in both descriptions causing Modelsim to
complain ?

Is it a simulation problem or will the indexing cause problems during
synthesis ?

Thank you for your opinion.

Rgds
Andre

 
Reply With Quote
 
 
 
 
Jim Lewis
Guest
Posts: n/a
 
      01-16-2007
wrote:
Variables get updated immediately so the process sees the new value.
Signals get updated at the beginning of the next delta cycle,
and hence it has a previous value on it. The previous value
at start-up is 0, the left-most value of the constrained type
(since you range it to be 0 t0 127).

Cheers,
Jim

> Hi newsgroup,
>
> I have the two following approaches in combinational processes:
>
> SIGNAL ls_idx : integer RANGE 0 TO 127;
> SIGNAL ls_wlist_copy_cache_q : std_logic_vector(63 DOWNTO 0);
> SIGNAL ls_rlist_cache_q : std_logic_vector(63 DOWNTO 0);
> SIGNAL ls_ba_checked_wlistc, ls_ba_checked_rlist : std_logic_vector(1
> DOWNTO 0);
> SIGNAL ls_pos_col_in_cache : std_logic_vector(5 DOWNTO 0);
>
> 1. approach:
>
> CHECKCACHES_comb: PROCESS(ls_check_w_wc_r_list, ls_pos_col_in_cache,
> ls_wlist_copy_cache_q,
> ls_rlist_cache_q, ls_idx)
> VARIABLE idx : integer RANGE 0 TO 127;
> BEGIN
> ls_ba_checked_wlistc <= "00";
> ls_ba_checked_rlist <= "00";
>
> IF ls_check_w_wc_r_list='1' THEN
> idx := 2 * to_integer(unsigned(ls_pos_col_in_cache)) - 1;
>
> ls_ba_checked_wlistc <= ls_wlist_copy_cache_q(idx DOWNTO idx-1);
> ls_ba_checked_rlist <= ls_rlist_cache_q(idx DOWNTO idx-1);
> ls_idx <= idx;
>
> END IF;
> END PROCESS CHECKCACHES_comb;
>
> 2. approach:
>
> CHECKCACHES_comb: PROCESS(ls_check_w_wc_r_list, ls_pos_col_in_cache,
> ls_wlist_copy_cache_q,
> ls_rlist_cache_q, ls_idx)
> BEGIN
> ls_ba_checked_wlistc <= "00";
> ls_ba_checked_rlist <= "00";
> ls_idx <= 0;
>
> IF ls_check_w_wc_r_list='1' THEN
> ls_idx <= 2 * to_integer(unsigned(ls_pos_col_in_cache)) - 1;
>
> ls_ba_checked_wlistc <= ls_wlist_copy_cache_q(ls_idx DOWNTO
> ls_idx-1);
> ls_ba_checked_rlist <= ls_rlist_cache_q(ls_idx DOWNTO ls_idx-1);
>
>
> END IF;
> END PROCESS CHECKCACHES_comb;
>
> When using the second approach I get the following fatal error when
> performing functional simulation
> (with ModelsimDesigner 6.1f):
>
>
> # ** Fatal: (vsim-3471) Slice range (0 downto -1) does not belong to
> the prefix index range (63 downto 0).
>
>
> Note that the signal "ls_pos_col_in_cache" NEVER gets "000000" when
> "ls_check_w_wc_r_list"
> is active.
> So where is the difference in both descriptions causing Modelsim to
> complain ?
>
> Is it a simulation problem or will the indexing cause problems during
> synthesis ?
>
> Thank you for your opinion.
>
> Rgds
> Andre
>

 
Reply With Quote
 
 
 
 
ALuPin@web.de
Guest
Posts: n/a
 
      01-16-2007
Hi Jim,
thank you for your response:

Yes, it is clear now for simulation.

But what about synthesis ? When using variables as shown in the first
approach, do I have to define the ELSE condition for the variable ?

CHECKCACHES_comb: PROCESS(ls_check_w_wc_r_list, ls_pos_col_in_cache,
ls_wlist_copy_cache_q,
ls_rlist_cache_q, ls_idx)
VARIABLE idx : integer RANGE 0 TO 127;
BEGIN
ls_ba_checked_wlistc <= "00";
ls_ba_checked_rlist <= "00";
idx := 0; -- ??? necessary


IF ls_check_w_wc_r_list='1' THEN
idx := 2 * to_integer(unsigned(ls_pos_col_in_cache)) - 1;


ls_ba_checked_wlistc <= ls_wlist_copy_cache_q(idx DOWNTO idx-1);
ls_ba_checked_rlist <= ls_rlist_cache_q(idx DOWNTO idx-1);
ls_idx <= idx;

END IF;
END PROCESS CHECKCACHES_comb;

Rgds
Andre

 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      01-16-2007
wrote:

> Yes, it is clear now for simulation.
> But what about synthesis ?


If the design simulates ok,
synthesis should be a detail.

The design process is that same
with or without variables.

With reasonable code design rules, the
simulation waveforms at the ports
matches what I see on the bench.

-- Mike Treseler
 
Reply With Quote
 
Jim Lewis
Guest
Posts: n/a
 
      01-16-2007
Mike Treseler wrote:
> If the design simulates ok,
> synthesis should be a detail.
>
> The design process is that same
> with or without variables.

I agree. The functionality will be correct,
however sometimes with variables the synthesis
tool will be a little generous with registers.
For example if a variable is read before it is
written, it may create a register even when
that register is redundant. In the process below
sometimes VAR will create a register eventhough
that register has the same inputs as the Count
register:

VarProc : Process
begin
wait until Clk = '1' ;
VAR := VAR + 1 ;
Count <= VAR ;
end process ;


> But what about synthesis ? When using variables as shown in the first
> approach, do I have to define the ELSE condition for the variable ?
>
> CHECKCACHES_comb: PROCESS(ls_check_w_wc_r_list, ls_pos_col_in_cache,
> ls_wlist_copy_cache_q,
> ls_rlist_cache_q, ls_idx)
> VARIABLE idx : integer RANGE 0 TO 127;
> BEGIN
> ls_ba_checked_wlistc <= "00";
> ls_ba_checked_rlist <= "00";
> idx := 0; -- ??? necessary
>
>
> IF ls_check_w_wc_r_list='1' THEN
> idx := 2 * to_integer(unsigned(ls_pos_col_in_cache)) - 1;
>
>
> ls_ba_checked_wlistc <= ls_wlist_copy_cache_q(idx DOWNTO idx-1);
> ls_ba_checked_rlist <= ls_rlist_cache_q(idx DOWNTO idx-1);
> ls_idx <= idx;
>
> END IF;
> END PROCESS CHECKCACHES_comb;


Good question. First this process does create latches for
ls_ba_checked_wlistc, ls_ba_checked_rlist, and ls_idx.
If it did create a latch for idx, that latch would be redundant
with the latch for ls_idx.

Without an assignment outside of the if condition, it is possible
that it would create a latch for idx - not very logical though,
but remember synthesis tools are algorithmic - not logical.

I would not assign idx to 0 outside the if statement as that
would imply a multiplexer for idx. Instead if I were worried,
I would move the assignment to idx outside of the if statement.

Cheers,
Jim Lewis
SynthWorks
 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      01-16-2007
Jim Lewis wrote:

> For example if a variable is read before it is
> written, it may create a register even when
> that register is redundant.


The implication is that using variables
wastes flops, and this simply is not true.

If the register is not intended,
that is a design error like any
other that would be picked up and corrected
during the edit-sim-edit cycle.
Is the wave correct or is it delayed by a tick?

The simulation results are what matters.
Synthesis tools are very efficient with
signals or variables.

> In the process below
> sometimes VAR will create a register even though
> that register has the same inputs as the Count
> register:
>
> VarProc : Process
> begin
> wait until Clk = '1' ;
> VAR := VAR + 1 ;
> Count <= VAR ;
> end process ;


The error here is that the port
assignment is inside a clocked clause.
This infers an output pipeline register.

If I put the port assignment
outside of the clocked clause,
no pipeline register is inferred.

clked : process(clk)
variable cnt_v : count_t;
begin
if rising_edge(clk) then
cnt_v := cnt_v + 1; -- increment on rising edge
end if;
cnt <= cnt_v; -- wire assignment outside of clocked clause
end process clked;

see synthesis results here:
http://home.comcast.net/~mike_treseler/rollover.pdf

see full design here:
http://home.comcast.net/~mike_treseler/rollover.vhd


-- Mike Treseler
 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      01-16-2007
Synplicity has always done a good job of optimizing out redundant
flops, so long as they really are redundant (i.e. both have same async
reset, etc.)!

I've found Mike's method of making the port/signal assignment
outside/after the clock clause to be more efficient, since it avoids
creating the redundant flop in the first place. Inside the clock clause
creates a count register with the combinatorial var as input, outside
the clock clause creates a combinatorial count signal from the
registered var. Sixes either way.

Interestingly, when I ran a test with two functionally (on a
clock-clock basis) identical output signals (one inside, one outside
the clock clause), synplicity did figure out that they were both
identical, and optimized one out. This was even when the LHS was an
expression of variables, as in:

if rising_edge(clk) then
vara := vara + 1;
varb := varb + 1;
siga <= vara + varb; -- register of combo values for a,b
end if; -- rising_edge
sigb <= vara + varb; -- combo of registered values for a,b

Andy


Mike Treseler wrote:
> Jim Lewis wrote:
>
> > For example if a variable is read before it is
> > written, it may create a register even when
> > that register is redundant.

>
> The implication is that using variables
> wastes flops, and this simply is not true.
>
> If the register is not intended,
> that is a design error like any
> other that would be picked up and corrected
> during the edit-sim-edit cycle.
> Is the wave correct or is it delayed by a tick?
>
> The simulation results are what matters.
> Synthesis tools are very efficient with
> signals or variables.
>
> > In the process below
> > sometimes VAR will create a register even though
> > that register has the same inputs as the Count
> > register:
> >
> > VarProc : Process
> > begin
> > wait until Clk = '1' ;
> > VAR := VAR + 1 ;
> > Count <= VAR ;
> > end process ;

>
> The error here is that the port
> assignment is inside a clocked clause.
> This infers an output pipeline register.
>
> If I put the port assignment
> outside of the clocked clause,
> no pipeline register is inferred.
>
> clked : process(clk)
> variable cnt_v : count_t;
> begin
> if rising_edge(clk) then
> cnt_v := cnt_v + 1; -- increment on rising edge
> end if;
> cnt <= cnt_v; -- wire assignment outside of clocked clause
> end process clked;
>
> see synthesis results here:
> http://home.comcast.net/~mike_treseler/rollover.pdf
>
> see full design here:
> http://home.comcast.net/~mike_treseler/rollover.vhd
>
>
> -- Mike Treseler


 
Reply With Quote
 
Jim Lewis
Guest
Posts: n/a
 
      01-16-2007
Mike,
>> For example if a variable is read before it is
>> written, it may create a register even when
>> that register is redundant.

>
> The implication is that using variables
> wastes flops, and this simply is not true.

Touchy are we

It only takes one counter case to prove this
statement wrong and I just showed you one.

> If the register is not intended,
> that is a design error like any
> other that would be picked up and corrected
> during the edit-sim-edit cycle.
> Is the wave correct or is it delayed by a tick?


The wave is correct - only one register in simulation.
Gate and RTL simulation match, yet the synthesis results
have 2 registers. If you look at the synthesis
results, you will see that both registers (VAR and Count)
have the same input - hence the tool did waste registers.

> The simulation results are what matters.
> Synthesis tools are very efficient with
> signals or variables.


With respect to registers, some synthesis tools
seem to be more generous producing registers than
others.

>> In the process below
>> sometimes VAR will create a register even though
>> that register has the same inputs as the Count
>> register:
>>
>> VarProc : Process
>> begin
>> wait until Clk = '1' ;
>> VAR := VAR + 1 ;
>> Count <= VAR ;
>> end process ;

>
> The error here is that the port
> assignment is inside a clocked clause.
> This infers an output pipeline register.


Nope. No extra pipeline delay.
BTW, this code is 1076.6-1999 and 1076.6-2004
compliant. As are results that produce either
one or two registers (the standard is about producing
results and not optimization).

> If I put the port assignment
> outside of the clocked clause,
> no pipeline register is inferred.
>
> clked : process(clk)
> variable cnt_v : count_t;
> begin
> if rising_edge(clk) then
> cnt_v := cnt_v + 1; -- increment on rising edge
> end if;
> cnt <= cnt_v; -- wire assignment outside of clocked clause
> end process clked;
>


The fact that you can fix the code is not the point.
The point is there is some code (not good code) that
looks fine, but will produce area inefficient results.

Also although you got results, is your code style portable?
In particular, does it work on Synopsys? I know they
did not support it in the past. Also it is not 1076.6-1999
compliant, it may not be 1076.6-2004 compliant either
(it certainly was not intended to be).

Cheers,
Jim

OTOH, so what if variables are inefficient with respect to
registers? Would you notice? Not unless you did not
fit in the chip.
 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      01-17-2007
Andy wrote:
> Synplicity has always done a good job of optimizing out redundant
> flops, so long as they really are redundant (i.e. both have same async
> reset, etc.)!


Quartus and ISE also take out the duplicate flops, post-fit.
However they can show up in the pre-fit RTL view.

> I've found Mike's method of making the port/signal assignment
> outside/after the clock clause to be more efficient, since it avoids
> creating the redundant flop in the first place.


This also gives me a clean RTL schematic
without running a full synthesis.

-- Mike Treseler
 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      01-17-2007
Jim Lewis wrote:

> It only takes one counter case to prove this
> statement wrong and I just showed you one.


The duplicate flops only show up in the RTL view,
not in the tech view. The removal is also
noted in the log file.

> The wave is correct - only one register in simulation.
> Gate and RTL simulation match, yet the synthesis results
> have 2 registers. If you look at the synthesis
> results, you will see that both registers (VAR and Count)
> have the same input - hence the tool did waste registers.


Yes, sorry, it is a duplication,
not a pipe at the RTL level.
But synthesis removes it, post-fit.

> With respect to registers, some synthesis tools
> seem to be more generous producing registers than
> others.
> The fact that you can fix the code is not the point.
> The point is there is some code (not good code) that
> looks fine, but will produce area inefficient results.


Hmmm. Synplicity, Quartus and ISE get it right,
even for the "not good code".
What synthesis should I use to duplicate
these inefficient results?

> Also although you got results, is your code style portable?
> In particular, does it work on Synopsys? I know they
> did not support it in the past. Also it is not 1076.6-1999
> compliant, it may not be 1076.6-2004 compliant either
> (it certainly was not intended to be).


I have one email reporting that my reference design produces
an error on an unspecified version of Synopsys, but it involves my use
of procedures, not variables. But without the use
of a license it is impossible for me to narrow it down,
and I have no interest in buying one.
Other than that, the style is portable, as far as I know.

> OTOH, so what if variables are inefficient with respect to
> registers? Would you notice? Not unless you did not
> fit in the chip.


I'm sure I wouldn't notice even if it were true.
But it isn't true for any of the tools that I use,
and I cringe when new users are frightened away
from perfectly useful synthesis concepts like
variable assignments.

-- Mike Treseler

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Dynamic indexing (multi-dimensional-indexing) (probably my most important/valuable posting up to this date) Skybuck Flying C Programming 30 09-18-2011 11:29 PM
Indexing services under Windows XP SP2 - Can I disable MS Indexing Service to hasten Google's OR does Google Desktop uses this MS Indexing Service? ricardodefaria Computer Support 6 08-05-2007 04:14 AM
How much slower is dict indexing vs. list indexing? Emin Python 4 01-12-2007 02:40 PM
Indexing PDF's using MS Indexing Service C ASP General 3 10-17-2003 05:47 PM
Indexing PDF Files using MS Indexing Service C ASP .Net 0 10-17-2003 04:27 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57