Jump to content
    

[Verilog] Накладывание сигналов

Я знаю людей, которые прекрасно понимают, как и что происходит внутри ПЛИС, успешно выполняют свою работу, но при этом считают, что то, что они описывают на HDL, тем не менее, программа

может такие люди и есть, но они не приходят на этот форум с одинаковыми с вопросами "почему у меня не работает".

в основе большой части создаваемых новых тем лежит именно непонимание каким именно образом набор буковок на HDL превращается в железо. более того, есть довольна большая группа писателей, гордящихся своим незнанием, им не интересно знать чем триггер отличается от защелки, безразлично как устроенна логическая ячейка. Они свято верят в умный компилятор/синтезатор и бесконечные размеры современных ПЛИС.

Share this post


Link to post
Share on other sites

Попутный вопрос: вот то, что компания nVidia предлагает в качестве расширений к ЯП С для поддержки технологии CUDA, - это "язык программирования" или HDL? :)

 

ЯП, так как в результате, после всех компиляций, ЭТО предполагает исполнение на их исполняющем устройстве - графическом акселераторе, а не превращается в электрическую схему соединений транзисторов. Все, что исполняется каким либо устройством - это программы, все, что превращается в схему соединений и взаимодействия каких либо элементов, это описание устройства. Да, можно одним и тем же языком представить и то, и это (даже русским - "пойди туда, принеси это" - программа, "бочка, соединенная шлангом с краном" - описание устройства) - все зависит лишь от конкретного частного случая применения языка и того, что будет физически в конечном результате.

Share this post


Link to post
Share on other sites

ЯП, так как в результате, после всех компиляций, ЭТО предполагает исполнение на их исполняющем устройстве - графическом акселераторе, а не превращается в электрическую схему соединений транзисторов. Все, что исполняется каким либо устройством - это программы, все, что превращается в схему соединений и взаимодействия каких либо элементов, это описание устройства. Да, можно одним и тем же языком представить и то, и это (даже русским - "пойди туда, принеси это" - программа, "бочка, соединенная шлангом с краном" - описание устройства) - все зависит лишь от конкретного частного случая применения языка и того, что будет физически в конечном результате.

В таком случае, когда вы пишете для имплементации в ПЛИС, вы тоже никакую схему не создаёте, схему давным-давно создала фирма-разработчик и производитель ПЛИС, т.е. эта схема там аппаратно существует, а вы лишь только настраиваете коммутацию и (в случае FPGA) инициализируете массивы памяти (блоки памяти и LUT'ы).

 

По вашему подходу вывод, что HDL'ем пользуются только разработчики самой ПЛИС и прочих ASIC'ов, а у остальных ЯП, а не HDL. :)

 

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

 

может такие люди и есть, но они не приходят на этот форум с одинаковыми с вопросами "почему у меня не работает".

в основе большой части создаваемых новых тем лежит именно непонимание каким именно образом набор буковок на HDL превращается в железо. более того, есть довольна большая группа писателей, гордящихся своим незнанием, им не интересно знать чем триггер отличается от защелки, безразлично как устроенна логическая ячейка. Они свято верят в умный компилятор/синтезатор и бесконечные размеры современных ПЛИС.

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

Share this post


Link to post
Share on other sites

Засада на меня намекал:)... иногда пренебрежение к программистам не дает оценить сложность их вопросов:)

 

Чтобы вам было еще сложнее расскажу что есть такая штука MPI - это расширение языка С на уровне библиотек, которая заставляет процессорный кластер абсолютно параллельно выполнять программу. Все процессоры вместе выполняют одну программу строчка за строчкой, но параллельно. По началу бошку рвет нереально, а потом привыкаешь.

 

когда я использую HDL я могу его использовать двумя способами:

1. Я хочу получить какую-то известную мне схему и языком описываю так чтобы получилась именно она (я так понимаю подход SM)

2. Я хочу получить от схему необходимую мне функциональность, и мне абсолютно феолетово на какие страдания пойдет синтезатор.

 

Признаюсь, чаще я иду по 2 пути, и потому для меня Verilog язык программирования, им я задаю желаемый мне функционал. Иногда я иду и по 1 пути, но только когда по 2 пути мне идти дорого: если я не влезаю в кристалл, или в частоту, тогда начинаю ковыряться что там да как.

 

1 путь работает всегда, 2 путь раньше практически всегда не работал, мне передавали мучения людей которые создавали схемы на самых первых ПЛИС. Сейчас стоимость ресурса ПЛИС неуклонно падает, и 2 путь начинает работать чаще и чаще.

 

И вот тут самое главное: второй путь абстрактный, написав на нем модуль один раз, я могу переносить его на разные кристаллы. К примеру вот мне тут совершенно случайно стало известно что на современных ПЛИС нет модулей которые выдают Z, но к счастью синтезатор это знал, и опираясь на мое описание функционала сформировал правильную схему.

 

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

 

Язык С# тоже идет по этому пути. Результатом компиляции являются не конкретные инструкции. Все для того чтобы успевать за сменой процессоров и систем. Программы на С# гораздо более живучие и легче переносятся с одной версии виндов на другую.

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

Вряд ли путь 2 можно считать хорошим. Если проект достаточно серьёзный/сложный, путь 2 почти никогда не работает или работает плохо. Это касается не только HDL, ПЛИС, но и любого программирования - для получения достойного результата всегда надо понимать, как это работает.

 

Путь 1 при наличии достаточного уровня владения темой реализуется простым следованием немногочисленному набору правил - например, в области плисоводства это понимание, во что синтезируется та или иная языковая конструкция, синхронный дизайн, соблюдение правил перехода сигналов между разными клоковыми доменами (может, ещё что-то забыл). Это не так сложно запомнить и следовать этому. А вот несоблюдение приведёт к неприятностям, которые избыток ресурсов ПЛИС вряд ли скомпенсирует.

 

Но хочется отметить, что выбор между путь 1 и путь 2 не имеет никакого отношения к тому, является ли HDL языком программирования. Выбор между путь 1 и путь 2 - это тщательный, взвешенный подход vs. экстенсивный путь, это относится практически к любой области. HDL vs ЯП тут ортогонально.

Share this post


Link to post
Share on other sites

Ну и наконец Вы уже достаточно долго возитесь с этой задачкой про светодиод - не находите??

Вот вам готовая логика зажигания:

reg led;
always @(posedge clock or posedge reset)
begin
if (reset)
   led <= #1 1'h0;
     else
       if (on)
         led <= #1 1'h1;
            else
              if (off)
                led <= #1 1'h0;
end

 

Обратите внимание, что в проекте появился reset!

Вам остается сформировать сигналы on и off как результат выделения положительного и отрицательного фронта

Даю их в качестве схемы - переведите в Verilog сами.

 

Я же говорил, что знаю как сделать по другому и что бы работало. вот например:

 

always @ (pin)
    begin
        if (pin === 1)
            begin 
                led = 1;
            end
        if (pin === 0)
            begin 
                led = 0;
            end
    end

Может не очень хорошо написано, но работает (и даже без клока).

А меня интересовал именно тот первоначальный пример и в первом же ответе мне объяснили в чём дело.

 

кстати можно писать

 

always @(posedge pin or negedge pin)
begin

end

 

счетчик внутри можно сделать, можно даже внешним пином помахать с кучей варнингов...

 

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

 

Если написать "always @(posedge pin or negedge pin)", компилятор выдаёт ошибку

Error (10239): Verilog HDL Always Construct error at test.v(9): event control cannot test for both positive and negative edges of variable "pin"

 

А вот если сделать счётчик по принципу как я писал выше, то можно условно считать, что он работает по обоим фронтам.

Edited by 2inltd

Share this post


Link to post
Share on other sites

Не надо путать абстрактные проекты и проекты с плохой архитектурой.

 

Можно написать класс с функцией сортировки, и ему будет все равно какой тип данных он сортирует. Но в тоже время в этом классе можно реализовать сортировку пузырьком.

 

Сделав первое без второго, можно проиграть в эффективности против класса который сортирует конкретный тип, но в поддержке кода и переносимости будет огромный выигрыш.

 

А теперь представьте что вы делаете не серию на 10 лет, а единичные приборы с тиражом сотня - две, основная стоимость которых время выхода на рынок.

 

2 фронт можно так использовать

 

if(CLK_PREDEVIDER == 0)
	always @(posedge Bus2IP_Clk or negedge Bus2IP_Clk)
		begin 
			MASTER_CLK_task();
		end	
      else		
	always @(posedge Bus2IP_Clk)
		begin 
			MASTER_CLK_task();
		end	


//процедура формирование сигналов для выходного мастерклока
task MASTER_CLK_task;
	begin
		if ( Bus2IP_Resetn == 1'b0 ) //сброс схемы
			begin
				MCLK <= 1'b0;
				INV_MCLK <= 1'b1;
				mclk_devider <= 0;
			end
		else
			begin
				if(mclk_devider < MCLK_DEVIDER_VAL) //выдерживаем паузу
					mclk_devider <= mclk_devider + 1;
				else //пауза выдержана меняем состояние клока
					begin
						mclk_devider <= 0; //сбрасываем счетчик
						MCLK <= ~MCLK;
						INV_MCLK <= ~INV_MCLK;
					end
			end
	end
endtask	

 

 

дальше синал MCLK и INV_MCLK вышли на ружу через DDR.

Кстати интересный факт, если бы я думал о том как это сделано в железе, я бы такое не написал, счетчик на 2 фронтах я по умолчанию не знаю. Но умный синтезатор что-то заменил, и вуаля...

 

 

П.С. Нужно это для деления клока на нечетное число со скважностью 50%

 

 

Share this post


Link to post
Share on other sites

Не надо путать абстрактные проекты и проекты с плохой архитектурой.

 

 

Кстати интересный факт, если бы я думал о том как это сделано в железе, я бы такое не написал, счетчик на 2 фронтах я по умолчанию не знаю. Но умный синтезатор что-то заменил, и вуаля...

Остается только выяснить, реализуются ли MASTER_CLK_task() в железе...

 

Share this post


Link to post
Share on other sites

Я же говорил, что знаю как сделать по другому и что бы работало. вот например:

 

always @ (pin)
    begin
        if (pin === 1)
            begin 
                led = 1;
            end
        if (pin === 0)
            begin 
                led = 0;
            end
    end

Ничего вы не знаете.

Вы хоть понимаете что вы написали?? Вот что:

assign led = pin;

Синтезатор cделал провод . Про-вод. А не регистр.

Да, провод работает без clock-а, это вы верно заметили.

Всё, я заканчиваю дискуссию. Зря я время потратил, "2inltd".

Share this post


Link to post
Share on other sites

Остается только выяснить, реализуются ли MASTER_CLK_task() в железе...

хм...

вот вы сказали и я подумал... А вдруг я его правда только симулировал... В реальном проекте частота четная, и там по одному фронту все работает. И я вот что-то сейчас не помню запускал ли я в железе на нечетной частоте... Но это корка для микроблайза, я ее имплементил точно до передачи в железо, но на какой частоте блин не помню... буду силы проверю, может чудес то и нет).

 

Ненавистники программистов готовьте дудки, похоже я правда облажался:)...

Share this post


Link to post
Share on other sites

Ничего вы не знаете.

Вы хоть понимаете что вы написали?? Вот что:

assign led = pin;

Провод cделал синтезатор. Про-вод. А не регистр.

Да, провод работает без clock-а, это вы верно заметили.

Всё, я заканчиваю дискуссию. Зря я время потратил, "2inltd".

1. По сути весь пример и является assign led = pin;. И это только пример, сама программа была другая, это только принцип задумки.

2. Первая задумка была почему 2 always не могут выдать разные значения в 1 провод. и как я уже говорил я получил ответ. и как я уже говорил я не знал что always является триггером защёлкой. иначе не задавал бы таких глупых вопросов.

3. Вторая задумка была (она появилась в основном в процессе жизни темы), чтобы программа работала и по нарастанию и по спаду (это только пример, что я написал "led = 1;" и "led = 0;". Здесь могут быть какие-нибудь инструкции выбора, математические функции и другой нормальный код). И условно можно считать, что это будет срабатывать и по переднему и по заднему фронтам.

как-то так.

Share this post


Link to post
Share on other sites

многим тяжело даются абстрактно сформулированные задачи, а потом мы почему то виноваты что они тему читали...

 

Я так понимаю реально работа по 2 фронтам возможно только как в DDR, типа 2 линии защелок, одна защелкивает данные по одному фронту, другая по другому, и какая-то схема потом анализирует оба сигнала по одному из фронтов или же на частоте сильно большей, полученной с ПЛЛ.

 

наверное пора признать что все таки не представляя кухни внутри ПЛИС эффективной разработки пока вести не получится...

 

 

еще есть варианта сдвинуть клок на четверть периода и поксорить его с исходником, тогда эта штука будет давать на каждый фронт восходящий и все получится...%)

Share this post


Link to post
Share on other sites

if(mclk_devider < MCLK_DEVIDER_VAL) //выдерживаем паузу

mclk_devider <= mclk_devider + 1;

 

А давайте я вам в двух словах объясню как task работает при синтезе?

 

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

Посмотрите страницы 48-49 в Книге (раздел 2.2.3)

http://books.google.ru/books?id=j1EFsHlqEg...zed&f=false

 

Или вот код с синтезируемым task, который я приводил около года назад

http://electronix.ru/forum/index.php?showt...t&p=1154353

 

Ваш фрагмент кода внутри task выше ("выдерживаем паузу") работает вообще не по clock-у.

Share this post


Link to post
Share on other sites

А давайте я вам в двух словах объясню как task работает при синтезе?

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

 

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

 

Ваш фрагмент кода внутри task выше ("выдерживаем паузу") работает вообще не по clock-у.

 

почему? Можно подробнее что имеется ввиду?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...