На самописное ядро я дал ссылку в статье: opencores.org/project,xge_mac,overview (Из-за запятых ссылка может не выделиться цветом полностью).
Во-вторых, для тех трансиверов с которыми я работаю, у конторы, в которой я работаю, подписан NDA и никакую их настройку, разумеется, я не могу выкладывать.
Возможно идет стагнация всего рынка процессоров, но я не верю, что в Intel/AMD сидят дураки. Возможно есть задачи, которые x86 не очень хорошо решает, но ведь это процессоры общего назначения. Его может использовать и домохозяйка, чтобы смотреть сериалы, сын-геймер, и муж-писатель. Если компания понимает, что x86 не подходит для решения их задач, никто не мешает сделать им свой ASIC, только это будет стоить недешево) Intel добавляет же специальные инструкции по запросу рынка: AES, к примеру. Всё регулирует рынок, и я ничего не вижу в этом плохого.
А вам действительно надо решать задачи на FPGA? Обычным процессором не обойтись?
Не могу с вами согласиться: технология FPGA не может спасти в этой ситуации.
FPGA действительно может решать некоторый класс задач лучше чем процессор. Но эти задачи должны быть относительно простые и поддаваться параллельности и конвейеризации. Я не очень представляю, как сделать на FPGA какую-нибудь сложную БД за адекватное время и деньги, чтобы по производительности она обогнала реализацию на процессоре. Я никогда не видел, чтобы Altera/Xilinx ставило перед собой задачу обогнать CPU на «всех» задачах, т.к. по тактовой частоте FPGA всегда будет проигрывать CPU, и они выезжают на других задачах.
Писать чудовищно тяжело.
Мне кажется, это миф. Конечно, реализовать какой-нибудь tcp-клиент/сервер на FPGA чудовищно тяжело по сравнению с java/python, где это делается в 10-50 строчек, но может не надо этого делать? А если надо, т.к. встал вопрос о производительности (хотите весь 10G забить TCP), то Вы продумываете архитектуру на уровне триггеров/блоков памяти, делаете свою обработку и за это естесственно платите временем/деньгами. Однако, это едиственный способ выжать максимальную производительности в любой задаче, которую решаете на FPGA. Есть вещи, в которых это критично. Вы не сможете продать сетевую карточку 10G, которая может принять только 5 Gbit/s, т.к. там написано не оптимально и о производительности не думали. Конечно, когда тактовые частоты в FPGA будут под несколько ГГц, то низкоуровневая оптимизация для этих задач уйдет на второй план)
Для упрощения разработки сейчас идет тренд использования OpenCL в FPGA, он показывает неплохие результаты на задачах, связанных с обработкой картинок/видео. Возможно, для этих задач разработка уйдет с HDL на OpenCL, если это будет выгодно рынку.
Чтобы была видна разница, я решил три теста одновременно показать в симуляторе: test0 — данные идут с триггеров gen_x. test1 — данные по @( posedge clk ) делаются. test2 — данные по #20 выставляются.
Если что, no_pipe_example — тот, который под Icarus «адаптирован».
А вот и симуляция:
Скрытый текст
Несмотря на то, что по картинке test0_x*, test1_x*, test2_x* полностью идентичны, симулятор их совершенно по разному воспринимает: test0 и test1 полностью идентичны, а test2 выполняет всё на такт раньше)
Зависит от того, что Вы вкладываете в слово «реальная жизнь».
В симуляторе мы отсматриваем модель того, что происходит в жизни. Есть модель функциональная, а есть временная. Еще можно симулировать не RTL-код, а нетлист или гейты, и тогда еще более реальная жизнь происходит. Когда мы выбираем какой-то тип симуляции, то соглашаемся с теми допущениями, что в ней есть. Все эти картинки, это лишь то, как симулятор видит нашу схему на тех входных воздействиях, что в нее подали)
Разницу между функциональной и временной можно увидеть выше.
К сожалению, из литературы по верификации мне ничего не приходит в голову хорошого и простого. Есть «SystemVerilog for Verification», там есть глава Connecting Testbench and Design, но там чисто SystemVerilog'овские штуки раскрываются и может быть всё усложнено. Посмотрите примеры на testbench.in / asic-world.com, например, www.asic-world.com/examples/verilog/arbiter.html
SystemVerilog это продолжение стандарта Verilog.
Туда добавили кучу новых плюшек, как синтезируемых, так и не синтезируемых, которые упрощают и убыстряют разработку.
Я предлагаю вынести создание клока в отдельный initial, что бы он не мешался.
В вашем примере вы явно не сообщаете симулятору, что x_* это сигналы, которые привязаны (либо синхронны) с tb_clk. Для того, что бы это указать можно использовать @( posedge tb_clk ) или сделать clocking block и писать что-то типа @cb.
Попробуйте так:
initial
begin
tb_clk = 1'b0;
forever
begin
#100;
tb_clk = !tb_clk;
end
end
initial
begin
@( posedge tb_clk );
x_1 <= 4;
x_2 <= 8;
x_3 <= 15;
x_4 <= 23;
@( posedge tb_clk );
x_1 <= 0;
x_2 <= 0;
x_3 <= 0;
x_4 <= 0;
end
always_ff @( posedge clk_i ) в этом примере эквивалентен always @( posedge clk_i ).
Попробуйте пример из сообщения чуть выше с sync подать в симуляцию, подав данные не по положительному фронту)
Какой конструкцией подаете сигналы x1-4 в Вашем примере?
Здесь есть тонкий момент, о котором я не написал, но подразумевал.
Считается, что схема полностью синхронная: вход x_i является выходом какого-то триггера, который тоже работает по clk_i. В первый posedge данные защелкнулись в триггер x_i, и стали валидны на его выходе. Весь такт сумматоры считают свои значения и на следующий положительный фронт сумма защелкнется в no_pipe_res_o.
Читаю про D-триггер, там речь о том, что по переднему фронту С он заносит значение в первый Т триггер и после падения С уже подается на выход.
SystemVerilog реально крутая вещь)
Для меня не очень понятны советы новичкам, которые спрашивают «VHDL или Verilog?», и ему отвечают Verilog, мол он проще и похож на С. Должен быть спор VHDL vs SystemVerilog) Сейчас всё быстро меняется, и если надо разрабатывать большие проекты, то там только SystemVerilog ИМХО. (Хотя от приложения зависит, может если тим DSP, то тех извращений, что я делаю с данными, там не надо делать)
Правда, насколько я знаю, есть проблема в том, что не все синтезаторы поддерживают, но Synplify вроде впереди планеты всей и всё поддерживает)
Я прекрасно понимаю, что это может быть неинтуитивно для тех, кто так не писал :)
Возможную проблему с латчем, если кто-то удалит первую строчку я тоже знаю. Никаких нарушений канонов либо устоявшихся рекомендаций (например, смешивание блокирующих и неблокирующих присваиваний в одном always-блоке) в таком написании я не вижу.
Раньше я писал через assign как раз так, как Вы предлагаете, но у меня очень часто возникает задача в длинном слове поменять часть байт и через assign и кучу конкатенаций мне не нравилось делать, т.к. пишется много кода. Больше кода — больше ошибок: можно не те биты заменить, либо на один промазать, читаемость хуже…
Этот прием мне пришел в голову, когда я понял, что намного проще сначала присвоить, грубо говоря, default value, задержанное на несколько тактов, а потом уже его модифицировать, подменяя только нужные байты. Такая подмена это более высокоуровневое написание, чем assign, следовательно, должна быть более интуитивным и понятным. Думаю, дело вкуса и не более.
Если не секрет, сколько времени заняло создание проекта без написания статьи?
Однако, такой код хавают симуляторы)
Своими исходники MAC-ядра я не планирую делиться, т.к. за это на работе могут наругать)
Во-вторых, для тех трансиверов с которыми я работаю, у конторы, в которой я работаю, подписан NDA и никакую их настройку, разумеется, я не могу выкладывать.
А вам действительно надо решать задачи на FPGA? Обычным процессором не обойтись?
FPGA действительно может решать некоторый класс задач лучше чем процессор. Но эти задачи должны быть относительно простые и поддаваться параллельности и конвейеризации. Я не очень представляю, как сделать на FPGA какую-нибудь сложную БД за адекватное время и деньги, чтобы по производительности она обогнала реализацию на процессоре. Я никогда не видел, чтобы Altera/Xilinx ставило перед собой задачу обогнать CPU на «всех» задачах, т.к. по тактовой частоте FPGA всегда будет проигрывать CPU, и они выезжают на других задачах.
Мне кажется, это миф. Конечно, реализовать какой-нибудь tcp-клиент/сервер на FPGA чудовищно тяжело по сравнению с java/python, где это делается в 10-50 строчек, но может не надо этого делать? А если надо, т.к. встал вопрос о производительности (хотите весь 10G забить TCP), то Вы продумываете архитектуру на уровне триггеров/блоков памяти, делаете свою обработку и за это естесственно платите временем/деньгами. Однако, это едиственный способ выжать максимальную производительности в любой задаче, которую решаете на FPGA. Есть вещи, в которых это критично. Вы не сможете продать сетевую карточку 10G, которая может принять только 5 Gbit/s, т.к. там написано не оптимально и о производительности не думали. Конечно, когда тактовые частоты в FPGA будут под несколько ГГц, то низкоуровневая оптимизация для этих задач уйдет на второй план)
Для упрощения разработки сейчас идет тренд использования OpenCL в FPGA, он показывает неплохие результаты на задачах, связанных с обработкой картинок/видео. Возможно, для этих задач разработка уйдет с HDL на OpenCL, если это будет выгодно рынку.
test0 — данные идут с триггеров gen_x.
test1 — данные по @( posedge clk ) делаются.
test2 — данные по #20 выставляются.
Код:
Если что, no_pipe_example — тот, который под Icarus «адаптирован».
А вот и симуляция:
Несмотря на то, что по картинке test0_x*, test1_x*, test2_x* полностью идентичны, симулятор их совершенно по разному воспринимает: test0 и test1 полностью идентичны, а test2 выполняет всё на такт раньше)
В симуляторе мы отсматриваем модель того, что происходит в жизни. Есть модель функциональная, а есть временная. Еще можно симулировать не RTL-код, а нетлист или гейты, и тогда еще более реальная жизнь происходит. Когда мы выбираем какой-то тип симуляции, то соглашаемся с теми допущениями, что в ней есть. Все эти картинки, это лишь то, как симулятор видит нашу схему на тех входных воздействиях, что в нее подали)
Разницу между функциональной и временной можно увидеть выше.
К сожалению, из литературы по верификации мне ничего не приходит в голову хорошого и простого. Есть «SystemVerilog for Verification», там есть глава Connecting Testbench and Design, но там чисто SystemVerilog'овские штуки раскрываются и может быть всё усложнено. Посмотрите примеры на testbench.in / asic-world.com, например, www.asic-world.com/examples/verilog/arbiter.html
Попробуйте следующий пример:
Модуль 1:
Модуль 2:
Просто просимулируйте и скиньте сюда картинку) В этом примере x_1-4 идут с триггеров.
Туда добавили кучу новых плюшек, как синтезируемых, так и не синтезируемых, которые упрощают и убыстряют разработку.
Я предлагаю вынести создание клока в отдельный initial, что бы он не мешался.
В вашем примере вы явно не сообщаете симулятору, что x_* это сигналы, которые привязаны (либо синхронны) с tb_clk. Для того, что бы это указать можно использовать @( posedge tb_clk ) или сделать clocking block и писать что-то типа @cb.
Попробуйте так:
Попробуйте вот так:
always_ff @( posedge clk_i ) в этом примере эквивалентен always @( posedge clk_i ).
Попробуйте пример из сообщения чуть выше с sync подать в симуляцию, подав данные не по положительному фронту)
Какой конструкцией подаете сигналы x1-4 в Вашем примере?
Я специально сигналы a и b пересохраняю в триггер, что бы с триггера отдались данные на сумматоры.
Так выглядит функциональная симуляция в Квартусе (кстати 13):
Вот так временная:
Теперь представьте, что a/b_sync вынесены из этого модуля и выходы этих триггеров подаются на a_i, b_i в таком примере:
По поведению ничего не поменяется)
Считается, что схема полностью синхронная: вход x_i является выходом какого-то триггера, который тоже работает по clk_i. В первый posedge данные защелкнулись в триггер x_i, и стали валидны на его выходе. Весь такт сумматоры считают свои значения и на следующий положительный фронт сумма защелкнется в no_pipe_res_o.
Если честно, такого никогда не видел…
Для меня не очень понятны советы новичкам, которые спрашивают «VHDL или Verilog?», и ему отвечают Verilog, мол он проще и похож на С. Должен быть спор VHDL vs SystemVerilog) Сейчас всё быстро меняется, и если надо разрабатывать большие проекты, то там только SystemVerilog ИМХО. (Хотя от приложения зависит, может если тим DSP, то тех извращений, что я делаю с данными, там не надо делать)
Правда, насколько я знаю, есть проблема в том, что не все синтезаторы поддерживают, но Synplify вроде впереди планеты всей и всё поддерживает)
Мне приходится со структурами похожую операцию проделывать:
Как это красиво переписать без первой строчки?
Возможную проблему с латчем, если кто-то удалит первую строчку я тоже знаю. Никаких нарушений канонов либо устоявшихся рекомендаций (например, смешивание блокирующих и неблокирующих присваиваний в одном always-блоке) в таком написании я не вижу.
Раньше я писал через assign как раз так, как Вы предлагаете, но у меня очень часто возникает задача в длинном слове поменять часть байт и через assign и кучу конкатенаций мне не нравилось делать, т.к. пишется много кода. Больше кода — больше ошибок: можно не те биты заменить, либо на один промазать, читаемость хуже…
Этот прием мне пришел в голову, когда я понял, что намного проще сначала присвоить, грубо говоря, default value, задержанное на несколько тактов, а потом уже его модифицировать, подменяя только нужные байты. Такая подмена это более высокоуровневое написание, чем assign, следовательно, должна быть более интуитивным и понятным. Думаю, дело вкуса и не более.