![]() |
|
|
|||||||
![]() |
VHDL - Variable vs. Signal on indexing |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
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 ALuPin@web.de |
|
|
|
|
#2 |
|
Posts: n/a
|
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 > Jim Lewis |
|
|
|
#3 |
|
Posts: n/a
|
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 ALuPin@web.de |
|
|
|
#4 |
|
Posts: n/a
|
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 Mike Treseler |
|
|
|
#5 |
|
Posts: n/a
|
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 Jim Lewis |
|
|
|
#6 |
|
Posts: n/a
|
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 Mike Treseler |
|
|
|
#7 |
|
Posts: n/a
|
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 Andy |
|
|
|
#8 |
|
Posts: n/a
|
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. Jim Lewis |
|
|
|
#9 |
|
Posts: n/a
|
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 Mike Treseler |
|
|
|
#10 |
|
Posts: n/a
|
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 Mike Treseler |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Need help on Modelsim VHDL syntax? ASAP:) | kaji | General Help Related Topics | 0 | 03-14-2007 10:43 PM |
| Need help on a Modelsim VHDL Syntax? ASAP:) | kaji | Software | 0 | 03-14-2007 10:43 PM |
| Need Help on a Modelsim VHDL Syntax....ASAP:) | kaji | Hardware | 0 | 03-14-2007 10:41 PM |
| IMHO, Digital SECAM video is better than Analog NTSC video | Radium | DVD Video | 167 | 10-25-2006 04:16 AM |
| Variable Scope in asp.Net | jansi_rk | Software | 1 | 09-18-2006 06:05 PM |