FPGARelated.com
Forums

how can I improve my code?

Started by Unknown April 29, 2005
info_ wrote:

> They don't quite say this (or they'd lie). > "If ... elseif" has an implied priority (first test true -> next tests > are not taken)... but that makes no sense when you describe a truth table ! > (as in my first encoder example)
"case" and "if then else" have no overlapping cases and therefore no priority. "if then else elsif elsif ... " only implies priority if cases overlap.
> I think this is the same with std_ulogic, which use was supposed > to help detect multiple drivers situations (it did). But there > are other ways to check this and so many other bad things are > to be tested at synthesis that everybody has dropped now this > unresolved type and obsolete style.
I agree that std_ulogic_vector is usually more trouble than it's worth. However std_ulogic has no such downside. I use std_ulogic as my default bit type. It port maps directly to std_logic without conversion. -- Mike Treseler
Hi Mike,

Mike Treseler wrote:

> "if then else elsif elsif ... " > only implies priority if cases overlap.
if A(7) = '1' then Q <= "111"; elsif A(6) = '1' then Q <= "110"; etc... do overlap, but even then, it does not necessarily require or imply a priority-based implementation.
> I agree that std_ulogic_vector is usually > more trouble than it's worth. > However std_ulogic has no such downside. > I use std_ulogic as my default bit type. > It port maps directly to std_logic without conversion.
Seems I was a bit too quick to burry std_ulogic... I still won't use it, nor RTL procedures, but this is more a matter of habits and personal taste. I once suspected that you were using both as a hidden signature to copyright your code ;-) Cheers, Bert Cuzeau
Hi Bert,

info_ wrote:

> if A(7) = '1' then Q <= "111"; > elsif A(6) = '1' then Q <= "110"; > etc... > do overlap, but even then, it does not necessarily > require or imply a priority-based implementation.
I agree. Synthesis is free to make any netlist that sims like the code. I have found that coding style has a negligible effect on utilization for equivalent descriptions. My point was that the logical idea of priority does not apply to all problems. Some are pieces of pie and some are Olympic rings.
> I still won't use it, nor RTL procedures, but this is more > a matter of habits and personal taste. I once suspected that > you were using both as a hidden signature to copyright your code > ;-)
Yes. It's a little like changing the spelling of my name on magazine subscriptions to see where it goes.
> Cheers
Hey howdy, -- Mike Treseler
I need to add some more information to be absolutely accurate :

> -- ------------------------------------- > Architecture RTL_if of HOTDECOD is > -- ------------------------------------- > -- and how many LUTS for this one ? > -- Isn't this description easier to rewrite under > -- the form of a (size-independant) function ? > begin > > process (A) > begin > if A(7) = '1' then Q <= "111"; > elsif A(6) = '1' then Q <= "110"; > elsif A(5) = '1' then Q <= "101"; > elsif A(4) = '1' then Q <= "100"; > elsif A(3) = '1' then Q <= "011"; > elsif A(2) = '1' then Q <= "010"; > elsif A(1) = '1' then Q <= "001"; > elsif A(0) = '1' then Q <= "000"; > else Q <= "---"; -- don't care > end if; > end process; > -- do you see a "priority" in the synthesized result ???
There IS in fact a priority in the description above which is indeed respected in the synthesized result ! This description works as a one hot decoder, but it is also a priority encoder when it handles the overlapping cases. This is why this solution is still not optimal (as a one-hot decoder)! (5 LUTs instead of 3). A really optimized one hot decoder (with all synthesis tools) can be built with the following function (provided by S. Weir in an old post) : ---------------------------------------------------------------------------- -- Encode a vector of discrete bits into a binary vector representation, -- WITHOUT guarding against multiple bits on. -- -- For a single bit on, the encoded value is the offset from the -- low index of src of the asserting bit, regardless of src's -- endianness. ---------------------------------------------------------------------------- function fnEncBin ( src : std_logic_vector ) return std_logic_vector is variable rslt : std_logic_vector( fnLog2M( src'length ) - 1 downto 0 ) ; begin rslt := ( rslt'range => '0' ) ; for rslt_idx in rslt'range loop for src_idx in src'length - 1 downto 0 loop if( ( ( src_idx / ( 2**rslt_idx ) ) MOD 2 ) = 1 ) then rslt( rslt_idx ) := rslt( rslt_idx ) OR src( src_idx + src'low ) ; end if ; end loop ; end loop ; return( rslt ) ; end ; This function simply infers the OR gates directly ! In the case of this post, the one hot decoder ends up in three (4 inputs) LUTs, one logic layer instead of 2 (or more). I don't think there is any other description that infers the minimal result with all synthesis tools. Bert Cuzeau
Info,
The code above given by you for onehot did sysnthesize differently. the
"case" version systhesized to 3 LUT's involving only OR gates and didnt
infer priority structure infact it optimized as you have mentioned to a
series of OR gates. But the "if" version systhesiszed to 6 LUT's and
inferred a priority structure. Leonardo was used for the systhesis.

Hi Symon,
for (most) of the given examples case and if-elsif will give the same result.
Why?
Because in both cases :-) your selector is fully covered (uses all of the bits of a vector or whatever you use as a 
selector). Your if-elsif collapses into a parallel structure, because there is no priority of one value over the other 
possible.

but how about this:

Selector <= A&B&C;  -- I MUST do this for a case statement !
case Selector is
   when "001" => Output <= Input1;
   when "010" => Output <= Input2;
   when "100" => Output <= Input2;
   when others => Output <= (others => 'Z');
end case;

vs.

If C = '1' then
   Output <= Input1;
elsif B= '1' then
   Output <= Input2;
elsif C= '1' then
   Output <= Input3;
else
   Output <= (others => 'Z');
end if;

NOW the case produces a parallel multiplexer structure that is sensitive for the given code of Selector.
The if-elsif does something different. Whenever C becomes '1' (No matter how unlikely or unneccesary this might be in 
your particular design) it switches Input1 to the output. Here we have the always cited priority encoder.

To get the same functionality with a case you have to write a different code:

Selector <= A&B&C;  -- I MUST do this for a case statement !
case Selector is
   when "--1" => Output <= Input1;
   when "-10" => Output <= Input2;
   when "100" => Output <= Input2;
   when others => Output <= (others => 'Z');
end case;

Now the first >when< hits whenever C becomes '1'.
This code might produce something more "parallel" than the if-elsif, but who knows about the tricks of modern synthesis 
tools. :-)

Have a nice synthesis

   Eilert



Neo wrote:
> Info, > The code above given by you for onehot did sysnthesize differently. the > "case" version systhesized to 3 LUT's involving only OR gates and didnt > infer priority structure infact it optimized as you have mentioned to a > series of OR gates. But the "if" version systhesiszed to 6 LUT's and > inferred a priority structure. Leonardo was used for the systhesis. >
Yes my point exactly. Not all tools do this correctly. Leoanrdo is right. Just try Precision Synthesis (or other tools) if you can and compare the results. The if .. elsif is a priority encoder which has a well defined behavior for the overlapping cases (more than one 1 in the vector), and this requires more logic than the "pure one hot". This edscription is more predictible acroos tools. Bert
backhus wrote:

> Hi Symon, > for (most) of the given examples case and if-elsif will give the same > result. > Why? > Because in both cases :-) your selector is fully covered (uses all of > the bits of a vector or whatever you use as a selector). Your if-elsif > collapses into a parallel structure, because there is no priority of one > value over the other possible. > > but how about this: > > Selector <= A&B&C; -- I MUST do this for a case statement ! > case Selector is > when "001" => Output <= Input1; > when "010" => Output <= Input2; > when "100" => Output <= Input2; > when others => Output <= (others => 'Z'); > end case; > > vs. > > If C = '1' then > Output <= Input1; > elsif B= '1' then > Output <= Input2; > elsif C= '1' then > Output <= Input3; > else > Output <= (others => 'Z'); > end if; > > NOW the case produces a parallel multiplexer structure that is sensitive > for the given code of Selector. > The if-elsif does something different. Whenever C becomes '1' (No matter > how unlikely or unneccesary this might be in your particular design) it > switches Input1 to the output. Here we have the always cited priority > encoder. > > To get the same functionality with a case you have to write a different > code: > > Selector <= A&B&C; -- I MUST do this for a case statement ! > case Selector is > when "--1" => Output <= Input1; > when "-10" => Output <= Input2; > when "100" => Output <= Input2; > when others => Output <= (others => 'Z'); > end case; > > Now the first >when< hits whenever C becomes '1'. > This code might produce something more "parallel" than the if-elsif, but > who knows about the tricks of modern synthesis tools. :-) > > Have a nice synthesis > > Eilert
Just a few errors : 1. you can in fact qualify the expression and not use a signal. A variable is usually preferable if you want one (otherwise, you must add Selector in your sensitivity list, and this slows down the simulation without usefulness). case SLV3'(A&B&C) is -- with subtype SLV3 is std_logic_vector (3 downto 0); 2. output <= 'Z' infers a tristate, nothing to do with a don't care! A don't care '-' does eliminate C from the result. 3. case ... is when "--1" is wrong ! Comparing anything (but a '-') to '-' produces a false. Comparing with '-' (to ignore the comparison) requires the use of std_match (not usable in case statement). VHDL is not always intuitive... Bert Cuzeau