Flip-fl0p 4 13 ноября, 2017 Опубликовано 13 ноября, 2017 (изменено) · Жалоба Сравнение с нулём - это простое ИЛИ всех битов счётчика. Сравнение с каким-то числом - это сначала XOR с заданным значением, после чего уже ИЛИ всех битов результата. Но в ПЛИС то это реализуется на LUT (Look-Up Table) и на них без разницы как сравнивать, нули или конкретное значение. Просто сказанное ниже, я имел ввиду применительно к ПЛИС: А какая разница ? Компаратору без разницы, что сравнивать, схема у него одинаковая, что для сравнения нулей или других чисел. Изменено 13 ноября, 2017 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nice_vladi 1 13 ноября, 2017 Опубликовано 13 ноября, 2017 · Жалоба А какая разница ? Компаратору без разницы, что сравнивать, схема у него одинаковая, что для сравнения нулей или других чисел. Другой вопрос, если нам надо например одним счетчиком отсчитывать разные интервалы. Например: Счетчик досчитал до 10 - что-то делаем, и сбрасываем счетчик. Счетчик досчитал до 15 - что-то делаем, и сбрасываем счетчик. Счетчик досчитал до 18 - что-то делаем, и сбрасываем счетчик. Счетчик досчитал до 24 - что-то делаем, и сбрасываем счетчик. Счетчик досчитал до 32 - что-то делаем, и сбрасываем счетчик. В этом случае у нас будет несколько схем сравнения с 10, 15, 18, 24, 32 - что собственно совсем не хорошо. В случае если счетчик считает до 0 у нас будет только 1 схема сравнения с нулем. А установка регистра счетчика в какую-то начальную величину не будет занимать логику? Т.е., получается, при счете до нуля мы тратим логику на инициализацию счетчика, а при счете до константы тратим логику на сравнение значения счетчика с константой, я правильно понимаю? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 13 ноября, 2017 Опубликовано 13 ноября, 2017 · Жалоба Если сравнивать с нулем и только с нулем, а при загрузке задавать произвольное значение счетчика, будет проще и быстрее, чем сравнивать с произвольным значением и сбрасывать счетчик. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 3 13 ноября, 2017 Опубликовано 13 ноября, 2017 · Жалоба Но в ПЛИС то это реализуется на LUT (Look-Up Table) и на них без разницы как сравнивать, нули или конкретное значение. Просто сказанное ниже, я имел ввиду применительно к ПЛИС: Даже если LUT, то в случае ИЛИ - одна ячейка обрабатывает столько бит входных данных, сколько у неё входов, в случае же сравнения с загруженным числом, на каждый бит нужен регистр. Да и интерконнект сильнее нагружается. Хотя, тут настаивать не буду - с ПЛИСами работаю крайне мало. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nice_vladi 1 13 ноября, 2017 Опубликовано 13 ноября, 2017 · Жалоба Если сравнивать с нулем и только с нулем, а при загрузке задавать произвольное значение счетчика, будет проще и быстрее, чем сравнивать с произвольным значением и сбрасывать счетчик. Почему так? Как было сказано выше, компаратору нет разницы, какие данные у него на входе. Нули-не нули, он все равно будет их сравнивать, так же, как и полноценные данные. Ну и с точки зрения наглядности - гораздо понятнее событие, которое происходит через Н тактов (запись cnt == N), чем событие, которое происходит, когда счетчик в 0( cnt == 0, а инициализация где-то в другой части модуля, например). Хотя тут уже вопрос привычки, я думаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 13 ноября, 2017 Опубликовано 13 ноября, 2017 · Жалоба Почему так? Как было сказано выше, компаратору нет разницы, какие данные у него на входе. Нули-не нули, он все равно будет их сравнивать, так же, как и полноценные данные. Как было сказано выше :-), сравнить только с нулем - это объединить биты по ИЛИ. Кроме того, я вообще не сравниваю биты счетчика, а использую бит переноса. Которым загружаю в счетчик число, хранящееся в рядом находящемся регистре. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alxkon 0 13 ноября, 2017 Опубликовано 13 ноября, 2017 · Жалоба Как было сказано выше :-), сравнить только с нулем - это объединить биты по ИЛИ. Кроме того, я вообще не сравниваю биты счетчика, а использую бит переноса. Которым загружаю в счетчик число, хранящееся в рядом находящемся регистре. А можете проилюстрировать в коде? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 13 ноября, 2017 Опубликовано 13 ноября, 2017 · Жалоба Вот. Последние варианты (4 и 5, одинаковые). Остальные показывают процесс разработки. :-) `define LENTH 28 `define VAR5 `ifdef VAR1 `define TIM1 `elsif VAR2 `define TIM1 `elsif VAR3 `define TIM1 `else `define TIM2 `endif module Timer_m `ifdef TIM1 ( (* chip_pin = "91", altera_attribute = "-name global_signal on; -name io_standard lvds" *) input bit clk, // high-speed clock input bit [`LENTH-1:0] rld, // reload data output bit pls // timer overload pulse ); `endif `ifdef VAR1 bit [`LENTH:0] cnt; always_ff @(posedge clk) begin if (cnt[`LENTH]) cnt <= {1'b0, rld}; else cnt <= cnt - 1; end assign pls = cnt[`LENTH]; `elsif VAR2 bit [`LENTH-1:0] cnt; always_ff @(posedge clk) begin if (cnt[`LENTH-1]) cnt <= rld; else cnt <= cnt - 1; end assign pls = cnt[`LENTH-1]; `elsif VAR3 bit [`LENTH-1:0] cnt; always_ff @(posedge clk) begin if (cnt[`LENTH-1]) cnt <= rld; else cnt <= cnt[`LENTH-2:0] - 1; end assign pls = cnt[`LENTH-1]; `endif `ifdef TIM2 ( (* chip_pin = "91", altera_attribute = "-name global_signal on; -name io_standard lvds" *) input bit clk, // high-speed clock input bit [`LENTH-1:0] rld, // reload data input bit ldp, // load pulse output bit pls // timer overload pulse ); `endif `ifdef VAR4 bit [`LENTH:0] cnt; always_ff @(posedge clk) begin if (cnt[`LENTH]) cnt <= {ldp, rld}; else cnt <= cnt[`LENTH-1:0] - 1; end assign pls = cnt[`LENTH]; `endif `ifdef VAR5 bit [`LENTH-1:0] cnt; always_ff @(posedge clk) begin if (pls) {pls, cnt} <= {ldp, rld}; else {pls, cnt} <= cnt - 1; end `endif endmodule : Timer_m Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Timmy 1 13 ноября, 2017 Опубликовано 13 ноября, 2017 · Жалоба Если речь о счётчике, то выгодней вообще не сравнивать все биты, а прекращать счёт при смене знака, то есть при переходе 0 -> -1 или -1 -> 0 в зависимости от направления счёта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 29 декабря, 2017 Опубликовано 29 декабря, 2017 · Жалоба Может кому пригодится. Обычный счетчик с синхронным сбросом и сигналом разрешения работы. Основной "фишкой" счетчика является возможность выбора направление счета, и уменьшение занимаемого места если коэффициент пересчета это 2^n. LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY KAA_COUNTER_ENA_SCLR IS GENERIC ( DIRECTION : STRING := "UP"; -- UP / DOWN Направление счета MAX_VALUE : INTEGER := 127 -- До скольки считает счетчик(от нуля до MAX_VALUE) ); PORT ( CLK : IN STD_LOGIC; ENA : IN STD_LOGIC; SCLR : IN STD_LOGIC; DATA_OUT : OUT INTEGER RANGE 0 TO MAX_VALUE ); END ENTITY; ARCHITECTURE RTL OF KAA_COUNTER_ENA_SCLR IS --===================================================================== -- Функция определения разрядности шины - логарифм по основанию 2 --===================================================================== FUNCTION LOG2 (MAX_VALUE : INTEGER) RETURN INTEGER IS -- Функция вычесления логарифма по основанию 2 для определения разрядности VARIABLE CNT : INTEGER := 0; -- Счетчик для подсчета количества делений на 2 VARIABLE TEMP : INTEGER := MAX_VALUE + 1; -- Делимое - это максимальное количество СОСТОЯНИЙ счетчика BEGIN WHILE (TEMP > 1) LOOP -- Пока делимое больше 1 совершаем цикл деления на 2 CNT := CNT + 1 ; -- Считаем количество циклов деления TEMP := TEMP/2; -- Делим число на 2 каждый цикл END LOOP; RETURN CNT; -- Значение счетчика и есть логарифм END LOG2; SIGNAL COUNTER_INTEGER : INTEGER RANGE 0 TO MAX_VALUE := 0; -- Счетчик обнуляемый условием максимального счета SIGNAL COUNTER_UNSIGNED : UNSIGNED(LOG2(MAX_VALUE)-1 DOWNTO 0) := (others => '0'); -- Счетчик с автомватическим обнулением при переполнении BEGIN --================================================================================ ========================== -- Если максимальное значение счетчика переведенное в двоичное число не состоит из одних только единиц -- Значит у нас счетчик обнуляется значением максимального счета т.е до наступления переполнения разрядов --================================================================================ ========================== COUNTER_INTEGER_GEN : IF ( TO_UNSIGNED(MAX_VALUE,LOG2(MAX_VALUE) ) /= ( LOG2(MAX_VALUE)-1 DOWNTO 0 => '1' ) ) GENERATE CNT_PROC : PROCESS ( CLK ) BEGIN IF (RISING_EDGE(CLK)) THEN --========================================================================== -- Генерируем суммирующий счетчик обнуляющийся максимальным значением счета --========================================================================== IF (DIRECTION = "UP") THEN -- Если направление счета "вверх" генерируется суммирующий счетчик IF (ENA = '1') THEN -- При активном сигнале разрешения раблоты IF (COUNTER_INTEGER = MAX_VALUE) THEN -- При наступлении максимального значения счетчика COUNTER_INTEGER <= 0; -- Обнулим его ELSE COUNTER_INTEGER <= COUNTER_INTEGER + 1; -- Иначе будем его инкрементировать END IF; END IF; IF (SCLR = '1') THEN -- При активном синхронном сбросе COUNTER_INTEGER <= 0; -- Сбросим счетчик в ноль END IF; END IF; --========================================================================== -- Генерируем вычитающий счетчик обнуляющийся максимальным значением счета --========================================================================== IF (DIRECTION = "DOWN") THEN -- Если направление счета "вниз" то генерируется вычитающий счетчик IF (ENA = '1') THEN -- При активном сигнале разрешения раблоты IF (COUNTER_INTEGER = 0) THEN -- При наступлении максимального значения счетчика COUNTER_INTEGER <= MAX_VALUE; -- Обнулим его ELSE COUNTER_INTEGER <= COUNTER_INTEGER - 1; -- Иначе будем его декрементировать END IF; END IF; IF (SCLR = '1') THEN -- При активном синхронном сбросе COUNTER_INTEGER <= MAX_VALUE; -- Сбросим счетчик в максимальное значение END IF; END IF; END IF; END PROCESS; DATA_OUT <= COUNTER_INTEGER; -- Выдадим значение счетчика на выходные порты модуля END GENERATE; --================================================================================ ========================== -- Если максимальное значение счетчика это (2**N - 1) -- Значит у нас полный счетчик, который обнуляется переполнением разрядов --================================================================================ ========================== COUNTER_UNSIGNED_GEN : IF ( TO_UNSIGNED(MAX_VALUE,LOG2(MAX_VALUE) ) = ( LOG2(MAX_VALUE)-1 DOWNTO 0 => '1' ) ) GENERATE CNT_PROC : PROCESS ( CLK ) BEGIN IF (RISING_EDGE(CLK)) THEN --========================================================================== -- Генерируем суммирующий счетчик обнуляющийся переполнением разрядов --========================================================================== IF (DIRECTION = "UP") THEN -- Если направление счета "вверх" генерируется суммирующий счетчик IF (ENA = '1') THEN -- При активном сигнале разрешения раблоты COUNTER_UNSIGNED <= COUNTER_UNSIGNED + "1"; -- Инкрементируем его каждый такт END IF; IF (SCLR = '1') THEN -- При активном синхронном сбросе COUNTER_UNSIGNED <= (OTHERS => '0'); -- Сбросим счетчик в ноль END IF; END IF; --========================================================================== -- Генерируем вычитающий счетчик обнуляющийся переполнением разрядов --========================================================================== IF (DIRECTION = "DOWN") THEN -- Если направление счета "вниз" то генерируется вычитающий счетчик IF (ENA = '1') THEN -- При активном сигнале разрешения раблоты COUNTER_UNSIGNED <= COUNTER_UNSIGNED - "1"; -- Декрементируем его каждый такт END IF; IF (SCLR = '1') THEN -- При активном синхронном сбросе COUNTER_UNSIGNED <= TO_UNSIGNED(MAX_VALUE,LOG2(MAX_VALUE) ); -- Сбросим счетчик в единицы END IF; END IF; END IF; END PROCESS; DATA_OUT <= TO_INTEGER(COUNTER_UNSIGNED); -- Выдадим значение счетчика на выходные порты модуля END GENERATE; END ARCHITECTURE; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 14 30 декабря, 2017 Опубликовано 30 декабря, 2017 · Жалоба Нет проверки на то, что что в DIRECTION будет нечто, отличное от "UP" и "DOWN". Например, "Up" или "Down". Не всем нравится верхний регистр. Лучше заменить строку на boolean. От счётчика с integer никакого профита. То же самое можно сделать двоичным счётчиком. Тем более, что вы не сможете сделать integer-счётчик более 32 бит. Есть старый программистский трюк: если число x является степенью 2, то x and (x - 1) = 0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 30 декабря, 2017 Опубликовано 30 декабря, 2017 (изменено) · Жалоба Нет проверки на то, что что в DIRECTION будет нечто, отличное от "UP" и "DOWN". Например, "Up" или "Down". Не всем нравится верхний регистр. Лучше заменить строку на boolean. От счётчика с integer никакого профита. То же самое можно сделать двоичным счётчиком. Тем более, что вы не сможете сделать integer-счётчик более 32 бит. Есть старый программистский трюк: если число x является степенью 2, то x and (x - 1) = 0 Спасибо за критику ! Я обязательно подумаю над этим. Вот со счётчиками типа integer я не совсем согласен. Какой тип использовать в качестве выхода: SLV, integer, unsigned - зависит лишь от предпочтений разработчика. Никаких преимуществ SLV над integer нет, как и наоборот. Это лишь вопрос удобства. В конце концов, всегда значение можно преобразовать в тот тип, который нужен :smile3046: Изменено 30 декабря, 2017 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 14 30 декабря, 2017 Опубликовано 30 декабря, 2017 · Жалоба Никаких преимуществ SLV над integer нет, как и наоборот. Это лишь вопрос удобства. В конце концов, всегда значение можно преобразовать в тот тип, который нуженНу попробуйте сделать на integer счётчик разрядностью более 32 бит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 30 декабря, 2017 Опубликовано 30 декабря, 2017 · Жалоба Ну попробуйте сделать на integer счётчик разрядностью более 32 бит. Вы снова правы ! Вот только мне ещё ни разу не приходилось работать с такими счетчиками... Можете сказать навскидку где вообще такой счетчик мог бы пригодится ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 11 30 декабря, 2017 Опубликовано 30 декабря, 2017 · Жалоба Можете сказать навскидку где вообще такой счетчик мог бы пригодится ? Для адресации внешней SDRAM памяти объемом 128 ГБайт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться