Программируемая логика - это не так уж и сложно. Разберемся вместе.
Ответить

Проблема с адаптивной линией задержки на EPM240

Вс авг 06, 2017 17:51:09

Приветствую.
Есть два идентичных (за исключением первого периода) сигнала fb_l и fb_r, но второй имеет частотозависимую задержку d2 относительно первого. Требуется сформировать сигнал ctrl, который отстает от fb_l на время d3 = d2 - d1, где d1 некоторая постоянная величина (d1 < d2).
Моя программа работает некорректно - часть периодов ctrl формируется правильно, но остальные "слипаются" или пропускаются. Причем количество и положение испорченных периодов меняется рандомно.

Фрагмент сигнала (d1 = 0 для наглядности)
СпойлерИзображение

Код
Спойлер
Код:
module EPM240
   (
    input wire clk,
    input wire in1,
    input wire in2,
    input wire in3,
    input wire in4,
    output wire out1,
    output wire out2,
    output wire out3,
    output wire out4
    );

localparam    clk_freq = 50_000_000,
            inter_coarse_freq = 10_000,   
            inter_coarse_value = clk_freq / inter_coarse_freq,
            period_coarse_freq = 200_000,
            period_coarse_value = clk_freq / period_coarse_freq,
            start_pulse_value = period_coarse_value / 8;
   
reg[15:0]   cnt = 0;   
   
reg[8:0]      d1 = 0,
            d2 = 72,
            d3 = 72;
           
reg[0:0]      fb_l = 0,
            fb_l_pre = 0,
            fb_r = 0,
            fb_r_pre = 0,
            channel_1 = 0,
            channel_2 = 0,
            d2_inc_en = 0,
            d3_dec_en = 0;
//----------
always @ (posedge clk)   
begin
//----------   
   fb_l = in1;
   fb_r = in2;
//----------   
   if (cnt != (inter_coarse_value - 1)) cnt = cnt + 1;
   else cnt = 0;
//----------   
   if (d2_inc_en == 1) d2 = d2 + 1;
   if (d3_dec_en == 1)
      begin
         if (d3 == 0)
            begin
               d3_dec_en = 0;
               if (fb_l == 0) channel_2 = 0;
               else channel_2 = 1;
            end
         else d3 = d3 - 1;
      end
//----------| start | ----------   
   if (cnt == 0) channel_1 = channel_1 ^ 1;
   if (channel_1 == 0) channel_2 = 0;
//----------| d2 & d3 | ----------
   if ((fb_l_pre == 0)&&(fb_l == 1))   // fb_l __/--
   begin
      d3_dec_en = 1;
      d2_inc_en = 1;
      d3 = d2 - d1;
      d2 = 0;
      fb_l_pre = fb_l;
   end
   
if ((fb_r_pre == 0)&&(fb_r == 1))      // fb_r __/--
   begin
      d2_inc_en = 0;
      fb_r_pre = fb_r;
   end
   
if ((fb_l_pre == 1)&&(fb_l == 0))      // fb_l --\__
   begin
      d3_dec_en = 1;
      d2_inc_en = 1;
      d3 = d2 - d1;
      d2 = 0;
      fb_l_pre = fb_l;
   end
   
if ((fb_r_pre == 1)&&(fb_r == 0))      // fb_r --\__   
   begin
      d2_inc_en = 0;
      fb_r_pre = fb_r;
   end
end
//----------
assign out1 = channel_1;
assign out2 = channel_2;

endmodule

Re: Проблема с адаптивной линией задержки на EPM240

Пн авг 07, 2017 23:31:02

Как-то так нужно.
Спойлер
Код:
module delay123
   #(
      parameter delay1 = 8,
      parameter max_delay2 = 20
   ) (
    input wire clk,
    input wire reset,
    input wire fb_l,
    input wire fb_r,
    output reg ctrl = 0
  );

  localparam max_delay3 = max_delay2 - delay1;

  reg [7:0] delay2 = 0;
  reg [$clog2(max_delay2 + 1) - 1:0] delay2_cnt = 0;
  reg [$clog2(max_delay3 + 1) - 1:0] delay3_cnt = 0;
  reg fb_l_perv = 0;
  reg fb_r_perv = 0;
  reg fb_trig;

  always @(posedge clk) begin
    fb_l_perv <= fb_l;
    fb_r_perv <= fb_r;
    if (fb_l && !fb_l_perv) begin
      fb_trig <= 1'b1;
      delay2_cnt <= 2;
    end
    if (fb_r && !fb_r_perv) begin
      fb_trig <= 1'b0;
      delay2 <= delay2_cnt;
    end
    if (fb_trig) begin
      delay2_cnt <= delay2_cnt + 1'b1;
    end
  end

  always @(posedge clk) begin
    if (fb_l) begin
      if (delay3_cnt < delay2 - delay1) begin
        delay3_cnt <= delay3_cnt + 1'b1;
      end else begin
        ctrl <= 1'b1;
      end
    end else begin
      if (delay3_cnt > 0) begin
        delay3_cnt <= delay3_cnt - 1'b1;
      end else begin
        ctrl <= 1'b0;
      end
    end
  end
endmodule
Plazmoid писал(а):Моя программа работает некорректно
Это не совсем программа, это описание цифрового устройства со всякими триггерами и комбинационными устройствами. Поэтому сначала нужно продумать схему до уровня отдельных счетчиков, регистров и комбинационных устройств, и только потом писать код. По этой же причине, чтобы однозначно отделить комбинационные части устройства от последовательностных, в блоках always не стоит использовать блокирующие присваивания.

Re: Проблема с адаптивной линией задержки на EPM240

Вт авг 08, 2017 20:08:22

Это не совсем программа, это описание цифрового устройства со всякими триггерами и комбинационными устройствами. Поэтому сначала нужно продумать схему до уровня отдельных счетчиков, регистров и комбинационных устройств, и только потом писать код.

То, что из кода синтезируется схема, это понятно :) . Вот только сообразить, что получится на выходе, не всегда удается. Один из предыдущих проектов был на XC9572XL - написал рабочий код, но при малейшей его модификации схема переставала синтезироваться, хотя был запас по макроячейкам, термам и регистрам. Причем происходило это совершенно непредсказуемо - "Если увеличить разрядность регистра cnt с 15 до 17 бит, будет задействовано на 2 регистра больше и на 6 термов меньше, а если поднять до 19 бит, то для синтеза внезапно не будет хватать 234 термов!". А на XC6SLX9 все работало без проблем, и, вроде, ячеек меньше занимало. CPLD очень требовательны к качеству кода.
По этой же причине, чтобы однозначно отделить комбинационные части устройства от последовательностных, в блоках always не стоит использовать блокирующие присваивания.

С этим есть проблемы. Во многих случаях важна последовательность команд, поэтому использую блокирующие присваивания. Но Квартус ругается на смешивание разных типов присваиваний, поэтому в итоге приходиться выдерживать все в одном стиле. :(

Ваш код пока не пробовал - сложновато для меня, нужно время, чтобы разобраться.
Ответить