sazh 8 7 июня, 2018 Опубликовано 7 июня, 2018 · Жалоба 1. Конструкция языка/библиотеки/устройства претерпела изменения за последнее время (или такое изменение напрашивается в ближайшем будущем). Пример: инициализация регистров при запуске ПЛИС "в железе". На сколько понял читая материалы в сети, в 90-е регистры инициализировались исключительно нулями. Сейчас ситуация поменялась, но ряд комментаторов по старой памяти утверждают, что это невозможно и сами не используют эту удобную опцию. Таким образом, если времени нет, разумеется приходится "ориентироваться на результат". Но если оно есть, почему бы не выяснить как именно работает тот или иной подход и почему именно так. Плясать надо не от библиотек, а от семейства fpga и его структуры. Как раньше говорили, если семейство на базе статической ячейки памяти, регистровая структура инициализируется нулями, что можно использовать для начальной установки регистров в любое значение. Другое дело что (например Альтера) ранние синтезаторы не позволяли это делать простым присваиванием в теле модуля. А теперь могут. Суть от времени не меняется. `timescale 1 ns / 1 ps `define ena_90 module initial_set #( parameter set = 8'd8 ) ( input clk, input [7:0] data_in, input ena, output [7:0] data_out ); `ifdef ena_90 reg [7:0] dffe_rg = 8'd0; assign data_out = dffe_rg ^ set; always @ (posedge clk) begin if (ena) dffe_rg <= data_in ^ set; end `else reg [7:0] dffe_rg = 8'd8; assign data_out = dffe_rg; always @ (posedge clk) begin if (ena) dffe_rg <= data_in; end `endif endmodule Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bad0512 2 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Приветствую! Простите но это просто глупость - Вы действительно считаете что счетчик описанный в FSM будет по другому синтезирован чем счетчик описанный вне FSM? Может приведете примеры такого "безобразия" ? Успехов! Rob. Думаю тут речь идёт больше о стиле написания кода, формально счётчик конечно будет одинаково синтезироваться в обоих случаях. Я тоже стараюсь в автоматы ничего лишнего не запихивать по двум причинам : 1. Код легче читается - в автомате ты сосредотачиваешься только на переходах и условиях перехода, всё остальное - в отдельные процессы. 2. При таком стиле труднее допустить ошибку (управление автоматом асинхронным сигналом, забыл описать else после if - получил латч и т.п.). Меньше портянка FSM - сложнее облажаться в мелочах. Это больше про coding style ИМХО. P.S. Топикстартеру - у меня есть корка именно под FT2232H Async 245 интерфейс, правда она под Xilinx-ISE-XPS, но никто же не обещал что будет легко. Надо? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
flammmable 4 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Думаю тут речь идёт больше о стиле написания кода, формально счётчик конечно будет одинаково синтезироваться в обоих случаях. Я тоже стараюсь в автоматы ничего лишнего не запихивать по двум причинам : 1. Код легче читается - в автомате ты сосредотачиваешься только на переходах и условиях перехода, всё остальное - в отдельные процессы. 2. При таком стиле труднее допустить ошибку (управление автоматом асинхронным сигналом, забыл описать else после if - получил латч и т.п.). Меньше портянка FSM - сложнее облажаться в мелочах. Это больше про coding style ИМХО. P.S. Топикстартеру - у меня есть корка именно под FT2232H Async 245 интерфейс, правда она под Xilinx-ISE-XPS, но никто же не обещал что будет легко. Надо? Буду очень признателен! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demon3200 0 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Простите но это просто глупость - Вы действительно считаете что счетчик описанный в FSM будет по другому синтезирован чем счетчик описанный вне FSM? Может приведете примеры такого "безобразия" ? Здесь, наверное, имелось ввиду то, что если вынести счетчик за пределы автомата и управлять им одним сигналом, то в реализации между автоматом и счетчиком путь сигнала разрешения будет более "компактным", чем если считать прямо в автомате. В этом случае между автоматом и счетчиком будет куча дополнительной логики. По таймингам такое решение будет хуже. Сам грешен, делаю счетчики прямо в автоматах. По таймингам обычно проблем с этим нет. Но что-то подсказывает, что первый вариант более правильный. Во-первых, мы упрощаем описание автомата, делая его более читабельным. Во-вторых, даем синтезатору больше свободы для раскладывания по кристаллу остальной части схемы, там где могут быть более чувствительные к задержкам пути. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bad0512 2 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Буду очень признателен! Держите. ft2232h_async_245_to_axilite_v1_00_a.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lembrix 0 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Пример: инициализация регистров при запуске ПЛИС "в железе". На сколько понял читая материалы в сети, в 90-е регистры инициализировались исключительно нулями. Сейчас ситуация поменялась, но ряд комментаторов по старой памяти утверждают, что это невозможно и сами не используют эту удобную опцию. И на сегодняшний день есть достаточное количество причин не использовать начальную инициализацию регистров. 1. Только для динамически реконфигурируемых схем, не поддерживается в ASIC. 2. Накладывает ограничение на синтез, такие регистры не могут быть оптимизированы. 3. Использование инициализации вместо сброса ограничивает reuse модуля в других проектах где сброс реально нужен. 4. Нет гарантии поддержки инициализации всеми синтезаторами. 5. В случае использования инициализации вместо сброса нет задержки на время стабилизации клока от PLL 6. В случае использования инициализации вместо сброса нет возможности задержки выхода схемы из сброса. 7. В случае использования инициализации вместо сброса нет возможности сброса схемы в процессе работы 8. Не поддерживается ALTERA Partial Reconfiguration. 9. Стандарты могут требовать сброса в явном виде. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Я бы ещё добавил, что на некоторых чипах инициализация единицами может потребовать дополнительные слои логики, что может быть недопустимым в проектах, работающих на предельных частотах (для конкретной ПЛИС). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 34 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Приветствую! Здесь, наверное, имелось ввиду то, что если вынести счетчик за пределы автомата и управлять им одним сигналом, то в реализации между автоматом и счетчиком путь сигнала разрешения будет более "компактным", чем если считать прямо в автомате. В этом случае между автоматом и счетчиком будет куча дополнительной логики. По таймингам такое решение будет хуже. Сам грешен, делаю счетчики прямо в автоматах. По таймингам обычно проблем с этим нет. Но что-то подсказывает, что первый вариант более правильный. Во-первых, мы упрощаем описание автомата, делая его более читабельным. Во-вторых, даем синтезатору больше свободы для раскладывания по кристаллу остальной части схемы, там где могут быть более чувствительные к задержкам пути.Очень бы хотелось примеры увидить что бы быть уверенным что мы говорим об одном и том же. Типа такого - думаете что для cnt1 будет более оптимальный путь управления чем для cnt2 ? module test #(CNT_WH=4) ( input wire clk , input wire rst , input wire cnt_en, output logic [CNT_WH-1:0] cnt1 , output logic [CNT_WH-1:0] cnt2 ); typedef enum logic [1:0] { ST_0 = '0, ST_1, ST_2, ST_3 } e_ST_t; e_ST_t st_nx, st_fsm; logic cnt1_clr; logic cnt1_inc; logic [CNT_WH-1:0] cnt2_nx; always_ff @(posedge clk) begin if (rst) begin st_fsm <= ST_0; cnt1 <= '0; cnt2 <= '0; end else begin st_fsm <= st_nx; cnt2 <= cnt2_nx; if (cnt1_clr) begin cnt1 <= '0; end else if (cnt1_inc) begin cnt1 <= cnt1 + 1; end // if (st_fsm==ST_0) begin // cnt1 <='0; // end // else if (st_fsm==ST_1 || st_fsm==ST_2) begin // cnt1 <= cnt1 + 1; // end end end always_comb begin : p_st_fsm st_nx <= st_fsm; cnt2_nx <= cnt2; cnt1_clr<= 0; cnt1_inc<= 0; case (st_fsm) ST_0: begin cnt1_clr<= 1; cnt2_nx <= '0; st_nx <= ST_1; end ST_1: begin if (cnt_en) begin cnt1_inc<= 1; cnt2_nx <= cnt2 + 1; if (cnt1==((1<<CNT_WH)/2-1)) begin st_nx <= ST_2; end end end ST_2: begin if (cnt_en) begin cnt1_inc<= 1; cnt2_nx <= cnt2 + 1; if (cnt2==((1<<CNT_WH)-1)) begin st_nx <= ST_3; end end end ST_3: begin if (cnt2==cnt1) begin st_nx <= ST_0; end end default : st_nx <= ST_0; endcase end endmodule Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demon3200 0 8 июня, 2018 Опубликовано 8 июня, 2018 (изменено) · Жалоба Ну вот такой теоретический пример module cnt_test ( //Global input CLK_i , input nRESET_i , //Input input IN_PULSE0_i , input IN_PULSE1_i , //Control input ENA_CNT_i , input CLR_CNT_i , //Output of counter output [31:0] OUT_CNT0_o32 , output [31:0] OUT_CNT1_o32 ); reg [31:0] out_cnt0_o32; reg [31:0] out_cnt1_o32; assign OUT_CNT0_o32 = out_cnt0_o32; assign OUT_CNT1_o32 = out_cnt1_o32; reg [7:0] state; //FSM localparam integer sIDLE = 0, sCOUNT = 1, sSTOP = 2; reg cnt_1_en; reg cnt_1_clr; always @(posedge CLK_i or negedge nRESET_i) begin if(~nRESET_i) begin out_cnt0_o32 <= 0; cnt_1_en <= 0; cnt_1_clr <= 0; state <= sIDLE; end else begin case(state) sIDLE: begin cnt_1_clr <= 0; if(ENA_CNT_i) state <= sCOUNT; end sCOUNT: begin if(ENA_CNT_i) begin if(IN_PULSE_i) begin out_cnt0_o32 <= out_cnt0_o32 + 1'b1; cnt_1_en <= 1'b1; end else cnt_1_en <= 0; end else begin cnt_1_en <= 0; state <= sSTOP; end end sSTOP: begin state <= sIDLE; if(CLR_CNT_i) begin out_cnt0_o32 <= 0; cnt_1_clr <= 1'b1; end end endcase end end always @(posedge CLK_i or negedge nRESET_i) begin if(~nRESET_i) begin out_cnt1_o32 <= 0; end else begin if(cnt_1_en) out_cnt1_o32 <= out_cnt1_o32 + 1'b1; else if(cnt_1_clr) out_cnt1_o32 <= 0; end end endmodule Два счетчика. Один работает напрямую из автомата, второй через сигналы разрешения и сброса. Насчет упрощения кода при выносе счетчика из автомата я ошибся - проще не получилось. Для работы встроенного счетчика достаточно всего двух строк. Выносного счетчика - целых 5. Вынос счетчика усложнил код. Плюс на выносной счетчик будет работать с задержкой в один такт. И это надо учитывать там, где критично. Но с точки зрения времянок выносной счетчик выиграет. Как раз за счет промежуточных триггеров на сигналах разрешения/сброса. На практике я это не проверял, это просто рассуждения. Warning from admin:Используйте codebox для оформления длинных блоков кода. Не загромождайте сообщения! Изменено 8 июня, 2018 пользователем makc предупреждение про codebox Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 34 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Приветствую! ... Два счетчика. Один работает напрямую из автомата, второй через сигналы разрешения и сброса. Насчет упрощения кода при выносе счетчика из автомата я ошибся - проще не получилось. Для работы встроенного счетчика достаточно всего двух строк. Выносного счетчика - целых 5. Вынос счетчика усложнил код. И это еще простой случай - а если еще надо загружать разные счетчики разными значениями и считать их вверх/вниз/поперек? :wacko: Плюс на выносной счетчик будет работать с задержкой в один такт. И это надо учитывать там, где критично. Но с точки зрения времянок выносной счетчик выиграет. Как раз за счет промежуточных триггеров на сигналах разрешения/сброса. Вот оно что - понятное дело если вы пропускаете сигналы управления через регистр то это уменьшает времянку - но это ведь разная логика работы счетчиков!!! При чем тут реализация счетчиков в FSM? Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Да собственно с точки зрения синтезатора - ему без разницы где счетчик описан. Внутри FSM, или снаружи. Лично проверял когда только-только начинал изучать FPGA. Выдача сигнала разрешения автоматом, либо счет счетчика в каком-то из состояний синтезируются в одно и тоже. Тут дело в другом, как я считаю. При стиле описания "все в одном": 1. Легче допустить ошибку в описании счетчика - и сложнее её обнаружить. 2. Увеличивается количество строк кода, что неизменно ухудшает его читаемость. Да и документировать такой код становится несколько сложнее. А документирование кода очень, и очень важная составляющая HDL проектов. 3. Увеличивается время отладки. Ибо чем больше строк в коде - тем дольше этот код отлаживать. При стиле описания "Автомат управляет счетчиком": 1. Легче описывать автомат, т.е нет необходимости описывать счетчики. Счетчик пишется один раз, и далее используется повторно. 2. Упрощается автомат - банально меньше писанины. И вместо инкрементирования счетчика внутри автомата - автомат выдает сигнал разрешения работы счетчику. 3. Упрощается тестирование - не работает счтчик, значит проблема в автомате. Проще найти ошибку. 4. Отдельному описанию счетчика можно задать кучу параметров: остановка счета при максимальном значении, максимальное значение счета, направление счета, вывод своего состояния на консоль и пр. И главное - счетчик описан один раз, и дальше повторно используется, и совершенствуется добавлением новых параметров. При таком подходе - мы имеем собственную проверенную библиотеку, которая имеет 100% работоспособность. И из этой библиотеки мы собираем свои проекты как из конструктора. За счет всевозможных настроек имеем большую гибкость, и уменьшение вероятности совершить "глупую" ошибку, которую, как правило, найти сложнее всего. Я от такого подхода вижу только полюсы. И это еще простой случай - а если еще надо загружать разные счетчики разными значениями и считать их вверх/вниз/поперек? wacko.gif Обычный счетчик с синхронной загрузкой, и сигналом разрешения загрузки. Автомат выдает сигнал разрешения загрузки и выдает данные, которые надо загрузить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demon3200 0 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Вот оно что - понятное дело если вы пропускаете сигналы управления через регистр то это уменьшает времянку - но это ведь разная логика работы счетчиков!!! При чем тут реализация счетчиков в FSM? Согласен, если через триггеры не пропускать, то, наверное, особой разницы в реализации не будет. Упрощается автомат - банально меньше писанины. И вместо инкрементирования счетчика внутри автомата - автомат выдает сигнал разрешения работы счетчику. Получается, наоборот. Если счетчик внутри автомата - достаточно просто одной строчкой делать инкремент там, где это надо. Если счетчик выносим, то надо выдать сигнал разрешения, а потом его еще снять. Получается 2 и более строк кода на одну только функцию. А еще есть сброс, загрузка... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Согласен, если через триггеры не пропускать, то, наверное, особой разницы в реализации не будет. Получается, наоборот. Если счетчик внутри автомата - достаточно просто одной строчкой делать инкремент там, где это надо. Если счетчик выносим, то надо выдать сигнал разрешения, а потом его еще снять. Получается 2 и более строк кода на одну только функцию. А еще есть сброс, загрузка... А всё дело в том, что Вы сигнал разрешения выдаете в "синхронной части" автомата. Поэтому ещё надо ещё где-то описать его снятие. Я все делаю в "комбинацонной" части автомата. Примерно вот так: --==================================================================== -- Кобинационная часть работы автомата --==================================================================== output_data : process(all) begin --============================= -- Сигналы по-умолчанию --============================= irdreq <= '0'; -- Запроса на чтение буффера нет aclr_buff <= '0'; -- Беффер не сбрасываем V_offset_ena <= '0'; -- Счет счетчику запрещен V_offset_sld_ena <= '0'; -- Ничего в него не загружаем H_offset_ena <= '0'; -- Счет счетчику запрещен H_offset_sld_ena <= '0'; -- Ничего в него не загружаем case pres_state is -- Анализируем текущее состояние автомата --================================================================================ =============================== when V_offset => -- В состоянии ожидания вертикального смещения if (DE_re = '1') then -- При начале периода активных данных V_offset_ena <= '1'; -- Инкрементируем счетчик вертикального смещения end if; --================================================================================ =============================== when H_offset => -- В состоянии горизонтального смещения H_offset_ena <= '1'; -- Инкрементируем счетчик горизонтального смещения --================================================================================ =============================== when PIP_image => -- В состоянии вывода масштабированного изображения irdreq <= '1'; -- Разрешаем чтение буффера с данными --================================================================================ =============================== when clear_buff => -- В состоянии сброса буффера aclr_buff <= '1'; -- Разрешаем его сброс --================================================================================ =============================== when wait_active_video => -- В состоянии ожидания начала периода активных данных H_offset_sld_ena <= '1'; -- Загружаем в счетчик горизонтального смещения значение этого смещения --================================================================================ =============================== when stop => -- В осостоянии остановки отрисованного изображание V_offset_sld_ena <= '1'; -- Загружаем счетчики необходимым значением смещения H_offset_sld_ena <= '1'; when others => null; end case; end process; А вообще, Вы можете в синхронной части задать значение "по-умолчанию" и в нужном состоянии выдавать сигналы разрешения. Т.е "по-умолчанию" сигнал разрешения снимается. А в каком-то из состояний он выставляется. Получите то-же самое, но только сдвинутое на такт. Более того. При таком стиле как у меня, если комбинационный сигнал зависит только от состояния автомата, то он идет с триггера, защелкнувшего это состояние, если идет кодировка "One-Hot" И выходы автомата у меня получаются сфоримрованны не комбинационной схемой, а триггером :rolleyes: Например сигнал "aclr_buff " - это выход триггера. Соответственно он не имеет иголок, и можно применить как асинхронный сброс. Во всяком случае у Altera DC FIFO имеет только такой тип сброса.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 34 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Приветствую! Обычный счетчик с синхронной загрузкой, и сигналом разрешения загрузки. Автомат выдает сигнал разрешения загрузки и выдает данные, которые надо загрузить. :) Ну и прикинте во что это выливается со внешним счетчиком. Фактически в автомате Вы сделаете все кроме непосредственного инкремента. А если считать надо не на +/-1 ? В общем случае для счетчика нужно 4 сигнала управления - set, set_value, count, count_value. Получается: Тут дело в другом, как я считаю. При стиле описания "все в одном": 1. Легче допустить ошибку в описании счетчика - и сложнее её обнаружить. 2. Увеличивается количество строк кода, что неизменно ухудшает его читаемость. Да и документировать такой код становится несколько сложнее. А документирование кода очень, и очень важная составляющая HDL проектов. 3. Увеличивается время отладки. Ибо чем больше строк в коде - тем дольше этот код отлаживать. Встроенный счетчик в FSM 2 линий для переменных cnt_cur, cnt_next 2 линий для сброса и cnt_cur<=cnt_next 1 линии начале FSM (default value) cnt_next <= cnt_cur 1 линия в каждой ветви где счетчиком надо управлять. При стиле описания "Автомат управляет счетчиком": 1. Легче описывать автомат, т.е нет необходимости описывать счетчики. Счетчик пишется один раз, и далее используется повторно. 2. Упрощается автомат - банально меньше писанины. И вместо инкрементирования счетчика внутри автомата - автомат выдает сигнал разрешения работы счетчику. При раздельном описании 9 линий кода для инстацирования модуля счетчика, 5 линии кода для описания сигналов управления, и собственно счетчика 4 линии для сигналов управления в начале FSM (default value) 2 (в среднем) линии для сигналов управления в каждой ветви где счетчиком надо управлять. Интересная экономия на размере кода получается :) . Отдельному описанию счетчика можно задать кучу параметров: остановка счета при максимальном значении, максимальное значение счета, направление счета, вывод своего состояния на консоль и пр. И главное - счетчик описан один раз, и дальше повторно используется, и совершенствуется добавлением новых параметров.Это из другой оперы - тут счетчик полностью управляется FSM и не может считать как ему хочется. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 8 июня, 2018 Опубликовано 8 июня, 2018 · Жалоба Экономия получается на отладке в Modelsim...., которая занимает ~80% времени. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться