WHEN-ELSE vs CASE statement

P

Peter

Guest
Hi,

I have always used a WHEN-ELSE statement to read back data from e.g. a
register bank. Example:

dout <= reg1 when adr = X"00"
else reg2 when adr = X"01"
...
...
...
else (others => '0';

In my last design I have run into timing problems, where the access
time is rather slow. My question is:
Would a CASE statement in general, lead to a faster - or a better
balanced - design?
The drawback with the CASE statement is of course that it has to be
used inside a process with an extensive sensitivity list.

Thanks in advance.

/Peter
 
Peter a écrit :

Hi,

I have always used a WHEN-ELSE statement to read back data from e.g. a
register bank. Example:

dout <= reg1 when adr = X"00"
else reg2 when adr = X"01"
...
...
...
else (others => '0';

In my last design I have run into timing problems, where the access
time is rather slow. My question is:
Would a CASE statement in general, lead to a faster - or a better
balanced - design?
The drawback with the CASE statement is of course that it has to be
used inside a process with an extensive sensitivity list.
Try a with-select concurrent statement!

JD.
 
Peter wrote:

Would a CASE statement in general, lead to a faster - or a better
balanced - design?
No. But a synchronous process might.

The drawback with the CASE statement is of course that it has to be
used inside a process with an extensive sensitivity list.
My suggestion for the sensitivity list is (reset, clk)

-- Mike Treseler
 
In this paricular case, the register bank in the FPGA is controlled
from a DSP.
I hesitated to make the bus interface synchronous, due to the problem
of transfering the 200 MHz DSP-clock to the bus interface with a
controlled timing between the DSPs bus cycle and the FPGA internal
clock. Therefore I made the bus interface asynchronous.
Thanks for all replies,
Further suggestions are welcome.

/Peter
 
Peter wrote:

I hesitated to make the bus interface synchronous, due to the problem
of transfering the 200 MHz DSP-clock to the bus interface with a
controlled timing between the DSPs bus cycle and the FPGA internal
clock. Therefore I made the bus interface asynchronous
.. . . and had timing problems.

This about synchronization not vhdl language.
Have a look at this:

http://www.chipdesignmag.com/display.php?articleId=32&issueId=5

-- Mike Treseler
 
Thanks Mike,

An interesting article that I will keep. But it is not obvious to me
that a synchronous design is without problems. How do you transfer the
200 MHz DSP clock to the FPGA, with a controlled delay under all
conditions?

In my case, all data catched in the asynchronous register bank, are
synchronised by 2-stage synchronisers before the are used in the
synchronous part of the design, but I got hold time violations in the
register bank due to a too large logic depth when the address bus was
decoded. When the write strobe was deactivated, data disappeared on the
bus before the strobe was decoded. This was solved by programming the
DSP to increase the hold time, but that leads back to my original
question: Are other language constructs better suited for decoding than
the WHEN-ELSE ?

/Peter
 
Peter wrote:

In my case, all data catched in the asynchronous register bank, are
synchronised by 2-stage synchronisers before the are used in the
synchronous part of the design, but I got hold time violations in the
register bank due to a too large logic depth when the address bus was
decoded. When the write strobe was deactivated, data disappeared on the
bus before the strobe was decoded. This was solved by programming the
DSP to increase the hold time, but that leads back to my original
question: Are other language constructs better suited for decoding than
the WHEN-ELSE ?
You might want to look into a case statement (parallel decoder).

The less you're decoding, of course, the faster the decode.

-a- (master of the obvious)
 
It seems like the previously mentioned WITH-SELECT is exactly what
you're looking for, as that will generate a mux instead of a long
priority selection chain.
 
jens wrote:
It seems like the previously mentioned WITH-SELECT is exactly what
you're looking for, as that will generate a mux instead of a long
priority selection chain.
A description of priority logic
requires overlapping cases. Synthesis
is not free to create priority
logic based on a keyword alone.

The vhdl branching statements
that cannot possibly describe priority
are based on a selection or a single
boolean expression:
1. A case statement.
2. A selected signal assignment
"with select when, ..., when ;"
3. The if statement with zero or one else clauses.
4. The conditional signal assignment
with zero or one else clauses.
" a <= a1 when b else a2;"

Complex "if elsif else" statements or
conditional signal assignments
with multiple else clauses can create priority
logic *only* if the expressions overlap.
It's not a matter of keywords
it's a matter of Kmaps.

-- Mike Treseler
 
As a general rule, I don't like to see if/else conditional on a
NON-overlapping argument such as an address decode regardless of the
intellegence of the synthesis tool. Am I beeing to rigid?

Due to the influx of software programmers to RTL, I want to know that
the person writing the code understands the hardware behind the text.
Putting 20 elsifs in a row seems sloppy and could be a sign of
uninformed coding.

Regarding OP, I use case/when but I cannot get the when/else or the
with/select code to work. Can someone fix this test case:

-- case_test.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity case_test is
Port (
clk : in std_logic; -- TBD Mhz system clk
rst_n : in std_logic; -- asynchronous, active low
data_in : in std_logic_vector(7 downto 0);
address : in std_logic_vector(3 downto 0);

product_out : out std_logic_vector(7 downto 0) );

end case_test;

architecture rtl of case_test is
-- Signal Declarations
signal d_q : std_logic_vector(7 downto 0);
begin

case_process: process (rst_n, clk)
begin

if rst_n = '0' then
product_out <= (others => '0');
d_q <= (others => '0');
elsif (clk'event and clk = '1') then
d_q <= data_in;

----Standard case/when example
--case address is
--when x"0" => product_out <= d_q(7 downto 0);
--when x"1" => product_out <= d_q(6 downto 0) & d_q(7);
--when x"2" => product_out <= d_q(5 downto 0) & d_q(7 downto 6);
--when x"3" => product_out <= d_q(4 downto 0) & d_q(7 downto 5);
--when x"4" => product_out <= d_q(3 downto 0) & d_q(7 downto 4);
--when x"5" => product_out <= d_q(2 downto 0) & d_q(7 downto 3);
--when x"6" => product_out <= d_q(1 downto 0) & d_q(7 downto 2);
--when x"7" => product_out <= d_q(0 downto 0) & d_q(7 downto 1);
--when others => product_out <= x"FF";
--end case;


----Failed attempt at when/else
product_out <= d_q when address = x"0"
else d_q(6 downto 0) & d_q(7) when address = x"1"
else d_q(5 downto 0) & d_q(7 downto 6) when address = x"2"
else d_q(4 downto 0) & d_q(7 downto 5) when address = x"3"
else d_q(3 downto 0) & d_q(7 downto 4) when address = x"4"
else d_q(2 downto 0) & d_q(7 downto 3) when address = x"5"
else d_q(1 downto 0) & d_q(7 downto 2) when address = x"6"
else d_q(0 downto 0) & d_q(7 downto 1) when address = x"7"
else x"FF" ;

end if;

end process;
end rtl;
 
I too tend to not make assumptions about what a synthesis tool is going
to do. If I write my VHDL in a manner that implies priority, I don't
assume that the synthesis tool is going to outsmart me. I've seen a
synthesis tool do some incredibly stupid things before... granted it
was a free version of Synplify that came with the free version of Actel
Libero.

The influx of software engineers does seem to be causing hardware
problems, maybe we need to come up with some motivational tapes, with
lines like "synchronous designs are good... use minimal clocks...
asynchronous designs are bad... synchronous designs are the way to
go... too many clocks are evil... think synchronous... use many clock
enables and only one clock... synchronous designs are your friend...
beware of signals crossing clock domains... become one with a
synchronous design..."

To answer Beanut's question about the failed attempt at when/else, use
when/else outside of a process and if/then/else inside a process (also
with/select outside a process and case inside a process).
 
Thanks Jens. My world doesn't exist outside a process.

I don't have motivational tapes, but I have my RTL 10 comandments that
I pass on to co/ops and untrained coworkers. Maybe I'll start a new
thread and let everyone make fun of them . . .
 
"Beanut" <fourbeans@gmail.com> writes:

As a general rule, I don't like to see if/else conditional on a
NON-overlapping argument such as an address decode regardless of the
intellegence of the synthesis tool. Am I beeing to rigid?
Yes. While I agree *in general*, it is sometimes necessary to use
if-elsif-else where case conditionals would be more readable.

Remember the rules for locally and globally static expressions.

-- Marcus
 
Marcus Harnisch wrote:

Yes. While I agree *in general*, it is sometimes necessary to use
if-elsif-else where case conditionals would be more readable.

Remember the rules for locally and globally static expressions.

Yes.
An "if" will take any expression.

A case expression can't be much more
than a type conversion or a scaler range.

-- Mike Treseler
 

Welcome to EDABoard.com

Sponsor

Back
Top