Грешка при синтез на VHDL код

Написах VHDL код, който реализира функционалността на PWM контролер. Симулирах го успешно и резултатите са според очакванията. Проверих и синтаксиса за синтез, но той не показа грешка. Когато отидох да го синтезирам с помощта на XILINX ISE 12.4, той не синтезира и се изписва грешка

"ГРЕШКА:Xst:827 - ред 67: Сигналът tmp_PC не може да бъде синтезиран, лошо синхронно описание. Стилът на описание, който използвате, за да опишете синхронен елемент (регистър, памет и т.н.), не се поддържа в текущата версия на софтуера."

--library UNISIM;
--use UNISIM.VComponents.all;

entity CONTROLLER is
PORT(

    CLK:    IN  STD_LOGIC;
    VOUT: IN  STD_LOGIC;
    M1:   OUT STD_LOGIC:='0';
    M2:   OUT STD_LOGIC:='0'

);


end CONTROLLER;

architecture Behavioral of CONTROLLER is

    SIGNAL VREF:        STD_LOGIC_VECTOR(7 DOWNTO 0):="01000000";
    SIGNAL V_ERR:       STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL PWM:         STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL PWM_NEW:         STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL COUNT:       STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL COUNT2:          STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL TEMP1:       STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL TEMP2:       STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL TEMP3:       STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL FEED_BACK:       STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL REG:         STD_LOGIC_VECTOR(7 DOWNTO 0):="00000000";
    SIGNAL PWM_COUNT:       STD_LOGIC_VECTOR(7 DOWNTO 0):="10000000";

BEGIN

PROCESS(CLK)

BEGIN

    IF(RISING_EDGE(CLK) AND COUNT2<"10000000")THEN
            COUNT <= COUNT+'1';
    END IF;

    IF(RISING_EDGE(CLK) AND COUNT2>="10000000")THEN
        COUNT <= COUNT+'1';
    END IF;

    IF (COUNT>"00000101" AND COUNT<"01111000") THEN
        IF(RISING_EDGE(CLK))THEN
            IF (VOUT='0') THEN
                FEED_BACK<= FEED_BACK+'1';
            END IF;
        END IF;
    END IF;   

    IF (COUNT>"01111000" AND COUNT<"01111100")THEN
        REG<=FEED_BACK;
        TEMP1<=VREF-REG;
        IF(TEMP1>"01000000") THEN
           TEMP2<=TEMP1+"11111111";
            V_ERR<=TEMP2+'1';
        END IF;
        IF (TEMP1<"01000000") THEN
                V_ERR<=TEMP1;
        END IF;

        PWM<=V_ERR+VREF;

        IF (PWM>"11000000")THEN
             PWM<="11000000";
        IF(PWM<"00001010")THEN
            PWM<="00001010";

        END IF;
        END IF;

    END IF;

    PWM_NEW<= PWM;

   IF (RISING_EDGE(CLK))THEN
        IF(COUNT="01111111")THEN
            COUNT<="00000000";
            FEED_BACK<="00000000";
        END IF;
    END IF;

    IF(RISING_EDGE(CLK))THEN
        COUNT2 <= COUNT2+ '1';
    END IF;

   IF(COUNT>"00000000" AND COUNT<("00000010"))THEN
        IF(RISING_EDGE(CLK)) THEN
            M1<='0';
            M2<='0';
        END IF;
   END IF;

    IF(COUNT>("00000010") AND COUNT<("00000010"+PWM_NEW))THEN
        IF(RISING_EDGE(CLK)) THEN
            M1<='1';
            M2<='0';
        END IF;
   END IF;

    IF(COUNT>("00000010"+PWM_NEW) AND COUNT<("00000100"+PWM_NEW))THEN
        IF ( RISING_EDGE(CLK)) THEN
            M1<='0';
            M2<='0';
        END IF;
    END IF;

    IF(COUNT>("00000100"+PWM_NEW) AND COUNT<("10000000"))THEN
        IF (RISING_EDGE(CLK)) THEN
            M1<='0';
            M2<='1';
        END IF;
    END IF;

    IF (COUNT=("10000000"))THEN
        IF (RISING_EDGE(CLK)) THEN
            COUNT2<="10000001";
        END IF;
    END IF;

END PROCESS;
end Behavioral;`

Опитах да потърся съобщението за грешка и получих различни отговори. Възможните причини изглеждат 1: Неправилно влагане „АКО“, което не е според шаблона за синтез. 2: Използването на "risisng_edge(clk)" вместо обичайното "(clk'event и clk='1')".

Все още не съм напълно сигурен какъв може да е точният проблем. Би било наистина полезно, ако някой може да предложи възможните грешки, които пропускам.


person Saurya Prakash    schedule 03.07.2012    source източник


Отговори (2)


За да бъде разпознат от инструментите за синтез, вашият процес трябва да има единствен if rising_edge(clk) блок.

Трябва да е лесно да адаптирате кода си, с изключение на блока с reg <= feed_back;

Ако този конкретен раздел моделира асинхронно поведение, тогава го преместете в комбиниран процес.

По отношение на възможните причини 1. и 2., които изброихте, кодът ви е ок и по отношение на двете: влагането е ок (синтактично) и използването на rising_edge е ок.

person wap26    schedule 03.07.2012

изглежда, че можете да кодирате пълен синхрон

process(clk)
begin
    -- put your asyncron code here if needed
    if(rising_edge(clk)) then
      if(reset = '1') then
      -- if you like to implement a synchron reset
      else
      -- all your synchron code e.g.

         if (COUNT2 >= "10000000") then
            COUNT <= COUNT+'1';
         end if;

         if (COUNT > ("00000100"+PWM_NEW)) AND (COUNT < "10000000") then
            M1 <= '0';
            M2 <= '1';
         end if;
         .
         .
         .

      end if;
   end if;
   -- put your asyncron code here if needed
end process;

не използвайте библиотеката unisim ... можете да правите всичко и с двете

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.NUMERIC_STD.all;

има стандартизирани.

За да стане малко по-ясно, можете да пишете шестнадесетичен

if (COUNT2 >= x"80") then -- 80 hex = 124 dec
   COUNT <= COUNT+'1';
end if;

или можете да използвате неподписани сигнали

SIGNAL COUNT:       unsigned (7 DOWNTO 0) := (others => '0'); -- same as "000000000" but looks better

if (COUNT2 >= 128) then
   COUNT <= COUNT + '1';
end if;

пресмятането не е проблем, напр.

if (COUNT > ("00000100"+PWM_NEW)) AND (COUNT < "10000000") then
   M1 <= '0';
   M2 <= '1';
end if;

би било

 if (COUNT > (unsigned(PWM_NEW) + 4)) AND (COUNT < 128) then
    M1 <= '0';
    M2 <= '1';
 end if;
person gatherer    schedule 03.07.2012