Strange 'X' values.

I

Ilya Kalistru

Guest
Good day.
I came across a strange behavior in my project and can't understand it. Maybe you could explain it to me.
I've reduced it to the point where it still persists.
I've tried to ask on the xilinx forum
but it looks like that that forum more engaged to help me avoid that problem then explain what is going on here...
Here is the code

entity test is
Port (
Clock : in std_logic;
Dev_Linked : in std_logic_vector(0 downto 0);
R_CHCS : out std_logic_vector(1 downto 0):="01"
);
end entity test;

architecture Behavioral of test is
begin

R_CHCS_proc : process (Clock) is
begin
if rising_edge(Clock) then
for i in 0 to 0 loop
R_CHCS(i * 2) <= '0';
end loop;
end if;
end process R_CHCS_proc;

R_CHCS(1) <= Dev_Linked(0) when rising_edge(Clock);

end Behavioral;

On the first clock cycle R_CHCS becomes "X0". And I don't know why. On Xilinx forum say that "Questa also gives the same output" and it's not a bug of the simulator and it's because each process makes it's own driver for CHCS and it gives 'X' value. But it doesn't make sense for me because if I remove unnecessary loop in R_CHCS_proc this problem disappears, and it is nothing to do with processes.

Maybe someone could explain this to me?
 
From www.eda.org/comp.lang.vhdl/FAQ1.html:
4.2.13 Signal Drivers
....
Further, VHDL needs to be able to statically (that is, during static elaboration) determine all drivers of a signal, in order to create a static network topology. A driver is created for the longest static prefix of each target signal. During elaboration the compiler analyzes the target of each signal assignment statement to determine the smallest portion of the signal that can be statically determined as being driven by the concurrent statement.. For example, the following model is erroneous, as both the process "p" and the concurrent signal assignment both drive "sig(3)", an unresolved signal.

architecture behave of test is
signal sig : bit_vector(0 TO 7);
constant c : integer := 3;
begin
p: process (sig)
begin
for i in 1 to 1 loop
sig(i) <= '1'; -- signal assignment statement
end loop;
end process;

sig(c) <= '1'; -- concurrent signal assignment driving
-- "sig(3)"
end behave;

In this example, the longest static prefix of the target of the assignment statement "sig(i) <= '1'" is the entire signal "sig", since "sig" is a static signal name and "i" is a loop constant and hence not static. Consequently, "p" has a driver for the entire signal "sig", although actuality only "sig(1)" will be driven by the process. Further, the longest static prefix of the concurrent signal assignment is "sig(3)", since "c" is a statically elaborated constant equal to 3. Hence, an error message should be generated to the effect that several processes are driving "sig(3)".
 
rickman <gnuarm@gmail.com> wrote:
On 10/16/2015 3:31 PM, Ilya Kalistru wrote:
I came across a strange behavior in my project and can't understand it.
Maybe you could explain it to me.

(snip)

R_CHCS_proc : process (Clock) is
begin
if rising_edge(Clock) then
for i in 0 to 0 loop
R_CHCS(i * 2) <= '0';
end loop;
end if;
end process R_CHCS_proc;

R_CHCS(1) <= Dev_Linked(0) when rising_edge(Clock);

(snip)

>> On the first clock cycle R_CHCS becomes "X0".

(snip)

I think Jim gave you an explanation even if it is a bit hard to
understand. VHDL has a lot of things like that. The basic rule is
"don't do that". I can't say I see any reason why you would want to do
that. Why not just include the assignment to bit 1 of R_CHCS in the
same clocked process as the other assignment to R_CHCS?

Yes. For each signal, use either the process form or the non-process
(verilog calls it continuous assignment) form, but don't mix them.

In verilog, you have to declare reg or wire, so you have to decide early
which way you want to go. VHDL doesn't have that, but you still have to
get it right.

It might work if you put the second one in its own process, but it has
to be in one.

Also, I didn't know that you could use rising_edge(clock) outside
of process, but then again, I never even thought to try it.


-- glen
 
On 10/16/2015 3:31 PM, Ilya Kalistru wrote:
Good day.
I came across a strange behavior in my project and can't understand it. Maybe you could explain it to me.
I've reduced it to the point where it still persists.
I've tried to ask on the xilinx forum
but it looks like that that forum more engaged to help me avoid that problem then explain what is going on here...
Here is the code

entity test is
Port (
Clock : in std_logic;
Dev_Linked : in std_logic_vector(0 downto 0);
R_CHCS : out std_logic_vector(1 downto 0):="01"
);
end entity test;

architecture Behavioral of test is
begin

R_CHCS_proc : process (Clock) is
begin
if rising_edge(Clock) then
for i in 0 to 0 loop
R_CHCS(i * 2) <= '0';
end loop;
end if;
end process R_CHCS_proc;

R_CHCS(1) <= Dev_Linked(0) when rising_edge(Clock);

end Behavioral;

On the first clock cycle R_CHCS becomes "X0". And I don't know why. On Xilinx forum say that "Questa also gives the same output" and it's not a bug of the simulator and it's because each process makes it's own driver for CHCS and it gives 'X' value. But it doesn't make sense for me because if I remove unnecessary loop in R_CHCS_proc this problem disappears, and it is nothing to do with processes.

Maybe someone could explain this to me?

I think Jim gave you an explanation even if it is a bit hard to
understand. VHDL has a lot of things like that. The basic rule is
"don't do that". I can't say I see any reason why you would want to do
that. Why not just include the assignment to bit 1 of R_CHCS in the
same clocked process as the other assignment to R_CHCS?

Rick

--

Rick
 
On 10/16/2015 8:35 PM, glen herrmannsfeldt wrote:
rickman <gnuarm@gmail.com> wrote:
On 10/16/2015 3:31 PM, Ilya Kalistru wrote:
I came across a strange behavior in my project and can't understand it.
Maybe you could explain it to me.

(snip)

R_CHCS_proc : process (Clock) is
begin
if rising_edge(Clock) then
for i in 0 to 0 loop
R_CHCS(i * 2) <= '0';
end loop;
end if;
end process R_CHCS_proc;

R_CHCS(1) <= Dev_Linked(0) when rising_edge(Clock);

(snip)

On the first clock cycle R_CHCS becomes "X0".

(snip)

I think Jim gave you an explanation even if it is a bit hard to
understand. VHDL has a lot of things like that. The basic rule is
"don't do that". I can't say I see any reason why you would want to do
that. Why not just include the assignment to bit 1 of R_CHCS in the
same clocked process as the other assignment to R_CHCS?

Yes. For each signal, use either the process form or the non-process
(verilog calls it continuous assignment) form, but don't mix them.

In verilog, you have to declare reg or wire, so you have to decide early
which way you want to go. VHDL doesn't have that, but you still have to
get it right.

It might work if you put the second one in its own process, but it has
to be in one.

Also, I didn't know that you could use rising_edge(clock) outside
of process, but then again, I never even thought to try it.

I've seen this discussed, making a clocked process from a concurrent
statement. But I've never tried it myself. I want to say I've read
that it will work, but perhaps not in all tools. There is a synthesis
VHDL spec if I am not mistaken and I bet this isn't in it.

--

Rick
 
Jim Lewis, thank you for your reply and a link to a good resource.
 
On Saturday, October 17, 2015 at 3:20:03 AM UTC+3, rickman wrote:
On 10/16/2015 3:31 PM, Ilya Kalistru wrote:
Good day.
I came across a strange behavior in my project and can't understand it. Maybe you could explain it to me.
I've reduced it to the point where it still persists.
I've tried to ask on the xilinx forum
but it looks like that that forum more engaged to help me avoid that problem then explain what is going on here...
Here is the code

entity test is
Port (
Clock : in std_logic;
Dev_Linked : in std_logic_vector(0 downto 0);
R_CHCS : out std_logic_vector(1 downto 0):="01"
);
end entity test;

architecture Behavioral of test is
begin

R_CHCS_proc : process (Clock) is
begin
if rising_edge(Clock) then
for i in 0 to 0 loop
R_CHCS(i * 2) <= '0';
end loop;
end if;
end process R_CHCS_proc;

R_CHCS(1) <= Dev_Linked(0) when rising_edge(Clock);

end Behavioral;

On the first clock cycle R_CHCS becomes "X0". And I don't know why. On Xilinx forum say that "Questa also gives the same output" and it's not a bug of the simulator and it's because each process makes it's own driver for CHCS and it gives 'X' value. But it doesn't make sense for me because if I remove unnecessary loop in R_CHCS_proc this problem disappears, and it is nothing to do with processes.

Maybe someone could explain this to me?

I think Jim gave you an explanation even if it is a bit hard to
understand. VHDL has a lot of things like that. The basic rule is
"don't do that". I can't say I see any reason why you would want to do
that. Why not just include the assignment to bit 1 of R_CHCS in the
same clocked process as the other assignment to R_CHCS?

Rick

--

Rick

I just came across this strange thing and I became curious what it is and why. I just want to understand VHDL better.

Originally it was written in a such way in attempt to separate different matters in different processes to make code more readable and assign different resets to this different matters. (there were a problems with huge fanout of a reset signal and failed timings as a result).
 
On Saturday, October 17, 2015 at 3:36:00 AM UTC+3, glen herrmannsfeldt wrote:
rickman <g***@gmail.com> wrote:
On 10/16/2015 3:31 PM, Ilya Kalistru wrote:
I came across a strange behavior in my project and can't understand it.
Maybe you could explain it to me.

(snip)

R_CHCS_proc : process (Clock) is
begin
if rising_edge(Clock) then
for i in 0 to 0 loop
R_CHCS(i * 2) <= '0';
end loop;
end if;
end process R_CHCS_proc;

R_CHCS(1) <= Dev_Linked(0) when rising_edge(Clock);

(snip)

On the first clock cycle R_CHCS becomes "X0".

(snip)

I think Jim gave you an explanation even if it is a bit hard to
understand. VHDL has a lot of things like that. The basic rule is
"don't do that". I can't say I see any reason why you would want to do
that. Why not just include the assignment to bit 1 of R_CHCS in the
same clocked process as the other assignment to R_CHCS?

Yes. For each signal, use either the process form or the non-process
(verilog calls it continuous assignment) form, but don't mix them.

In verilog, you have to declare reg or wire, so you have to decide early
which way you want to go. VHDL doesn't have that, but you still have to
get it right.

It might work if you put the second one in its own process, but it has
to be in one.

Also, I didn't know that you could use rising_edge(clock) outside
of process, but then again, I never even thought to try it.


-- glen

Thank you for your advice.

As for rising_edge(clock) outside of process, I met it somewhere and I found that it's good way to save few lines of code when you need something simple.
Later I met this document
http://www.synthworks.com/papers/VHDL_RTL_Synthesis_Standard_HDLCON_2002.pdf
in which this way to make a register is also described.
It works well with xilinx; I've been using it for several years.
 
On 10/17/2015 5:51 AM, Ilya Kalistru wrote:
On Saturday, October 17, 2015 at 3:20:03 AM UTC+3, rickman wrote:
On 10/16/2015 3:31 PM, Ilya Kalistru wrote:
Good day. I came across a strange behavior in my project and
can't understand it. Maybe you could explain it to me. I've
reduced it to the point where it still persists. I've tried to
ask on the xilinx forum but it looks like that that forum more
engaged to help me avoid that problem then explain what is going
on here... Here is the code

entity test is Port ( Clock : in std_logic; Dev_Linked : in
std_logic_vector(0 downto 0); R_CHCS : out std_logic_vector(1
downto 0):="01" ); end entity test;

architecture Behavioral of test is begin

R_CHCS_proc : process (Clock) is begin if rising_edge(Clock)
then for i in 0 to 0 loop R_CHCS(i * 2) <= '0'; end loop; end
if; end process R_CHCS_proc;

R_CHCS(1) <= Dev_Linked(0) when rising_edge(Clock);

end Behavioral;

On the first clock cycle R_CHCS becomes "X0". And I don't know
why. On Xilinx forum say that "Questa also gives the same output"
and it's not a bug of the simulator and it's because each process
makes it's own driver for CHCS and it gives 'X' value. But it
doesn't make sense for me because if I remove unnecessary loop in
R_CHCS_proc this problem disappears, and it is nothing to do with
processes.

Maybe someone could explain this to me?

I think Jim gave you an explanation even if it is a bit hard to
understand. VHDL has a lot of things like that. The basic rule
is "don't do that". I can't say I see any reason why you would
want to do that. Why not just include the assignment to bit 1 of
R_CHCS in the same clocked process as the other assignment to
R_CHCS?

Rick

--

Rick

I just came across this strange thing and I became curious what it is
and why. I just want to understand VHDL better.

Originally it was written in a such way in attempt to separate
different matters in different processes to make code more readable
and assign different resets to this different matters. (there were a
problems with huge fanout of a reset signal and failed timings as a
result).

I guess the question then is, if these two signals need to be
differentiated, why are they separate bits in the same vector? Make
them separate signals and you can express their assignments totally
separately.

The common reset signal often does not meet any timing spec. It is
better to design your circuits so that the timing on the reset does not
matter. Any sequential logic that must leave the reset state together
should use a common synchronization signal controlling the exit from
reset. This often results in much smaller nets since the reset exit
requirement is usually a local one rather than global. If it is global,
then you will need a common control with multiple output FFs as
repeaters so the fan out of each copy is not so great.

--

Rick
 
I guess the question then is, if these two signals need to be
differentiated, why are they separate bits in the same vector? Make
them separate signals and you can express their assignments totally
separately.

I had similar thoughts just after reading of your comments to my post. R_CHCS is a register which indicates states of a coprocessor for a CPU and different bits of it have different meanings. So, in this case I should have different signals for different indicators and then I should concatenate them in R_CHCS. I would have done that if it had been my code, but I am just trying to fix my colleague's code.



The common reset signal often does not meet any timing spec. It is
better to design your circuits so that the timing on the reset does not
matter. Any sequential logic that must leave the reset state together
should use a common synchronization signal controlling the exit from
reset. This often results in much smaller nets since the reset exit
requirement is usually a local one rather than global. If it is global,
then you will need a common control with multiple output FFs as
repeaters so the fan out of each copy is not so great.

it's exactly how I fixed this problem.
 
"glen herrmannsfeldt" <gah@ugcs.caltech.edu> wrote in message
news:mvs55c$vs$1@speranza.aioe.org...
rickman <gnuarm@gmail.com> wrote:
On 10/16/2015 3:31 PM, Ilya Kalistru wrote:
I came across a strange behavior in my project and can't understand
it.
Maybe you could explain it to me.

(snip)

R_CHCS_proc : process (Clock) is
begin
if rising_edge(Clock) then
for i in 0 to 0 loop
R_CHCS(i * 2) <= '0';
end loop;
end if;
end process R_CHCS_proc;

R_CHCS(1) <= Dev_Linked(0) when rising_edge(Clock);

(snip)

On the first clock cycle R_CHCS becomes "X0".

(snip)

Also, I didn't know that you could use rising_edge(clock) outside
of process, but then again, I never even thought to try it.


-- glen

Actually,
R_CHCS(1) <= Dev_Linked(0) when rising_edge(Clock);
IS a process; it's just an unnamed process. Any concurrent VHDL
statement is a process whether you explicitly call it a process or not.
Similarly,
Y <= A and B;
is also a process and just a shorthand way of writing:
some_proc: process(A,B) begin
Y <= A and B;
end process;

Charles Bailey
 

Welcome to EDABoard.com

Sponsor

Back
Top