jokolemene 0 August 21, 2015 Posted August 21, 2015 · Report post Всем привет! Тема такая: создаю схему на верилоге. В ней есть регистр переменного размера. Размер его задаётся через 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. Как сделать так, чтобы этого варнинга не было? Очень уж мне такие варнинги не нравятся. Да и как схема синтезируется в случае подобных конструкций - не совсем понятно. А я люблю, когда всё понятно и прозрачно. Quote Share this post Link to post Share on other sites More sharing options...
Shivers 0 August 21, 2015 Posted August 21, 2015 · Report post Мне кажется, сначала надо поработать над условиями задачи. Есть регистр, хранящий нули, и только один бит в единице. А что на выходе хотите получить - не понятно. Если на выходе нужен HEX - ставьте шифратор, если DEC - то достаточно сам регистр вывести. Если нужен признак установления единицы, надо все разряды через ИЛИ сжать до одного провода. Ну и т.д. Нарисуйте сначала схему, что получить хотите, а потом верилог пишите Quote Share this post Link to post Share on other sites More sharing options...
jokolemene 0 August 21, 2015 Posted August 21, 2015 · Report post На порту result_o нужно получить порядковый номер бита регистра result_reg, установленного в единицу. Например, если регистр result_reg имеет размер 8192 бита, и в нём установлен бит номер 4015, то на порту result_o нужно получить число 4015. Quote Share this post Link to post Share on other sites More sharing options...
_4afc_ 40 August 21, 2015 Posted August 21, 2015 · Report post А цикл for тут не поможет? Пусть само синтезируется в комбинаторику... Quote Share this post Link to post Share on other sites More sharing options...
embddr 0 August 21, 2015 Posted August 21, 2015 (edited) · Report post Компилируется и вроде даже работает как надо, но при компиляции выдаётся 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". Edited August 21, 2015 by embddr Quote Share this post Link to post Share on other sites More sharing options...
jokolemene 0 August 21, 2015 Posted August 21, 2015 · Report post Так там действительно защелка образуется. Чтобы ее не было, нужно перед "for" присвоить num_bit_reg значение по умолчанию, например 0. Кстати, ваш код будет считать номер бита с конца. Чтобы считал сначала, нужно после "num_bit_reg = i" поставить "break". Да, регистр был не инициализирован. Инициализировал. Всё равно варнинг рисуется. Посмотрел сгенерённую схему: куча комбинаторики и в самом конце стоят защёлки - в них используются входы ACLR и PRESET. А насчёт порядка счёта: без разницы откуда считать. Единичный бит в регистре только в одном экземпляре. PS: Добавил в цикл break - перестало компилироваться. Выдаёт ошибку: can't resolve reference to object "break". Quote Share this post Link to post Share on other sites More sharing options...
embddr 0 August 21, 2015 Posted August 21, 2015 (edited) · Report post Да, регистр был не инициализирован. Инициализировал. Всё равно варнинг рисуется. Посмотрел сгенерённую схему: куча комбинаторики и в самом конце стоят защёлки - в них используются входы 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'. Edited August 21, 2015 by embddr Quote Share this post Link to post Share on other sites More sharing options...
jokolemene 0 August 21, 2015 Posted August 21, 2015 · Report post 2 embddr: Да, точно! Я понял в чём была моя ошибка. Теперь всё синтезируется без варнинга и защёлок. Большое спасибо за помощь! Quote Share this post Link to post Share on other sites More sharing options...
iosifk 3 August 21, 2015 Posted August 21, 2015 · Report post 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 и там напишите что нужно. Подробнее читайте в "Кратком Курсе"... Удачи! Quote Share this post Link to post Share on other sites More sharing options...
embddr 0 August 21, 2015 Posted August 21, 2015 · Report post Введите условие else и там напишите что нужно. В данном конкретном случае с else не получится. Quote Share this post Link to post Share on other sites More sharing options...
Serhiy_UA 1 August 21, 2015 Posted August 21, 2015 · Report post На порту result_o нужно получить порядковый номер бита регистра result_reg, установленного в единицу. Например, если регистр result_reg имеет размер 8192 бита, и в нём установлен бит номер 4015, то на порту result_o нужно получить число 4015. Вариантов решения может быть много, все определяется требованием к скорости и аппаратурным затратам, возможность конвейеризации и т.п.. Один из вариантов такой. Регистр разбивается на блоки, каждый из которых обрабатывает соседние разряды регистра. При этом число разрядов входящих в блок задается из ряда 2, 4, 8 или 16, а из блока выходят сигнал наличия единицы в блоке (СНЕ) и код ее позиции (КП), если единица там есть. Далее блоки группируются в слои, первый слой блоков подключен к регистру, а каждый последующий слои принимает сигналы наличия единицы (СНЕ) из блоков предыдущего слоя. И так до тех пор, пока слои не закончатся, получается что-то похожее на двоичную пирамиду. Теперь в каждом слое блоков должен быть один большой коммутатор, входы которого подключены к выходам кодов КП блоков, а управляться коммутатор должен сигналами СНЕ этого слоя. Если между блоками поставить регистры для конвейеризации, то получится еще веселей… Похоже, что задача относится к цифровой части АЦП... Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 August 21, 2015 Posted August 21, 2015 · Report post мне кажется вы только что описали обычный шифратор, только не даете синтезатору проявить смекалку и использовать особенности архитектуры (например в спартанах можно по 6 сигналов за раз обрабатывать). кстати у ТС нет клока, потому про конвейер трудно говорить... Quote Share this post Link to post Share on other sites More sharing options...
krux 9 August 21, 2015 Posted August 21, 2015 · Report post по-моему тоже обычный шифратор. единственное, на что обратить внимание, - что у шифратора на входе разрядность шины должна быть степенью двойки от выходной разрядности. Quote Share this post Link to post Share on other sites More sharing options...
Serhiy_UA 1 August 21, 2015 Posted August 21, 2015 · Report post по-моему тоже обычный шифратор. единственное, на что обратить внимание, - что у шифратора на входе разрядность шины должна быть степенью двойки от выходной разрядности. Еще один вариант с методом двоичного взвешивания. Весь N- разрядный регистр делится на две части, и разряды старшей части подключаются к элементу ИЛИ на N/2 входов. Сигнал на выходе элемента ИЛИ укажет, в старшей или младшей части регистра находится значащая единица, и по сути он есть самый старший разряд результата. Далее разряды обеих частей регистра подаются на двухвходовой N/2-разрядный коммутатор, который пропускает для дальнейшего анализа часть кода со значащей единицей (здесь старшая часть выбирается единицей, а младшая нулем). На второй итерации имеем уже N/2-разрядный код, который также делится пополам и старшие N/4 разрядов также подключаются к элементу ИЛИ, но уже на N/4 входов. На выходе элемента ИЛИ формируется уже второй слева разряд результата, а обе части кода подаются на двухвходовой N/4-разрядный коммутатор, который пропускает для дальнейшего анализа часть кода также со значащей единицей. Далее выполняются аналогичные итерационные действия, в которых разрядность элемента ИЛИ и соответствующего ему коммутатора в два раза меньше чем в предыдущей итерации. То есть реализуется метод двоичного взвешивания.. Быстродействие здесь достаточно большое... Так что это за задача, где еще приходится находить позицию единицы? В приложении схема этого варианта 1.rar Quote Share this post Link to post Share on other sites More sharing options...
GAYVER 2 August 24, 2015 Posted August 24, 2015 (edited) · Report post На порту 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 уже предложил это решение :) Edited August 24, 2015 by GAYVER Quote Share this post Link to post Share on other sites More sharing options...