Search code examples
vhdlfpga

reset statement is not synthesizable since it does not hold its value under NOT(clock-edge) condition


I have searched about this problem but it all seemed Greek to me so I came here as last effort.I have the following VHDL code that I want to be implemented on an fpga.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use work.conversions.all;

entity counter is
port ( clk_in: in std_logic;                                    --new clock
    target : in std_logic_vector(7 downto 1);               --Set the target with the switches (SW7-SW1)
    start : in std_logic;                                       --Start/pause (SW0)
    rst : in std_logic;                                         --Reset (BT0)
    LD : out std_logic_vector(7 downto 1);                  --Leds show the target at binary (LD7-LD1)
    LD0 : out std_logic;                                            --LD0 indicates thw the limit has been reached
    seg : out std_logic_vector(7 downto 0);                 --7 segment display
    digit : out std_logic_vector(3 downto 0) 
); 
end counter;

architecture Behavioral of counter is
begin
process(clk_in,target,rst)
variable timer : natural := 0;
variable counter : natural := 0;
variable display_counter : natural range 0 to 4 := 0;
begin
    LD0 <= '0';
    LD <= target;                                                   --Show the target at the leds
    digit <= "1110";                                                --Last digit active
    seg <= "00000011";                                          --Show zero
    <--->if(rst='1') then                                               --Reset counter
        counter := 0;
        timer := 0;
        digit <= "1110";                                            --Last digit active
        seg <= "00000011";                                      --Show zero
        LD0 <= '0';
    elsif rising_edge(clk_in) then
        if(start = '0') then                                        --Pause
            --counter := counter;
        elsif(counter = conv_integer(unsigned(target))) then    --timer limit has been reached
            LD0 <= '1';
        else
            counter := counter + 1;
            display_counter := display_counter + 1;
            if(counter rem 10 = 0) then                     --one second has elapsed (10Hz cycle)
                timer := timer + 1;                             --increase timer                    
            end if;
            case display_counter is                             --Select which digits are gonna be activated and with what
                when 1 => 
                    seg <= int2led(timer/1000);
                    if(int2led(timer/1000) = "00000000") then
                        digit(3) <= '1';
                    else
                        digit(3) <= '0';
                    end if;
                when 2 => 
                    seg <= int2led((timer/100) mod 10);
                    if(int2led((timer/100) mod 10) = "00000000") then
                        digit(2) <= '1';
                    else
                        digit(2) <= '0';
                    end if; 
                when 3 => 
                    seg <= int2led((timer/10) mod 10);
                    if(int2led((timer/10) mod 10) = "00000000") then
                        digit(1) <= '1';
                    else
                        digit(1) <= '0';
                    end if;
                when others => 
                    seg <= int2led(timer/10);
                    if(int2led(timer/10) = "00000000") then
                        digit(1) <= '1';
                    else
                        digit(1) <= '0';
                    end if;
            end case;
            if (display_counter = 4) then                       --reset the display counter from time to time
                display_counter := 0;
            else
                display_counter := display_counter;
            end if;
        end if;
    end if;
end process;
end Behavioral;

The problem is at if(rst='1') then. Can anyone explain to me in plain English why is this happening and a solution to it so I won't have the same kind problems again? Thanks in advance


Solution

  • You have default signal assignments before the if rst='1' then clause.

    That means, when rst returns to 0 (in simulation) these default assignments will execute, and delete the reset values of those signals.

    XST is telling you that the hardware can't actually do that.

    The solution is to delete those default assignments, which will restore this process to a standard form. Then think carefully about what they were for and how to keep their functionality if you need to.

    The traditional place for such assignments is immediately after the elsif rising_edge(clk) then clause, where they will be executed on every clock edge (provided Rst is low) then overridden by any other assignments that are executed yb the process.