|
|
  |
FAQ по языкам описания аппаратуры |
|
|
|
Jul 28 2015, 07:25
|

Лентяй
     
Группа: Свой
Сообщений: 2 203
Регистрация: 11-10-04
Из: Санкт-Петербург
Пользователь №: 843

|
Цитата(Грендайзер @ Jul 28 2015, 10:14)  Правда напсал чуть короче Ну тогда и последний else можно опустить.  Цитата(Грендайзер @ Jul 28 2015, 10:14)  Но почему всё же первый вариант не прокатил?  Навскидку предполагаю, что из-за: а) в VHDL последующая транзакция отменяет предыдущую. б) у Вас два последовательных if'а в одном процессе (и, кстати, их условий нет в списке чувствительности). в) особенностей картусовского синтезатора при обработке совокупности указанных выше условий.
--------------------
Чтобы слова не расходились с делом, нужно молчать и ничего не делать...
|
|
|
|
|
Jul 28 2015, 07:40
|
Местный
  
Группа: Участник
Сообщений: 368
Регистрация: 18-04-11
Из: Город-герой Москва
Пользователь №: 64 451

|
Цитата Ну тогда и последний else можно опустить. sm.gif Да, пожалуй Вы правы Цитата Навскидку предполагаю, что из-за: более склоняюсь к последнему... Спасибо за помощь
|
|
|
|
|
Jul 28 2015, 09:57
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 14-12-11
Пользователь №: 68 851

|
Цитата(Грендайзер @ Jul 28 2015, 10:40)  более склоняюсь к последнему... А может просто else-ы конфликтуют с "противоположными" if? Не определены действия когда лоу=0, а хай=1. Первый иф говорит перезаписывай значение, а второй - пиши новое в старшие байты. И наоборот. Наверняка там варнинг был соответствующий. ИМХО вина сапра только в том что эррор не выкатил)
|
|
|
|
|
Jul 28 2015, 13:00
|
Местный
  
Группа: Участник
Сообщений: 368
Регистрация: 18-04-11
Из: Город-герой Москва
Пользователь №: 64 451

|
Что значит Цитата с "противоположными" if ? Есть 2 разных флага, по значению которых необходимо произвести разные действия с общим буфером. Цитата ИМХО вина сапра только в том что эррор не выкатил) Дык тут то сапр как раз прав оказался, никакой ошибки нет.
|
|
|
|
|
Jul 28 2015, 13:23
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 14-12-11
Пользователь №: 68 851

|
Цитата(Грендайзер @ Jul 28 2015, 16:00)  Что значит ? Есть 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 - Jul 28 2015, 13:34
|
|
|
|
|
Oct 12 2016, 10:47
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
А можете помочь разобраться как правильнее написать При помощи логики : Код 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 - Oct 12 2016, 10:47
|
|
|
|
|
Oct 13 2016, 15:37
|
Местный
  
Группа: Свой
Сообщений: 301
Регистрация: 18-09-07
Из: Украина
Пользователь №: 30 647

|
Цитата(Flip-fl0p @ Oct 12 2016, 13:47)  А можете помочь разобраться как правильнее написать При помощи логики : Код 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, то первая.
|
|
|
|
|
Oct 26 2016, 15:38
|
Частый гость
 
Группа: Участник
Сообщений: 135
Регистрация: 19-10-13
Пользователь №: 78 795

|
Цитата(Flip-fl0p @ Oct 26 2016, 13:44)  Возник вопрос по параметризации модуля, который я пишу на 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 модулям так, чтобы на модуль с нужным выходным сигналом приходили соответствующие данные.
|
|
|
|
|
Oct 26 2016, 20:21
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Цитата(Tausinov @ Oct 26 2016, 18:38)  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 И действительно в проекте у меня остаются "висящими в воздухе" эти выводы у двух серилайзеров. CODE --================================================================ -- Серилайзер для матрицы 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 области включать отключать процесс: CODE 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 - Oct 28 2016, 04:28
Причина редактирования: code => codebox
|
|
|
|
|
Oct 27 2016, 20:39
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Спасибо за помощь. В общем теперь модуль выглядит так: CODE --================================================================ -- Серилайзер для матрицы 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 - Oct 28 2016, 04:26
Причина редактирования: code => codebox - spoiler
|
|
|
|
|
Nov 17 2016, 06:19
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
А на сколько допустимо применение в 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 - Nov 17 2016, 06:22
|
|
|
|
|
Nov 17 2016, 07:03
|
Профессионал
    
Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757

|
В операторе case вы обязаны перечислить все возможные состояния. Если в каких-то из них ничего делать не надо, то и используется null. Код CASE PRESS_STATE IS WHEN IDLE => NULL; -- В состоянии ожидания ничего не делаем WHEN WAIT_FIFO_READING => NULL; -- В состоянии ожидания опустошения FIFO буфера мтарицы ничего не делаем WHEN OTHERS => NULL; Тут idle и wait_fifo_reading можно опустить, потому что есть others с таким же (без)действием.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|