синтез verilog не сходится после 2000 итераций - PullRequest
0 голосов
/ 24 октября 2018

Я написал приведенный ниже код для простого умножения 2 n-битных чисел (здесь n = 16).Он моделируется с желаемой формой выходного сигнала, но проблема в том, что он не синтезируется в vivado 17.2, даже если я написал static 'for loop' (т.е. итерация цикла постоянна).Я получаю указанную ниже ошибку.

[Синтез 8-3380] условие цикла не сходится после 2000 итераций

Примечание: я написал

for(i=i;i<n;i=i+1)

вместо

for(i=0;i<n;i=i+1)

, потому что последний выполнялся еще раз после того, как я достиг n.Так что это не ошибка.Пожалуйста, помогите.Спасибо за ваше время

//unsigned integer multiplier
module multiplication(product,multiplier,multiplicand,clk,rset);
parameter n = 16; 
output reg [(n<<1)-1:0]product;
input [n-1:0]multiplier, multiplicand;
input clk,rset;
reg [n:0]i='d0; 
always @( posedge clk or posedge rset)
begin
    if (rset) product <= 'd0;
    else
    begin
        for(i=i;i<n;i=i+1)
        begin
        product =(multiplier[i] == 1'b1)? product + ( multiplicand << i ): product;
        $display("product =%d,i=%d",product,i);
        end
    end
end
endmodule

Ответы [ 3 ]

0 голосов
/ 24 октября 2018

Сообщение об ошибке не об итерациях вашего цикла, а об итерациях внутреннего алгоритма вашей программы синтеза.Он говорит вам, что Vivado не удалось создать схему, которая могла бы быть реализована на выбранной вами ПЛИС с выбранной вами тактовой частотой и которая действительно выполняет то, что вы просите.

Позвольте мне уточнить, после того как я упомянудва элемента общего импорта: не используйте блокирующие назначения (=) внутри блоков always @(posedge clk).Они почти никогда не делают то, что вы хотите.Только неблокирующие назначения (<=) должны быть синхронизированы.Во-вторых, правильный способ синтеза цикла for - это generate, хотя Вивадо, кажется, принимает простой for.

Вы строите здесь довольно большой блок комбинаторной логики.Помните, что когда вы синтезируете комбинаторную логику, вы запрашиваете схему, которая может оценить выражение, которое вы написали за один такт .Фактическое выражение, принятое во внимание, - это выражение после цикла for.То есть вы (условно) добавляете 16-битное число к 32-битному числу 16 раз, каждый раз сдвигаясь на один бит дальше влево.Каждое из этих дополнений имеет бит переноса.Таким образом, каждое из этих дополнений фактически должно рассматривать все старшие 16 битов результата предыдущего добавления, и каждое из них будет зависеть от всех, кроме самого младшего бита предыдущего добавления.Сумматор на один бит + перенос требует O (5) затворов.Каждое дополнение является условным, которое добавляет по крайней мере еще один вентиль для каждого бита.Таким образом, вы запрашиваете как минимум 16 * 16 * 6 = 1300 взаимозависимых вентилей, которые должны стабилизироваться в течение одного такта.Vivado говорит вам, что он не может выполнить эти требования.

Одним из способов решения этой проблемы будет синтез для более низкой тактовой частоты, когда у затворов будет больше времени для стабилизации, и, таким образом, вы сможете построить более длинные логические цепочки.,Другим вариантом может быть конвейеризация операции, скажем, путем оценки только того, что соответствует четырем итерациям цикла в течение одного тактового цикла, а затем построения результата за несколько тактовых циклов.Это добавит некоторую логику учета в ваш код, но это неизбежно, если кто-то захочет оценивать сложные выражения с конечными ресурсами на высоких тактовых частотах.Это также познакомит вас с синхронной логикой, которую вам все равно придется изучить, если вы хотите сделать что-нибудь нетривиальное с FPGA.Обратите внимание, что этот тип конвейерной передачи не окажет значительного влияния на пропускную способность, поскольку ваша FPGA будет затем выполнять несколько умножений параллельно.

Вы также можете переписать выражение для обработки битов переноса и взаимозависимостей в более умномспособ, который позволяет Vivado найти свой путь через выражение (вероятно, есть такой способ, я предполагаю, что он синтезирует, если вы просто напишите оператор умножения?).

Наконец, многие FPGA поставляются с выделенными единицами умножения, потому что умножениеэто обычная операция, но ее реализация в логических элементах тратит много ресурсов.Как вы узнали.

0 голосов
/ 24 октября 2018

Вернитесь к использованию вашего исходного цикла for (i=0.

Ваша ошибка в том, что вы принимаете i = 0 из-за reg [n:0]i='d0; Это верно только для в первый раз .Таким образом, только один раз, в начале моделирования.

потому что последний выполнялся еще раз после того, как я достиг n.

Да, цикл будет повторяться снова и снова для каждого тактового цикла .Это то, что делает @( posedge clk ...).

Больше ошибок:

  • Вы используете блокирующее назначение в секции часов, используйте неблокирующее:

    произведение <= (множитель [i] == 1'b1)?product + (multiplicand << i): product; </p>

  • Ваш продукт корректен только в первый раз после сброса (когда он начинается с нуля).Во втором тактовом цикле после сброса вы снова делаете умножение, но начинаете с предыдущего значения произведения.

  • Ваш i немного больше, вы используете 17 бит, чтобы сосчитать до 16.Также у глобальных переменных цикла есть подводные камни.Я предлагаю вам использовать системный синтаксис Verilog: `for (int i = 0; ....)

0 голосов
/ 24 октября 2018

Прежде всего, не рекомендуется использовать циклы для , , тогда как , если вы действительно хотите реализовать свой дизайн на ПЛИС (Vivado оптимизирован для использованияреализовать свой дизайн на ПЛИС).Даже если вы можете успешно синтезировать свой дизайн, вы можете столкнуться с проблемами синхронизации или неожиданными ошибками.

Я думаю, вы можете найти свой ответ здесь .

Редактировать: Я просто хотел сообщить вам, что в целом управление синхронизацией очень важно в проектировании HW, особенно когда вы хотите интегрировать свой дизайн с другой системой, циклы могут быть кошмаром для этого.

...