Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
8 years ago

"For... Loop" simulates differently then discrete assignments?

Can someone help me understand why the first code snippet works as I would expect it, but the second snippet simulation holds all values at 'U'?

Note: WRITE_ENABLE_FIBRE_REG(0) is assigned in a different process;

Works fine:

process (CLK, RESET_N) is
  begin
       if CLK'event and CLK = '1' then     -- rising clock edge
           WRITE_ENABLE_FIBRE_REG(1) <= WRITE_ENABLE_FIBRE_REG(0);
           WRITE_ENABLE_FIBRE_REG(2) <= WRITE_ENABLE_FIBRE_REG(1);
       end if;
  end process;

Nothing but 'U':

process (CLK, RESET_N) is
  begin
  if CLK'event and CLK = '1' then     -- rising clock edge
           for i in 1 to 2 loop
              WRITE_ENABLE_FIBRE_REG(i) <= WRITE_ENABLE_FIBRE_REG(i - 1);
           end loop;  -- i
       end if;
  end process;

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Do you have any assignments to any other bits of WRITE_ENABLE_FIBRE_REG outside of the process?

    please post all of the code?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Do you have any assignments to any other bits of WRITE_ENABLE_FIBRE_REG outside of the process?

    please post all of the code?

    --- Quote End ---

    Thanks for the interest. Unfortunately, I can't post the rest of the code. I can assure you that, other then WRITE_ENABLE_FIBRE_REG(0), there are no assignments outside this process. I tried expanding the loop from just 1~2 to 1~7 and that made no difference. I then tried creating an intermediary, and that worked.

      process (CLK, RESET_N) is
      begin
        if CLK'event and CLK = '1' then     -- rising clock edge
          WRITE_ENABLE_FIBRE_REG_TEST(1) <= WRITE_ENABLE_FIBRE_REG(0);
          for i in 2 to 7 loop
            WRITE_ENABLE_FIBRE_REG_TEST(i) <= WRITE_ENABLE_FIBRE_REG_TEST(i - 1);
          end loop;  -- i
        end if;
      end process;
      WRITE_ENABLE_FIBRE_REG (2 downto 1) <= WRITE_ENABLE_FIBRE_REG_TEST(2 downto 1);

    I can't explain why it would work one way and not the other, but since I have a work-around I'm going to leave it for now. For the record, this is with ModelSim - INTEL FPGA STARTER EDITION 10.5b Revision: 2016.10 Date: Oct 5 2016.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I can assure you that, other then WRITE_ENABLE_FIBRE_REG(0), there are no assignments outside this process.

    --- Quote End ---

    This will be the reason why it wasnt working.

    When you use a loop, the compiler does not know which bits are set and which are not, so when you assign even 1 bit inside the loop, it assumes all the bits are driven in the process. This leads to a multiple driver error on any bits assigned outside the process. This is just how VHDL works and NOT and error with the compiler.

    moral of the story - if you use a loop, you MUST assign ALL bits for that signal inside the process. This is why your temporary version works, as you do assign WRITE_ENABLE_FIBRE_REG_TEST inside the loop.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    just so I might learn, why use a loop for this and not just

    
    avect(2 to 7) <= anothervect(2 to 7);
    

    or

    
    avect(7 downto 2) <= anothervect(7 downto 2);
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    you MUST assign ALL bits for that signal inside the process. This is why your temporary version works, as you do assign WRITE_ENABLE_FIBRE_REG_TEST inside the loop.

    --- Quote End ---

    Thanks, that is interesting. I'm surprised I didn't see a 'multiple driver' warning or something similar. At least I'll know to avoid doing that going forward.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    PietervanderStar: There are lots of ways to do it. I originally had it set up as a shift register of arbitrary length, but then simplified it as much as possible before posting in order to not confuse things.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Thanks, that is interesting. I'm surprised I didn't see a 'multiple driver' warning or something similar. At least I'll know to avoid doing that going forward.

    --- Quote End ---

    You wont get a multiple driver warning in simulation because std_logic is a resolved type and allows multiple drivers. If it worked in synthesis, its probably because the Quartus compiler isnt very strict when it comes to some HDL rules.

    If you wanted the multiple drivers to pop out in simulation, then use std_ulogic and std_ulogic_vectors. They are unresolved types and never allow multiple drivers.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    use std_ulogic and std_ulogic_vectors. They are unresolved types and never allow multiple drivers.

    --- Quote End ---

    If anyone is interested, Tricky is correct. When I changed the loop code to std_ulogic_vector I got the following:

    --- Quote Start ---

    ** Error: (vsim-3344) Signal "/receive_path_tb/DUT/WRITE_ENABLE_FIBRE_REG(0)" has multiple drivers but is not a resolved signal.

    --- Quote End ---

    Cheers Tricky!