如何使用 chisel3 黑盒实例化 Xilinx 差分时钟缓冲器?

How to instanciate Xilinx differential clock buffer with chisel3 blackboxes?

我想在我的 AC701 kit (artix7) 上写一个简单的 chisel3 闪烁 LED 设计。但要做到这一点,我必须实例化一个时钟输入差分缓冲器。 Xilinx 提供以下 verilog 模板来执行此操作:

IBUFDS #(
    .DIFF_TERM("TRUE"),
    .IOSTANDARD("DEFAULT")
) IBUFDS1_inst (
    .O(clock1), // Clock buffer
    .I(clock1_p), // Diff_p clock
    .IB(clock1_n) // Diff_n clock
);

我在 chisel documentation 上读到我必须使用 «blackbox» class 来实例化它。但我做不到。 我试过了:

class IbufdsParam extends VerilogParameters {
    val DIFF_TERM  = "TRUE" 
    val IOSTANDARD = "DEFAULT"
}

class IBUFDS extends BlackBox {
  val params = new IbufdsParam()
  val io = IO(new Bundle {
    val O = Output(Bool())
    val I = Input(Bool())
    val IB = Input(Bool())})
  io.O.setName("O")
  io.I.setName("I")
  io.IB.setName("IB")

  /* For simulation */
  io.O := io.I & ~io.IB
}

但是chisel3好像不知道VerilogParameters class :

[error] blinking_led/blink.scala:5: not found: type VerilogParameters
[error] class IbufdsParam extends VerilogParameters {

而且我不知道怎么说«不要使用这个模块的时钟和重置»。

一旦正确声明了这个黑盒,我就必须将输出时钟 ('O') 连接到闪烁模块的主时钟。我不确定该怎么做。我正在考虑:

class Blink extends Module {
  val io = IO(new Bundle {
    val clock_p = Input(Bool())
    val clock_n = Input(Bool())
    val led  = Output(Bool())
  })

  val ibufds = IBUFDS()

  Driver.implicitClock := ibufds.io.O
  ibufds.io.I := io.clock_p
  ibufds.io.IB:= io.clock_n

...
}

但我认为这可能不是正确的方法,不是吗?

这是一个文档错误,我一定会尽快在 chisel3 wiki 上添加一个关于参数化黑盒的页面。参数化黑盒目前是 Chisel3 的任何实验性功能,可以通过将 String 映射到 Strings 或 Ints 或 Longs 传递给 BlackBox 构造函数来使用。因此,对于您的特定情况,请尝试:

import chisel3._
import chisel3.experimental._

class IBUFDS extends BlackBox(Map("DIFF_TERM" -> "TRUE",
                                  "IOSTANDARD" -> "DEFAULT")) {
  val io = IO(new Bundle {
    val O = Output(Clock())
    val I = Input(Clock())
    val IB = Input(Clock())
  })
}

在 chisel3 中,BlackBox 没有隐式时钟或重置,端口也无法重命名,而是会使用 io Bundle 中给出的名称(不添加任何 io_)。目前也不支持模拟行为,但您可以提供 Verilog 实现并使用 Verilator 模拟您的整个设计。

现在,我们要使用 IBUFDSO 输出并将其连接到某个 Blink 模块。您不能使用子模块来否决其父模块的时钟,但可以设置子模块的时钟。因此,我可以提供一些 Top 模块来实例化 IBUFDSBlink,例如

class Blink extends Module {
  val io = IO(new Bundle {
    val led = Output(Bool())
  })
  val reg = Reg(init = false.B)
  reg := !reg
  io.led := reg
}

class Top extends Module {
  val io = IO(new Bundle {
    val clock_p = Input(Clock())
    val clock_n = Input(Clock())
    val led  = Output(Bool())
  })

  val ibufds = Module(new IBUFDS)
  ibufds.io.I := io.clock_p
  ibufds.io.IB:= io.clock_n

  val blink = Module(new Blink)
  blink.clock := ibufds.io.O
  io.led := blink.io.led   
}

此代码导致 IBUFDS 实例化如下:

IBUFDS #(.DIFF_TERM("TRUE"), .IOSTANDARD("DEFAULT")) ibufds (
  .IB(ibufds_IB),
  .I(ibufds_I),
  .O(ibufds_O)
);

我相信应该做你想做的!