【IC设计】Chisel API之Arbiter和RRArbiter的使用

介绍

仲裁器在NoC路由器中是重要的组成部分,虚通道仲裁和交叉开关仲裁都需要使用仲裁器。
Chisel提供了Arbiter和RRArbiter仲裁器
Arbiter是基础的低位优先仲裁器,
RRArbiter初始情况下也是低位优先仲裁,但在某个通道仲裁胜出后,该通道的优先级将置为最低。
举例:
假设有3个通道,0 1 2,初始情况下0优先级最高,1其次,2最低,假设1和2同时请求资源,那么根据低位优先的原则,
通道1获胜,然后优先级从高到低位0 2 1,然后0和2同时请求资源,那么通道0获胜,优先级变为2 1 0

Chisel的Valid和Ready流控

Ready-Valid接口是一种简单的控制流接口,包含:

  1. data:发送端向接收端发送的数据;
  2. valid:发送端到接收端的信号,用于指示发送端是否准备好发送数据;
  3. ready:接收端到发送端的信号,用于指示接收端是否准备好接收数据;
    在这里插入图片描述
    发送端在data准备好之后就会设置valid信号,接收端在准备好接收一个字的数据的时候就会设置ready信号。数据的传输会在两个信号,valid信号和ready信号,都被设置时才会进行。如果两个信号有任何一个没被设置,那就不会进行数据传输。
    更详细的内容参考该博客

在对RRArbiter进行测试过程中,由于仲裁器是接收数据的设备,因此valid和data是输入信号,ready是接收信号,需要对valid和data信号设置激励,并查看输出端获胜的数据。

build.sbt

程序的build.sbt配置如下:

ThisBuild / scalaVersion     := "2.13.8"
ThisBuild / version          := "0.1.0"
ThisBuild / organization     := "BATHTUB"

val chiselVersion = "3.6.0"

lazy val root = (project in file("."))
  .settings(
    name := "noc-router-main",
    libraryDependencies ++= Seq(
      "edu.berkeley.cs" %% "chisel3" % chiselVersion,
      "edu.berkeley.cs" %% "chiseltest" % "0.6.0" % "test",
      //包含ChiselTest会自动包含对应版本的ScalaTest
      //导入scalatest的库
      //"org.scalatest" %% "scalatest" % "3.1.4" % "test"
    ),
    scalacOptions ++= Seq(
      "-language:reflectiveCalls",
      "-deprecation",
      "-feature",
      "-Xcheckinit",
      "-P:chiselplugin:genBundleElements",
    ),
    addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % chiselVersion cross CrossVersion.full),
  )

RRArbiter代码示例

以下代码可以直接运行,并给出了详细注释。
输出结果:
在这里插入图片描述

//3个输入的RRArbiter官方API测试
//依次测试001~111请求下的输出数据
//初始情况下默认低位优先,在每次仲裁后,将仲裁胜利的通道置为优先级最低,进行下次仲裁
class OfficialRRArbTest extends AnyFreeSpec with ChiselScalatestTester{
  "OfficialRRArbiter should pass" in {
    test(new RRArbiter(UInt(8.W), 3)).withAnnotations(Seq(WriteVcdAnnotation)) { c =>
      //第一次测试 此时从高到低优先级为0 1 2 通道0发起请求
      c.io.in(0).valid.poke(true.B)
      c.io.in(1).valid.poke(false.B)
      c.io.in(2).valid.poke(false.B)

      //假设在全部测试中通道0的数据为0 通道1的数据为1 通道2的数据为2
      c.io.in(0).bits.poke(0)
      c.io.in(1).bits.poke(1)
      c.io.in(2).bits.poke(2)
      c.io.out.ready.poke(true.B)
      c.clock.step(2)
      //初始状态下接收端已准备好接受in(0),in(1),in(2)  因此ready均为1
      //println(s"${c.io.in(0).ready.peek().litValue},${c.io.in(1).ready.peek().litValue},${c.io.in(2).ready.peek().litValue}")
      //通道0获胜,输出0
      println(s"1\t out.valid=${c.io.out.valid.peek().litValue}, out.bits=${c.io.out.bits.peek().litValue}\n")

      //第二次测试  此时优先级从高到低为1 2 0 通道1发起请求
      c.io.in(0).valid.poke(false.B)
      c.io.in(1).valid.poke(true.B)
      c.io.in(2).valid.poke(false.B)
      c.clock.step(2)
      //通道1获胜,输出1
      println(s"2\t out.valid=${c.io.out.valid.peek().litValue}, out.bits=${c.io.out.bits.peek().litValue}\n")

      //第三次测试  此时优先级从高到低为2 0 1 通道0和1发起请求
      c.io.in(0).valid.poke(true.B)
      c.io.in(1).valid.poke(true.B)
      c.io.in(2).valid.poke(false.B)
      c.clock.step(2)
      //通道0获胜,输出0
      println(s"3\t out.valid=${c.io.out.valid.peek().litValue}, out.bits=${c.io.out.bits.peek().litValue}\n")

      //第四次测试  此时优先级从高到低为2 1 0 通道2发起请求
      c.io.in(0).valid.poke(false.B)
      c.io.in(1).valid.poke(false.B)
      c.io.in(2).valid.poke(true.B)
      c.clock.step(2)
      //通道2获胜,输出2
      println(s"4\t out.valid=${c.io.out.valid.peek().litValue}, out.bits=${c.io.out.bits.peek().litValue}\n")

      //第五次测试  此时优先级从高到低为1 0 2 通道0和2发起请求
      c.io.in(0).valid.poke(true.B)
      c.io.in(1).valid.poke(false.B)
      c.io.in(2).valid.poke(true.B)
      c.clock.step(2)
      //通道0获胜,输出0
      println(s"5\t out.valid=${c.io.out.valid.peek().litValue}, out.bits=${c.io.out.bits.peek().litValue}\n")

      //第六次测试 此时优先级从高到低为1 2 0 通道1和2发起请求
      c.io.in(0).valid.poke(false.B)
      c.io.in(1).valid.poke(true.B)
      c.io.in(2).valid.poke(true.B)
      c.clock.step(2)
      //通道1获胜,输出1
      println(s"6\t out.valid=${c.io.out.valid.peek().litValue}, out.bits=${c.io.out.bits.peek().litValue}\n")

      //第七次测试 此时优先级从高到低为2 0 1 通道2、0、1发起请求
      c.io.in(0).valid.poke(true.B)
      c.io.in(1).valid.poke(true.B)
      c.io.in(2).valid.poke(true.B)
      c.clock.step(2)
      //通道2获胜,输出2
      println(s"7\t out.valid=${c.io.out.valid.peek().litValue}, out.bits=${c.io.out.bits.peek().litValue}\n")
    }
  }
}
  • 22
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Chisel 是一种基于 Scala 语言的硬件描述语言,它支持硬件描述与数字系统设计。与传统的硬件描述语言相比,Chisel 使用了更加现代化的语法结构,使得数字系统的设计更加简洁、灵活。Chisel 与数字系统设计 pdf 的关系在于,它可以帮助工程师们在数字系统设计过程中更加高效地进行开发,提高设计的灵活性和可重用性。 Chisel 语言的特点之一是支持硬件生成,这意味着它能够生成 Verilog 或者 VHDL 代码,从而可以与现有的数字系统设计工具兼容,同时也可以很好地与其他硬件描述语言一起协同工作。此外,Chisel 还提供了更加强大的抽象能力,支持参数化的模块化设计,从而可以更加高效地进行硬件设计和验证。 数字系统设计 pdf 是一本介绍数字系统设计原理和实践的教材,它包含了数字系统设计的基本概念、原理和方法。Chisel 与数字系统设计 pdf 的关系在于,它可以作为一种工具,帮助读者更好地理解和应用数字系统设计的知识。通过使用 Chisel 进行硬件描述和设计,读者可以在实践中加深对数字系统设计 pdf 中所学内容的理解,并将其应用到实际的硬件开发项目中去。 总的来说,Chisel 语言与数字系统设计 pdf 有着密切的关系,它们可以相互促进,帮助工程师和学习者更加高效地进行数字系统设计和开发。通过掌握 Chisel 语言并结合数字系统设计 pdf 的知识,可以使数字系统设计的学习和实践变得更加顺畅和高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

农民真快落

我琢磨着也没人给我打赏呀。。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值