Chisel入门教程

xiaoxiao2021-02-28  146

Chisel的基本概念 1、Chisel硬件表达 此版本的Chisel只支持二进制逻辑,不支持三态信号。 2、Chisel数据类型 数据类型用于指定状态元素中保存的值或wire上传输的值。  类型有SInt,UInt,Bool,Bundle,Vcc。 Bundles&Vecs  Bundle和Vec是可以允许用户使用其他数据类型来扩展Chisel数据类型集合的类。Bundle用class来定义,用户可以通过将一个类定义为Bundle的子类来定义自己的bundle。 原始类(SInt,UInt和Bool)加上聚合类(Bundles和Vecs)都继承自一个公共的超类Data。在电路中,每个最终继承自Data的对象都可以表示为一个位向量 3、组合电路 在Chisel中,电路会被表示为一张节点图。每个节点是具有零个或多个输入并驱动一个输出的硬件运算符。 Uint是一种退化类型的节点,它没有输入,并且在其输出上驱动一个恒定的值。创建和连接节点的一种方法是使用字面表达式。 eg. (a&b)|(c&d) 任何简单的表达式都可以直接转换成电路树,在叶子处使用命名的导线和操作符形成内部节点。表达式的电路输出取自树根处的运算符,在本示例中是按位或运算 3、函数 我们可以定义函数来分解一个重复的逻辑,这样可以在后续设计中重复使用。 eg. def clb(a: UInt, b: UInt, c: UInt, d: UInt): UInt = (a & b) | (~c & d) 其中clb是表示以a,b,c,d为参数的函数,并返回一个布尔电路的输出。def关键字是Scala的一部分,表示引入了一个函数定义,每个语句后面跟一个冒号,然后是它的类型,函数返回类型在参数列表之后的冒号之后。(=)符号将函数参数列表与函数定义分隔开。  然后我们就可以在其他的电路中使用了: val out = clb(a,b,c,d) 4、端口 端口用作硬件组件的接口。一个端口可以是任意的Data对象,但它是具有方向的。 Chisel提供端口构造函数,以允许在构建时给对象添加(输入或输出)。原始的端口构造函数需要将方向作为第一个参数(方向为INPUT或OUTPUT),将位数作为第二个参数(除了始终为1位的布尔值)。 eg. 端口声明如下所示 class Decoupled extends Bundle { val ready = Bool(OUTPUT) val data = UInt(INPUT, 32) val valid = Bool(INPUT) } 5、模块 我们现在可以构建电路层次,我们可以从较小的子模块开开始构建更大的模块。 Module用class来定义,继承Module。 6、状态元素 Chisel支持的状态元素的最简单形式是上升沿触发寄存器,可以实例化为: val reg  = Reg(next = in) 该电路具有输出,该输出是前一个时钟周期的输入信号产生的值。在当前版本的Chisel中,时钟和复位是全局信号,在需要时可以隐式包含。 6.1、转发声明 纯组合电路在节点之间不存在周期,如果检测到这样的周期,则Chisel将报告错误。因为它们不具有周期,所以可以总是以前馈方式构建组合电路,通过添加一些输入从已经定义的节点导出的新节点。时序电路在节点之间具有反馈,因此有时需要在生成节点被定义之前输出。因为Scala顺序执行程序语句,所以我们允许数据节点作为wire来提供节点声明,这样可以立即被使用,但其输入将稍后设置。如下例所示,在简单的CPU中,我们需要定义pcPlus4和brTarget的线,以便在定义之前引用它们: val pcPlus4 = UInt() val brTarget = UInt() val pcNext = Mux(io.ctrl.pcSel, brTarget, pcPlus4) val pcReg = Reg(next = pcNext, init = UInt(0, 32)) pcPlus4 := pcReg + UInt(4) ... brTarget := addOut 接线操作符:=用于在pcReg和addOut定义后连接。 6.2、条件更新 (1)在前面使用到寄存器的示例中,我们简单地将组合逻辑块连接到寄存器的输入。当描述状态元素的操作时,指定何时将发生寄存器更新并且用几个单独的语句指明这些更新。Chisel以when的形式提供条件更新规则,以支持这种顺序逻辑描述的风格。 val r = Reg(init = UInt(0, 16)) when (cond) { r := r + UInt(1) } 其中只有在cond为真时,才在当前时钟周期的结尾更新寄存器r。 when的参数是返回Bool值。后面的更新块只能包含使用赋值运算符:=,简单表达式和用val定义的命名引线的更新语句 (2)在条件更新序列中,条件为真的最近条件更新优先。 6.3、有限状态机 class Parity extends Module { val io = new Bundle { val in = Bool(dir = INPUT) val out = Bool(dir = OUTPUT) } val s_even :: s_odd :: Nil = Enum(UInt(), 2) val state = Reg(init = s_even) when (io.in) { when (state === s_even) { state := s_odd } when (state === s_odd) { state := s_even }  } io.out := (state === s_odd) } 其中Enum(Uint(), 2)生成两个UInt数。当io.in为true时更新状态。需要注意的是,FSM的所有机制都建立在寄存器,线和条件更新的基础上。
转载请注明原文地址: https://www.6miu.com/read-26172.html

最新回复(0)