Search code examples
vhdl

Unable to determine signal value in VHDL


I am currently in the midst of an 12 hour debug session and I cannot, for the life of me, get passed this hump.

The way my code is setup, I have an 8 bit std_logic_vector mapped to 8 switches on the DE2-115 board. Each bit corrosponds to the logic level activated by the relative switch (0 or 1).

The goal is to have the board wait for any of the 8 switches to be activated before is starts the timer. This will be activated when the signal relative_time_enable is set to logic state of 1. Once the signal is set to 1 it will ultimately never be reset back to 0. This variable is initialized as shown:

signal relative_time_enable          : STD_LOGIC := '0';
signal signal_in                     : STD_LOGIC_VECTOR(7 downto 0);

signal_in gets mapped to 'in' ports delclared in my entity, or rather, vice-versa. However it is said, signal_in corrosponds to the switches. Here is the code I have right now.

process(clk_1MHz_enable, signal_in)     
begin
    if(clk_1MHz_enable = '1') then

            if(relative_time_enable = '0') and (signal_in /= "00000000")then
                    relative_time_enable <= '1';
            end if;
    end if;
end process;

I believe I have deduced the problem down to being that the if-statement is always coming up as true. Almost as though the signal_in is going through multiple states within the first cycles causing the value to immediately be set to 1, I couldn't find anything online that could point me to the right direction.

At this point, I have tried everything in order to determine what the values actually are including replacing "00000000" with "11111111", "UUUUUUUU", "ZZZZZZZZ", "XXXXXXXX" and all of them still get through.

I have also tried:

process(clk_1MHz_enable, signal_in)     
begin
    if(clk_1MHz_enable = '1') then

            if(relative_time_enable = '0') and (signal_in /= "00000000")then

                    for i in 0 to 7 loop
                            if(signal_in(i) = '1') then
                                    relative_time_enable <= '1';
                            end if;
                    end loop;

            end if;
    end if;
end process;

This method seems like it should 'double check' but somehow it keeps getting through and setting the value to 1 before any switches are activated. Also, I have signal_in displaying on the lCD and changes when I move switches and at startup, everything reads 00000000.

FYI: I have only been working with this FPGA and VHDL for 2 weeks so it's very possible that I missing something very fundamental. Also, I am not exactly 100% confident with my skills in ModelSIM and not sure how I would translate what I see into problems with code.

Any help would be greatly appreciated. If you need to see anymore of the code, just let me know I'll be happy to post whatever is needed. I just didn't put all of it up because there is a pretty lengthy state machine that controls the LCD which isn't relevant for this post.

Also, I should mention that the following code works as expected, but the problem with this code is that it resets relative_time_enable back to 0 which is a big no no. The only reason I am showing this is because it essentially does wait until a switch is active before starting the clock, but once I deactivate the switch, the clock stops running which is a problem.

process(clk_1MHz_enable, signal_in)     
begin
    if(clk_1MHz_enable = '1') then

            if(relative_time_enable = '0') and (signal_in /= "00000000")then
                    relative_time_enable <= '1';
            else
                    relative_time_enable <= '0';
            end if;
    end if;
end process;

Solution

  • Your test would work with a bit_vector because each bit would take either the '0' value or the '1' value. So, /= "00000000" would really mean: at least one bit is '1'. But as you are using an std_logic_vector, each bit can take 9 different values (std_logic is a 9-values enumerated type). So /= "00000000" does not mean that at least one bit is '1'. It can mean that one bit is set to 'U' or any other value different from '0'. At the beginning of a simulation signal_in is initialized with "UUUUUUUU" (U stands for Uninitialized). relative_time_enable is initialized with '0' because you declared it that way. So your test passes on the first rising edge of clk_1MHz_enable and relative_time_enable gets stuck at '1' almost immediately.

    Assuming clk_1MHz_enable is a clock (strange name but why not), and you want an edge-triggered D-flip-flop, the following code solves this issue:

    process(clk_1MHz_enable)     
    begin
      if clk_1MHz_enable = '1' and clk_1MHz_enable'event then
        for i in signal_in'range loop
          if signal_in(i) = '1' then
            relative_time_enable <= '1';
          end if;
        end loop;
      end if;
    end process;
    

    And if you want a level-triggered latch instead of an edge-triggered D-flip-flop:

    process(clk_1MHz_enable, signal_in)
    begin
      if clk_1MHz_enable = '1' then
        for in in signal_in'range loop
          if signal_in(i) = '1' then
            relative_time_enable <= '1';
          end if;
        end loop;
      end if;
    end process;