• process problem in VHDL

    From albert.pierre1000@gmail.com@21:1/5 to All on Tue Jun 23 14:40:46 2020
    Hello,

    I'm working on a project using a CPLD. All the functions of my code are working, but the overcurrent detection (OCD).

    It's been long time since I used VHDL. So I'm a bit rusted. I would apreciate it , if someone could have a look at my problem.

    The function is not so complicated. When I receive the OCD signal (DOI4, active low), I need to raise a flag as an output (OCD_FLAG) set to '1' for say 1 sec, then to '0' for another 1 sec. During the period when the signal OCD_FLAG is set to '1', the
    load will be disconnected so the circuitry will not report an OCD anymore (even if it is still present) so the signal DOI(4) should be 1 (deactivated).

    The idea is to cut off the load of the circuit when an overcurrent is detected, let some time for the component to lower their temperature, then reactivate the load during 1 sec and after that period check if the overcurrent is still here.

    here is the signal declared earlier in the code:

    -- inputs
    DOI :in std_logic_vector(10 DOWNTO 1); (my inputs signals: DOI(4) is used for the overcurrent
    CPLD_CLK :in std_logic;
    CLOSE_OUT :in std_logic;
    -- outputs
    OCD_FLAG :out std_logic;

    --internal signals
    RST :in std_logic;
    signal OCD_CNT : std_logic_vector(20 downto 0) := "000000000000000000000";


    here is a bit of my code:

    HICCUP: process (RST,CLOSE_OUT,CPLD_CLK)
    begin
    elsif (rising_edge(CPLD_CLK)) then
    -- deactivation
    if DOI(4) = '0' then
    if OCD_CNT(20) = '0' then
    OCD_CNT <= OCD_CNT + 1;
    end if;
    else
    OCD_CNT <= '0' & OCD_CNT(20 downto 1);
    end if;
    -- shotdown duration
    if OCD_CNT(20) = '1' then
    OCD_CNT <= OCD_CNT + 1;
    end if;
    end if;
    end process;

    OCD_FLAG <= OCD_CNT(20);


    the problem I have is that the OCD_FLAG never change its state. always '1'.

    I try a solution using while....loop but I'm not sure I can use this command in a process.
    If there is a simple way I'm interested in any information that can help me to progress.

    Thank you,

    Pierre

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rick C@21:1/5 to albert.p...@gmail.com on Tue Jun 23 16:28:56 2020
    On Tuesday, June 23, 2020 at 5:40:49 PM UTC-4, albert.p...@gmail.com wrote:
    Hello,

    I'm working on a project using a CPLD. All the functions of my code are working, but the overcurrent detection (OCD).

    It's been long time since I used VHDL. So I'm a bit rusted. I would apreciate it , if someone could have a look at my problem.

    The function is not so complicated. When I receive the OCD signal (DOI4, active low), I need to raise a flag as an output (OCD_FLAG) set to '1' for say 1 sec, then to '0' for another 1 sec. During the period when the signal OCD_FLAG is set to '1', the
    load will be disconnected so the circuitry will not report an OCD anymore (even if it is still present) so the signal DOI(4) should be 1 (deactivated).

    The idea is to cut off the load of the circuit when an overcurrent is detected, let some time for the component to lower their temperature, then reactivate the load during 1 sec and after that period check if the overcurrent is still here.

    here is the signal declared earlier in the code:

    -- inputs
    DOI :in std_logic_vector(10 DOWNTO 1); (my inputs signals: DOI(4) is used for the overcurrent
    CPLD_CLK :in std_logic;
    CLOSE_OUT :in std_logic;
    -- outputs
    OCD_FLAG :out std_logic;

    --internal signals
    RST :in std_logic;
    signal OCD_CNT : std_logic_vector(20 downto 0) := "000000000000000000000";


    here is a bit of my code:

    HICCUP: process (RST,CLOSE_OUT,CPLD_CLK)
    begin
    elsif (rising_edge(CPLD_CLK)) then
    -- deactivation
    if DOI(4) = '0' then
    if OCD_CNT(20) = '0' then
    OCD_CNT <= OCD_CNT + 1;
    end if;
    else
    OCD_CNT <= '0' & OCD_CNT(20 downto 1);
    end if;
    -- shotdown duration
    if OCD_CNT(20) = '1' then
    OCD_CNT <= OCD_CNT + 1;
    end if;
    end if;
    end process;

    OCD_FLAG <= OCD_CNT(20);


    the problem I have is that the OCD_FLAG never change its state. always '1'.

    I try a solution using while....loop but I'm not sure I can use this command in a process.
    If there is a simple way I'm interested in any information that can help me to progress.

    It sounds to me like you want to time OCD_FLAG high for a second and then low for a second triggered by DOI(4) being high. Once the end of this two second cycle is reached the function should be back in it's starting state where it can resume waiting
    for DOI(4) to go high.

    You haven't shown all of the code for this process, but why is CLOSE_OUT in the sensitivity list? That typically won't cause a problem in simulation or synthesis though.

    I think the problem is just your implementation of the state machine. I don't know how you initialize the counter, but I don't understand your handling of it. You have two independent conditionals to control the counter. You may not realize that
    whichever assignment is last made to the counter is the one that takes effect. So while DOI(4) is '0' the counter will free run. Is DOI(4) = '0' the active state or is '1' the active state?

    The counter will free run because while DOI(4) is '0' and the counter msb is '0' it will be incremented in the first conditional. Then when the counter msb is '1' it will continue to be incremented since this is the last assignment and will take
    precedence. So the counter will be in an arbitrary state at any given time.

    When DOI(4) is '1' the counter is right shifted with the msb becoming '0'... unless it is already a '1' in which case the final assignment has precedence again and simply increments it.

    I think you just need to look at your logic. Try drawing a state machine. There will be two states, asserting OCD_FLAG and not asserting the flag. Once the counter reaches a terminal count it should stop. This will require detecting the terminal
    count just before rolling over to setting the msb.

    I would use a down counter. Then the terminal count is zero. When the DOI(4) signal is asserted you can resume the count down with the next count setting the OCD_FLAG (counter msb). After that the count down will resume until it reaches zero again.

    You can even avoid the extra logic of the zero comparison by detecting that the next count msb is '1'. That requires separating the counter register from the counter logic. So create a next count value in a concurrent logic statement outside the
    process.

    next_cnt <= cur_cnt - 1;

    process (...
    elsif (rising_edge(CPLD_CLK)) then
    if (next_cnt /= -1) or (DOI(4) = '1') then
    cur_cnt <= next_cnt;
    end_if;
    end_if;
    end process;

    BTW, how are you incrementing an SLV? Shouldn't you be using a signed or unsigned data type? If you use a signed type you can use my trick above which should make use of the carry out from the counter carry chain.

    --

    Rick C.

    - Get 1,000 miles of free Supercharging
    - Tesla referral code - https://ts.la/richard11209

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)