2015-02-05 3 views
0

Я пытаюсь сделать кумулятивную сумму с серией вложенных циклов, и мне не повезло. Я думаю, мне нужно лучше понять, как Verilog разворачивает циклы for, прежде чем я смогу реально представить, как решить мою проблему.Как Verilog разворачивается в петлях?

По существу, у меня есть серия выходов крана (tap_output_i и tap_output_q), которые являются 3D-массивами (src, dst, tap). Я хочу суммировать весь источник и краны, идущие в конкретное место назначения на каждый такт.

Вот что я, что не работает (out_sig 0 каждый раз):

//NODES = 2 
wire signed [DAC_BUS_WIDTH-1:0]  out_sig_i [NODES-1:0]; 
wire signed [DAC_BUS_WIDTH-1:0]  out_sig_q [NODES-1:0]; 
reg signed [DAC_BUS_WIDTH-1:0] out_sig_i_reg[NODES-1:0]; 
reg signed [DAC_BUS_WIDTH-1:0] out_sig_q_reg[NODES-1:0]; 

integer dstVal,srcVal, tapVal; 
//generate 
always @(posedge clk) begin: AlwaysSummingForLoop 
    for (dstVal=0; dstVal<2; dstVal=dstVal+1) begin:SummingForLoop 
    out_sig_i_reg[dstVal] <= 0; 
    out_sig_q_reg[dstVal] <= 0; 
     for (srcVal=0; srcVal<2; srcVal=srcVal+1) begin:SrcForLoop 
     if(srcVal != dstVal) begin:innerIf 
      for (tapVal=0; tapVal<8; tapVal=tapVal+1) begin:tapSum 
       out_sig_i_reg[dstVal] <= out_sig_i_reg[dstVal] + tap_output_i[srcVal][dstVal][tapVal]; 
       out_sig_q_reg[dstVal] <= out_sig_q_reg[dstVal] + tap_output_q[srcVal][dstVal][tapVal]; 
      end 
     end 
     end 
    end 
end 
//endgenerate 
assign out_sig_i[0] = out_sig_i_reg[0]; 
assign out_sig_q[0] = out_sig_q_reg[0]; 
assign out_sig_i[1] = out_sig_i_reg[1]; 
assign out_sig_q[1] = out_sig_q_reg[1]; 

Где я бегу в проблемы сбрасывает кумулятивный (out_sig_i_reg и out_sig_q_reg) сумма каждый отсчет ...

+0

Да, я использую out_sig_i_reg и out_sig_q_reg как свою суммирующую сумму. То, что я не могу понять, состоит в том, как заставить его суммировать сумму и сбрасывать до нуля каждый раз до суммирования ... – toozie21

ответ

5

<= является неблокирующим назначением. То есть, временная копия правой стороны выполняет процедурно (неблокирующее) выполнение кода для этого времени, а затем делает назначение из переменной темпа в левую сторону. Он используется для моделирования моделирования поведения триггера.

Флип-флоп может изменять значение только один раз за такт.

Вы (упрощенный код):

out_sig_q_reg[dstVal] <= 0; 
for (i=0; i<2; i=i+1) begin 
    for (j=0; j<8; j=j+1) begin 
    out_sig_q_reg[dstVal] <= out_sig_q_reg[dstVal] + tap_output_q[i][dstVal][j]; 
    end 
end 

В приведенном выше коде out_sig_q_reg[dstVal] <= 0; никогда не вступит в силу он всегда переопределяется следующей инструкции; out_sig_q_reg[dstVal] <= out_sig_q_reg[dstVal] ...

Ваш цикл for повторно использует ту же левую сторону, но выигрывает только последнее задание. Для данного регистра может быть эффективным только один <= за такт. Эффективным для петель нужно будет изменить внутренний левый регистр.

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

always @* begin 
    //.. 
    out_sig_q[dstVal] = 0; 
    for (i=0; i<2; i=i+1) begin 
    for (j=0; j<8; j=j+1) begin 
     out_sig_q[dstVal] = out_sig_q[dstVal] + tap_output_q[i][dstVal][j]; 
    end 
    end 
    //.. 
end 

always (@posedge clk) begin 
    for ... 
    out_sig_q_reg[dstVal] <= out_sig_q[dstVal]; 
+0

Спасибо за быстрый ответ. Итак, вы помещаете оба этих блока всегда в один размер: for (dstVal = 0; dstVal <2; dstVal = dstVal + 1)? – toozie21

+0

@ toozie21 Нет, вам придется поместить это внутри каждого блока всегда. Обычно не всегда внутри внутри, поскольку это становится генератором for-loop. Я добавил '// ..' в качестве загадочного руководства для заполнения деталей цикла. – Morgan

+0

Хм, похоже, не нравится. У меня есть «always @ * begin», за которым следует «for (dstVal = 0; dstVal <2; dstVal = dstVal + 1)», за которым следует «out_sig_q [dstVal] = 0;». но что выбрасывает «Процедурное присвоение не-регистру out_sig_q не разрешено, левая сторона должна быть ошибкой reg/integer/time/genvar». – toozie21