如何将重置添加到队列凿类

时间:2018-09-13 07:03:19

标签: chisel

我正在尝试使用凿子Queue类,并希望能够在重置时刷新它。 过去似乎在Class构造函数中有一个重置选项

@deprecated("Module constructor with override _reset deprecated, use withReset", "chisel3")
  def this(gen: T, entries: Int, pipe: Boolean, flow: Boolean, _reset: Bool)

但是,由于弃用消息暗示我应该使用withReset。 我该怎么办?
这与3年前的question类似,但答案建议使用_reset argumnet,现已弃用。

2 个答案:

答案 0 :(得分:3)

该弃用方法是指withReset。可以在here中找到(Spartan)API文档,并在here中找到源代码。此外,在Chisel3 Wiki上有多个时钟域的讨论,提供了一些示例用法。

这些方法使您可以更改在代码块中使用的时钟,重置或时钟和重置。如果您想更改使用哪个重置,将执行以下操作:

import chisel3.experimental.withReset
// ...

  withReset(myReset) {
    // Anything in here will be reset to myReset
  }

有关更详细的示例,MultiClockSpec测试提供了一些具体示例。参见:src/test/scala/chiselTests/MultiClockSpec.scala

答案 1 :(得分:2)

我设法刷新了异步fofo(凿2代码),并使用特殊队列将其重写,如下所示:

class QueueIOFlush[T <: Data](gen: T, entries: Int) extends Bundle {
  val enq   = Decoupled(gen.cloneType).flip
  val deq   = Decoupled(gen.cloneType)
  val count = UInt(OUTPUT, log2Up(entries + 1))
  val flush = Bool(INPUT)
}

/** Asynchronous Fifo. Used to cross two clock domains.
 *
 * @param T the data to transmit
 * @param entries size of fifo. The actual size will be
 *                arrounded in the upper 2^n (size = 1<<log2Up(entries))
 * @param enq_clk clock for the writing side (input)
 * @param deq_clk clock for the reading side (output)
 */
class AsyncFifoFlushable[T<:Data](gen: T,
                                  entries: Int,
                                  enq_clk: Clock = null,
                                  deq_clk: Clock) extends Module(enq_clk) {
  val io = new QueueIOFlush(gen, entries)
  val asize = log2Up(entries)

  val s1_rptr_gray = Reg(init=UInt(0, asize+1), clock=enq_clk)
  val s2_rptr_gray = Reg(init=UInt(0, asize+1), clock=enq_clk)
  val s1_rst_deq = Reg(init=Bool(false), clock=enq_clk)
  val s2_rst_deq = Reg(init=Bool(false), clock=enq_clk)

  val s1_wptr_gray = Reg(init=UInt(0, asize+1), clock=deq_clk)
  val s2_wptr_gray = Reg(init=UInt(0, asize+1), clock=deq_clk)
  val s1_rst_enq = Reg(init=Bool(false), clock=deq_clk)
  val s2_rst_enq = Reg(init=Bool(false), clock=deq_clk)

  val s1_flush = Reg(init=Bool(false), clock=enq_clk)
  val s2_flush = Reg(init=Bool(false), clock=enq_clk)

  val slow_flush = Reg(init=Bool(false), clock=deq_clk)

  val wptr_bin = Reg(init=UInt(0, asize+1), clock=enq_clk)
  val wptr_gray = Reg(init=UInt(0, asize+1), clock=enq_clk)
  val not_full = Reg(init=Bool(false), clock=enq_clk)

  val wptr_bin_next = wptr_bin + (io.enq.valid & not_full)
  val wptr_gray_next = (wptr_bin_next >> UInt(1)) ^ wptr_bin_next
  val not_full_next = !(wptr_gray_next === Cat(~s2_rptr_gray(asize,asize-1),
                                               s2_rptr_gray(asize-2,0)))

  val rptr_bin = Reg(init=UInt(0, asize+1), clock=deq_clk)
  val rptr_gray = Reg(init=UInt(0, asize+1), clock=deq_clk)
  val not_empty = Reg(init=Bool(false), clock=deq_clk)

  val rptr_bin_next = rptr_bin + (io.deq.ready & not_empty)
  val rptr_gray_next = (rptr_bin_next >> UInt(1)) ^ rptr_bin_next
  val not_empty_next = !(rptr_gray_next === s2_wptr_gray)

  s2_rptr_gray := s1_rptr_gray; s1_rptr_gray := rptr_gray
  s2_rst_deq := s1_rst_deq; s1_rst_deq := enq_clk.getReset
  s2_wptr_gray := s1_wptr_gray; s1_wptr_gray := wptr_gray
  s2_rst_enq := s1_rst_enq; s1_rst_enq := deq_clk.getReset

  s1_flush := io.flush; s2_flush := s1_flush;

  /* flush read pointer (deqclk) */
  slow_flush := io.flush
  when(slow_flush) {
    rptr_bin := UInt(0, rptr_bin.getWidth())
  }.otherwise{
    rptr_bin := rptr_bin_next
  }

  /* flush write pointer (enqclk) */
  when(s2_flush) {
    wptr_bin := UInt(0, wptr_bin.getWidth())
  }.otherwise{
    wptr_bin := wptr_bin_next
  }

  wptr_gray := wptr_gray_next
  not_full := not_full_next && !s2_rst_deq

  rptr_gray := rptr_gray_next
  not_empty := not_empty_next && !s2_rst_enq

  io.enq.ready := not_full
  io.deq.valid := not_empty

  val mem = Mem(gen, 1 << asize, clock=enq_clk)
  when (io.enq.valid && io.enq.ready) {
    mem(wptr_bin(asize-1,0)) := io.enq.bits
  }
  io.deq.bits := mem(rptr_bin(asize-1,0))
}