Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   VHDL (http://www.velocityreviews.com/forums/f18-vhdl.html)
-   -   Process vs concurrent stataments? (http://www.velocityreviews.com/forums/t666140-process-vs-concurrent-stataments.html)

p.tucci 01-18-2009 09:44 PM

Process vs concurrent stataments?
 
Hi all,
I'm a VHDL beginner and I've a trouble with a simple VHDL piece code.

Writing the same thing in two ways that (appearently to me) seem to be
the same,
produce different resuls.

In one case the code is synthesized, in the other it is not.

This is the first piece of code, written as a process.
It is well synthesized:

sample_parallel_data : process(SYS_CK_IN,RESET) begin
if(RESET = '0') then
tx_data <= (others => '0');
elsif(rising_edge(SYS_CK_IN)) then
if(counter mod (SYS_CK_RATIO/2) = 0) then
if(last_lr_ck = '1') then
tx_data <= "0" & DATA_R
(IN_WIDTH-1 downto 0) & "0000000";
else
tx_data <= "0" & DATA_L
(IN_WIDTH-1 downto 0) & "0000000";
end if;
else
tx_data <= tx_data(BITXCH-2 downto 0)
& '0'; --shift data left
end if;
end if;
end process;

Now there's the some code, written as a concurrent statement... this
one reports me the error
"Signal tx_data cannot be synthesized, bad synchronous description."

tx_data <=
(others => '0') when RESET='0'
else
'0' & DATA_L(IN_WIDTH-1 downto 0) & "0000000"
when rising_edge(SYS_CK_IN)
and (counter mod (SYS_CK_RATIO/2) = 0)
and last_lr_ck = '1'
else
'0' & DATA_R(IN_WIDTH-1 downto 0) & "0000000"
when rising_edge(SYS_CK_IN)
and (counter mod (SYS_CK_RATIO/2) = 0)
and last_lr_ck = '0'
else
tx_data(BITXCH-2 downto 0) & '0'
when rising_edge(SYS_CK_IN);


For both designs:
tx_data is a signal
signal signal tx_data : std_logic_vector(BITXCH-1 downto 0);

DATA_L and DATA_R are two input ports
DATA_L : in std_logic_vector(IN_WIDTH-1 downto 0);
DATA_R : in std_logic_vector(IN_WIDTH-1 downto 0);

BITXCH is a constant = 32
IN_WIDTH is a constant = 24

Why are these piece of code different?
It appear the same thing in my mind !


Thanks all,
Primiano Tucci
--
http://www.primianotucci.com/

Mike Treseler 01-18-2009 10:34 PM

Re: Process vs concurrent stataments?
 
p.tucci <a t> gmail.com wrote:

> In one case the code is synthesized, in the other it is not.


See Mr Bromley in comp.arch.fpga

jeppe 01-18-2009 10:43 PM

Hi Primiano

The problem with your concurrent code as follows:
1) You got more then one Rising_egde( ) statement in the same structure.
(If you try the same in a process will you fail there as well)
2) Worse - you specify and else to a Rising_egde statement - this will surely
give you an error as you can't have a F/F which react on rising_egde and else do ....;

I never try implement sekvential logic with Concurrent statement - but
properly can it be done.

Your welcome
Jeppe

Tricky 01-19-2009 09:00 AM

Re: Process vs concurrent stataments?
 
Basically, synthesisers will only recognise the following synchronous
template:

sync_proc : process(clk, reset)
begin
if reset = '1' then
--async reset (avoid using if possible)
elsif rising_edge(clk) then
if sync_reset = '1' then
--sync reset prefered
elsif enable = '1' then
--put synchronous code here.
end if;
end if;
end process;



Tricky 01-19-2009 09:14 AM

Re: Process vs concurrent stataments?
 

>
> tx_data <=
> (others => '0') when RESET='0'
> else
> '0' & DATA_L(IN_WIDTH-1 downto 0) & "0000000"
> when rising_edge(SYS_CK_IN)
> and (counter mod (SYS_CK_RATIO/2) = 0)
> and last_lr_ck = '1'
> else
> '0' & DATA_R(IN_WIDTH-1 downto 0) & "0000000"
> when rising_edge(SYS_CK_IN)
> and (counter mod (SYS_CK_RATIO/2) = 0)
> and last_lr_ck = '0'
> else
> tx_data(BITXCH-2 downto 0) & '0'
> when rising_edge(SYS_CK_IN);
>



Another reason why this code is bad, is that it becomes sensitive to
EVERY signal on the RHS of a assignment. To the synthesiser, it looks
more like a MUX template which you dont actually mean. This code would
probably work in simulation, but would be much slower than the
standard template because it's re-evaluating the equations every time
one of them changes (counter, SYS_CK_IN, RESET, Last_Lr_Ck, tx_data,
DATA_R, DATA_L), which is not like real hardware. The process version
only gets re-evaluated when the clock or reset changes.

Also, although you may find it odd, but the rising_edge/falling_edge
functions actually use non-synthesisable constructs within them (the
'LAST_VALUE and 'EVENT attributes).So they can only be recognised
within the appropriate template.

p.tucci 01-19-2009 11:10 AM

Re: Process vs concurrent stataments?
 
You were so precise and clear in you answer.
Indeed, I prefer the process statement too, because it's more
readable.
But now I have another question... i've not completely clear the
semantics of process statemens.

I'm quite sure that at this point you'll hate me for my "find the
differece" questions ;)
but they're a nice way for me to understand VHDL semantics
So, the big question is (single process or multiple processes?):

are these two piece of code the same?

-----------------------------------------------
------------- CUT ONE -------------------------
-----------------------------------------------
process(SYS_CK_IN)
begin
if(rising_edge(SYS_CK_IN)) then
-- Generate the BIT_CK
-- every SYS_CK_RATIO / BIT_CK_RATIO System Clock Rising edge
if( counter mod ((SYS_CK_RATIO / BIT_CK_RATIO) / 2) =
(SYS_CK_RATIO/2 - 1)) then
last_bit_ck <= not last_bit_ck;
end if;

-- Generate the LR_CK
-- every SYS_CK_RATIO System Clocks (SYS_CK_RATIO/2 rising edges)
if( counter mod (SYS_CK_RATIO/2) = 0) then
--last_lr_ck <= not last_lr_ck; --commented out...
--what if i'd put here instead of below?
if(last_lr_ck = '1') then
tx_data <= "0" & DATA_R(IN_WIDTH-1 downto 0) & "0000000";
last_lr_ck <= '0';
else
tx_data <= "0" & DATA_L(IN_WIDTH-1 downto 0) & "0000000";
last_lr_ck <= '1';
end if;

else
tx_data <= tx_data(BITXCH-2 downto 0) & '0';
--Would be this more appropriate?
--It does not explicit the leading zero
--but i do not matter about the dirty bit being shifted
--for i in (BITXCH-2) downto 0 loop
--tx_data(i+1) <= tx_data(i);
--end loop;

end if;

counter <= counter + 1 mod (SYS_CK_RATIO/2);
end if;--rising_edge
end process;

DOUT <= tx_data(BITXCH-1);
SYS_CK_OUT <= SYS_CK_IN;
BIT_CK <= last_bit_ck;
LR_CK <= last_lr_ck;

-----------------------------------------------
------------- CUT TWO -------------------------
-----------------------------------------------

-- Generate the BIT_CK
-- every SYS_CK_RATIO / BIT_CK_RATIO System Clock Rising edge
generate_bit_clock : process(SYS_CK_IN) begin
if(rising_edge(SYS_CK_IN)) then
if(counter mod ((SYS_CK_RATIO / BIT_CK_RATIO) / 2) = 0) then
last_bit_ck <= not last_bit_ck;
end if;
end if;
end process;

-- Generate the LR_CK
-- every SYS_CK_RATIO System Clocks (SYS_CK_RATIO/2 rising edges)
generate_lrck_clock : process(SYS_CK_IN) begin
if(rising_edge(SYS_CK_IN)) then
if(counter mod (SYS_CK_RATIO/2) = (SYS_CK_RATIO/2 - 1) ) then
last_lr_ck <= not last_lr_ck;
end if;
end if;
end process;

-- Sample parallel data
-- every SYS_CK_RATIO System Clocks (SYS_CK_RATIO/2 rising edges)
sample_parallel_data : process(SYS_CK_IN) begin
if(rising_edge(SYS_CK_IN)) then
if(counter mod (SYS_CK_RATIO/2) = 0) then
if(last_lr_ck = '1') then
tx_data <= "0" & DATA_R(IN_WIDTH-1 downto 0) & "0000000";
else
tx_data <= "0" & DATA_L(IN_WIDTH-1 downto 0) & "0000000";
end if;
elsif(last_bit_ck = '1') then --MOD HERE, was 0
tx_data <= tx_data(BITXCH-2 downto 0) & '0';
end if;
end if;
end process;

-- Increment counter every SYS_CK_IN edge
update_counter : process(SYS_CK_IN) begin
if(rising_edge(SYS_CK_IN)) then
counter <= (counter + 1) mod (SYS_CK_RATIO/2);
end if;
end process;


BIT_CK <= last_bit_ck;
LR_CK <= last_lr_ck;
DOUT <= tx_data(BITXCH-1);
SYS_CK_OUT <= SYS_CK_IN;


Thanks,
Primiano Tucci
--
http://www.primianotucci.com/

Tricky 01-19-2009 11:40 AM

Re: Process vs concurrent stataments?
 
The two code sections you have written are now identical, except you
have separated out each signal into it's own process. Some people like
this because it specifically defines each register, but it just makes
the code more wordy. Personally I try and group together stuff into
fewer processes, trying to get the code to flow from top to bottom
like you might see on a system diagram from left to right.

As for this comment:

tx_data <= tx_data(BITXCH-2 downto 0) & '0';
--Would be this more appropriate?
--It does not explicit the leading zero
--but i do not matter about the dirty bit being shifted

--for i in (BITXCH-2) downto 0 loop
--tx_data(i+1) <= tx_data(i);
--end loop;

Having ignored bit 0 in simulation it will come up as 'U'. In
synthesis, it will be connected to '1' or '0', dependent on the
synthesisors flavour and mood, and might even be set at the fitter
stage.


Other things that concern me: you have signals called "BIT_CK",
"LR_CK", "SYS_CK_OUT". I am concerned you are using these elsewhere in
the design as clocks, and not enables. if this is for an FPGA be
warned that logic generated clocks are not very practical, useful or
safe. Its best to use enables tied into the system clock instead. To
generate proper system clocks at different speeds, it is best to use a
PLL or a DCM, and make sure your data crosses the domains correctly,
normally via a FIFO.


p.tucci 01-19-2009 01:01 PM

Re: Process vs concurrent stataments?
 
> Other things that concern me: you have signals called "BIT_CK",
> "LR_CK", "SYS_CK_OUT". I am concerned you are using these elsewhere in
> the design as clocks, and not enables. if this is for an FPGA be
> warned that logic generated clocks are not very practical, useful or
> safe. Its best to use enables tied into the system clock instead. To
> generate proper system clocks at different speeds, it is best to use a
> PLL or a DCM, and make sure your data crosses the domains correctly,
> normally via a FIFO.


The vhdl is an audio parallel to i2s.
It takes a System Clock (generated by a PLL, about 6 Mhz) in input and
parallel data.
It outputs:
-A bit clock (that is SYS_CK_IN divided by two)
-An LRCK clock (taht is SYS_CK_IN divided by 64)
-A Data output (timed with Bit Clock).

It sounds interesting the fact of enable the system clock, but, how to
do it?
Do you have any examples?

Thans all for your great support

p.tucci 01-19-2009 01:13 PM

Re: Process vs concurrent stataments?
 
Just another thing,
The SYS_CK_OUT, LRCK and BIT_CK are not used anymore into the design
but are exported to the output pins of the CPLD (an xc95144xl) that
will connect to and drive a Digital to Analog Converter

Andy 01-20-2009 06:06 PM

Re: Process vs concurrent stataments?
 
On Jan 19, 3:00*am, Tricky <Trickyh...@gmail.com> wrote:
> Basically, synthesisers will only recognise the following synchronous
> template:
>
> sync_proc : process(clk, reset)
> begin
> * if reset = '1' then
> * * --async reset (avoid using if possible)
> * elsif rising_edge(clk) then
> * * if sync_reset = '1' then
> * * * --sync reset prefered
> * * elsif enable = '1' then
> * * * --put synchronous code here.
> * * end if;
> * end if;
> end process;


Most synthesizers also infer a register from this:

q <= d when rising_edge(clk);

The behavior of this concurrent statement is identical to a clocked
process. The implied process from this concurrent statement will wake
up on changes to d, but no assignment will be made. Just like clocked
processes will wake up on the "other" edge of the clock, but no
assignments will be made. The only time I use the above is when I need
a register in between structural elements (entity instantiations).

You can add an asynchronous reset assignment to the concurrent
register template, but not multiple clock specifications (or enables
thereof).

q <= '0' when rst = '1' else d when rising_edge(clk);

The problem is, there are no "nested if" capabilities in concurrent
statements like there are in processes.

For that matter I'm also not aware of any synthesizers that accept
multiple "clocked" if statements that control assignments to the same
signal/variable (which would be the analagous process).

Andy



All times are GMT. The time now is 06:47 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.