Использование оператора импликации для разных диапазонов адресов

#system-verilog

#system-verilog

Вопрос:

Мне интересно, как можно использовать оператор импликации, если я хочу выбирать между разными диапазонами адресов. Я использую if/else условие, но, похоже, решатель ограничений не принимает никакого решения для этого.

   constraint ctCopy { mode == C_CMD -> if      (addr_range == "DST_SRAM") {dstAddr inside {[0:'hFFFF]}; }
                                          else if (addr_range == "DST_AXI")  {dstAddr inside {['h30000:'h3FFFF]}; }
                                          else if (addr_range == "DST_AHB")  {dstAddr inside {[20000:'h2FFFF]}; }
                                          else                               {dstAddr inside {[0:'hFFFF]}; }
                      mode == C_CMD -> if      (addr_range == "SRC_SRAM") {srcAddr inside {[0:'hFFFF]}; }
                                          else if (addr_range == "SRC_AXI")  {srcAddr inside {[0:'h30000]}; }
                                          else                               {srcAddr inside {[0:'hFFFF]}; }
                      mode == C_CMD -> cSize inside {[2:10]} ;
                      }
  

Я пытаюсь использовать with ограничение, но решатель не принимает. Вот фрагмент:

   Trn0.randomize() with { mode == C_CMD; addr_range == "DST_AHB";};
  

небольшой пример для воспроизведения, как показано ниже

 class top;
  rand logic [3:0] mode;
  rand logic [16:0] dstAddr;
  rand logic [16:0] srcAddr;
  string addr_range;
  rand logic [4:0] copySize;

  constraint ctCopy { mode == 1 -> if      (addr_range == "DST_SRAM") {dstAddr inside {[0:'hFFFF]}; }
                                       else if (addr_range == "DST_AXI")  {dstAddr inside {['h30000:'h3FFFF]}; }
                                       else if (addr_range == "DST_AHB")  {dstAddr inside {[20000:'h2FFFF]}; }
                                       else                               {dstAddr inside {[0:'hFFFF]}; }
                      mode == 1 -> if      (addr_range == "SRC_SRAM") {srcAddr inside {[0:'hFFFF]}; }
                                       else if (addr_range == "SRC_AXI")  {srcAddr inside {[0:'h30000]}; }
                                       else                               {srcAddr inside {[0:'hFFFF]}; }
                      mode == 1 -> copySize inside {[2:10]} ;
                      }
  
endclass

module tb;
  initial begin
    top tb = new;
    tb.randomize() with { mode == 1; addr_range == "DST_AHB";};
    $display("dstAddr=
,srcAddr=
",tb.dstAddr,tb.srcAddr);
  end
endmodule
  

Автономный пример в:

https://www.edaplayground.com/x/rjZy

Ответ №1:

addr_range имеет тип string , что означает, что он не может быть rand переменной. Один из способов решить вашу проблему — установить addr_range перед вызовом randomize :

 module tb;
  initial begin
    top tb = new;
    tb.addr_range = "DST_AHB";
    tb.randomize() with { mode == 1; };
    $display("dstAddr=
,srcAddr=
",tb.dstAddr,tb.srcAddr);
  end
endmodule
  

Другой способ — использовать перечисления вместо строк, если вы хотите addr_range быть случайными.


При запуске с Cadence на edaplayground он генерирует предупреждающие сообщения о том, что некоторые значения в вашем ограничении находятся вне диапазона. Например, вы объявили dstAddr как 17-битное значение, но 'h3FFFF требуется не менее 18 бит. Вы должны исправить свои значения.