前一篇见此:

chisel快速入门(二)_沧海一升的博客-CSDN博客简单介绍了chisel,使硬件开发者能快速上手chisel。https://blog.csdn.net/qq_21842097/article/details/121418806

十四、模块的功能创建

制造用于模块构造的功能接口也是有用的。例如,我们可以构建一个构造函数,它将多路复用器输入作为参数,并返回多路复用器输出:

object Mux2 {def apply (sel: UInt, in0: UInt, in1: UInt) = {val m = new Mux2() m.io.in0 := in0 m.io.in1 := in1 m.io.sel := sel m.io.out}
}

其中对象Mux2在Mux2模块类中创建一个Scala单例对象,并且apply定义了创建Mux2实例的方法。有了这个Mux2创建功能,Mux4的规格现在明显更简单。

class Mux4 extends Module { val io = new Bundle {val in0 = UInt(INPUT, 1)val in1 = UInt(INPUT, 1) val in2 = UInt(INPUT, 1) val in3 = UInt(INPUT, 1) val sel = UInt(INPUT, 2) val out = UInt(OUTPUT, 1)}io.out := Mux2(io.sel(1), Mux2(io.sel(0), io.in0, io.in1), Mux2(io.sel(0), io.in2, io.in3))
}

选择输入非常有用,以至于 Chisel 将其内置并称之为 Mux。 然而,与上面定义的 Mux2 不同,内置版本允许 in0 和 in1 上的任何数据类型,只要它们有一个共同的超类。

Chisel提供MuxCase,其本质上是一个n-way Mux。

MuxCase(default, Array(c1 -> a, c2 -> b, ...))

十五、多态性和参数化

Scala是一种强类型语言,使用参数化类型来指定通用函数和类。 在本节中,我们展示了Chisel用户如何使用参数化类来定义自己的可重用函数和类。

1、参数化函数

前面我们在Bool上定义了Mux2,但现在我们展示如何定义一个通用的多路复用器功能。我们使用一个布尔条件和con和alt参数(对应于then和else表达式)来定义一个T类型的函数:

def Mux[T <: Bits](c: Bool, con: T, alt: T): T { ... }

其中T需要是Bits的子类。Scala确保在Mux的每个使用中,它可以找到实际的con和alt参数类型的公共超类,否则会导致Scala编译类型错误。

2、参数化类

与参数化函数一样,我们也可以参数化类,使它们可重用程度更高。例如,我们可以将Filter类概括为可以使用任何类型的链接。

我们可以通过参数化FilterIO类和定义构造函数采取零参数类型构造函数来做到这点,如下所示:

class FilterIO[T <: Data](type: T) extends Bundle { val x = type.asInput.flipval y = type.asOutput
}

我们现在可以通过定义一个模块类来定义Filter,该模块类也接收一个链接类型构造函数参数,并将其传递给FilterIO接口构造器:

class Filter[T <: Data](type: T) extends Module { val io = new FilterIO(type)...
}

另一个例子,通用FIFO可以这样定义,并使用如下:

class DataBundle extends Bundle { val A = UInt(width = 32)val B = UInt(width = 32)
}
object FifoDemo {def apply () = new Fifo(new DataBundle, 32)
}class Fifo[T <: Data] (type: T, n: Int) extends Module {val io = new Bundle {val enq_val = Bool(INPUT) val enq_rdy = Bool(OUTPUT) val deq_val = Bool(OUTPUT) val deq_rdy = Bool(INPUT) val enq_dat = type.asInput val deq_dat = type.asOutput}val enq_ptr = Reg(init = UInt(0, sizeof(n)))val deq_ptr = Reg(init = UInt(0, sizeof(n)))val is_full = Reg(init = Bool(false))val do_enq  = io.enq_rdy && io.enq_valval do_deq  = io.enq_rdy && io.deq_val val is_empty = !is_full && (enq_ptr === deq_ptr)val deq_ptr_inc = deq_ptr + UInt(1)val enq_ptr_inc = enq_ptr + UInt(1)val is_full_next = Mux(do_enq && ~do_deq && (enq_ptr_inc === deq_ptr), Bool(true), Mux(do_deq && is_full, Bool(false), is_full)) enq_ptr := Mux(do_enq, enq_ptr_inc, enq_ptr) deq_ptr := Mux(do_deq, deq_ptr_inc, deq_ptr) is_full := is_full_nextval ram = Mem(n) when (do_enq) {ram(enq_ptr) := io.enq_dat }io.enq_rdy := !is_full io.deq_val := !is_empty ram(deq_ptr) <> io.deq_dat
}

对FIFO定义通用解耦接口,可以简化IO:

class DecoupledIO[T <: Data](data: T) extends Bundle {val ready = Bool(INPUT)val valid = Bool(OUTPUT)val bits = data.clone.asOutput
}class DecoupledDemo
extends DecoupledIO()( new DataBundle )class Fifo[T <: Data] (data: T, n: Int) extends Module {val io = new Bundle {val enq = new DecoupledIO( data ).flip() val deq = new DecoupledIO( data )}...
}

十六、多时钟域

1、创建时钟域

为了使用多个时钟域,用户必须创建多个时钟。 在Chisel中,时钟是使用复位信号参数创建的第一级节点,定义如下:

class Clock (reset: Bool) extends Node { def reset: Bool // returns reset pin
}

在Chisel中有一个内置的隐式时钟,状态元素默认使用:

var implicitClock = new Clock( implicitReset )

状态元素和模块的时钟可以使用名为clock的附加命名参数来定义:

Reg(... clock: Clock = implicitClock)
Mem(... clock: Clock = implicitClock)
Module(... clock: Clock = implicitClock)

2、跨时钟域

有两种方式可以定义电路在时钟域之间发送数据。第一种也是最原始的方式就是使用由两个寄存器组成的同步器电路,如下所示:

// signalA is in clock domain clockA,
// want a version in clockB as signalB
val s1 = Reg(init = UInt(0), clock = clockB)
val s2 = Reg(init = UInt(0), clock = clockB)
s1 := signalA
s2 := s1;
signalB := s2

由于亚稳性问题,该技术只限于在域之间传递一位数据。

在域之间发送数据的第二种和更一般的方式是通过使用异步fifo:

class AsyncFifo[T<:Data](gen: T, entries: Int, enq_clk: Clock, deq_clock:Clock) extends Module

当通过指定标准fifo参数和两个时钟,然后使用标准解耦ready/valid信号从时钟域clockA到clockB获取一个版本的signalA时:

val fifo =
new AsyncFifo(Uint(width = 32), 2, clockA, clockB)
fifo.io.enq.bits := signalA
signalB := fifo.io.deq.bits
fifo.io.enq.valid := condA
fifo.io.deq.ready := condB

3、后端多时钟处理

每个 Chisel 后端都需要用户以后端特定的方式设置和控制多个时钟。 为了展示如何驱动多时钟设计,我们以具有两个模块的硬件为例进行说明,该例子使用 AsyncFifo 与不同时钟的每个模块进行通信:fastClock 和 slowClock。

在Verilog中:

  • Chisel为每个时钟/复位创建一个新端口,
  • Chisel将所有的时钟连到顶层模块
  • 用户必须要为每个时钟i创建一个always块时钟驱动
module emulator;reg fastClock = 0, slowClock = 0, resetFast = 1, resetSlow = 1; wire [31:0] add, mul, test;always #2 fastClock = ~fastClock;always #4 slowClock = ~slowClock; initial begin# 8resetFast = 0; resetSlow = 0; #400$finish;
end
ClkDomainTest dut (.fastClock(fastClock), .slowClock(slowClock), .io_resetFast(resetFast),.io_resetSlow(resetSlow),.io_add(add), .io_mul(mul), .io_test(test));
endmodule

chisel快速入门(三)相关推荐

  1. sql语言和php,SQL语言快速入门(三)_php

    我们日常使用SQL语言的工作过程中,使用最多的还是从已经建立好的数据库中查询信息.下面,我们就来详细介绍一下如何使用SQL语言实现各种数据库查询操作. SELECT-FROM 为方便讲解,我们在数据库 ...

  2. chisel快速入门(二)

    上一篇见此: chisel快速入门(一)_沧海一升的博客-CSDN博客简单介绍了chisel,使硬件开发者能快速上手chisel.https://blog.csdn.net/qq_21842097/a ...

  3. AS3多线程快速入门(三):NAPE物理引擎+Starling

    原文:http://blog.domlib.com/articles/345 [更新]Adobe在11.4正式发布的最后一刻移除了ByteArray.shareable功能的支持,推迟到11.5版本再 ...

  4. AS3多线程快速入门(三):NAPE物理引擎+Starling[译]

    原文链接:http://esdot.ca/site/2012/intro-to-as3-workers-part-3-nape-physics-starling [更新]Adobe在11.4正式发布的 ...

  5. chisel快速入门(一)

    一.概述 Chisel(Constructing Hardware In a Scala Embedded Language)是一种嵌入在高级编程语言Scala的硬件构建语言.Chisel实际上只是一 ...

  6. MySQL简单快速入门 (三)高级查询——JEPLUS软件快速开发平台

    03.SQL高级查询_分组: 1).需求:一条查询,查询出每种商品的最高价格 2).分组的命令:group by 分组字段 3).实现上例: select category_id,max(price) ...

  7. 自助分析平台(一):快速入门三种数据可视化插件

    前言 数据中台的主要工作就是输出数据指标.数据中台要对接公司内部的多条产品线,每条产品线都会定期提一些数据需求,随着数据中台和各条产品线的合作越来越紧密,每条产品线都会积累很多指标. 随着时间和产品线 ...

  8. mysql快速入门_MySQL快速入门(三)

    1. 性能优化 1.1  MySQL索引 什么是索引? 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含 着对数据表里所有记录的引用指针.更通俗的说,数据库索引好比是 ...

  9. mybatis快速入门(三)

    上面2章写了mybatis的基本操作,今天就写写mybatis的动态代理吧. 动态代理有4个基本原则: 1.userMapper.xml里面的namespace="cn.my.dao.Use ...

最新文章

  1. java何时支持await,内存-为什么Java等待这么长时间才能运行垃圾回收器?
  2. 【解决方案】OpenCV配置【Win10+VS2017】(本人于2018年3月30日完成)
  3. 1 文巾解题 191. 位1的个数
  4. springboot接收多对象_SpringBoot同时接收单个对象和List<object>参数
  5. Winform中实现设置ZedGraph的GraphPane的大小匹配ZedGraphControl
  6. python计算机基础_python计算机基础
  7. 《个体软件过程》—第1章1.1节什么是软件工程
  8. jvm的架构模型:基于栈式的架构和基于寄存器架构的特点
  9. boost::sort模块实现spreadsort 浮点函子排序示例
  10. 高斯噪声,椒盐噪声的思想及多种噪声的实现
  11. OpenCV4每日一练day13:双目相机校正
  12. spring整合quartz框架
  13. Wordpress博客首页能打开 子页打不开解决办法
  14. 杂谈异常处理try-catch-finally
  15. 计算机组成原理课题讨论——编译器对程序的影响
  16. worldpress小工具自定义html,教程 | 用 worldpress 搭建自己的博客 – 小白教程
  17. 项目管理PMBOK中各知识领域过程的关系图
  18. 成都启英泰伦科技有限公司
  19. 【项目分享】基于AB32和RT-Thread的墨水屏智能日历
  20. Multism14安装问题

热门文章

  1. 前端性能优化 Web前端应该从哪些方面来优化网站?
  2. oracle 中时间类型 date 与 long 互转
  3. 算法(伪代码)的书写
  4. 跟着别人的感觉做网络推广之二
  5. Oracle 随机获取N条数据
  6. SpringBoot、mysql配置PageHelper插件
  7. MSSQL-to-MySQL v5.3, 从MSSQL迁移到mySQL的最佳工具
  8. Django 学习资源
  9. ubuntu安装sublime
  10. hdu 5199 map或二分或哈希