1

在 Chisel 文档中,我们有一个上升沿检测方法的示例,定义如下:

      def risingedge(x: Bool) = x && !RegNext(x)

我的 github项目 blp上提供了所有示例代码。

如果我在声明如下的输入信号上使用它:

class RisingEdge extends Module {
  val io = IO(new Bundle{
    val sclk = Input(Bool())
    val redge = Output(Bool())
    val fedge = Output(Bool())
  })

  // seems to not work with icarus + cocotb
  def risingedge(x: Bool) = x && !RegNext(x)
  def fallingedge(x: Bool) = !x && RegNext(x)
  // works with icarus + cocotb
  //def risingedge(x: Bool) = x && !RegNext(RegNext(x))
  //def fallingedge(x: Bool) = !x && RegNext(RegNext(x))

  io.redge :=  risingedge(io.sclk)
  io.fedge := fallingedge(io.sclk)
}

有了这个 icarus/cocotb 测试平台:

class RisingEdge(object):
    def __init__(self, dut, clock):
        self._dut = dut
        self._clock_thread = cocotb.fork(clock.start())

    @cocotb.coroutine
    def reset(self):
        short_per = Timer(100, units="ns")
        self._dut.reset <= 1
        self._dut.io_sclk <= 0
        yield short_per
        self._dut.reset <= 0
        yield short_per

@cocotb.test()
def test_rising_edge(dut):
    dut._log.info("Launching RisingEdge test")
    redge = RisingEdge(dut, Clock(dut.clock, 1, "ns")) 
    yield redge.reset()
    cwait = Timer(10, "ns")
    for i in range(100):
        dut.io_sclk <= 1
        yield cwait
        dut.io_sclk <= 0
        yield cwait

我永远不会在 io.redge 和 io.fedge 上获得上升脉冲。要获得脉冲,我必须将上升沿的定义更改如下:

  def risingedge(x: Bool) = x && !RegNext(RegNext(x))

使用双 RegNext() : 双 RegNext 截图

使用简单的 RegNext() : 简单的 RegNext 截图

这是正常行为吗?

[编辑:我用上面给出的 github 示例修改了源示例]

4

2 回答 2

3

我不确定 Icarus,但使用默认的 Treadle 模拟器进行这样的测试。

class RisingEdgeTest extends FreeSpec {
  "debug should toggle" in {
    iotesters.Driver.execute(Array("-tiwv"), () => new SlaveSpi) { c =>
      new PeekPokeTester(c) {
        for (i <- 0 until 10) {
          poke(c.io.csn, i % 2)
          println(s"debug is ${peek(c.io.debug)}")
          step(1)
        }
      }
    }
  }
}

我看到了输出

[info] [0.002] debug is 0
[info] [0.002] debug is 1
[info] [0.002] debug is 0
[info] [0.003] debug is 1
[info] [0.003] debug is 0
[info] [0.003] debug is 1
[info] [0.004] debug is 0
[info] [0.004] debug is 1
[info] [0.005] debug is 0
[info] [0.005] debug is 1

波形看起来像 在此处输入图像描述

你能解释一下你认为这应该是什么样子吗?

于 2019-09-10T15:35:02.210 回答
1

不要在时钟上升沿改变模块输入值。

好的,我发现了我的错误。在 cocotb 测试台中,我在同步时钟的同一边沿上切换了输入值。如果我们这样做,输入会在 D-Latch 的设置时间下准确地修改,那么行为是未定义的!

然后,问题是 cocotb 测试台错误而不是 Chisel 错误。为了解决这个问题,我们只需要改变时钟边缘来切换像它这样的值:

@cocotb.test()
def test_rising_edge(dut):
    dut._log.info("Launching RisingEdge test")
    redge = RisingEdge(dut, Clock(dut.clock, 1, "ns")) 
    yield redge.reset()
    cwait = Timer(4, "ns")
    yield FallingEdge(dut.clock) #   <--- 'synchronize' on falling edge
    for i in range(5):
        dut.io_sclk <= 1
        yield cwait
        dut.io_sclk <= 0
        yield cwait
于 2019-09-19T11:36:40.213 回答