【问题标题】:how to generate array of interfaces having different connections?如何生成具有不同连接的接口数组?
【发布时间】:2017-11-13 15:49:13
【问题描述】:

我已经声明了以下接口:

interface data_x #(parameter g_DataWidth = 8)
   (input ckrs_t ClkRs_ix);
   logic [g_DataWidth-1:0] data;
   bit         enable;
   ckrs_t ClkRs;

   always_comb begin
      ClkRs = ClkRs_ix;
   end
endinterface

接口有数据总线和数据使能,同时还与时钟和复位信号相关联,即typedef ckrs_t。

我有一个模块,它接受这些接口的参数数组:

module fourmclinks
   (...
    data_x packet_ox[NUMBER_OF_GBT_LINKS-1:0],
    data_x packet_ix[NUMBER_OF_GBT_LINKS-1:0],
    ...
    );

我遇到的问题是,我需要在顶级实体中声明这些 data_x 接口的数组,但每次使用不同的 ClkRs_ix 输入时钟。 (它用于 gbts,每个接收器都有自己的时钟和复位信号)。

我尝试了很多东西,包括这个:

   ckrs_t txclock_x;
   assign txclock_x.clk = GbtTxFrameClk40MHz_k;
   assign txclock_x.reset = GbtReset_r;
   data_x #(.g_DataWidth(g_FrameSize)) packet_ox[NUMBER_OF_GBT_LINKS-1:0](.ClkRs_ix(txclock_x));

   data_x #(.g_DataWidth(g_FrameSize)) packet_ix[NUMBER_OF_GBT_LINKS-1:0]();
   genvar                 linkiface;
   generate
      for(linkiface=1; linkiface < NUMBER_OF_GBT_LINKS+1; linkiface++) begin : linkgenerator
     assign packet_ix[linkiface-1].ClkRs_ix.clk =
                             GbtRxFrameClk40Mhz_kb4[linkiface];
     assign packet_ix[linkiface-1].ClkRs_ix.reset = GbtReset_r;
     assign packet_ix[linkiface-1].enable = 0;
     assign packet_ix[linkiface-1].data = RxDataAppSfpGbtUserData_4b80[linkiface];
      end
   endgenerate

因此制作空/虚拟/未分配/...接口数组声明,然后在生成循环中为其分配正确的信号。这模拟,但 quartus 不编译它声称

值不能分配给输入“ClkRs_ix”。

如何正确生成接口数组,每个接口都有不同的输入连接?请帮忙

【问题讨论】:

  • 我希望您的代码能够正常工作,但没有进一步调查。由于它不起作用,我建议将您的接口实例移动到生成“for”循环中并忘记实例数组。无论如何它都会变得更干净。

标签: system-verilog


【解决方案1】:

我现在更聪明了,所以这里是问题的解决方案。但第一个问题:

  • 不能只从上面 data_x 接口声明中的端口声明中删除“输入”方向。如果这样做了,则必须为 data_x 对象的每个实例手动分配时钟和复位线。这确实是可能的,但是失去了在接口实例化期间自动分配时钟和重置的所有美感

  • 在这种特殊情况下,也不可能创建一个虚拟接口,并在 for 循环中连接信号。其根本原因是 always_comb 的存在,它接收输入复位/时钟并将其分配给内部信号。因此,这种分配,连同顶层实体中的复位和时钟手动分配导致驱动来自两个源的信号,Quartus 不会消化这些信号

所以我发现的唯一可能的方法是:

声明data_x接口,按需生成always_comb:

interface data_x #(
          parameter g_hasClock = 1,
          parameter g_DataWidth = 8)
   (
    input ckrs_t ClkRs_ix
    );

   logic [g_DataWidth-1:0] data;
   bit         enable;
   ckrs_t ClkRs;

   generate
      if(g_hasClock) begin
     always_comb begin
        ClkRs = ClkRs_ix;
     end
      end
   endgenerate

endinterface // data_x

用未绑定的 ClkRs_ix 实例化接口。注意 g_hasClock 的使用,它在没有 always_comb 块的情况下实例化 data_x 接口,因此 Quartus 停止抱怨多个驱动程序:

   data_x #(.g_DataWidth(g_FrameSize),
        .g_hasClock(0)) packet_ix[NUMBER_OF_GBT_LINKS-1:0]();

然后生成不同时钟的接口:

   genvar                 linkiface;
   generate
      for(linkiface=1; linkiface < NUMBER_OF_GBT_LINKS+1; linkiface++)
   begin : linkgenerator

     assign packet_ix[linkiface-1].ClkRs.clk = GbtRxFrameClk40Mhz_kb4[linkiface];
     assign packet_ix[linkiface-1].ClkRs.reset = GbtReset_r;
     assign packet_ix[linkiface-1].enable = 0;
     assign packet_ix[linkiface-1].data = RxDataAppSfpGbtUserData_4b80[linkiface];
      end
   endgenerate

这行得通。这不是很好,因为我们必须手动完成。只是为了完整起见:如果所有接口的时钟都相同,那么上面的所有代码都归结为这个 sn-p:

  ckrs_t txclock_x, rxclock_x;
   assign txclock_x.clk = GbtTxFrameClk40MHz_k;
   assign txclock_x.reset = GbtReset_r;
   data_x #(.g_DataWidth(g_FrameSize)) packet_ox[NUMBER_OF_GBT_LINKS-1:0](.ClkRs_ix(txclock_x));

我确信这不是有史以来最好的解决方案,但它是可编译的并给出了所需的结果。

【讨论】:

    猜你喜欢
    • 2010-12-12
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    相关资源
    最近更新 更多