jokolemene 0 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба Всем привет! Тема такая: создаю схему на верилоге. В ней есть регистр переменного размера. Размер его задаётся через parameter, а затем выполняется перекомпиляция схемы. В результате работы схемы в регистре только один бит устанавливается в 1, остальные остаются в нуле. Вопрос: как комбинаторикой узнать номер этого установленного бита? Вот, например, как это было бы мной реализовано, если бы регистр был постоянного размера, скажем, восьмибитовым: reg [7:0] result_reg; assign result_o = result_reg[7] ? 7 : result_reg[6] ? 6 : result_reg[5] ? 5 : result_reg[4] ? 4 : result_reg[3] ? 3 : result_reg[2] ? 2 : result_reg[1] ? 1 : 0; А как это сделать если регистр переменного размера? Пытаюсь сделать нечто в этом роде: parameter XX = 8; // Количество бит в регистре результата parameter NB = log2(XX); // Логарифм по основанию 2 от XX (вычисляется функцией log2) reg [XX-1:0] result_reg; // Регистр с результатом работы схемы reg [NB-1:0] num_bit_reg; // Номер установленного бита в регистре result_reg assign result_o = num_bit_reg; // result_o - output-порт модуля always @( result_reg ) begin integer i; for( i=0; i < XX; i=i+1 ) if( result_reg[i] ) num_bit_reg = i; end Компилируется и вроде даже работает как надо, но при компиляции выдаётся warning: inferring latch(es) for variable "num_bit_reg", which holds its previous value in one or more paths through the always construct. Как сделать так, чтобы этого варнинга не было? Очень уж мне такие варнинги не нравятся. Да и как схема синтезируется в случае подобных конструкций - не совсем понятно. А я люблю, когда всё понятно и прозрачно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shivers 0 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба Мне кажется, сначала надо поработать над условиями задачи. Есть регистр, хранящий нули, и только один бит в единице. А что на выходе хотите получить - не понятно. Если на выходе нужен HEX - ставьте шифратор, если DEC - то достаточно сам регистр вывести. Если нужен признак установления единицы, надо все разряды через ИЛИ сжать до одного провода. Ну и т.д. Нарисуйте сначала схему, что получить хотите, а потом верилог пишите Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jokolemene 0 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба На порту result_o нужно получить порядковый номер бита регистра result_reg, установленного в единицу. Например, если регистр result_reg имеет размер 8192 бита, и в нём установлен бит номер 4015, то на порту result_o нужно получить число 4015. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_4afc_ 26 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба А цикл for тут не поможет? Пусть само синтезируется в комбинаторику... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
embddr 0 21 августа, 2015 Опубликовано 21 августа, 2015 (изменено) · Жалоба Компилируется и вроде даже работает как надо, но при компиляции выдаётся warning: inferring latch(es) for variable "num_bit_reg", which holds its previous value in one or more paths through the always construct. Как сделать так, чтобы этого варнинга не было? Так там действительно защелка образуется. Чтобы ее не было, нужно перед "for" присвоить num_bit_reg значение по умолчанию, например 0. Кстати, ваш код будет считать номер бита с конца. Чтобы считал сначала, нужно после "num_bit_reg = i" поставить "break". Изменено 21 августа, 2015 пользователем embddr Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jokolemene 0 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба Так там действительно защелка образуется. Чтобы ее не было, нужно перед "for" присвоить num_bit_reg значение по умолчанию, например 0. Кстати, ваш код будет считать номер бита с конца. Чтобы считал сначала, нужно после "num_bit_reg = i" поставить "break". Да, регистр был не инициализирован. Инициализировал. Всё равно варнинг рисуется. Посмотрел сгенерённую схему: куча комбинаторики и в самом конце стоят защёлки - в них используются входы ACLR и PRESET. А насчёт порядка счёта: без разницы откуда считать. Единичный бит в регистре только в одном экземпляре. PS: Добавил в цикл break - перестало компилироваться. Выдаёт ошибку: can't resolve reference to object "break". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
embddr 0 21 августа, 2015 Опубликовано 21 августа, 2015 (изменено) · Жалоба Да, регистр был не инициализирован. Инициализировал. Всё равно варнинг рисуется. Посмотрел сгенерённую схему: куча комбинаторики и в самом конце стоят защёлки - в них используются входы ACLR и PRESET. А насчёт порядка счёта: без разницы откуда считать. Единичный бит в регистре только в одном экземпляре. PS: Добавил в цикл break - перестало компилироваться. Выдаёт ошибку: can't resolve reference to object "break". Вот такой код должен быть: always @( result_reg ) begin integer i; num_bit_reg = 0; for( i=0; i < XX; i=i+1 ) if( result_reg[i] ) num_bit_reg = i; end Это квартус? Ошибка на 'break' потому, что его нет в Verilog-е. Нужно поставить тип файла SystemVerilog. В Verilog-е можно использовать 'disable'. Изменено 21 августа, 2015 пользователем embddr Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jokolemene 0 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба 2 embddr: Да, точно! Я понял в чём была моя ошибка. Теперь всё синтезируется без варнинга и защёлок. Большое спасибо за помощь! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба for( i=0; i < XX; i=i+1 ) if( result_reg ) num_bit_reg = i; Компилируется и вроде даже работает как надо, но при компиляции выдаётся warning: inferring latch(es) for variable "num_bit_reg", which holds its previous value in one or more paths through the always construct. Как сделать так, чтобы этого варнинга не было? Очень уж мне такие варнинги не нравятся. Да и как схема синтезируется в случае подобных конструкций - не совсем понятно. А я люблю, когда всё понятно и прозрачно. Латчи получаются если не доопределены все состояния шифратора. Введите условие else и там напишите что нужно. Подробнее читайте в "Кратком Курсе"... Удачи! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
embddr 0 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба Введите условие else и там напишите что нужно. В данном конкретном случае с else не получится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Serhiy_UA 1 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба На порту result_o нужно получить порядковый номер бита регистра result_reg, установленного в единицу. Например, если регистр result_reg имеет размер 8192 бита, и в нём установлен бит номер 4015, то на порту result_o нужно получить число 4015. Вариантов решения может быть много, все определяется требованием к скорости и аппаратурным затратам, возможность конвейеризации и т.п.. Один из вариантов такой. Регистр разбивается на блоки, каждый из которых обрабатывает соседние разряды регистра. При этом число разрядов входящих в блок задается из ряда 2, 4, 8 или 16, а из блока выходят сигнал наличия единицы в блоке (СНЕ) и код ее позиции (КП), если единица там есть. Далее блоки группируются в слои, первый слой блоков подключен к регистру, а каждый последующий слои принимает сигналы наличия единицы (СНЕ) из блоков предыдущего слоя. И так до тех пор, пока слои не закончатся, получается что-то похожее на двоичную пирамиду. Теперь в каждом слое блоков должен быть один большой коммутатор, входы которого подключены к выходам кодов КП блоков, а управляться коммутатор должен сигналами СНЕ этого слоя. Если между блоками поставить регистры для конвейеризации, то получится еще веселей… Похоже, что задача относится к цифровой части АЦП... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба мне кажется вы только что описали обычный шифратор, только не даете синтезатору проявить смекалку и использовать особенности архитектуры (например в спартанах можно по 6 сигналов за раз обрабатывать). кстати у ТС нет клока, потому про конвейер трудно говорить... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба по-моему тоже обычный шифратор. единственное, на что обратить внимание, - что у шифратора на входе разрядность шины должна быть степенью двойки от выходной разрядности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Serhiy_UA 1 21 августа, 2015 Опубликовано 21 августа, 2015 · Жалоба по-моему тоже обычный шифратор. единственное, на что обратить внимание, - что у шифратора на входе разрядность шины должна быть степенью двойки от выходной разрядности. Еще один вариант с методом двоичного взвешивания. Весь N- разрядный регистр делится на две части, и разряды старшей части подключаются к элементу ИЛИ на N/2 входов. Сигнал на выходе элемента ИЛИ укажет, в старшей или младшей части регистра находится значащая единица, и по сути он есть самый старший разряд результата. Далее разряды обеих частей регистра подаются на двухвходовой N/2-разрядный коммутатор, который пропускает для дальнейшего анализа часть кода со значащей единицей (здесь старшая часть выбирается единицей, а младшая нулем). На второй итерации имеем уже N/2-разрядный код, который также делится пополам и старшие N/4 разрядов также подключаются к элементу ИЛИ, но уже на N/4 входов. На выходе элемента ИЛИ формируется уже второй слева разряд результата, а обе части кода подаются на двухвходовой N/4-разрядный коммутатор, который пропускает для дальнейшего анализа часть кода также со значащей единицей. Далее выполняются аналогичные итерационные действия, в которых разрядность элемента ИЛИ и соответствующего ему коммутатора в два раза меньше чем в предыдущей итерации. То есть реализуется метод двоичного взвешивания.. Быстродействие здесь достаточно большое... Так что это за задача, где еще приходится находить позицию единицы? В приложении схема этого варианта 1.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GAYVER 2 24 августа, 2015 Опубликовано 24 августа, 2015 (изменено) · Жалоба На порту result_o нужно получить порядковый номер бита регистра result_reg, установленного в единицу. Например, если регистр result_reg имеет размер 8192 бита, и в нём установлен бит номер 4015, то на порту result_o нужно получить число 4015. если вы в дальгейшем будите использовть это интежеровское значение в схеме, то оно дополнительно будет переводится в лоджик вектор через еще кучу логики. возможно вам сам подход к задаче надо переработать - зачем вам нужен порядковый номер, и можно ли обойтись без него. мне как то надо было проверить массив переменной длинны с шинами фиксированной размерности на наличие хотя бы одной 1. на вхдл-е я это так сделал. process(bu_data_v) begin for i in 31 downto 0 loop for j in 1 to num_adc loop if bu_data_v(j)(i)='1' then bu_data(i)<='1'; end if; bu_data(i)<='0'; end loop; end loop; end process; насколько это разводибельно - пока не проверял , но человек, интегрирующий мой блок в общий проект пока что на него не жаловался :) вам достаточно запоминать номер индекса, на котором получена "1" зы упс, не дочитал... embddr уже предложил это решение :) Изменено 24 августа, 2015 пользователем GAYVER Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться