Search code examples
if-statementhexvhdlintel-fpga

Compare std_logic_vector in a if() condition vhdl


I am trying to compare counting value (std_logic_vector) with a defined hex value. but i dont get the result the way i did as below

signal count : STD_LOGIC_VECTOR(res_bits-1 DOWNTO 0):= x"0000"; --res_bits =16
signal round : STD_LOGIC_VECTOR(res_bits-1 DOWNTO 0):= x"0000";
signal cnt : STD_LOGIC_VECTOR(res_bits-1 DOWNTO 0):= x"0000"; --res_bits =16
    process(clk_50)
begin
    if (falling_edge(clk_50)) then
        t(1)<=t(0); 
        t(0)<=A;
        t(3)<=t(2); 
        t(2)<=B;
        case (temp) is
            when "0001" => cnt<= cnt + '1';
            when "0010" => cnt<= cnt - '1';
            when "1000" => cnt<= cnt + '1';     
            when "1011" => cnt<= cnt - '1';

        end case;
        count <= cnt;
        if (count = x"0320") then --if count 800
            round <= round + '1';
            cnt <= x"0000";   -- reset cnt
            count <= x"0000";   -- reset count
        end if;
    end if;
end process;

Solution

  • First things first: What do you think a std_logic_vector is? std_logic_vector is an array of std_logic. std_logic is an std_ulogic which has been resolved. std_ulogic is a type that defines states of an electrical line in digital circuits. But more importantly: std_logic[_vector] is not an integer type.

    If you want to do arithmetic with the + and - operators, you should use an arithmetic type. signed and unsigned, defined in numeric_std, are best suited for this. so don't use use ieee.std_logic_arith.all(non standard), but use use ieee.numeric_std.all (defined in the standard).


    Next, some information an resetting a signal. What if you decide to set res_bits = 17? Then

    signal count : STD_LOGIC_VECTOR(res_bits-1 DOWNTO 0):= x"0000";
    

    will not work. So instead use others to set all bits to '0' for maximum flexibility. I.e.

    signal count : UNSIGNED(res_bits-1 DOWNTO 0) := (others => '0');
    

    Now lets look at the process... Hmmm. There are a number of assignments to temp... but you never define temp. Cannot help you there...

    Then look at the case statements. case (temp) is.... I see a when for 1, 2, 4, 7, 8, etc... but what happens when temp is e.g. 0? You need to define a when for all possibilities. But what if you don't want to do anything for these cases? ... Just do null! E.g.

    case (temp) is
        when "0001" => cnt<= cnt + '1';
        [...]
        when "1110" => cnt<= cnt + '1';
        when others => null; -- <== required
    end case;
    

    Another thing for case-statements. Combine situations with the pipe symbol.

    case (temp) is
        when "0001" | "0111" | "1000" | "1110" => cnt <= cnt + '1';
        when "0010" | "0100" | "1011" | "1101" => cnt <= cnt - '1';
        when others => null;
    end case;
    

    Then about signal assignment. A value applied to a signal will not be applied until the next delta cycle. But this delta cycle does not occur until after the process is finished. E.g.:

    • Imagine cnt=799=x"031F" and temp="0001" when the process starts.
    • at the case statement, cnt <= cnt + 1 is selected. This operation is scheduled for the next delta cycle, nut cnt will stay 799 for now.
    • So, at count <= cnt;, 799 will be scheduled to be assigned to count, not 800! But as this operation is also scheduled, count will for now still have it's old value (likely 798).
    • This means that at if (count =, count will still be seen as 798. It will take another two clock cycles for count to reach 800, due to the extra registers inferred.

    You should probably use variables for temporary values in the process. But watch out with what you are doing: variables loose their value when the process finishes and should never be used outside of the process.