Search code examples
processsignalsvhdlfpgatiming

Signal is not activating process?


so I seem to be having a problem in regards to flag signal getting asserted. So basically I am implementing i2c interface between 2 fpga's. My master will send over 50 bytes. On my slave side I want to store the byte coming in into an array. So I check when ever the whole byte is read and available i put it into an array. Now the problem is that after i fill up the whole array i want to assert a signal that should activate a process. My problem is that when the signal is asserted and the process is activated that that I am stuck in the idle loop forever, which confuses me because I was under the assumption that when i enter the process and check the flag signal assertion condition that it is suppose to be high. So is the problem that my signal is not activating the process or is my problem that the by the time i check the flag assertion conditional that the flag already went back to 0? I have attached some code:

  signal i : integer range 0 to 49 := 0;

  type field_array is array(0 to 49) of std_logic_vector(7 downto 0);
begin
process(clk,rst) 
begin

if( rst = '1') then

    i <= 0;

elsif (rising_edge(clk)) then

    if(data_available = '1') then

        array_of_data(i) <= Master_Data;

        i <= i + 1;

    end if;

    if(i = 49) then

        i <= 0; -- reset index back to zero

    end if;

end if;

end process;

flag <= '1' when i = 49 else '0'; 

process(state,flag)
begin

next_state   <= state;

case (state) is 

    when idle =>

        if(flag = '1') then

            next_state <= Send_data;

        end if;

     when Send_data =>...

Solution

  • There is a bounds check failure on your assignment, i <= i+1;. It is trying to evaluate it before the check that is performed later (if i=49...).

    Change the synchronous part of you code to:

    elsif rising_edge(clk) then
        if data_available = '1' then
            array_of_data(i) <= Master_Data;
            if i = 49 then
                i <= 0;
            else
                i <= i + 1;
            end if;
        end if;
    end if;
    

    EDIT:

    You can see that the flag is being asserted and the state changes here.

    Further EDIT:

    Consider making your state machine synchronous and removing the next_state signal. eg.

    type state_t is (idle_s, send_s, others_s);
    signal state : state_t := idle_s;
    ...
    process(clk,rst)
    begin
        if rst = '1' then
            -- rst
        elsif rising_edge(clk) then
            case (state) is
                when idle_s =>
                    if flag = '1' then
                        state <= send_s;
                    else
                        state <= idle_s;
                    end if;
                when send_s =>
                -- Do stuff
                when others =>
                -- stuff
            end case;
        end if;
    end process;
    

    If you want to assign your outputs as soon as your state changes, you can use a two process state machine. One of the processes (synchronous) is used to control state transitions, the other is used to control the output (combinational). You would effectively have another process similar to the first:

    process(state)
    begin
        case state is
            when idle_s =>
                my_output <= '0';
            when send_s =>
                -- Assign output as necessary
                my_output <= '1';
            when others =>
            --assign output
        end case;
    end process;
    

    An example is shown here.