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

Тернарный оператор VS конструкция if-else

Предположим, есть конечный автомат, который в работе должен пробрасывать тактовую частоту через себя, а в состоянии IDLE установить выход тактовой частоты в единицу.

 

Тогда код может быть следующий:

wire clk_in;
wire clk_out;
reg state;

assign clk_out = clk_in | ~(state^IDLE);

Т.е. если state и IDLE совпадают бит-в-бит, то их побитовый XOR будет равен нулю. Инвертированный ноль - это единица. Единица или clk_in - единица. В противном случае, ноль или clk_in - это clk_in.

Всё абсолютно прозрачно синтезируется.

 

Или код может быть такой:

wire clk_in;
wire clk_out;
reg state;

assign clk_out = clk_in | (state == IDLE);//На месте синтезатора я заменил бы данную конструкцию на предыдущую

 

Или такой:

wire clk_in;
wire clk_out;
reg state;

assign clk_out =(state == IDLE) ? 1 : clk_in;

 

Но почему не прокатывает следующий вариант?

wire clk_in;
wire clk_out;
reg state;

always @(state)
begin
if(state == IDLE) begin
  clk_out = 1;
end
else begin
  clk_out = clk_in;
end
end

В таком варианте Квартус ругается на то, что "10137: Object on left-hand side of assignment must have a variable data type".

 

Не, ну нельзя, так - нельзя. Но эмм... в списке чувствительности отсутствуют posedge/negedge. В любом случае, синтезатор будет разворачивать эту конструкцию в комбинационную логику (причем, скорее всего в такую, как в первом примере). Так чего же он лезет на рожон (регистр ему подавай)? Какова логика языка? Почему так писать некорректно?

 

 

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


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

1. Я бы вообще никаких манипуляций с частотой не производил.

2. Если уж так нужно, обратите внимание на: altera clkctrl

 

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


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

Приветсвую!

 

...

...

Но почему не прокатывает следующий вариант?

wire clk_in;
wire clk_out;
reg state;

always @(state)
...
  clk_out = clk_in;
...
end

В таком варианте Квартус ругается на то, что "10137: Object on left-hand side of assignment must have a variable data type".

 

Не, ну нельзя, так - нельзя. Но эмм... в списке чувствительности отсутствуют posedge/negedge. В любом случае, синтезатор будет разворачивать эту конструкцию в комбинационную логику (причем, скорее всего в такую, как в первом примере). Так чего же он лезет на рожон (регистр ему подавай)? Какова логика языка? Почему так писать некорректно?

Это не Квартус лезет на рожон скорее это Вы пристаете к синтезатору с классическим вопросом "...Закурить найдется?" :) А он Вам вежливо - не курю не могу присвоить значение переменной типа wire в процедурном блоке. Для wire допустимо использование только assign (так пацаны на сходке решили еще аж 1995 году). Если Вы смелы то объявите
 reg clk_out;

Тогда Квартус примет Вас за своего и получите сигаретку назначение переменной в процедурном блоке ;)

 

Удачи! Rob.

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


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

1. Я бы вообще никаких манипуляций с частотой не производил.

2. Если уж так нужно, обратите внимание на: altera clkctrl

Без обид.

Смотрите внимательно, то что я напишу.

Для одних - ПЛИС это кусок хлеба. И форум - это товарищи, которые помогают начать прилично зарабатывать. Поэтому их советы ценятся. Потому что на работе надо давать результат, иначе не будет зарплаты, причем результат нужен каждый день, а не когда-то потом. И я помню, что сам был в такой же ситуации. До этого я писал на VHDL, пришел на новую работу и там сказали - только Verilog. И я учился "в бою". И мне абсолютно некогда было "изобретать художества". Брал проверенные шаблоны и из них делал код, в том числе и по выходным, чтобы успеть.

А для других ПЛИС - это игра. Им результат как таковой не нужен. Они "проводят изыскания" в кусках кода, в "триггерах, нарисованных вьюерами" и т.д. Им советы, выдаваемые на форуме вроде как и нужны, но они все равно все сделают по-своему, "через Альпы".

Вот так и здесь. Есть основы:

клоки не изобретать и проект делать синхронным;

"внутри автоматов не плодить счетчики и не делать клоки.

 

И это написано практически во всех руководствах. Ну и что? Это же так интересно, написать что-то принципиально "свое", а потом задавать об этом вопросы на форуме. Чтобы все, кто готов помочь, бросились объяснять очевидные вещи.

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

Вот как-то так....

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


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

Предположим, есть конечный автомат, который в работе должен пробрасывать тактовую частоту через себя, а в состоянии IDLE установить выход тактовой частоты в единицу.

 

Тогда код может быть следующий:

wire clk_in;
wire clk_out;
reg state;

assign clk_out = clk_in | ~(state^IDLE);

Т.е. если state и IDLE совпадают бит-в-бит, то их побитовый XOR будет равен нулю. Инвертированный ноль - это единица. Единица или clk_in - единица. В противном случае, ноль или clk_in - это clk_in.

Это в идеале. IRL из-за всяких задержек вы получите на clk_out хороший такой дребезг. Нельзя просто так взять и смешать клок с обычным сигналом, тем более многоразрядным.

 

Но эмм... в списке чувствительности отсутствуют posedge/negedge. В любом случае, синтезатор будет разворачивать эту конструкцию в комбинационную логику (причем, скорее всего в такую, как в первом примере). Так чего же он лезет на рожон (регистр ему подавай)? Какова логика языка? Почему так писать некорректно?
Про разницу reg/wire вам уже сказали. Добавлю, что если в always описывается комбинационная схема, в списке чувствительности должны присутствовать все сигналы, от которых зависит выход. У вас там не хватает clk_in, поэтому вы получите не комбинационную схему, а latch.

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


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

1. Я бы вообще никаких манипуляций с частотой не производил.

Конкретная задача. FPGA соединена с PC при помощи моста "USB - что_угодно" FT2232H, который способен работать в режиме асинхронного FIFO. У моста есть два буфера - TX и RX. Для передачи данных в FPGA мосту надо стробировать nRD. Для отправки на PC (и захвата данных во входной буфер) этому мосту надо стробировать nWR. Правильнее было бы описать дергание стробов в состояниях конечного автомата?

 

Приветсвую!

 

Это не Квартус лезет на рожон скорее это Вы пристаете к синтезатору с классическим вопросом "...Закурить найдется?" :) А он Вам вежливо - не курю не могу присвоить значение переменной типа wire в процедурном блоке. Для wire допустимо использование только assign (так пацаны на сходке решили еще аж 1995 году). Если Вы смелы то объявите

 reg clk_out;

Тогда Квартус примет Вас за своего и получите сигаретку назначение переменной в процедурном блоке ;)

 

Удачи! Rob.

Добрый день!

Про то, что с доп.регистром всё заработает - это да. Только этот же регистр всё равно не синтезируется. Всё сведется к XOR-у + лог.ИЛИ (как в первом примере). И это понятно по отсутствию posedge/negedge в списке чувствительности. Чем руководствовались пацаны в 1995 году, когда так договаривались? От чего они пытались оградить программистов? Не собираются ли пацаны выпустить новый стандарт? Ибо тернарный оператор выглядит костылеобразно (не круто).

Спасибо!

 

Это в идеале. IRL из-за всяких задержек вы получите на clk_out хороший такой дребезг. Нельзя просто так взять и смешать клок с обычным сигналом, тем более многоразрядным.

Спасибо за ценное замечание. Действительно, если клок управляется значением шины hAA и шина переключается из состояния h0F в hF0 не синхронно а как бы по пути h0F->h0A->hAA->hA0->hF0 может произойти неприятное.

 

Добавлю, что если в always описывается комбинационная схема, в списке чувствительности должны присутствовать все сигналы, от которых зависит выход. У вас там не хватает clk_in, поэтому вы получите не комбинационную схему, а latch.

Точно. Ну в любом случае синтезатор не даст такой синтаксической конструкции собраться.

 

Без обид.

Без обид, разумеется.

Ув.iosifk мне кажется есть два (как минимум) случая, когда "ориентированность на результат" приведет к негативным последствиям:

1. Конструкция языка/библиотеки/устройства претерпела изменения за последнее время (или такое изменение напрашивается в ближайшем будущем).

Пример: инициализация регистров при запуске ПЛИС "в железе". На сколько понял читая материалы в сети, в 90-е регистры инициализировались исключительно нулями. Сейчас ситуация поменялась, но ряд комментаторов по старой памяти утверждают, что это невозможно и сами не используют эту удобную опцию.

2. Хрестоматийный пример, на который нужно равняться, содержит незаметную ошибку.

Пример: в LabVIEW есть пример работы с высокоскоростными модулями HSDIO. Коротко, работа с HSDIO представляет последовательность Init->Transmit/Receive->Close. Но Close может быть двух типов - "Закрыть по завершении Transmit/Receive" и "Закрыть немедленно". Так вот в официальном примере использовано "Закрыть немедленно". HSDIO в режиме Transmit/Receive работает автономно от PC и обычно гораздо быстрее. Так что программы на основе примера работают корректно. Но если забить буфер HSDIO под завязку, и выставить частоту работы по минимуму, "хвост" передачи будет обрублен. Причем без каких-либо эксепшенов.

 

Таким образом, если времени нет, разумеется приходится "ориентироваться на результат". Но если оно есть, почему бы не выяснить как именно работает тот или иной подход и почему именно так.

 

Кроме того есть замечательное руководство "Как правильно задавать вопросы на технических ресурсах". Надеюсь я правильно истолковываю данный кодекс, полагая что вопрос в духе "вот моя плата на 100 микросхем, вот мой код на 10.000 строк, тут что-то не работает" хуже, чем вопрос "Вот три строчки кода, которые не работают. Вот стремный воркэраунд на десять строчек, который работает. Можно ли написать красивее и правильнее?". И если у меня возникает вопрос первого типа, его нужно свести к вопросу второго типа и только потом обращаться за помощью.

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

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


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

Но почему не прокатывает следующий вариант?

wire clk_in;
wire clk_out;
reg state;

always @(state)
begin
if(state == IDLE) begin
  clk_out = 1;
end
else begin
  clk_out = clk_in;
end
end

В таком варианте Квартус ругается на то, что "10137: Object on left-hand side of assignment must have a variable data type".

Все что формируется в блоке always, не зависимо от того, что вы хотите видеть после синтеза (последовательностный элемент или комбинационный) должно быть типа reg.

А вообще вы описали защелку (latch). Я бы тоже с клоками не баловался подобным образом, но если уж на то пошло, то:

wire clk_in;
reg clk_out;
reg state;

always @(*)
begin
if(state == IDLE) begin
  clk_out = 1;
end
else begin
  clk_out = clk_in;
end
end

 

-----------------------------------------------------------------------------

Упс, повторяюсь за выше отписавшимися...

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

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


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

Конкретная задача. FPGA соединена с PC при помощи моста "USB - что_угодно" FT2232H, который способен работать в режиме асинхронного FIFO. У моста есть два буфера - TX и RX. Для передачи данных в FPGA мосту надо стробировать nRD. Для отправки на PC (и захвата данных во входной буфер) этому мосту надо стробировать nWR. Правильнее было бы описать дергание стробов в состояниях конечного автомата?

 

Таким образом, если времени нет, разумеется приходится "ориентироваться на результат". Но если оно есть, почему бы не выяснить как именно работает тот или иной подход и почему именно так.

 

Для начала - http://www.sunburst-design.com/

Ищем статьи отцов-основателей.

Вот здесь: http://www.sunburst-design.com/papers/

И если поискать, то найдете, что когда пишите assert, то это для wire... А когда есть события - на которые указывает "@", то это все в основном для регистров.

Если Вы знаете, что такое "автомат", то попробуйте представить себе набор автоматов - мастер-слэйв-слэйв. Нижний работает только на уровне бита при последовательной передаче или слова при параллельной. Средний - передает слова или кадры. А верхний - сообщения, которые могут состоять из нескольких кадров.

Причем "внутри" описания автомата я не рекомендую врезать какие-либо счетчики или что-то еще. Автомат должен только лишь выдавать стробы для управления всеми другими узлами.

Что еще? Основной "подход" - это не тонкости описания, а именно то, как Вы строите архитектуру вычислительного узла. Вот скажем проблема со стробами nWR Вас интересует, а протокол передачи данных по линии связи видимо пока еще нет. А парсер протокола делать будете?

 

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


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

Приветсвую!

Про то, что с доп.регистром всё заработает - это да. Только этот же регистр всё равно не синтезируется. Всё сведется к XOR-у + лог.ИЛИ (как в первом примере).
Увы тип reg ввоодит в заблуждение - переменная этого типа не всегда синтезируется в регистр как многие ожидают от названия. Это зависит где и как Вы работаете с этой переменной.

И это понятно по отсутствию posedge/negedge в списке чувствительности. Чем руководствовались пацаны в 1995 году, когда так договаривались? От чего они пытались оградить программистов? Не собираются ли пацаны выпустить новый стандарт? Ибо тернарный оператор выглядит костылеобразно (не круто).
Пацаны руководствовались тем что было - бригада собралась молодая, дерзкая, но ума/силенок на первых порах не хватало - приходилось отбиваться от банды с соседнего VHDL двора. :maniac:

Сейчас уже поумнев добавили возможность разработчикам использовать always @(*) или даже always_comb. A чтобы не путать неокрепшие умы молодой братвы вместо reg использовать bit или logic. Но тернарный оператор не обижайте! - я за него "...пасть порву, моргалы выколю ..." ®Доцент :)

 

Главное в любой разработке (а не только для FPGA) это не тупое использование чьих-то шаблонов для заработка куска хлеба

а старание понять почему и для чего они сделаны. От чего зависит применении тех или иных конструкций языка. Во что это выливается в конкретном симуляторе/синтезаторе/железе. И Ваше желание разобраться в этом похвально. Тогда со временем сможете намазать чем то FPGAшный кусок хлеба ну или сами начнете писать тупые шаблоны для других ;).

 

Удачи! Rob.

 

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


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

Для начала - http://www.sunburst-design.com/

Ищем статьи отцов-основателей.

Вот здесь: http://www.sunburst-design.com/papers/

И если поискать, то найдете, что когда пишите assert, то это для wire... А когда есть события - на которые указывает "@", то это все в основном для регистров.

Если Вы знаете, что такое "автомат", то попробуйте представить себе набор автоматов - мастер-слэйв-слэйв. Нижний работает только на уровне бита при последовательной передаче или слова при параллельной. Средний - передает слова или кадры. А верхний - сообщения, которые могут состоять из нескольких кадров.

Причем "внутри" описания автомата я не рекомендую врезать какие-либо счетчики или что-то еще. Автомат должен только лишь выдавать стробы для управления всеми другими узлами.

Что еще? Основной "подход" - это не тонкости описания, а именно то, как Вы строите архитектуру вычислительного узла. Вот скажем проблема со стробами nWR Вас интересует, а протокол передачи данных по линии связи видимо пока еще нет. А парсер протокола делать будете?

Т.к. я пишу и клиентскую часть и прошивку для FPGA, то протокол могу менять сам, подстраивая его под возможности и ограничения оборудования. Процесс итеративен - я смотрю что можно "выжать" из LabVIEW, FT2232H и MAX-10 по максимуму. И как это правильнее сделать, что бы это не был "write only code".

Огромное спасибо, ув.iosifk за Ваши советы!

 

 

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


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

Т.к. я пишу и клиентскую часть и прошивку для FPGA, то протокол могу менять сам, подстраивая его под возможности и ограничения оборудования. Процесс итеративен - я смотрю что можно "выжать" из LabVIEW, FT2232H и MAX-10 по максимуму. И как это правильнее сделать, что бы это не был "write only code".

Огромное спасибо, ув.iosifk за Ваши советы!

Тогда вот

wave_gen_ver_v6.zip

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


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

Вот так и здесь. Есть основы:

клоки не изобретать и проект делать синхронным;

"внутри автоматов не плодить счетчики и не делать клоки.

 

Простите, а что плохого в счетчиках внутри автоматов?

 

 

инициализация регистров при запуске ПЛИС "в железе". На сколько понял читая материалы в сети, в 90-е регистры инициализировались исключительно нулями. Сейчас ситуация поменялась, но ряд комментаторов по старой памяти утверждают, что это невозможно и сами не используют эту удобную опцию.

Я сам с Альтерой не работал, но слышал, что там до сих пор инициализация только нулями. У lattice тоже не у всех семейств поддерживается инициализация.

 

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


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

Простите, а что плохого в счетчиках внутри автоматов?

Синхронный проект должен работать по клокам.

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

А если при описании автомата, Вы запихиваете счетчик "внутрь" комбинационной части, то что будет подано на тактовые входы счетчика? Но даже если компилятор сообразит подать туда клоки, то все равно, к комбинационной части добавятся еще N разрядов счетчика. И все это надо будет уложить в период тактовой частоты.

Поэтому я так стараюсь никогда не делать.

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

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

Если хотите, то могу росказать подробнее.

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


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

Приветствую!

 

Синхронный проект должен работать по клокам.

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

А если при описании автомата, Вы запихиваете счетчик "внутрь" комбинационной части, то что будет подано на тактовые входы счетчика? Но даже если компилятор сообразит подать туда клоки, то все равно, к комбинационной части добавятся еще N разрядов счетчика. И все это надо будет уложить в период тактовой частоты.

Поэтому я так стараюсь никогда не делать.

Простите но это просто глупость - Вы действительно считаете что счетчик описанный в FSM будет по другому синтезирован чем счетчик описанный вне FSM? Может приведете примеры такого "безобразия" ?

 

Успехов! Rob.

 

 

 

 

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


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

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

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

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

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

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

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

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

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

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