Simple circuit not working.... VHDL

Status
Not open for further replies.

strange_steve

Newbie level 4
Joined
Oct 9, 2010
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,346
its been a while since ive done some VHDL am trying to see whats wrong with this synchronizer code
for some reason in sim my arrays have all 'U' and my 'sync_out' is XXXX '
and yet my sync_in is valid known value, what am i missing here

----------------------------------------------------------------------------------


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
 
 
 entity sync_16 is
   port (
     rst                  : in  std_logic; 
     sync_out_clk         : in  std_logic;                   
     sync_in              : in  std_logic_vector(15 downto 0);
     sync_out             : out std_logic_vector(15 downto 0)
    );
 end sync_16;
 
  --//////////////////////////////////////////////////////////////////////////////
 architecture sync_16_arch of sync_16 is
  --//////////////////////////////////////////////////////////////////////////////
 
  ------------------------------------------------------
  -- sync signals                                  begin
  ------------------------------------------------------
  type  sync_array is array (0 to 3) of std_logic_vector(15 downto 0);
  signal sync_z           : sync_array;
  ------------------------------------------------------
  -- sync signals                                    end
  ------------------------------------------------------
 
 --//////////////////////////////////////////////////////////////////////////////
 begin
 --//////////////////////////////////////////////////////////////////////////////
 
  sync_z(0)    <= sync_in(15 downto 0);
  sync_out     <= sync_z(2);
 
  process (sync_out_clk, rst) is
  begin
    if (rst = '1') then
      for i in 1 to 3 loop
        sync_z(i) <= (others => '0');
      end loop;  
    elsif rising_edge(sync_out_clk) then
      for j in 1 to 3 loop
        sync_z(j) <= sync_z(j-1);
      end loop;  
    end if;
  end process;
 
--//////////////////////////////////////////////////////////////////////////////
end architecture sync_16_arch;
--///////////////////////////////////////

 
Last edited by a moderator:

Re: simple circuit not working.... VHDL

Do you have a valid clock and reset?
 

Re: simple circuit not working.... VHDL

Is sync_out all X, or is it really all U? (usually when displaying a bus in hex, anything with a non-0/1 value will get displayed as X)
As vGoodtimes has suggested - if the above code is really what you're simulating - looks like missing clock and reset.
 

Re: simple circuit not working.... VHDL

Yes has valid inputs as I said in OP, the clock, reset and sync in are all tthere and valid. Soon after reset deserted sync_z ( 0) goes to U. Then one clock later sync_z (1) goes u. Then one clock later sync_z (2) goes u. Since sync_out is ties to sync_z (2) it goes x at this time and stays that way forever. I know what the signals mean it just doesn't make sense as the logic seems good perhaps it's a vivado issue. I just don't see the problem but haven't written any vhdl in a few years. Guess I could rewrite in verily but would be just interested to know what's going on here with this logic.

- - - Updated - - -

I should not that during reset and prior to reset being deasserted the sync_out is correctly modeled and is 16'd0
 

Re: simple circuit not working.... VHDL

Why does it show this thread as closed? I tried to reply saying my resets and clocks are good as well as my inputs. But none of my replies are appearing.... who closed the thread?
 

Re: simple circuit not working.... VHDL

It has to do with assigning the sync_z(0) outside the process. Personally I would write the code as follows:

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
process (sync_out_clk, rst) is
  begin
    for i in 0 to 3 loop
      if (rst = '1') then
        sync_z(i) <= (others => '0');
      elsif rising_edge(sync_out_clk) then
        if (i = 0) then
          sync_z(0) <= sync_in(15 downto 0);
        else
          sync_z(i) <= sync_z(i-1);
        end if;
      end if;
    end loop;  
  end process;


This makes sync_z(0) another FF, so you should use sync_out <= sync_z(1) to match your original intention.

I make it a rule to never assign things separately in different places and in different loops like you have (I have this rule because of subtle issues like this).

- - - Updated - - -

Also making a width generic and using the VHDL 'range attribute you can avoid all the bus widths and make it useful for other than 16-bits. You can also make the selection of the sync_z width a generic so you can make the code easily handle 2 or 3+ synchronizer stages.

- - - Updated - - -

Yes has valid inputs as I said in OP, the clock, reset and sync in are all tthere and valid.
BTW look back at your OP you only mentioned you had a valid sync_in.

- - - Updated - - -

Why does it show this thread as closed? I tried to reply saying my resets and clocks are good as well as my inputs. But none of my replies are appearing.... who closed the thread?
New users are moderated, so there may be delays before your posts appear. Also currently the forum seems to be experiencing some severe slow downs and timeouts.
 
Re: simple circuit not working.... VHDL

It has to do with assigning the sync_z(0) outside the process. Personally I would write the code as follows:

Actually yes this is the problem, but it is only a problem because the for loop is used.
In VHDL array elements and record fields are all separate objects, so you can drive them all in separate processes if you really want
BUT
if you use a for loop to drive elements, the compiler cannot work out what is driven and what is not, hence it assumes the entire array is driven inside the process. But because element 0 is driven outside the process, (0) gets multiple drivers and hence 'X'.
Its a stupid rule - but an annoying gotcha.

If you use direct indexing, there should be no problem:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
sync_z(0)    <= sync_in(15 downto 0);
sync_out     <= sync_z(2);
 
process (sync_out_clk, rst) is
begin
  if (rst = '1') then
    sync_z(1 to 3) <= (others =>(others => '0'));
  elsif rising_edge(sync_out_clk) then
    sync_z(1 to 3) <= sync_z(0 to 2);
  end if;
end process;

 
Re: simple circuit not working.... VHDL

Come to think of it I've seen this exact problem before with the for loop causing problems with compiler not knowing what is driving each element.

I definitely like the direct indexing method, I'm not as familiar with tricks like that in VHDL as I primarily use Verilog.
 

Re: simple circuit not working.... VHDL

Thanks guys this helped - yeah i didnt think about doing it like ads-ee method - think i too have been stuck in the verilog world too long. I do normally use the direct indexed approach but only with bits and not bit_vectors/busses. I too thought that despite the strong type of VHDL that you could still manipulate all objects and that the compiler would unroll the bounded for loop, thats why i started the loop at one and not zero, but i guess this isnt' the case with for loops. Thought i was gong mad do appreciate your time, and the subtle gotcha with the for-loop. Thanks again.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…