Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Modelsim - strange problem with partial assignments

Status
Not open for further replies.

shaiko

Advanced Member level 5
Joined
Aug 20, 2011
Messages
2,644
Helped
303
Reputation
608
Reaction score
297
Trophy points
1,363
Activity points
18,302
Hello,

This is my code:

Code:
signal x : std_logic_vector ( 7 downto 0 ) ; 

x ( 0 ) <= '1' ;

strange : process ( CLOCK , RESET ) is 
begin
  if RESET = '1' then						
    x ( 7 downto 1 ) <= ( others => '0' ) ;	
  elsif rising_edge ( CLOCK ) then	
    for index in 0 to 6 loop
      x ( index + 1 ) <= x ( index ) ;
    end loop ;	
  end if ;		
end process strange ;

I simulated the above in Modelsim.
I expected bit #0 of x to always be 0. But it's 'U'.
Is it a bug ?
 

You wrote
x ( 0 ) <= '1' ;

x(0) must be '1' every time, not '0'.

I think it will be better:

Code:
signal x : std_logic_vector ( 7 downto 0 ) ; 

strange : process ( CLOCK , RESET ) is 
begin
  if RESET = '1' then						
    x ( 7 downto 0 ) <= "00000001";	
  elsif rising_edge ( CLOCK ) then	
    for index in 0 to 6 loop
      x ( index + 1 ) <= x ( index ) ;
    end loop ;	
  end if ;		
end process strange ;

And using for...loop constraction is bad idea. It works not the same like in C/C++ and others high-level languages.
 
Last edited:

That's correct - just a typo. It needs to '1' but it's not. It's 'U'
 

I am not sure.....try this!

signal x : std_logic_vector ( 7 downto 0 ) := "0000001" ;

You may comment out this: x ( 0 ) <= '1' ;
 

I am not sure.....try this!

signal x : std_logic_vector ( 7 downto 0 ) := "0000001" ;

You may comment out this: x ( 0 ) <= '1' ;

I'm not trying to work around a solution - it's easy.
I want to understand the reason for why I see what I see.
In my real code:
Code:
x ( 0 ) <= some_entity_input ;
I wrote:
Code:
x ( 0 ) <= '1' ;
Instead of:
Code:
x ( 0 ) <= some_entity_input ;
Just to illustrate the problem (as it persists with both cases).
x ( 0 ) is 'U'...
 

You wrote
x ( 0 ) <= '1' ;

x(0) must be '1' every time, not '0'.

I think it will be better:

Code:
signal x : std_logic_vector ( 7 downto 0 ) ; 

strange : process ( CLOCK , RESET ) is 
begin
  if RESET = '1' then						
    x ( 7 downto 0 ) <= "00000001";	
  elsif rising_edge ( CLOCK ) then	
    for index in 0 to 6 loop
      x ( index + 1 ) <= x ( index ) ;
    end loop ;	
  end if ;		
end process strange ;

And using for...loop constraction is bad idea. It works not the same like in C/C++ and others high-level languages.

Using for loops like this is just fine. You're looping through an array for parrallel assignment. using loops that keep memory between iterations is a bad idea.

@shaiko - looks like a bug as the following works fine:

Code:
x(7 downto 1) <= x(6 downto 0);

raise a ticket with mentor.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
If you try copy input bit in all bits of x:

Code:
library ieee;
use ieee.std_logic_1164.all;

entity test is
port(
arst : in std_logic;
clk : in std_logic;
din : in std_logic;
dout : out std_logic_vector (7 downto 0)
);
end entity;

architecture arch of test is
begin

process(arst,clk)
begin 
 if arst = '1' then
  dout <= (others=>'0');
   elsif rising_edge (clk) then
    dout <= din & din & din & din & din & din & din & din;
	end if;
end process;

end arch;

It simulated corretly
 

If you try copy input bit in all bits of x:

Code:
library ieee;
use ieee.std_logic_1164.all;

entity test is
port(
arst : in std_logic;
clk : in std_logic;
din : in std_logic;
dout : out std_logic_vector (7 downto 0)
);
end entity;

architecture arch of test is
begin

process(arst,clk)
begin 
 if arst = '1' then
  dout <= (others=>'0');
   elsif rising_edge (clk) then
    dout <= din & din & din & din & din & din & din & din;
	end if;
end process;

end arch;

It simulated corretly

Thats not what the OP posted - he posted a shift register with the input stuck at '1'.
 

If you try copy input bit in all bits of x:

Code:
library ieee;
use ieee.std_logic_1164.all;

entity test is
port(
arst : in std_logic;
clk : in std_logic;
din : in std_logic;
dout : out std_logic_vector (7 downto 0)
);
end entity;

architecture arch of test is
begin

Code:
process(arst,clk)
begin 
 if arst = '1' then
  dout <= (others=>'0');
   elsif rising_edge (clk) then
    dout <= din & din & din & din & din & din & din & din;
	end if;
end process;

end arch;
It simulated corretly[/QUOTE]

This doesn't resemble to the original code.
My logic synthesizes correctly.
And if I put the x(0) <= '1' inside the process - I.E:

[CODE]strange : process
begin
  x ( 0 ) <= '1' ;
  if RESET = '1' then						
    x ( 7 downto 1 ) <= ( others => '0' ) ;	
  elsif rising_edge ( CLOCK ) then	
    for index in 0 to 6 loop
      x ( index + 1 ) <= x ( index ) ;
    end loop ;	
  end if ;		
end process strange ;

It also works.
I'm almost sure it's a bug.
 

So if not a bug? Did you tested your code in real FPGA device?
As I said - Quartus synthesizes the circuit without any issues.
The RTL Viewer shows x(0) as a wire and all other bits of x as DFFs.
It's a Modelsim problem - not a VHDL or Logic problem.
 

It's not a bug with Modelsim...I suspect it has something to do with how the LRM is being interpreted, though I don't have the time to research it.

The following code with three different ways of assigning that don't modify the x(0) <= '1' assignment like adding it to the RESET, shows that the Vivado simulator behaves the same way as Modelsim.


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
51
52
53
54
Library IEEE ;
Use IEEE.Std_logic_1164.all ;
 
entity test is
end test;
 
architecture rtl of test is
 
  signal CLOCK : std_logic;
  signal RESET : std_logic;
  signal x : std_logic_vector ( 7 downto 0 ) ; 
  signal y : std_logic_vector ( 7 downto 0 ) ; 
  signal z : std_logic_vector ( 7 downto 0 ) ; 
 
begin
 
-- original failed simulation with U on x(0)
x (0) <= '1' ;
original : process ( CLOCK , RESET ) is 
begin
  if RESET = '1' then                       
    x ( 7 downto 1 ) <= ( others => '0' ) ; 
  elsif rising_edge ( CLOCK ) then  
    for index in 0 to 6 loop
      x ( index + 1 ) <= x ( index ) ;
    end loop ;  
  end if ;      
end process original ;
 
-- working simulation y(0) is assigned '1'
y (0) <= '1' ;
no_for : process ( CLOCK , RESET ) is 
begin
  if RESET = '1' then                       
    y ( 7 downto 1 ) <= ( others => '0' ) ; 
  elsif rising_edge ( CLOCK ) then  
    y (7 downto 1) <= y (6 downto 0);
  end if ;      
end process no_for;
 
-- also works as z(0) gets assigned '1', this is the way I would have coded this.
embed_assign : process (CLOCK, RESET) is
begin
  z (0) <= '1';
  if RESET = '1' then                       
    z ( 7 downto 1 ) <= ( others => '0' ) ; 
  elsif rising_edge ( CLOCK ) then  
    for index in 0 to 6 loop
      z ( index + 1 ) <= z ( index ) ;
    end loop ;  
  end if ;      
end process embed_assign;
 
end rtl;


This is one of the reasons why I make a habit of assigning all bits of a vector in the same process/always block and never split them out like the first and second versions. I'm pretty sure I've run into this behavior before.
 
Are you saying it's the same with Verilog?

Yes, that is exactly what I mean, I've seen weird things happen when splitting up a vector and assigning parts of it in different places. Verilog though does keep you from using continuous assignments when you have the rest of the bus in a always block as the first uses the wire type and the always block uses reg. With the logic type you could get into the same trouble as VHDL.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Yes, that is exactly what I mean, I've seen weird things happen when splitting up a vector and assigning parts of it in different places. Verilog though does keep you from using continuous assignments when you have the rest of the bus in a always block as the first uses the wire type and the always block uses reg. With the logic type you could get into the same trouble as VHDL.
Either way. Regarding the "not a bug" thing...I couldn't find any information about it. And if it's out of LRM
behavior - I'd expect Modelsim to at least show a warning.
 

Vivado's simulator also shows no warnings for this, that's why I suggested the behavior might be defined by the LRM assignment scheduling definition. One could easily assume that the behavior if not well defined in the LRM would result in different behaviors across vendor's tools, but considering both tools show the exact same behavior with the same condition seems to indicate that it might be the expected behavior, though I'll admit the synthesis tools do something entirely different (another good reason to avoid this type of coding).
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Vivado's simulator also shows no warnings for this, that's why I suggested the behavior might be defined by the LRM assignment scheduling definition. One could easily assume that the behavior if not well defined in the LRM would result in different behaviors across vendor's tools, but considering both tools show the exact same behavior with the same condition seems to indicate that it might be the expected behavior, though I'll admit the synthesis tools do something entirely different (another good reason to avoid this type of coding).

Having scoured the LRM - I cannot find the issue.
The LRM does specify that all elements of arrays and records are considered their own objects, so you can assign each element of an array or record in separate processes.
The fact they share the same behaviour could still be an LRM thing, but I know that tool vendors often get their compilers from the same 3rd party (I think Verific provide the comiler/parser for both Quartus and Xilinx).

Ive raised a defect with mentor - they're usually good at identifying specific LRM issues.

- - - Updated - - -

It is an LRM issue - basically the loop variable is not globally static and hence the compiler has to assume all bits of X have a driver inside the loop. Synthesizers get away with it because they unroll loops during compilation.

Mentor already have a technote on the issue if you have access to their supportnet: MG579750
 
  • Like
Reactions: ads-ee

    ads-ee

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top