the "|" operator

A

abasili

Hi everyone I would have liked to ask you about the difference between
the two following codes:

-- case 1

process (clk, nrst)
begin
if nrst = '0' then
En <= '0';
elsif rising_edge (clk) then
case present_state is
when S0 | S1 | S2 =>
En <= '1';
when others =>
En <= '0';
end case;
end if;
end process;

-- case 2

process (clk, nrst)
begin
if nrst = '0' then
En <= '0';
elsif rising_edge (clk) then
case present_state is
when S0 =>
En <= '1';
when S1 =>
En <= '1';
when S2 =>
En <= '1';
when others =>
En <= '0';
end case;
end if;
end process;


I found this example on few references (as the VHDL Reference Manual of
Synario design automation), but when I look at the RTL produced with
Synplify then it's clear that the compiler produces something different
in the two cases.

My logic works fine (so far) and i'm using the first case but only
recently I realized about the differences and i was wondering why the
RTLs are different and whether one syntax is more convenient than the
other one. By the way I still didn't learn what's the name of that
symbol (i know is something that produce a mutually exclusive logic) and
I didn't yet find some information through Google and some books i have.
Thanks a lot for any help or reference.

Al
 
T

Tricky

My guess would be that Synplify hasnt recognised that in the 2nd case
S0, S1 and S2 outcomes are the same, whereas in the first you have
explicitly told it so. With this being the case, you only need 1 bit
to represent "present_state", whereas in case 2 its probably given you
2 and muxed it.
 
A

abasili

Tricky said:
My guess would be that Synplify hasnt recognised that in the 2nd case
S0, S1 and S2 outcomes are the same, whereas in the first you have
explicitly told it so. With this being the case, you only need 1 bit
to represent "present_state", whereas in case 2 its probably given you
2 and muxed it.

present_state is not defined here, so the number of bit associated with
it can be anything. According to the present_state definition (which is
elsewhere), the second case generates only a mux to generate En, while
in apparently in the first case it has an additional OR which i don't
know where it comes from.
The so called "vertical bar" (or "vertical line") apparently is needed
for mutually exclusive choices, as it should be in a case statement, so
the outcome should always be a mux, but I don't understand why the two
RTL are different.
Am I missing something? Probably yes :)
 
K

KJ

I found this example on few references (as the VHDL Reference Manual of
Synario design automation), but when I look at the RTL produced with
Synplify then it's clear that the compiler produces something different
in the two cases.

You might want to recheck what you're seeing, I couldn't reproduce
your results. At the end of this post is a complete design that
incorporates your logic. What I added to it to make it complete is an
entity and logic to cycle 'present_state' through it's various values.

Given this design, whether I use the 'case 1' approach or the 'case 2'
approach Synplify (vers 9.6.1) appears to produce the exact same RTL
and Technology views which is what is expected.
My logic works fine (so far) and i'm using the first case but only
recently I realized about the differences and i was wondering why the
RTLs are different

Maybe you changed something else in your code between when you tried
'case 1' and 'case 2'.

As an example, take a look at the code I added for driving the signal
'present_state'. What I have is a simple two bit roll over counter
that produces an index and then I convert that index to a valid
't_state' for the assignment to 'present_state'. If instead of an
unsigned counter you simply write code for 'present_state' that simply
cycles through 'S0'...'S3' you'll likely get a different RTL and Tech
view because Synplify might implement 'present_state' in one hot form
(i.e. use four flops, only one of which is '1' at any given time).
However, when you switch between 'case 1' and 'case 2' I think you'll
still end up with the same thing, just not the same as with my posted
code. If you then tell Synplify to use binary encoding instead of one
hot or default then you should end up with the same RTL/Tech view as
with my posted code. It could simply be that whatever you changed
when testing 'case 1' and 'case 2' changed something else that caused
'present_state' to be implemented differently.

Assuming that the above is the explanation for the differences that
you're seeing, then all you're seeing is the result of different
implemenation approaches (one hot versus binary encoding). Whether
one is 'better' or not depends on what your criteria for 'better' is.
For the most part the synthesis tool writers know the devices very
well and the resulting logic fits and meets timing which is the real
bottom line.
and whether one syntax is more convenient than the
other one.

The first form had less typing and is probably less prone to making
errors.

Kevin Jennings

-- Start of code
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Foo is
port(
clk: in std_ulogic;
nrst: in std_ulogic;
en: out std_ulogic);
end Foo;

architecture RTL of Foo is
type t_state is (S0, S1, S2, S3);
signal present_state: t_state;
signal counter: unsigned(1 downto 0);
begin

process(clk)
begin
if rising_edge(clk) then
if (nrst = '0') then
counter <= to_unsigned(0, counter'length);
else
counter <= counter + 1;
end if;
end if;
end process;

present_state <= t_state'val(to_integer(counter));

process (clk, nrst)
begin
if nrst = '0' then
En <= '0';
elsif rising_edge (clk) then
case present_state is
when S0 | S1 | S2 =>
En <= '1';
when others =>
En <= '0';
end case;
end if;
end process;


-- case 2


--Case 2 process (clk, nrst)
--Case 2 begin
--Case 2 if nrst = '0' then
--Case 2 En <= '0';
--Case 2 elsif rising_edge (clk) then
--Case 2 case present_state is
--Case 2 when S0 =>
--Case 2 En <= '1';
--Case 2 when S1 =>
--Case 2 En <= '1';
--Case 2 when S2 =>
--Case 2 En <= '1';
--Case 2 when others =>
--Case 2 En <= '0';
--Case 2 end case;
--Case 2 end if;
--Case 2 end process;

end RTL;
-- End of code
 
A

abasili

KJ said:
As an example, take a look at the code I added for driving the signal
'present_state'. What I have is a simple two bit roll over counter
that produces an index and then I convert that index to a valid
't_state' for the assignment to 'present_state'. If instead of an
unsigned counter you simply write code for 'present_state' that simply
cycles through 'S0'...'S3' you'll likely get a different RTL and Tech
view because Synplify might implement 'present_state' in one hot form
(i.e. use four flops, only one of which is '1' at any given time).

Most probably I was not focusing on the "present_state" implementation
which might have been different in the two cases (even though I don't
understand why) and this of course affected the way the rest of the
logic I was focusing on did change.
Assuming that the above is the explanation for the differences that
you're seeing, then all you're seeing is the result of different
implemenation approaches (one hot versus binary encoding). Whether
one is 'better' or not depends on what your criteria for 'better' is.
For the most part the synthesis tool writers know the devices very
well and the resulting logic fits and meets timing which is the real
bottom line.

Totally agree, optimization is always a very delicate point and I do
believe tools are much more advanced than users to optimize code.
Usually I first try to make it working, than maybe I will "beautify" it.
The first form had less typing and is probably less prone to making
errors.

I think it facilitates readability of the code as well and it's easier
to maintain.
 
A

abasili

Mike said:
The RTL viewer shows a logical netlist *before* optimization.
Small differences that are logically correct can be safely ignored.
But still when at least I write code I have some RTL in mind and if
there are some differences than maybe I'm not completely understanding
what I'm doing, which means that something is wrong in my hardware
description.
If I am debugging synth code on the simulator,
there is no need to worry about the state encoding.
I just view the state as an enumeration.
I describe outputs in terms of enum values.
I let synthesis use its default encoding.
There is no need for me to even know what
the encoding is.

That's true, but I guess we are interested in implementation as well,
otherwise we will have hard time to fit the logic into the device, no?
If I did care about the encoding,
I shouldn't be using an enumeration in the first place.

Also true, but again that means your are interested in the
implementation in the very first place. You may want to have different
strategies even though your logic works perfectly in simulation. Maybe I
don't trust that much the simulation tool, especially because I don't
have a very good experience with "test patterns", but most of all
because I found it hard to simulate the whole environment your logic
will work in.

Al
 
M

Mike Treseler

But still when at least I write code I have some RTL in mind and if
there are some differences than maybe I'm not completely understanding
what I'm doing, which means that something is wrong in my hardware
description.

.... or maybe synthesis found a better way to pack the gates.
The only way to be sure the code does what I expect
is to run a sim.
That's true, but I guess we are interested in implementation as well,
otherwise we will have hard time to fit the logic into the device, no?

To really count registers and LUTs and verify timing,
I have to run a full synthesis, which takes
much longer than a sim, and tells me little about
how the design functions.

-- Mike Treseler
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top