Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: FAQ по языкам описания аппаратуры
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Языки проектирования на ПЛИС (FPGA)
Страницы: 1, 2, 3
iosifk
Цитата(Димыч @ Sep 9 2012, 23:16) *
Нажмите для просмотра прикрепленного файла

Всем доброго времени суток!

Вчера, для аргументирования перехода со схемного ввода на HDL (для коллег), набросал небольшой документ. sm.gif - во вложении.

Если есть комментарии - велкам sm.gif


Написано большей частью верно. Вот только не написано самого основного - про отладку проектов, особенно больших. Посмотрите у меня на сайте, в статьях "Краткий Курс", о том как отлаживать, как подгружать в тестбенч данные из файлов и как данные выводить на монитор...
И еще. В русском, термина "схематик" - нет! Это жаргон!
stu
Некоторые моменты заинтересовали. Если не трудно, поясните пжлст.
------------------------------------------------------------------------------------------------
2. Параметризация. В HDL модуля легко параметризируются - либо "модулях", либо "модули", нет?
------------------------------------------------------------------------------------------------
6. Версионность. Для проектов, написанных на схематике - думаю, описываем, нет?
------------------------------------------------------------------------------------------------
10. Открытые базы проектов. На данный момент существует большое количество как открытых, так и платных проектов/коров/модулей на HDL - что это? Не слышал.
------------------------------------------------------------------------------------------------
Реализован простой механизм, который позволяет дизайнеру безболезненно переключаться между различными описаниями (вариантами) одного и того же вложенного модуля - мне очень интересно что это значит? Что мешает в Верилоге описать модули Test, Test_2, а при вызове просто поменять поменять из:
Код
...
Test #(parameters)
tst(in, out ports);
....

в
Код
...
Test_2 #(parameters)
tst(in, out ports);
...

если порты и параметры одинаковы, а отличается только лишь внутренняя структура файла ????
sazh
Цитата(stu @ Sep 10 2012, 13:42) *
Некоторые моменты заинтересовали. Если не трудно, поясните пжлст.

А зачем.
Обычно в графическом редакторе работают разработчики старшего поколения.
Они будут исходить из принципа разумной достаточности.
Этим должно озадачиться руководство. (Новые проекты - только на стандартизированных языках описания аппаратуры)
stu
Цитата(sazh @ Sep 10 2012, 15:21) *
А зачем.
Обычно в графическом редакторе работают разработчики старшего поколения.
Они будут исходить из принципа разумной достаточности.
Этим должно озадачиться руководство. (Новые проекты - только на стандартизированных языках описания аппаратуры)

Что "зачем"... Вы то тут причем? Заинтересовало, попросил пояснить...
Руководству проекты готовые нужны быстро и сейчас. Пока они операторы изучат, пока конструкции с ними... ну Вы поняли
slawikg
Цитата(Димыч @ Sep 9 2012, 22:16) *
Нажмите для просмотра прикрепленного файла

Всем доброго времени суток!

Вчера, для аргументирования перехода со схемного ввода на HDL (для коллег), набросал небольшой документ. sm.gif - во вложении.

Если есть комментарии - велкам sm.gif


Я бы хотел говорить чуть шире, о графическом описании проектов, поскольку кроме схем существуют ещё, блок-схемы алгоритмов, диаграммы автоматов.

1. Ничто не мешает создать текстовый модуль и сделать соответствующую текстовую конструкцию, а затем вставить в модуль более высокого уровня описанным в графике.

2. Никаких проблем в графике с параметризацией нет, всё тоже самое в HDL Дизайнере MentorGraphics, как, в общем-то и в Квартусе.

3. По крайней мере, в HDL Дизайнере есть много режимов обновлений и поиск- замена которые позволяют менять в проекте, как в файлах так и по иерархии. Если не наворотить в схеме то и в, дальнейшем проблем с размещением блоков и линий не будет.

4. Совершенно наоборот, когда текстовое описание проще делаешь узел/модуль в тексте а остальное в графике.

5. С этим согласен на 100 %, надо к этому добавить ещё время на изучение тузлов и поддержание библиотек.

6. Никто не мешает сравнивать сгенерированные текстовые файлы, а для перехода в графику достаточно щёлкнуть мышкой.

7. В HDL Дизайнере можно и нужно размещать комментарии, которые будут передаваться в соответствующие места сгенерированных текстовых файлов. Кроме того графика является уже подготовленной для того чтобы её вставлять в тест описай документации.

8. Как раз наоборот: графику во все времена было рассматривать проще. Не зря же составляют для пояснения программ, блок-схемы алгоритмов, диаграммы автоматов и схемы.

9. Ничего подобного. Помню как в своё время меня пытались заставить сделать функциональную схему на описание в альтеровском AHDL чтобы разобраться в проекте.

10. Коры и модули проще вставлять в схему . Если вы хотите дорабатывать проект сделанный в тексте, тут ничего не придумаешь, надо корректировать соответствующий текст.

Димыч
Цитата(iosifk @ Sep 10 2012, 09:47) *
Написано большей частью верно. Вот только не написано самого основного - про отладку проектов, особенно больших. Посмотрите у меня на сайте, в статьях "Краткий Курс", о том как отлаживать, как подгружать в тестбенч данные из файлов и как данные выводить на монитор...
И еще. В русском, термина "схематик" - нет! Это жаргон!

Спасибо за комментарий и подсказку "где копать ещё" sm.gif
Правда, очень ценно - так что буду систематизировать и дополнять.

Касаемо жаргона. Ну что ж, да - ему не место в официальных изданиях, книгах и научных трудах. Но здесь - совсем другой коленкор (сорри за жаргон). Как говорится, "излишняя бюрократизация страны способна затормозить прогрессивные изменения в ней".

с уважением,
Д.
Maverick
по поводу описания на HDL от gaisler

Цитата
Fault-tolerant Microprocessors for Space Applications
RuSTA
Возможно ли подключить в проект какое нибудь ядро с opencores.org на языке verilog в проект на языке verilogSystem?
Maverick
Цитата(RuSTA @ Sep 24 2013, 19:49) *
Возможно ли подключить в проект какое нибудь ядро с opencores.org на языке verilog в проект на языке verilogSystem?

можно
RuSTA
В ПЛИСах еще новичок. Почему возникает следующий вопрос. Довольно много программирую на C и Java, т.е. с данным синтаксисом хорошо знаком, по-этому интересует именно этот язык. Имеется ли какая нибудь толковая статья либо же книга, где на пальцах объясняют программирование на SystemVerilog?
А то что то когда про какие то АВТОМАТЫ идет речь, при этом перечисляемый тип объявляется "enum {IDLE,REQ,RESP} states;" повергает в ступор)))
andrew_b
Цитата(RuSTA @ Sep 24 2013, 23:28) *
А то что то когда про какие то АВТОМАТЫ идет речь, при этом перечисляемый тип объявляется "enum {IDLE,REQ,RESP} states;" повергает в ступор)))
Гуглите "Конечный автомат" или "Finite state machine". К языку не имеет отношения. Этот метод используется и при создании софта, а не только железа.
Radov Dmitrii
Уважаемые знатоки Verilog, не могли бы Вы подсказать ответы на волнующие меня вопросы, или дать ссылку на источник информации, где можно найти эти ответы.
1) на одном украинском сайте выложена статья про reusable code, там в качестве примера приводится АЛУ. там перед (вызовом модуля) module instantiation написано следующее ALU #(size_A, size_B) ALU_DUT , что это за задержка такая #(size_A, size_B)? size_A и size_B явл-ся параметрами вызываемого модуля. В этой же статье не совсем понятно что означает сие объявление reg [6*8:0] _Mode_names [3:0];
2) необходимо реализовать устройство на синхронной логике, реагирующее по фронту тактовой частоты и асинхронным reset и En. Вопрос заключается в следующем, поскольку мне важна последовательность назначений, можно ли использовать блокирующие назначения внутри конструкции always??? Согласно статье Сергея Емеца за 2001 год - "Если в блоке требуется провести последовательное исполнение операторов, следует применять блокирующий тип присвоения". Я полагаю, таким образом у меня появятся триггеры-защелки, как на Ваш взгляд было бы более качественно(меньшие аппаратные затраты, более высокое время исполнения) реализовать этот модуль?
always @(posedge clk or negedge reset)
if (!reset) or (AMCount == 1)
result <= DATA_WIDTH_out'b0;
else
begin
if (En)
begin // использовали блокирующее присвоение
R = R + (((C >> 56) & 0xFF) * 113);
R = R + (((C >> 48) & 0xFF) * 61);
R = R + (((C >> 40) & 0xFF) * 23);
R = R + (((C >> 32) & 0xFF) * 131);
R = R + (((C >> 24) & 0xFF) * 79);
R = R + (((C >> 16) & 0xFF) * 91);
R = R + (((C >> 8) & 0xFF) * 47);
R = R + (((C & 0xFF) * 157);

result = R % AMCount;

end
end



3) Если у меня между аппаратными блоками передаются данные с типом структура T размером 18 байт , в которую входит набор элементов-данных (1байт.1байт.8байт.8байт.2байта.8байт) мне необходимо эту структуру передавать по шине, соответствующей размерности, а уже внутри моего блока-приемника разделить эту шину, на интересующие меня сигналы(wire) ? Или на практике это реализуется несколько иначе? Если не затруднит, не могли бы скинуть ссылку, где описывается данная проблема.
dima32rus
Цитата(Radov Dmitrii @ Jul 9 2015, 12:43) *
там перед (вызовом модуля) module instantiation написано следующее ALU #(size_A, size_B) ALU_DUT , что это за задержка такая #(size_A, size_B)? size_A и size_B явл-ся параметрами вызываемого модуля.

Это реализация экземпляра параметризованного модуля ALU, имя экземпляра ALU_DUT. В скобках после "решетки" задаются параметры экземпляра. Подробнее можно почитать тут http://www.kit-e.ru/articles/circuit/2008_12_121.php

Цитата(Radov Dmitrii @ Jul 9 2015, 12:43) *
В этой же статье не совсем понятно что означает сие объявление reg [6*8:0] _Mode_names [3:0];

Объявлен массив 48-ми разрядных слов _Mode_names, состоящий из 4-х элементов. Чтобы обратиться, например, к третьему элементу массива, нужно записать так _Mode_names[2] <= 48'hFFFF_FFFF_FFFF;


Цитата(Radov Dmitrii @ Jul 9 2015, 12:43) *
Если у меня между аппаратными блоками передаются данные с типом структура T размером 18 байт , в которую входит набор элементов-данных (1байт.1байт.8байт.8байт.2байта.8байт) мне необходимо эту структуру передавать по шине, соответствующей размерности, а уже внутри моего блока-приемника разделить эту шину, на интересующие меня сигналы(wire) ? Или на практике это реализуется несколько иначе? Если не затруднит, не могли бы скинуть ссылку, где описывается данная проблема.

У Вас получается 1+1+8+8+2+8 = 28 байт, а не 18, если я правильно понял. Можно, конечно, сделать широкую шину и передавать одним тактом. Но, если "время терпит", лучше передать последовательно несколькими словами. Или вообще, по одной линии. В приемнике сдвигаете все в один регистр и дальше используете, как нужно. Погуглите термины "сериализация" и "десериализация". В сети также есть примеры на HDL. Например, на Verilog http://stackoverflow.com/questions/2901655...o-8-verilog-hdl
Radov Dmitrii
Можно ли внутри одного модуля чередовать комбинационные и синхронные блоки always?
Можно ли внутри блока always реагирующего по фронту сигнала использовать блокирующие присваивания?
Можно ли в Quartus 2 задавать 64-битным переменные(64-bit wide binary number)? Так возможно -> C = 64'b0 ?
des00
Цитата(Radov Dmitrii @ Jul 14 2015, 17:36) *
Можно ли внутри одного модуля чередовать комбинационные и синхронные блоки always?
Можно ли внутри блока always реагирующего по фронту сигнала использовать блокирующие присваивания?
Можно ли в Quartus 2 задавать 64-битным переменные(64-bit wide binary number)? Так возможно -> C = 64'b0 ?

{3{да}}

PS. Без обид. Учите матчасть.
dima32rus
Цитата(Radov Dmitrii @ Jul 14 2015, 13:36) *
Можно ли внутри одного модуля чередовать комбинационные и синхронные блоки always?


Можно, порядок следования блоков always в модуле ни на что не влияет.

Цитата(Radov Dmitrii @ Jul 14 2015, 13:36) *
Можно ли внутри блока always реагирующего по фронту сигнала использовать блокирующие присваивания?


Можно. Вот полезная статья по теме http://svo.2.staticpublic.s3-website-us-ea...og/assignments/

Цитата(Radov Dmitrii @ Jul 14 2015, 13:36) *
Можно ли в Quartus 2 задавать 64-битным переменные(64-bit wide binary number)? Так возможно -> C = 64'b0 ?


Здесь Вы присваиваете переменной 64-битное значение, но при этом определяете только один бит из 64-х. Тут надо смотреть, как поведет себя Quartus, во что такая запись синтезируется.
Лучше, конечно, определить все разряды. Я бы написал так С = 64'h00_00_00_00_00_00_00_00; Громоздко, но зато однозначно.
Можно еще так попробовать С = 64'd0; Но Quartus, кажется, считает десятичные числа 32-х разрядными. Поэтому старшие 32 бита опять могут повиснуть в воздухе.
Попробуйте разные варианты, посмотрите как оно получается в железе.
des00
Цитата(dima32rus @ Jul 14 2015, 18:41) *
Здесь Вы присваиваете переменной 64-битное значение, но при этом определяете только один бит из 64-х.

Вы не правы. IEEE Std 1364-2001 -> 2. Lexical conventions -> 2.5 Numbers -> 2.5.1 Integer constants
dima32rus
А еще лучше, как товарищ des00 выше подсказал, написать С = {64{1'b0}}; Так будет более правильно.

Цитата(des00 @ Jul 14 2015, 14:50) *
Вы не правы. IEEE Std 1364-2001 -> 2. Lexical conventions -> 2.5 Numbers -> 2.5.1 Integer constants


Возможно, как-то всегда избегал подобных записей. Спасибо за подсказку.
des00
Цитата(dima32rus @ Jul 14 2015, 18:52) *
написать С = {64{1'b0}}; Так будет более правильно.

Это лучше предотвращением предупреждения синтезатора в случае если длинна вектора задается параметром и может плавать. Т.е. {PIPA{1'b0}} - корректная конструкция, PIPA'd0 - нет. Но диапазон таких "красивых" констант ограничен.

Цитата
Возможно, как-то всегда избегал подобных записей. Спасибо за подсказку.

Ну и зря. Стандарт писали умные люди. Сами посудите, вы жестко задаете разрядность RHS, зачем писать нулевые старшие элементы? Вот если бы константа была безразмерная, то да,
Radov Dmitrii
upd.

В Квартусе, начиная с 14 версии задавать 64-bit wide binary number можно. Я не правильно сформулировал вопрос.

Если кто знает, не подскажите как выделить из 64-разрядной переменной, младшие/старшие 8 разрядов? Может ли integer x быть 64-разрядным? Верней integer, по всей видимости, по умолчанию это 32-разрядное целое число, а как задать его 64-разрядным?



upd upd Спасибо большое за ответы.
des00
Цитата(Radov Dmitrii @ Jul 14 2015, 20:43) *
Если кто знает, не подскажите как выделить из 64-разрядной переменной, младшие/старшие 8 разрядов? Может ли integer x быть 64-разрядным? Верней integer, по всей видимости, по умолчанию это 32-разрядное целое число, а как задать его 64-разрядным?

1.
pipa <= popa[7:0];
pipa <= popa[63:56];
2. integer может быть только 32 бита. А вот вектор может быть 2^16 битным.

ЗЫ. Не хотите читать стандарт, прочитайте любой другой нормальный материал по языку который собираетесь использовать для работы. Уважайте себя, не поднимайте насмех.
Radov Dmitrii
upd.

В Квартусе, начиная с 14 версии задавать 64-bit wide binary number можно. Я не правильно сформулировал вопрос.



Суть вопроса(опять криво сформулированного):
У меня есть переменная(64бит), у которой по очереди берут по одному байту начиная со старшего, умножают на некоторое число, затем результат отправляют в другую переменную(полагаю, что тип reg, иначе не получится сохранить полученные промежуточные значения)

dima32rus: спасибо за ссылку и ответы, но я эту статью прочёл в прошлый раз, когда Вы мне её прислали. Меня слегка сбил материал с Марсохода, я видимо не так понял, но мне показалось что там прослеживалась логика если по уровню то комб. логика и блокирующие присваивании если по фронту то синх. лог и неблок. присваивания.

des00: спасибо за ответ. Простите не успел отредактировать вопрос, т.е. стереть вопросы. Стандарт прочту.

upd upd Спасибо большое за ответы.
Грендайзер
Всем доброго времени суток. Не совсем знал куда писать, так что напишу сюда. Сталкнулся с такой проблемой - написал ядро (avalon - slave) для NiosII. Приведу несколько строк кода:
Код
  wr_tx_udp_data_LOW <=
               '1' when address = "1000" and wr_en='1' else '0'; -- 8 TX_UDP_DATA_LOW
       wr_tx_udp_data_HIGH <=
               '1' when address = "1001" and wr_en='1' else '0'; -- 9 TX_UDP_DATA_HIG
                                      .
                                      .
                                      .
           process(clk50, resetn)
           begin
           if rising_edge(clk50) then
          
           if wr_tx_udp_data_LOW = '1' then
        tx_udp_data_reg(31 downto 0) <= writedata(31 downto 0);
       else
        tx_udp_data_reg <= tx_udp_data_reg;
       end if;

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


Имеется 64-х разрядный буфер tx_udp_data_reg, в него необходимо записать данные с 32-х разрядной шины writedata. Я решил записать сначала младшие 4 байта, затем страршие 4 байта. Но как оказалось после компиляции запись происходит лишь в старшие 4 байта. После этого я закоментил строки:

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

Запись как и положено произошла в младшие 4 байта. Я сделал вывод, что компилятор оптимизирует логику в первом коде, но почему?

Stewart Little
A если так:
Код
           if wr_tx_udp_data_LOW = '1' then
                 tx_udp_data_reg(31 downto 0) <= writedata(31 downto 0);
                 tx_udp_data_reg(63 downto 32) <= tx_udp_data_reg(63 downto 32);
           elsif wr_tx_udp_data_HIGH = '1' then
                 tx_udp_data_reg(31 downto 0) <= tx_udp_data_reg(31 downto 0);
                 tx_udp_data_reg(63 downto 32) <= writedata(31 downto 0);
           else
                 tx_udp_data_reg <= tx_udp_data_reg;
           end if;
Грендайзер
Stewart Little, спасибо за совет, помогло. Правда напсал чуть короче:
Код
if wr_tx_udp_data_LOW = '1' then
                 tx_udp_data_reg(31 downto 0) <= writedata(31 downto 0);
           elsif wr_tx_udp_data_HIGH = '1' then
                 tx_udp_data_reg(63 downto 32) <= writedata(31 downto 0);
           else
                 tx_udp_data_reg <= tx_udp_data_reg;
           end if;


Но почему всё же первый вариант не прокатил? 05.gif
Stewart Little
Цитата(Грендайзер @ Jul 28 2015, 10:14) *
Правда напсал чуть короче
Ну тогда и последний else можно опустить. sm.gif

Цитата(Грендайзер @ Jul 28 2015, 10:14) *
Но почему всё же первый вариант не прокатил? 05.gif
Навскидку предполагаю, что из-за:
а) в VHDL последующая транзакция отменяет предыдущую.
б) у Вас два последовательных if'а в одном процессе (и, кстати, их условий нет в списке чувствительности).
в) особенностей картусовского синтезатора при обработке совокупности указанных выше условий. sm.gif
Грендайзер
Цитата
Ну тогда и последний else можно опустить. sm.gif

Да, пожалуй Вы правы cool.gif
Цитата
Навскидку предполагаю, что из-за:

более склоняюсь к последнему...
Спасибо за помощь sm.gif
Barktail
Цитата(Грендайзер @ Jul 28 2015, 10:40) *
более склоняюсь к последнему...


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

Дык тут то сапр как раз прав оказался, никакой ошибки нет.
Barktail
Цитата(Грендайзер @ 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 это кажется называется. Хотя тут не уверен.
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;


Записи эквиваленты с точки зрения функционала.
Andrew Su
Цитата(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,
то первая.
Flip-fl0p
Мне необходимо, чтобы в момент когда подана команда записи данных в SDRAM память данные, которые контроллер памяти выдает на шину данных SDRAM памяти были стабильными и не менялись до прихода переднего фронта частоты SDRAM контроллера, которым эти данные и зафиксируются. Для этого мне необходимо чтобы в это время данные были стабильными.
Фактически я на "железе" проверил оба варианта, и они работают. Но с точки зрения увеличения максимальной частоты проекта, какой способ более правильный ?
Flip-fl0p
Возник вопрос по параметризации модуля, который я пишу на VHDL.
Допустим есть некий модуль "COMPONENT_MODULE" который что-то умеет делать.
В этом модуле есть некий процесс "CONTROL_DATA", который выдает сигнал в зависимости от внешних условий.
В проекте более высокого уровня я использую 10 таких модулей.
Но сигнал "CONTROL_DATA" мне нужен только от одного из модулей(неважно какого). В остальных модулях данный сигнал мне не нужен.
Есть ли в VHDL возможность сделать процесс параметризированным и в зависимости от какой-либо константы описанной в GENERIC области он будет включен/выключен ?
На данный момент я просто не использую эти сигналы, но Quartus выдает предупреждение о них. Хотелось бы как-нибудь красиво это описать.
Tausinov
Цитата(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 модулям так, чтобы на модуль с нужным выходным сигналом приходили соответствующие данные.
Flip-fl0p
Цитата(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;

Спасибо за ответ. Завтра с утра на свежую голову попробую сделать, как Вы советовали.
Flip-fl0p
Спасибо за помощь. В общем теперь модуль выглядит так:
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
Admin: при вставке кода пользуйтесь тегом codebox. Не загромождайте тему.
Flip-fl0p
А на сколько допустимо применение в 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. Нет ли каких подводных камней у этого оператора. В книжках ничего толкового про это не написано....
andrew_b
В операторе case вы обязаны перечислить все возможные состояния. Если в каких-то из них ничего делать не надо, то и используется null.
Код
        
             CASE PRESS_STATE IS

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

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

                 WHEN OTHERS                     =>  NULL;

Тут idle и wait_fifo_reading можно опустить, потому что есть others с таким же (без)действием.
Flip-fl0p
Цитата(andrew_b @ Nov 17 2016, 10:03) *
В операторе case вы обязаны перечислить все возможные состояния. Если в каких-то из них ничего делать не надо, то и используется null.
Код
        
             CASE PRESS_STATE IS

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

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

                 WHEN OTHERS                     =>  NULL;

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

Спасибо. Забыл, что их можно опустить. Просто к чему я задал вопрос:
Я ведь могу задать так:
Код
WHEN OTHERS    =>
        REQ_RD            <= '0';                                     -- По умолчанию нет запроса на чтение
        REQ_WR            <= '0';                                     -- По умолчанию нет запроса на чтение
        CNT_ENA           <= '0';                                     -- Работа счетчиков запрещена
        RESET_ALL_COUNTER <= '0';

По сути ничего не меняется. Quartus количество ячеек не меняет. Где-то в книге читал (но не помню какой), что оператор NULL надо применять о большой осторожностью. Но вот больше ничего конкретного, чего надо остерегаться, написано не было. Вот и хотелось бы разобраться, а так ли страшен черт как его малюют ?
Flip-fl0p
Добрый день, уважаемые форумчане.

Не могли бы Вы мне подсказать один момент:
Допустим у меня есть рабочий проект UART приёмника, состоящий из нескольких более мелких модулей. К примеру все файлы проекта UART приёмника расположенный папке С:\UART_RECEIVER
Я хочу применить этот модуль в своем проекте MY_PROJECT. К примеру он будет расположен в папке С:\MY_PROJECT
Когда я компилирую проект MY_PROJECT мне приходится чтобы Quartus не ругался:
1. Закинуть UART приёмника в папку с проектом MY_PROJECT т.е. С:\MY_PROJECT\UART_RECEIVER
2. Далее обвить проект UART в проекте верхнего уровня MY_PROJECT при помощи ENTITY WORK.UART
3. И каждый файл проекта UART добавить в текущий проект MY_PROJECT т.е для каждого файла выполнить File --> open затем project --> add curent file to project

А можно ли как-то упростить процедуру прикрепления модуля UART приёмника ?
Пытался по-по всякому объявить его при помощи директивы USE. Но Quartus меня не понял....


andrew_b
Цитата(Flip-fl0p @ Nov 25 2016, 11:18) *
Пытался по-по всякому объявить его при помощи директивы USE.
Причём тут use? Use используется для модулей уже готовой библиотеки. Для вашего модуля нужно сделать отдельную библиотеку для Квартуса. Как это сделать и можно ли это сделать в принципе, я не знаю.
Наверное, как-то это можно сделать через файл qip, как для ядер.
Flip-fl0p
Стыдно признаться, но у меня сейчас каша в голове. Собственно никак не могу понять смысл простейшей терминологии:
Большинство авторов книг по VHDL пишут, что есть три стиля описания схем:
- Структурное
- Поведенческое
- Потоковое
Что такое структурное описание вопросов не возникает.
А вот в чём разница между потоковым описанием и поведенческим в книгах толком и не раскрыта. Никак не могу уловить суть. Хотя это знание и никак не влияет на конечный результат, но хочется понимать какой смысл заложен в эти фразы.

Poluektovich
Потоковое описание (RTL) должно быть синтезопригодным, а поведенческое содержит несинтезируемые конструкции и используется для верификации.
Flip-fl0p
Цитата(Poluektovich @ Jan 10 2017, 10:15) *
Потоковое описание (RTL) должно быть синтезопригодным, а поведенческое содержит несинтезируемые конструкции и используется для верификации.

Неужели так просто ? wacko.gif
Fitc
Цитата(Flip-fl0p @ Jan 10 2017, 09:43) *
Стыдно признаться, но у меня сейчас каша в голове. Собственно никак не могу понять смысл простейшей терминологии:
Большинство авторов книг по VHDL пишут, что есть три стиля описания схем:
- Структурное
- Поведенческое
- Потоковое
Что такое структурное описание вопросов не возникает.
А вот в чём разница между потоковым описанием и поведенческим в книгах толком и не раскрыта. Никак не могу уловить суть. Хотя это знание и никак не влияет на конечный результат, но хочется понимать какой смысл заложен в эти фразы.

Советую почитать главу 2 документации по Yosys там довольно подробно расписано про разницу в данных стилях. Там это называется уровнями абстракции: поведенческий (Behavioural Level) и RTL-уровень рассматриваются с точки зрения синтеза.
http://www.clifford.at/yosys/files/yosys_manual.pdf
Flip-fl0p
Возник маленький вопрос при написании тестов на VHDL. А как заставить условие выполняться только один раз ?
Например у меня есть кусок кода тестбенча:
Код
    COUNTER_PROC : PROCESS
    (
        CLK
    )
        VARIABLE COUNTER : INTEGER RANGE 0 TO 15;
    BEGIN
        IF (RISING_EDGE(CLK)) THEN
            IF (COUNTER = 15) THEN
                COUNTER := 0;
            ELSE
                COUNTER := COUNTER + 1;
            END IF;
        END IF;
        
        IF (COUNTER = 14) THEN
            LOAD_DATA <= "0111";
            LOAD_ENA  <= '1';
        ELSE
            LOAD_DATA <= (OTHERS => '0');
            LOAD_ENA  <= '0';
        END IF;

    END PROCESS;

А если мне надо, чтобы данный процесс выполнился только один раз, как мне быть ?
Я придумал вариант, что когда счётчик досчитал до конца он зацикливается, но мне этот вариант не нравится. Такое чувство, что можно описать как-то красивее, правильнее.
Код
        IF (RISING_EDGE(CLK)) THEN
            IF (COUNTER = 15) THEN
                COUNTER := 15;
            ELSE
                COUNTER := COUNTER + 1;
            END IF;
        END IF;

Решение ждать конкретное время:
Код
WAIT FOR 780 ns;
Выглядит чуть более красиво, мне как-то не симпатизирует, поскольку не хочу заморачиваться с подсчётом времени и подстановкой в нужное мне время нужных значений сигналов.
andrew_b
wait без указания времени будет ждать вечность.
Flip-fl0p
Цитата(andrew_b @ Jan 18 2017, 13:55) *
wait без указания времени будет ждать вечность.

Спасибо ! Забыл, что можно оператор wait использовать...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.