Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Условный Timing Control на Verilog
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Языки проектирования на ПЛИС (FPGA)
DmitryR
Решил я оптимизировать один простой контроллер, чтобы был кратким (как выстрел, ЛОЛ) и полностью конфигурируемым. В частности чтобы можно было ему задавать фронт, по которому работать. Ну и пишу:

clocking get_edge @((posedge clk iff a) or (negedge clk iff !a));

И сразу же выясняется, что ни clocking, ни даже iff синтезатором (Квартус) не поддерживаются. У кого-нибудь есть идеи, как это сделать элегантно с помощью синтезируемых конструкций? Я понимаю, как это сделать с помощью условной компиляции, но это мне кажется как-то... Не совсем современно, что ли.
iosifk
Цитата(DmitryR @ Jan 24 2018, 17:14) *
Решил я оптимизировать один простой контроллер, чтобы был кратким (как выстрел, ЛОЛ) и полностью конфигурируемым. В частности чтобы можно было ему задавать фронт, по которому работать.

Поскольку исходный постулат совершенно неправильный, то начинать надо не с ответа на пост ТС.
Начинать надо с принципов организации проекта как такового.
Нельзя строить проект вот так:
(posedge clk iff a) or (negedge clk iff !a)); - это вредительство чистой воды!!!
В проекте должна быть "системная синхрочастота" на которой и должен быть построен проект в основном клоковом домене. Внутри этого домена активный фронт должен быть только положительный, а активный логический уровень - только "1"...
DmitryR
С этого постулата хорошо начинать учить людей основам цифрового дизайна, однако в общем случае он не верен. Если бы это было так - то в верилоге не появилось бы слово negedge, а в ПЛИС не появилось бы не то что DDR-триггеров - не стали бы делать даже поддержки negedge (потому что это стоит ресурсов, которые в ПЛИС по сей день не дёшевы). Однако вариантов, когда надо использовать задний фронт, в реальной жизни масса.
ViKo
У меня такт инвертируется с помощью xor. Но это не основной тактовый сигнал в проекте.
Димыч
Цитата(iosifk @ Jan 24 2018, 17:25) *
<...> Внутри этого домена активный фронт должен быть только положительный


Совершенно верно, но в некоторых случаях "клочить" всё по фронту, а часть логики по спаду - оправдано. И даже максимальная частота проекта не сильно падает (если понимаешь - зачем это сделано и как оно работает).

Бездумно расставлять posedge - negedge конечно нельзя.
Shivers
Топикстартер жжет. Особенно про DDR-триггер порадовало. Конечно, и DDR-триггер можно сделать, но в ПЛИС используются обычные флип-флопы, состоящие из двух защелок с разнополярным управлением (если точнее - однопроводным двухфазным управлением).
В проекте можно использовать сигнал управления записью обеих полярностей, надо только понимать, что это порождает пути длинной пол-периода, т.е. дизайн фактически начинает работать на удвоенной частоте. А вот задач, где надо оперативно инвертировать клок "на лету" я не встречал. Это какая то особо извращенная фантазия топикстартера. По хорошему, лучше идти читать учебник по схемотехнике сначала, а потом браться за верилог.
Golikov A.
строго говоря в СПИ иногда надо клок инвертироватьsm.gif

iff a - это конструкция для условной симуляции

Если оставить вопросы зачем это надо, то один раз я видел решение подобно проблемы через дефайн, который по сути текстовая подстановка. Но по мне генерайт лучше.
Кстати там же автор решал проблемы выбора синхронного и асинхронного сброса.
DmitryR
Цитата(Shivers @ Jan 24 2018, 20:14) *
А вот задач, где надо оперативно инвертировать клок "на лету" я не встречал. Это какая то особо извращенная фантазия топикстартера. По хорошему, лучше идти читать учебник по схемотехнике сначала, а потом браться за верилог.

Почему все всегда подозревают в людях худшее, да ещё и хамят при этом? Я совершенно не собираюсь менять клок "на лету" (в данном случае), а хочу настраивать его константой времени компиляции.


Цитата(Golikov A. @ Jan 24 2018, 22:41) *
строго говоря в СПИ иногда надо клок инвертироватьsm.gif

Проблема в том, что если я напишу

wire real_clk = a ? clk:!clk;

то скорее всего получу на самом деле инвертированный клок со всеми сопутствующими прелестями (в смысле инвертированный именно инвертором, на логике), а вовсе не переход на обратный фронт. И вот это уже совершенно нехорошо.
RobFPGA
Приветствую!

Цитата(DmitryR @ Jan 25 2018, 10:54) *
Почему все всегда подозревают в людях худшее, да ещё и хамят при этом? Я совершенно не собираюсь менять клок "на лету" (в данном случае), а хочу настраивать его константой времени компиляции.

Проблема в том, что если я напишу

wire real_clk = a ? clk:!clk;

то скорее всего получу на самом деле инвертированный клок со всеми сопутствующими прелестями (в смысле инвертированный именно инвертором, на логике), а вовсе не переход на обратный фронт. И вот это уже совершенно нехорошо.
Почему все всегда подозревают в компиляторах худшее ... А Вы пробовали в реальном проекте ? И для какого типа FPGA?

Как Вы думаете если напишете
Код
module bla_bla_bla (....
always @(posedge clk) begin
...
end
always @(negedge clk) begin
...
end
Как синтезатор сделает Вам тригера с инверсными клоками?

Удачи! Rob.
DmitryR
Цитата(RobFPGA @ Jan 25 2018, 11:16) *
А Вы пробовали в реальном проекте ? И для какого типа FPGA?

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

Цитата(RobFPGA @ Jan 25 2018, 11:16) *
Как Вы думаете если напишете
Код
module bla_bla_bla (....
always @(posedge clk) begin
...
end
always @(negedge clk) begin
...
end
Как синтезатор сделает Вам тригера с инверсными клоками?

Никак, но этого и не требуется. Вы не поняли вопрос.
Shivers
Цитата(DmitryR @ Jan 25 2018, 10:54) *
Почему все всегда подозревают в людях худшее, да ещё и хамят при этом? Я совершенно не собираюсь менять клок "на лету" (в данном случае), а хочу настраивать его константой времени компиляции.

Хамить и не думал, но - мои извинения.
Не хотите читать учебчники? ОК, извольте:
На верилоге можно много чего написать, но результатом интерпретации должен стать либо флоп, либо защелка. С клоком возможны манипуляции, к примеру - можно мультиплексировать входной клок со своей инверсией (как в Вашем посте). Если же Вы хотите получить флоп, тактируемый передним фронтом, либо тот же флоп. но тактируемый задним фронтом (в зависимости от параметра компиляции) то используйте конструкцию generate, либо дефайны. Но на мой вкус, это уже ветвление архитектуры, и совмещать такое ветвление в одном файле - неправильно.
RobFPGA
Приветствую!

Цитата(DmitryR @ Jan 25 2018, 11:22) *
Пробовал, но это не важно, ...
Хи - результат неважен?

Цитата(DmitryR @ Jan 25 2018, 11:22) *
так как я хочу написать универсальный библиотечный код, который будет гарантированно правильно компилироваться везде.
Это абстрактная недостижимая цель. Если пишете для синтеза реального железа приходится всегда иметь ввиду особенности конкретных синтезаторов, целевого железа и структуры проекта. Хотя самый близкий способ к такой "идеальной универсальности" это макросы.

Цитата(DmitryR @ Jan 25 2018, 11:22) *
Никак, но этого и не требуется. Вы не поняли вопрос.
Проясните что я не понял.
А я поясню мой намек который судя по ответу Вы не поняли -
Код
module bla_bla_bla2(input clk, ...
controller_super_shot #(.clock_polarity_select_lol(0)) i_ctrl_neg (.clk(clk), ...);
controller_super_shot #(.clock_polarity_select_lol(1)) i_ctrl_pos (.clk(clk), ...);
...
endmodule
Если по Вашему сделать модули с триггерами с инверсными клоками в таком случае "... Никак ..." то зачем Вам тогда делать такой универсальный модуль?

Удачи! Rob.
DmitryR
Цитата(Shivers @ Jan 25 2018, 11:47) *
Если же Вы хотите получить флоп, тактируемый передним фронтом, либо тот же флоп. но тактируемый задним фронтом (в зависимости от параметра компиляции) то используйте конструкцию generate, либо дефайны. Но на мой вкус, это уже ветвление архитектуры, и совмещать такое ветвление в одном файле - неправильно.

Спасибо, мне это всё понятно. Но define - это устаревшая конструкция, а использование generate в данном случе приводит к удвоению объёма кода.

Цитата(Shivers @ Jan 25 2018, 11:47) *
Но на мой вкус, это уже ветвление архитектуры, и совмещать такое ветвление в одном файле - неправильно.

Возьмите хотя бы SPI - там в зависимости от параметров CPHA и CPOL меняются фронты, по которым происходят захват и выдача данных. Другое дело, что в реальных реализациях клок там чаще всего так или иначе эмулируется, но с точки зрения теории это уже детали.
Shivers
Цитата(DmitryR @ Jan 25 2018, 12:38) *
Возьмите хотя бы SPI - там в зависимости от параметров CPHA и CPOL меняются фронты, по которым происходят захват и выдача данных. Другое дело, что в реальных реализациях клок там чаще всего так или иначе эмулируется, но с точки зрения теории это уже детали.

В DDR интерфейсах на приеме данных ставят параллельно два флопа: один работает всегда по райзу, второй всегда по фоллу. За ними получаем поток двойной ширины, но обработка идет по одному фронту - райзу, к примеру. Выходные данные DDR - те же два флопа с мультиплексором по выходу. Т.е. выходной поток двойной ширины (и работой по райзу) делится, но и передается наружу по двум фронтам - райзу и фоллу. Так что, все довольно просто.
DmitryR
Цитата(Shivers @ Jan 25 2018, 12:55) *
Выходные данные DDR - те же два флопа с мультиплексором по выходу. Т.е. выходной поток двойной ширины (и работой по райзу) делится, но и передается наружу по двум фронтам - райзу и фоллу. Так что, все довольно просто.

Я в итоге к этому решению и склоняюсь, но оно имеет массу недостатков: код получается совсем не такой уж и компактный, плюс непереносимость на другую архитектуру. Мы это переживём, так как работаем только с Альтерой, но чувство прекрасного это ранит.
Dantist2k17
Цитата(DmitryR @ Jan 24 2018, 14:14) *
Решил я оптимизировать один простой контроллер, чтобы был кратким (как выстрел, ЛОЛ) и полностью конфигурируемым. В частности чтобы можно было ему задавать фронт, по которому работать. Ну и пишу:

clocking get_edge @((posedge clk iff a) or (negedge clk iff !a));

И сразу же выясняется, что ни clocking, ни даже iff синтезатором (Квартус) не поддерживаются. У кого-нибудь есть идеи, как это сделать элегантно с помощью синтезируемых конструкций? Я понимаю, как это сделать с помощью условной компиляции, но это мне кажется как-то... Не совсем современно, что ли.


Сам не пробовал, ну а вдруг

Объявите
`define EDGE_CLK posedge
ну или
`define EDGE_CLK negedge

и используйте

always@(`EDGE_CLK my_clk) begin
end
blackfin
Цитата(DmitryR @ Jan 25 2018, 12:38) *
Но define - это устаревшая конструкция, ...

А где написано, что она устаревшая? Можете привести цитату из стандата на SV или хотя бы ссылку на страницу этого стандарта?

Использую повсеместно define и уже начинаю беспокоиться за своё чувство прекрасного.. wink.gif
DmitryR
Цитата(Dantist2k17 @ Jan 25 2018, 13:53) *
Сам не пробовал, ну а вдруг

Объявите
`define EDGE_CLK posedge
ну или
`define EDGE_CLK negedge

и используйте

always@(`EDGE_CLK my_clk) begin
end

Это несомненно возможно, только мне не это надо. Надо, чтобы это зависело от parameter. А в верилоге условная компиляци работает только от define (ifdef/ifndef), параметр как аргумент эти директивы принимать не могут.
blackfin
..
RobFPGA
Приветствую!
Цитата(DmitryR @ Jan 25 2018, 15:10) *
Это несомненно возможно, только мне не это надо. Надо, чтобы это зависело от parameter. А в верилоге условная компиляци работает только от define (ifdef/ifndef), параметр как аргумент эти директивы принимать не могут.
Вы так и не ответили чем же тогда Вас не устраивает
Код
parameter clk_sel=0;
wire real_clk = clk_sel ? clk : !clk;

Так как после синтеза (для FPGA) в любом случае для клоков под negedge будет добавлен инвертор.
А вот будет ли он (инвертор) :
встроенным в примитив триггера,
или как примитив для целой ALM или LCELL макро ячейки
или даже как отдельный gobal buffer к инвертному выходу PLL
или проосто инвертер на LUT
или ...
зависит от многих факторов, а не от того как это описанно в RTL - !clk или negedge.

Удачи! Rob.
iosifk
Цитата(blackfin @ Jan 25 2018, 14:53) *
А где написано, что она устаревшая? Можете привести цитату из стандата на SV или хотя бы ссылку на страницу этого стандарта?

У Сазерленда есть статья с примерно таким названием: "скажи дефайну - прощай"...
blackfin
Цитата(iosifk @ Jan 25 2018, 16:12) *
У Сазерленда есть статья с примерно таким названием: "скажи дефайну - прощай"...

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

Почему я должен верить какому-то Сазерленду и не верить IEEE?
iosifk
Цитата(blackfin @ Jan 25 2018, 16:20) *
Ну я только что просканировал весь стандарт на SV и никаких намеков на "прощай, дефайн" не нашел.

Почему я должен верить какому-то Сазерленду и не верить IEEE?

Я и не скзал о стандарте ни одного слова... А Сазерленд - один из основателей верилога и более ничего.. sm.gif
blackfin
Цитата(iosifk @ Jan 25 2018, 16:27) *
А Сазерленд - один из основателей верилога и более ничего.. sm.gif

Видимо, в то время он ещё не догадывался, что у Altera, Xilinx, Lattice и Synopsys'a будут разные атрибуты синтеза для выполнения одних и тех же архитектурно зависимых фич. biggrin.gif

Например, тот же (* use_dsp48 = "no" *) в Vivado 2017.3 уже выглядит как (* use_dsp = "no" *).

В Quartus'e и в Synplify'e есть аналогичные, но другие атрибуты.

Переписывать ради этого кучу файлов нет никакого желания. Пусть этим занимается компилятор.. А я просто изменю одну строку в define. biggrin.gif
Golikov A.
define - это когда их используют как параметры. Тут все как с С, и проблемы те же. Им и прощай.
А дефайн для ветвления - ок и он все еще с нами

Цитата
`define EDGE_CLK posedge

именно такое решение я и видел. Я бы предпочел генерайт, именно в силу ограничений дефайна.

Боюсь реально необходимость настраиваемого фронта для модуля - ненужная вещь, которая множит ошибки. Если же вы думаете про технику улучшения времянок когда не успевая принять по переднему фронту, переходят на задний - так это порочная практика, ее надо пресекать. Да, да...
Shivers
Лично я больше предпочитаю параметры в RTL, чем дефайны. Потому что при синтезе тулы (эсик) добавляют названия и значения параметров в название модуля: после синтеза в любой момент можно узнать, какие параметры использовались. А вот значения дефайнов синтезатор никуда не сохраняет. Итого, из-за дефайнов возникает больше всего ошибок при сборке проекта, и найти баг намного сложнее, чем при неверном задании параметра. Вместе с тем, дефайны до сих пор есть в каждом втором проекте, с которым приходится работать.
_Sam_
Цитата
хочу настраивать его константой времени компиляции.


Код
generate
    if(a)begin
        ...
    end
    else begin
        ...
    end
endgenerate
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.