Перейти к содержанию
    

FAQ по языкам описания аппаратуры

Правда напсал чуть короче
Ну тогда и последний else можно опустить. :)

 

Но почему всё же первый вариант не прокатил? :05:
Навскидку предполагаю, что из-за:

а) в VHDL последующая транзакция отменяет предыдущую.

б) у Вас два последовательных if'а в одном процессе (и, кстати, их условий нет в списке чувствительности).

в) особенностей картусовского синтезатора при обработке совокупности указанных выше условий. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну тогда и последний else можно опустить. sm.gif

Да, пожалуй Вы правы B)

Навскидку предполагаю, что из-за:

более склоняюсь к последнему...

Спасибо за помощь :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

более склоняюсь к последнему...

 

А может просто else-ы конфликтуют с "противоположными" if? Не определены действия когда лоу=0, а хай=1. Первый иф говорит перезаписывай значение, а второй - пиши новое в старшие байты. И наоборот. Наверняка там варнинг был соответствующий. ИМХО вина сапра только в том что эррор не выкатил)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что значит

с "противоположными" if
? Есть 2 разных флага, по значению которых необходимо произвести разные действия с общим буфером.

ИМХО вина сапра только в том что эррор не выкатил)

Дык тут то сапр как раз прав оказался, никакой ошибки нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что значит ? Есть 2 разных флага, по значению которых необходимо произвести разные действия с общим буфером.

 

В том и дело что действия разные, а буфер один. Строго следуя исходному тексту получаем что при хай=1, а лоу=0, один if требует сохранить текущее значение в буфере, а второй требует переписать старшие разряды. Беда именно в том что Вы сами и прописали такой конфликт задав else в каждом if. Без else я думаю все и в исходном варианте работало бы. Хотя и не лучшим образом.

 

Также работало бы если

if wr_tx_udp_data_HIGH = '1' then
        tx_udp_data_reg(63 downto 32) <= writedata(31 downto 0);
        else
        tx_udp_data_reg(63 downto 32) <= tx_udp_data_reg(63 downto 32);
        end if;

        if wr_tx_udp_data_LOW = '1' then
        tx_udp_data_reg(31 downto 0) <= writedata(31 downto 0);
       else
        tx_udp_data_reg(31 downto 0) <= tx_udp_data_reg(31 downto 0);
       end if;

 

Дык тут то сапр как раз прав оказался, никакой ошибки нет.

 

Multi-source error это кажется называется. Хотя тут не уверен.

Изменено пользователем Barktail

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А можете помочь разобраться как правильнее написать

 

При помощи логики :

 SDRAM_DQ <= WR_DATA_REG2    WHEN (PRES_STATE = WRITE_STATE) ELSE
                          (OTHERS => 'Z');

 

Или при помощи синхронного процесса:

   WRITE_DATA_FROM_MEMORY:PROCESS
    (
        CLK
    )
    BEGIN
        IF (CLK'EVENT AND CLK = '1') THEN
            IF (NEXT_STATE = WRITE_STATE) THEN
                SDRAM_DQ <= WR_DATA_REG1;
            ELSE
                SDRAM_DQ <= (OTHERS => 'Z');
            END IF;
        END IF;
    END PROCESS;

 

Записи эквиваленты с точки зрения функционала.

Изменено пользователем Flip-fl0p

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А можете помочь разобраться как правильнее написать

 

При помощи логики :

 SDRAM_DQ <= WR_DATA_REG2    WHEN (PRES_STATE = WRITE_STATE) ELSE
                           (OTHERS => 'Z');

 

Или при помощи синхронного процесса:

   WRITE_DATA_FROM_MEMORY:PROCESS
     (
         CLK
     )
     BEGIN
         IF (CLK'EVENT AND CLK = '1') THEN
             IF (NEXT_STATE = WRITE_STATE) THEN
                 SDRAM_DQ <= WR_DATA_REG1;
             ELSE
                 SDRAM_DQ <= (OTHERS => 'Z');
             END IF;
         END IF;
     END PROCESS;

 

Записи эквиваленты с точки зрения функционала.

 

Добрый день.

Зависит от того, как вам надо.

Если надо, чтобы данные SDRAM_DQ фиксировались по фронту CLK, то вторая запись.

Если просто мультиплексор, управляемый условием PRES_STATE = WRITE_STATE,

то первая.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне необходимо, чтобы в момент когда подана команда записи данных в SDRAM память данные, которые контроллер памяти выдает на шину данных SDRAM памяти были стабильными и не менялись до прихода переднего фронта частоты SDRAM контроллера, которым эти данные и зафиксируются. Для этого мне необходимо чтобы в это время данные были стабильными.

Фактически я на "железе" проверил оба варианта, и они работают. Но с точки зрения увеличения максимальной частоты проекта, какой способ более правильный ?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возник вопрос по параметризации модуля, который я пишу на VHDL.

Допустим есть некий модуль "COMPONENT_MODULE" который что-то умеет делать.

В этом модуле есть некий процесс "CONTROL_DATA", который выдает сигнал в зависимости от внешних условий.

В проекте более высокого уровня я использую 10 таких модулей.

Но сигнал "CONTROL_DATA" мне нужен только от одного из модулей(неважно какого). В остальных модулях данный сигнал мне не нужен.

Есть ли в VHDL возможность сделать процесс параметризированным и в зависимости от какой-либо константы описанной в GENERIC области он будет включен/выключен ?

На данный момент я просто не использую эти сигналы, но Quartus выдает предупреждение о них. Хотелось бы как-нибудь красиво это описать.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возник вопрос по параметризации модуля, который я пишу на VHDL.

Допустим есть некий модуль "COMPONENT_MODULE" который что-то умеет делать.

В этом модуле есть некий процесс "CONTROL_DATA", который выдает сигнал в зависимости от внешних условий.

В проекте более высокого уровня я использую 10 таких модулей.

Но сигнал "CONTROL_DATA" мне нужен только от одного из модулей(неважно какого). В остальных модулях данный сигнал мне не нужен.

Есть ли в VHDL возможность сделать процесс параметризированным и в зависимости от какой-либо константы описанной в GENERIC области он будет включен/выключен ?

На данный момент я просто не использую эти сигналы, но Quartus выдает предупреждение о них. Хотелось бы как-нибудь красиво это описать.

 

IF (condition) GENERATE

A: process(.....)

....

END GENERATE

 

 

IF (condition) GENERATE

B: process(.....)

....

END GENERATE

 

Так на этапе компиляции будет выбрано, какую реализацию процесса использовать. А если ни одно из условий выполняться не будет, то процесса просто не будет.

 

Только вот какого рода варнинг вы хотите убрать? Если выходной порт назначается из этого процесса, то факт того, что он не будет назначаться ниоткуда, не уберет варнинг о том, что порт не используется.

 

Если нужно убрать такой варнинг, то создайте две архитектуры. У 9 модулей будет архитектура без этого сигнала, а у одного с ним. Этот сигнал и используйте дальше. А через параметр задайте подключение входных сигналов ко всем 10 модулям так, чтобы на модуль с нужным выходным сигналом приходили соответствующие данные.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

IF (condition) GENERATE

A: process(.....)

....

END GENERATE

 

 

IF (condition) GENERATE

B: process(.....)

....

END GENERATE

 

Так на этапе компиляции будет выбрано, какую реализацию процесса использовать. А если ни одно из условий выполняться не будет, то процесса просто не будет.

 

Только вот какого рода варнинг вы хотите убрать? Если выходной порт назначается из этого процесса, то факт того, что он не будет назначаться ниоткуда, не уберет варнинг о том, что порт не используется.

 

Если нужно убрать такой варнинг, то создайте две архитектуры. У 9 модулей будет архитектура без этого сигнала, а у одного с ним. Этот сигнал и используйте дальше. А через параметр задайте подключение входных сигналов ко всем 10 модулям так, чтобы на модуль с нужным выходным сигналом приходили соответствующие данные.

Quartus стал выдавать такие сообщения:

Warning (12241): 1 hierarchies have connectivity warnings - see the Connectivity Checks report folder

В сообщении написано что:

clkn    Output    Info    Connected to dangling logic. Logic that only feeds a dangling port will be removed.    1
clkp    Output    Info    Connected to dangling logic. Logic that only feeds a dangling port will be removed.    2

И действительно в проекте у меня остаются "висящими в воздухе" эти выводы у двух серилайзеров.

--================================================================
-- Серилайзер для матрицы  TX23D38VM0CAA
--================================================================
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY SERILAISER IS
PORT
(
	DATA_IN		 :IN  STD_LOGIC_VECTOR(6 DOWNTO 0);  -- Входные данные для серилайзера
	DATA_CLOCK	  :IN  STD_LOGIC;					 -- Синхрочастота входных данных
	CLOCKx7		 :IN  STD_LOGIC;					 -- Частота х7 для серилайзера
	ENABLE		  :IN  STD_LOGIC;					 -- Сигнал разрешения работы

	CLKn			:OUT STD_LOGIC;					 -- Отрицательный выход LVDS линии синхрочастоты
	CLKp			:OUT STD_LOGIC;					 -- Положительный выход LVDS линии синхрочастоты

	TXn			 :OUT STD_LOGIC;					 -- Отрицательный выход LVDS линии данных
	TXp			 :OUT STD_LOGIC					  -- Положительный выход LVDS линии данных
);
END SERILAISER;

ARCHITECTURE SERILAISER_arc OF SERILAISER IS
SIGNAL DATA_REG0   :STD_LOGIC_VECTOR(6 DOWNTO 0);	   -- Регистр хранения входных данных
SIGNAL DATA_REG1   :STD_LOGIC_VECTOR(0 TO 6);		   -- Регистр1 для передачи в другой клоковый домен
SIGNAL DATA_REG2   :STD_LOGIC_VECTOR(0 TO 6);		   -- Регистр2 для передачи в другой клоковый домен
SIGNAL DATA_REG3   :STD_LOGIC_VECTOR(0 TO 6);		   -- Регистр3 С которого сериализируются данные 
SIGNAL CLK_CNT	 :INTEGER RANGE 0 TO 6;			   -- Счетчик для серилайзера и востановления синхрочастоты
BEGIN
WRITE_INPUT_DATA:PROCESS
(
	DATA_CLOCK
)
BEGIN
	IF (DATA_CLOCK'EVENT AND DATA_CLOCK = '1') THEN
		IF (ENABLE = '1') THEN
			DATA_REG0 <= DATA_IN;					   -- По переднему фронту запишем входные данные 
		END IF;
	END IF;
END PROCESS;

COUNTER_AND_CROSS_DOAIN_DATA:PROCESS
(
	CLOCKx7
)
BEGIN 
	IF (CLOCKx7'EVENT AND CLOCKx7 = '1') THEN
	   IF (ENABLE = '1') THEN 
			DATA_REG1(0 TO 6) <= DATA_REG0(6 DOWNTO 0);  -- Передаем данные через клоковый домен старшим битом вперед.
			DATA_REG2 <= DATA_REG1;					  -- Вторая ступень синхронизации
			IF (CLK_CNT = 6) THEN						-- Как только счетчик досчитает до 6 
				DATA_REG3<= DATA_REG2;				   -- Перепишем данные последний регистр
				CLK_CNT <= 0;							-- Обнулим счетчик
			ELSE 
				CLK_CNT <= CLK_CNT + 1;				  -- Пока счетчик не досчитал до 6 инкрементируем его на 1
			END IF;
		END IF;
	END IF;
END PROCESS;

CREATING_MATRIX_CLOCK:PROCESS
(
	CLOCKx7
)
BEGIN 
	IF (CLOCKx7'EVENT AND CLOCKx7 = '1') THEN
		IF (ENABLE = '1') THEN 
			IF (CLK_CNT >=1  AND CLK_CNT <= 3) THEN	-- Подставим фронты синхрочатоты матрицы как в даташите на матрицу
				CLKp <= '0';
				CLKn <= '1';
			ELSE  
				CLKp <= '1';
				CLKn <= '0';
			END IF;
		END IF;
	END IF;
END PROCESS;
TXp <=	 DATA_REG3(CLK_CNT);
TXn <= NOT DATA_REG3(CLK_CNT);
END SERILAISER_arc;

Вот модуль серилайзера для одной линии LVDS матрицы. В этом модуле так-же формируется сигнал синхрочастоты, матрицы, где фронты подставлены под последовательный поток данных в соответствии с требованиями матрицы. Знаю, что не совсем корректно реализовал этот модуль, поскольку правильно не частоту подставлять под данные, а данные под частоту. Но такой вариант работает, и в железе всё функционирует. Да и если честно частота матрицы небольшая (34 Мгц), думаю это не очень страшно на такой частоте. А полноценно вывести PLL наружу я не могу, свободных выходов PLL у меня нет. В идеале бы осциллографом глянуть форму сигнала. Но это пока мечты. Почитаю умных книжек, посмотрю форумы и сделаю правильно. Но потом.

Сейчас мне хочется при помощи GENERIC области включать отключать процесс:

CREATING_MATRIX_CLOCK:PROCESS
(
	CLOCKx7
)
BEGIN 
	IF (CLOCKx7'EVENT AND CLOCKx7 = '1') THEN
		IF (ENABLE = '1') THEN 
			IF (CLK_CNT >=1  AND CLK_CNT <= 3) THEN	-- Подставим фронты синхрочатоты матрицы как в даташите на матрицу
				CLKp <= '0';
				CLKn <= '1';
			ELSE  
				CLKp <= '1';
				CLKn <= '0';
			END IF;
		END IF;
	END IF;
END PROCESS;

Спасибо за ответ. Завтра с утра на свежую голову попробую сделать, как Вы советовали.

Изменено пользователем makc
code => codebox

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за помощь. В общем теперь модуль выглядит так:

--================================================================
-- Серилайзер для матрицы  TX23D38VM0CAA
--================================================================
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY SERILAISER IS
GENERIC
(
	CLK_MATRIX : INTEGER := 0	-- 0 disable. 1 enable out signals
);
PORT
(
	DATA_IN		 :IN  STD_LOGIC_VECTOR(6 DOWNTO 0);  -- Входные данные для серилайзера
	DATA_CLOCK	  :IN  STD_LOGIC;					 -- Синхрочастота входных данных
	CLOCKx7		 :IN  STD_LOGIC;					 -- Частота х7 для серилайзера
	ENABLE		  :IN  STD_LOGIC;					 -- Сигнал разрешения работы

	TXn			 :OUT STD_LOGIC;					 -- Отрицательный выход LVDS линии данных
	TXp			 :OUT STD_LOGIC;					 -- Положительный выход LVDS линии данных

	----------------------- СИНХРОСИГНАЛ МАТРИЦЫ ВКЛЮЧАЕТСЯ ЕСЛИ ПЕРЕМЕННАЯ CLK_MATRIX = 1-----------------------------
	CLKn			:OUT STD_LOGIC_VECTOR(CLK_MATRIX - 1 DOWNTO 0);  -- Отрицательный выход LVDS линии синхрочастоты
	CLKp			:OUT STD_LOGIC_VECTOR(CLK_MATRIX - 1 DOWNTO 0)   -- Положительный выход LVDS линии синхрочастоты
);
END SERILAISER;

ARCHITECTURE SERILAISER_arc OF SERILAISER IS
SIGNAL DATA_REG0   :STD_LOGIC_VECTOR(6 DOWNTO 0) := (OTHERS => '0');   -- Регистр хранения входных данных
SIGNAL DATA_REG1   :STD_LOGIC_VECTOR(0 TO 6)	 := (OTHERS => '0');   -- Регистр1 для передачи в другой клоковый домен
SIGNAL DATA_REG2   :STD_LOGIC_VECTOR(0 TO 6)	 := (OTHERS => '0');   -- Регистр2 для передачи в другой клоковый домен
SIGNAL DATA_REG3   :STD_LOGIC_VECTOR(0 TO 6)	 := (OTHERS => '0');   -- Регистр3 С которого сериализируются данные 
SIGNAL CLK_CNT	 :INTEGER RANGE 0 TO 6 := 0;						 -- Счетчик для серилайзера и востановления синхрочастоты
BEGIN
WRITE_INPUT_DATA:PROCESS
(
	DATA_CLOCK
)
BEGIN
	IF (DATA_CLOCK'EVENT AND DATA_CLOCK = '1') THEN
		IF (ENABLE = '1') THEN
			DATA_REG0 <= DATA_IN;						-- По переднему фронту запишем входные данные 
		END IF;
	END IF;
END PROCESS;

COUNTER_AND_CROSS_DOAIN_DATA:PROCESS
(
	CLOCKx7
)
BEGIN 
	IF (CLOCKx7'EVENT AND CLOCKx7 = '1') THEN
	   IF (ENABLE = '1') THEN 
			DATA_REG1(0 TO 6) <= DATA_REG0(6 DOWNTO 0);  -- Передаем данные через клоковый домен старшим битом вперед.
			DATA_REG2 <= DATA_REG1;					  -- Вторая ступень синхронизации
			IF (CLK_CNT >= 6) THEN						-- Как только счетчик досчитает до 6 
				DATA_REG3<= DATA_REG2;					--- Перепишем данные последний регистр					  
				CLK_CNT <= 0;							-- Обнулим счетчик
			ELSE 
				CLK_CNT <= CLK_CNT + 1;				  -- Пока счетчик не досчитал до 6 инкрементируем его на 1
			END IF;
		END IF;
	END IF;
END PROCESS;

CLKMATRIX : IF (CLK_MATRIX > 0) GENERATE
	CREATING_MATRIX_CLOCK:PROCESS
	(
		CLOCKx7
	)
	BEGIN 
		IF (CLOCKx7'EVENT AND CLOCKx7 = '1') THEN
			IF (ENABLE = '1') THEN 
				IF (CLK_CNT >=2  AND CLK_CNT <= 4) THEN	-- Подставим фронты синхрочатоты матрицы как в даташите на матрицу
					CLKp <= "1";
					CLKn <= "0";
				ELSE  
					CLKp <= "0";
					CLKn <= "1";
				END IF;
			END IF;
		END IF;
	END PROCESS;
END GENERATE;

OUT_DATA_CREATING:PROCESS
(
	CLOCKx7
)
BEGIN
	IF (CLOCKx7'EVENT AND CLOCKx7 = '1') THEN
		IF (ENABLE = '1') THEN 
			TXp <=	 DATA_REG3(CLK_CNT);
			TXn <= NOT DATA_REG3(CLK_CNT);
		END IF;
	END IF;
END PROCESS;

END SERILAISER_arc;

Чтобы выходные сигналы то-же удалилась я из объявил как

CLKn :OUT STD_LOGIC_VECTOR(CLK_MATRIX - 1 DOWNTO 0)

При сборке проекта Quartus все ещё выкатывает warning но теперь эти сигналы удаляются. Если их просто объявить как STD_LOGIC, то они остаются, в проекте но никуда не подключатся. Поскольку процесса, создающего этот сигнал нет. Подозреваю что при прошивке ПЛИС они вообще удаляются.

Изменено пользователем makc
code => codebox - spoiler

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Admin: при вставке кода пользуйтесь тегом codebox. Не загромождайте тему.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А на сколько допустимо применение в VHDL оператора NULL ?

Есть такой код, которой формируется в процессе работ машины состояний:

WORK_STATE_MACHINE:PROCESS
    (
        PRESS_STATE
    )
    BEGIN
        REQ_RD            <= '0';                                     -- По умолчанию нет запроса на чтение
        REQ_WR           <= '0';                                     -- По умолчанию нет запроса на запись
        CNT_ENA           <= '0';                                     -- Работа счетчиков запрещена
        RESET_ALL_COUNTER <= '0';                                     -- Запрещено сбрасывать сётчики
        
            CASE PRESS_STATE IS

                WHEN IDLE               =>  NULL;                     -- В состоянии ожидания ничего не делаем

                WHEN READ_DATA          =>                            -- В состоянии чтения SDRAM памяти
                                            REQ_RD   <= '1';          -- Посылаем запрос на чтение
                                            CNT_ENA  <= '1';          -- Разрешаем работу счётчиков - формирователей адреса
                                            
                WHEN NEW_FRAME          =>                            -- В состоянии поступившего нового кадра
                                            RESET_ALL_COUNTER <= '1'; -- Сбрасываем счетчики - формирователи адреса
                
                WHEN WRITE_DATA         =>                            -- В состоянии записи данных в SDRAM
                                            REQ_WR   <= '1';          -- Посылаем запро на запись
                                            CNT_ENA  <= '1';          -- Разрешаем работу счётчиков - формирователей адреса
                                            
                WHEN WAIT_FIFO_READING  =>  NULL;                     -- В состоянии ожидания опустошения FIFO буфера мтарицы ничего не делаем

                WHEN OTHERS                     =>  NULL;                
            END CASE;
    END PROCESS;

По логике работы есть 2 состояния, в которых мне никакие сигналы формировать не надо. Допустимо ли применять в этом случае оператор NULL. Нет ли каких подводных камней у этого оператора. В книжках ничего толкового про это не написано....

Изменено пользователем Flip-fl0p

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В операторе case вы обязаны перечислить все возможные состояния. Если в каких-то из них ничего делать не надо, то и используется null.

        
             CASE PRESS_STATE IS

                 WHEN IDLE               =>  NULL;                     -- В состоянии ожидания ничего не делаем

                                             
                 WHEN WAIT_FIFO_READING  =>  NULL;                      -- В состоянии ожидания опустошения FIFO буфера мтарицы ничего не  делаем

                 WHEN OTHERS                     =>  NULL;

Тут idle и wait_fifo_reading можно опустить, потому что есть others с таким же (без)действием.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...