Q: code advice 
Author Message
 Q: code advice

To VHDL professionals,

   I don't have the resources to check the synthesizability of this code, but I
am wondering which would be more efficient and accurate representation of what
I need: a nested if-elsif-else block or a case statement derived as shown?
   Here's some background: I have to mux 1 of 4 data lines or 0's to an output
port, depending on the configurations of the 4 data generators.  Specifically,
a maximum of 1 generator, if any, can have the desired config:
(GENn_CNF = "11001"). This will be guaranteed by an
external control block. Inputs are the 4 data streams and the 4 generator
configurations. Data bus is 20 bits wide, and here is the code:

   --check which generator,if any, has the proper coding
   --EXERPT #1:

   if (GEN1_CNF = "11001") then              
      MUX_V := MEMI_1;
      GO_V := MEMI_1_GO;        
   elsif (GEN2_CNF = "11001") then
      MUX_V := MEMI_2;
      GO_V := MEMI_2_GO;        
   elsif (GEN3_CNF = "11001") then
      MUX_V := MEMI_3;
      GO_V := MEMI_3_GO;
   elsif (GEN4_CNF = "11001") then
      MUX_V := MEMI_4;
      GO_V := MEMI_4_GO;
   else
      MUX_V := (others => '0')
      GO_V := '0';
   end if;

   --EXERPT #2:

   MUX_SEL := (GEN1_CNF = "11001") & (GEN2_CNF = "11001") &
                (GEN3_CNF = "11001") & (GEN4_CNF = "11001");

   case MUX_SEL is
     when "1000" =>
       MUX_V := MEMI_1;
       GO_V := MEMI_1_GO;      
     when "0100" =>
       MUX_V := MEMI_2;
       GO_V := MEMI_2_GO;
     when "0010" =>
       MUX_V := MEMI_3;
       GO_V := MEMI_3_GO;
     when "0001" =>
       MUX_V := MEMI_4;
       GO_V := MEMI_4_GO;
     when others =>          --"0000" will be only permissible
       MUX_V := (others => '0');
       GO_V := '0';
   end case;

Thanks in advance for any assistance.
Jeff



Fri, 05 Feb 1999 03:00:00 GMT  
 Q: code advice

Quote:

>  Specifically,a maximum of 1 generator, if any, can have the desired config: (GENn_CNF = "11001"). This will be guaranteed by an
>external control block.
>   --check which generator,if any, has the proper coding
>   --EXERPT #1:

>   if (GEN1_CNF = "11001") then          
>      MUX_V := MEMI_1;
>      GO_V := MEMI_1_GO;    
>   elsif (GEN2_CNF = "11001") then
>      MUX_V := MEMI_2;
>      GO_V := MEMI_2_GO;    
>   elsif (GEN3_CNF = "11001") then
>      MUX_V := MEMI_3;
>      GO_V := MEMI_3_GO;
>   elsif (GEN4_CNF = "11001") then
>      MUX_V := MEMI_4;
>      GO_V := MEMI_4_GO;
>   else
>      MUX_V := (others => '0')
>      GO_V := '0';
>   end if;

>   --EXERPT #2:

>   MUX_SEL := (GEN1_CNF = "11001") & (GEN2_CNF = "11001") &
>            (GEN3_CNF = "11001") & (GEN4_CNF = "11001");

>   case MUX_SEL is
>     when "1000" =>
>       MUX_V := MEMI_1;
>       GO_V := MEMI_1_GO;  
>     when "0100" =>
>       MUX_V := MEMI_2;
>       GO_V := MEMI_2_GO;
>     when "0010" =>
>       MUX_V := MEMI_3;
>       GO_V := MEMI_3_GO;
>     when "0001" =>
>       MUX_V := MEMI_4;
>       GO_V := MEMI_4_GO;
>     when others =>              --"0000" will be only permissible
>       MUX_V := (others => '0');
>       GO_V := '0';
>   end case;

>Thanks in advance for any assistance.
>Jeff

In neither Excerpt can the tool see that your signals are truely mutual
exclusive.

Excerpt #1 is a priority encoder.  
Excerpt #2 might get the desired result if MUX_V := (others => 'X'), but
you would be at the mercy of your synthesizer.

If you want the efficient synthesis, what you want is AND-OR logic.

SEL1 := (GEN1_CNF = "11001") ;
..
SEL4 := (GEN4_CNF = "11001") ;

MUX_V := (SEL1 and MEMI_1) or (SEL2 and MEMI_2) or ... (SEL4 and MEMI_4)

OOPS you have a vector.  You will have to overload the and function so
that it will take a bit value (std_logic) and "AND" it with a vector
(std_logic_vector).

I do this type of thing all the time and have such an AND function.

Cheers,
Jim Lewis
ASIC and HDL Consultant



Sat, 06 Feb 1999 03:00:00 GMT  
 Q: code advice

Jeffrey,

I did not specifically go through the code that you posted.  But, when
writing synthesizable code case statements translate into a mux with
control logic to drive the select inputs, while if-else statements
translate into a priority encoder.

Hope this helps.

Duncan Halstead

--
******************************************************************
Duncan Halstead
Systems Integration Test Engineer
Symbios Logic
2001 Danfield Court            Fax  : (970) 225-4829
Fort Collins, CO 80525         Ph # : (970) 223-5100 x 9032
******************************************************************



Sat, 06 Feb 1999 03:00:00 GMT  
 Q: code advice

: To VHDL professionals,

:    I don't have the resources to check the synthesizability of this code, but I
: am wondering which would be more efficient and accurate representation of what
: I need: a nested if-elsif-else block or a case statement derived as shown?
:    Here's some background: I have to mux 1 of 4 data lines or 0's to an output
: port, depending on the configurations of the 4 data generators.  Specifically,
: a maximum of 1 generator, if any, can have the desired config:
: (GENn_CNF = "11001"). This will be guaranteed by an
: external control block. Inputs are the 4 data streams and the 4 generator
: configurations. Data bus is 20 bits wide, and here is the code:

:    --check which generator,if any, has the proper coding
:    --EXERPT #1:

:    if (GEN1_CNF = "11001") then            
:       MUX_V := MEMI_1;
:       GO_V := MEMI_1_GO;      
:    elsif (GEN2_CNF = "11001") then
:       MUX_V := MEMI_2;
:       GO_V := MEMI_2_GO;      
:    elsif (GEN3_CNF = "11001") then
:       MUX_V := MEMI_3;
:       GO_V := MEMI_3_GO;
:    elsif (GEN4_CNF = "11001") then
:       MUX_V := MEMI_4;
:       GO_V := MEMI_4_GO;
:    else
:       MUX_V := (others => '0')
:       GO_V := '0';
:    end if;

:    --EXERPT #2:

:    MUX_SEL := (GEN1_CNF = "11001") & (GEN2_CNF = "11001") &
:               (GEN3_CNF = "11001") & (GEN4_CNF = "11001");

I would have thought that the construct (GEN1_CNF = "11001") is a relational
expression and so returns BOOLEAN. Hence, you appear to be concatenating
four boolean expressions. This boolean expression is then used in a case statement
where the selections are bit/logic_vectors. I don't think this will work.

How about MUX_SEL(0) := '1' if (GEN1_CNF = "11001") else '0';
          MUX_SEL(1) := '1' if (GEN2_CNF = "11001") else '0';
          MUX_SEL(2) := '1' if (GEN3_CNF = "11001") else '0';
          MUX_SEL(3) := '1' if (GEN4_CNF = "11001") else '0';
          case MUX_SEL is

On a general note, I have asked our synopsys AE's the question about the
equivalence of CASE vs IF-THEN-ELSIF-ELSIF....

It should first be noted that all selections in a case statement are
mutually exclusive - only one selection can be true at any one time.
Now, if the case statement was translated into an equivalent if-then-elsif-elsif
structure, then it would be seen that each of the branches are still mutually
exclusive.

The AE's indicated that if and if-then-elsif-elsif structure has mutually
exclusive brances, then dc-shell will recognize this and synthesize to a level
of quality similar to a case statement. By "level of quality similar to" I mean
that the synthesis process will treat each of the inputs to the combinatorial
block logic in an equal manner. No one input has an implied priority over the
other.

It is important to note that the mutual exclusivity must be determined from the
conditions in the branches and not by knowledge of the signals that provide the
expressions in the branches. To explain, consider the example above. From
a system point of view, it may be known that only one of the conditions will
evaluate to be true. In this instance, the system provides mutual exclusivity
of the branches. But the synthesis tool will not have knowledge of the system
behaviour. It can only look at the expressions, and it will note that some or all
of the expression can be true at the same time. This means, that it will maintain
the priority encoding and will give a different quality of result than with the
case statement below.
Functioanally, the case statement below is equivalent, but the synthesis tool
can determine that each branch is mutually exclusive and can use this to
obtain a better quality of synthesis.

Does anyone else agree??
Andrew

:    case MUX_SEL is
:      when "1000" =>
:        MUX_V := MEMI_1;
:        GO_V := MEMI_1_GO;    
:      when "0100" =>
:        MUX_V := MEMI_2;
:        GO_V := MEMI_2_GO;
:      when "0010" =>
:        MUX_V := MEMI_3;
:        GO_V := MEMI_3_GO;
:      when "0001" =>
:        MUX_V := MEMI_4;
:        GO_V := MEMI_4_GO;
:      when others =>                --"0000" will be only permissible
:        MUX_V := (others => '0');
:        GO_V := '0';
:    end case;

: Thanks in advance for any assistance.
: Jeff



Tue, 09 Feb 1999 03:00:00 GMT  
 Q: code advice

Quote:

>Functioanally, the case statement below is equivalent, but the synthesis tool
>can determine that each branch is mutually exclusive and can use this to
>obtain a better quality of synthesis.

>Does anyone else agree??
>Andrew

>:    case MUX_SEL is
>:      when "1000" =>
>:        MUX_V := MEMI_1;
>:        GO_V := MEMI_1_GO;
>:      when "0100" =>
>:        MUX_V := MEMI_2;
>:        GO_V := MEMI_2_GO;
>:      when "0010" =>
>:        MUX_V := MEMI_3;
>:        GO_V := MEMI_3_GO;
>:      when "0001" =>
>:        MUX_V := MEMI_4;
>:        GO_V := MEMI_4_GO;
>:      when others =>            --"0000" will be only permissible
>:        MUX_V := (others => '0');
>:        GO_V := '0';
>:    end case;

I would say that this case statement does not take full advantage of the
mutual exclusiveness.  

Consider the case when MUX_SEL = "1001".  We all agree that this will not
happen due to the assertions about mutual exclusion.  The "when others"
setting things to zero forces this condition to '0'.  To minimize the
logic, one thing we could say is that we don't care.  Setting 'X' in the
"when others".  In this case the tool may see the minimization and take
advantage of the mutual exclusiveness of the select logic - on the other
hand, it may not.  

If you want to hit it every time, see my prevoius follow up to this on
using AND-OR logic.  Some might argue that it is a little more low level
coding, but I get the results I want without having to play games with
the synthesis tool.

Cheers,
Jim Lewis

P.S. great explination on the case vs. if-else decisions.  I avoid the
if-else unless I want priority (or a 2-1 mux).



Tue, 09 Feb 1999 03:00:00 GMT  
 Q: code advice


Quote:

...
>   I don't have the resources to check the synthesizability of this code,
>but I am wondering which would be more efficient and accurate representation
...
>   if (GEN1_CNF = "11001") then          
>      MUX_V := MEMI_1;
>      GO_V := MEMI_1_GO;    
>   elsif (GEN2_CNF = "11001") then
>      MUX_V := MEMI_2;
>      GO_V := MEMI_2_GO;    
>   elsif (GEN3_CNF = "11001") then
>      MUX_V := MEMI_3;
>      GO_V := MEMI_3_GO;
>   elsif (GEN4_CNF = "11001") then
>      MUX_V := MEMI_4;
>      GO_V := MEMI_4_GO;
>   else
>      MUX_V := (others => '0')
>      GO_V := '0';
>   end if;
...

>   MUX_SEL := (GEN1_CNF = "11001") & (GEN2_CNF = "11001") &
>            (GEN3_CNF = "11001") & (GEN4_CNF = "11001");

>   case MUX_SEL is
>     when "1000" =>
>       MUX_V := MEMI_1;
>       GO_V := MEMI_1_GO;  
>     when "0100" =>
>       MUX_V := MEMI_2;
>       GO_V := MEMI_2_GO;
>     when "0010" =>
>       MUX_V := MEMI_3;
>       GO_V := MEMI_3_GO;
>     when "0001" =>
>       MUX_V := MEMI_4;
>       GO_V := MEMI_4_GO;
>     when others =>              --"0000" will be only permissible
>       MUX_V := (others => '0');
>       GO_V := '0';
>   end case;

...


...

Quote:
>I would have thought that the construct (GEN1_CNF = "11001") is a relational
>expression and so returns BOOLEAN. Hence, you appear to be concatenating
>four boolean expressions. This boolean expression is then used in a case statement
>where the selections are bit/logic_vectors. I don't think this will work.

>How about MUX_SEL(0) := '1' if (GEN1_CNF = "11001") else '0';
>          MUX_SEL(1) := '1' if (GEN2_CNF = "11001") else '0';
>          MUX_SEL(2) := '1' if (GEN3_CNF = "11001") else '0';
>          MUX_SEL(3) := '1' if (GEN4_CNF = "11001") else '0';
>          case MUX_SEL is

Yes, but the revised code doesn't work either.  What Hana wrote would
be OK if MUX_SEL were a signal and the "if" were a "when" and it was a
concurrent statement.  But to use variables, it must be sequential and
the if/then/else controls must bracket complete signal assignments.

Below are versions which give an area of 51 and a speed of 6.3 ns for
the IF/THEN (case_if1) and an area of 52 and speed of 6.1 for the CASE
(case_if2).

This shows that using a case sometimes causes a good bit of work.  (I
may have missed an easier approach.)  Once you get the equivalent logic
described it doesn't make much difference in the result.

----------------- IF/THEN ------------------------------------------------

LIBRARY ieee;
USE ieee.std_Logic_1164.ALL;
ENTITY case_if1 IS
  PORT( MEMI_1, MEMI_2, MEMI_3, MEMI_4   : IN  std_logic_vector(4 DOWNTO 0);
        MEMI_1_GO, MEMI_2_GO, MEMI_3_GO,
        MEMI_4_GO: IN  std_logic;
        GEN1_CNF, GEN2_CNF, GEN3_CNF,
        GEN4_CNF : IN  std_logic_vector(4 DOWNTO 0);
        MUX      : OUT std_logic_vector(4 DOWNTO 0);
        GO       : OUT std_logic);
END;

ARCHITECTURE try OF case_if1 IS
BEGIN
  PROCESS(MEMI_1, MEMI_2, MEMI_3, MEMI_4, MEMI_1_GO, MEMI_2_GO,
          MEMI_3_GO, MEMI_4_GO, GEN1_CNF, GEN2_CNF, GEN3_CNF, GEN4_CNF)
    VARIABLE MUX_V: std_logic_vector(4 DOWNTO 0);
    VARIABLE GO_V : std_logic;
  BEGIN
    IF GEN1_CNF = "11001" THEN                
      MUX_V := MEMI_1;
      GO_V := MEMI_1_GO;        
    ELSIF GEN2_CNF = "11001" THEN
      MUX_V := MEMI_2;
      GO_V := MEMI_2_GO;        
    ELSIF GEN3_CNF = "11001" THEN
      MUX_V := MEMI_3;
      GO_V := MEMI_3_GO;
    ELSIF GEN4_CNF = "11001" THEN
      MUX_V := MEMI_4;
      GO_V := MEMI_4_GO;
    ELSE
      MUX_V := (OTHERS => '0');
      GO_V := '0';
    END IF;
    MUX <= MUX_V;
    GO <= GO_V;
  END PROCESS;
END;

----------------- CASE ------------------------------------------------

LIBRARY ieee;
USE ieee.std_Logic_1164.ALL;
ENTITY case_if2 IS
  PORT( MEMI_1, MEMI_2, MEMI_3, MEMI_4   : IN  std_logic_vector(4 DOWNTO 0);
        MEMI_1_GO, MEMI_2_GO, MEMI_3_GO,
        MEMI_4_GO: IN  std_logic;
        GEN1_CNF, GEN2_CNF, GEN3_CNF,
        GEN4_CNF : IN  std_logic_vector(4 DOWNTO 0);
        MUX      : OUT std_logic_vector(4 DOWNTO 0);
        GO       : OUT std_logic);
END;

ARCHITECTURE try OF case_if2 IS
BEGIN
  PROCESS(MEMI_1, MEMI_2, MEMI_3, MEMI_4, MEMI_1_GO, MEMI_2_GO,
          MEMI_3_GO, MEMI_4_GO, GEN1_CNF, GEN2_CNF, GEN3_CNF, GEN4_CNF)
    VARIABLE MUX_SEL: std_logic_vector(3 DOWNTO 0);
    VARIABLE MUX_V  : std_logic_vector(4 DOWNTO 0);
    VARIABLE GO_V   : std_logic;
  BEGIN
    IF GEN1_CNF = "11001" THEN
      MUX_SEL(0) := '1';
    ELSE
      MUX_SEL(0) := '0';
    END IF;
    IF GEN2_CNF = "11001" THEN
      MUX_SEL(1) := '1';
    ELSE
      MUX_SEL(1) := '0';
    END IF;
    IF GEN3_CNF = "11001" THEN
      MUX_SEL(2) := '1';
    ELSE
      MUX_SEL(2) := '0';
    END IF;
    IF GEN4_CNF = "11001" THEN
      MUX_SEL(3) := '1';
    ELSE
      MUX_SEL(3) := '0';
    END IF;
    CASE MUX_SEL IS
      WHEN "0001" | "0011" | "0101" | "0111" |
           "1001" | "1011" | "1101" | "1111"   =>
        MUX_V := MEMI_1;
        GO_V := MEMI_1_GO;      
      WHEN "0010" | "0110" | "1010" | "1110"   =>
        MUX_V := MEMI_2;
        GO_V := MEMI_2_GO;
      WHEN "0100" | "1100"=>
        MUX_V := MEMI_3;
        GO_V := MEMI_3_GO;
      WHEN "1000" =>
        MUX_V := MEMI_4;
        GO_V := MEMI_4_GO;
      WHEN OTHERS =>                 --"0000" will be only permissible
        MUX_V := (OTHERS => '0');
        GO_V := '0';
    END CASE;
    MUX <= MUX_V;
    GO <= GO_V;
  END PROCESS;
END;

Rich



Fri, 12 Feb 1999 03:00:00 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. Advice on Code please

2. (long) need advice to improve code

3. ADVICE: Code that prints itself

4. Wanted: TCP/IP in ADA (code & advice)

5. Advice sought: using g77,f2c for fortran code development

6. Efficient coding advice?

7. Advice for syntax-coloring Python code

8. Need advice on parallelizing fortran 90 code

9. iso TCL code design advice - long

10. Need advice for obfuscating Python code

11. Need advice on tcl/tk code!

12. several Qs

 

 
Powered by phpBB® Forum Software