版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
3.模块与硬件类型一、硬件类型二、赋值三、端口四、模块五、线网六、寄存器(组)七、补充与总结2目
录一、硬件类型3
硬件类型
Chisel的数据类型是无法独立工作的,实际的电路应该是由硬件类型的对象构成的硬件类型完成:信号的声明、用赋值进行信号传递valx=Wire(UInt(4.W))数据类型对象作为参数定义:位宽是多少、按无符号数还是有符号数解释、是不是向量valx=Wire(UInt(4.W))4二、赋值5赋值首次创建变量时用赋值运算符“=”初始化valx=Wire(UInt(4.W))
valy=Wire(UInt(4.W))
x:="b1010".U
//向4bit的线网x赋予了无符号数10
y:=~x
//把x按位取反,传递给y
驱动该端口时,就需要通过变量名来进行赋值操作,使用方法“:=”作为赋值运算符“=”的代替“:=”优先级与“=”一致,是最低的6三、端口7端口3.1定义端口列表端口列表是由方法“IO[T<:Data](iodef:T)”定义参数通常是一个Bundle类型的对象而且引用的字段名称必须是“io”(继承自Module的模块)8端口通过“io.xxx”来使用端口从性质上来说它仍然属于组合逻辑的线网3.2端口方向classMyIOextendsBundle{
valin=Input(Vec(5,UInt(32.W)))
valout=Output(UInt(32.W))
}
classMyModuleextendsModule{
valio=IO(newMyIO)
//模块的端口列表
......
}端口存在方向,需要方法“Input[T<:Data](source:T)”和“Output[T<:Data](source:T)”来为每个端口表明具体方向9端口3.3翻转端口列表的方向使用情况:
对于两个相连的模块,可能存在大量同名但方向相反的端口方法:Flipped[T<:Data](source:T)实现细节
其把参数里所有的输入端口转为输出端口,输出端口转为输入端口
10端口classMyIOextendsBundle{
valin=Input(Vec(5,UInt(32.W)))
valout=Output(UInt(32.W))
}
classMyModule_1extendsModule{
valio=IO(newMyIO)
//in是输入,out是输出
......
}
classMyModule_2extendsModule{
valio=IO(Flipped(newMyIO))
//in是输出,out是输入
......
}11MyModule_1inoutMyModule_2inout端口3.4端口整体连接使用整体连接符号“<>”该操作符会把符号左右两边的端口列表里所有同名的端口进行连接
同一级的模块的端口方向必须是输入连输出、输出连输入;父级模块和子级模块的端口方向则是输入连输入、输出连输出不能存在端口名字、数量、类型不同的情况classMyIOextendsBundle{
valin=Input(Vec(5,UInt(32.W)))
valout=Output(UInt(32.W))
}
classMyModuleextendsModule{
valio=IO(newBundle{
valx=newMyIO
valy=Flipped(newMyIO)
})
io.x<>io.y
//相当于io.y.in:=io.x.in;
//io.x.out:=io.y.out
}12四、模块134.1模块的分类Module/LegacyModuleChisel的模块分为三类,继承关系如下(箭头指向父类)MultiIOModuleRawModule必须实现抽象成员io有隐式时钟(称为clock)和隐式复位(称为reset)123模块根据需要定义IO无抽象成员io不提供隐式时钟和复位根据需要定义IO无抽象成员io有隐式时钟和复位144.2定义模块模块继承自Module类包含一个用于接口的抽象字段“io”在类的主构造器里进行内部电路连线//mux2.scala
packagetest
importchisel3._
classMux2extendsModule{
valio=IO(newBundle{
valsel=Input(UInt(1.W))
valin0=Input(UInt(1.W))
valin1=Input(UInt(1.W))
valout=Output(UInt(1.W))
})
io.out:=(io.sel&io.in1)|(~io.sel&io.in0)
}“newBundle{...}”是声明一个继承自Bundle的匿名类,然后实例化该匿名类。定义一个二选一多路选择器:15模块4.3例化模块//mux4.scala
packagetest
importchisel3._
classMux4extendsModule{
valio=IO(newBundle{
valin0=Input(UInt(1.W))
valin1=Input(UInt(1.W))
valin2=Input(UInt(1.W))
valin3=Input(UInt(1.W))
valsel=Input(UInt(2.W))
valout=Output(UInt(1.W))
})
valm0=Module(newMux2)
m0.io.sel:=io.sel(0)
m0.io.in0:=io.in0
m0.io.in1:=io.in1
valm1=Module(newMux2)
m1.io.sel:=io.sel(0)
m1.io.in0:=io.in2
m1.io.in1:=io.in3
valm2=Module(newMux2)
m2.io.sel:=io.sel(1)
m2.io.in0:=m0.io.out
m2.io.in1:=m1.io.out
io.out:=m2.io.out
}例化一个模块,要把实例对象传递给单例对象Module的apply方法通过例化刚才的双输入多路选择器构建四输入多路选择器:16模块4.4例化多个模块对于要多次例化的重复模块,可以利用向量的工厂方法VecInit[T<:Data]通常使用待例化模块的io字段组成的序列作为参数://mux4_2.scala
packagetest
importchisel3._
classMux4_2extendsModule{
valio=IO(newBundle{
valin0=Input(UInt(1.W))
valin1=Input(UInt(1.W))
valin2=Input(UInt(1.W))
valin3=Input(UInt(1.W))
valsel=Input(UInt(2.W))
valout=Output(UInt(1.W))
})17模块生成序列的方法:
调用单例对象Seq里的方法fill,该方法的一个重载版本有两个单参数列表,第一个参数接收Int类型的对象,表示序列的元素个数,第二个是传名参数,接收序列的元素。
valm=VecInit(Seq.fill(3)(Module(newMux2).io))
//例化了三个Mux2,并且参数是端口字段io
m(0).sel:=io.sel(0)//模块的端口通过下标索引,并且路径里没有“io”
m(0).in0:=io.in0
m(0).in1:=io.in1
m(1).sel:=io.sel(0)
m(1).in0:=io.in2
m(1).in1:=io.in3
m(2).sel:=io.sel(1)
m(2).in0:=m(0).out
m(2).in1:=m(1).out
io.out:=m(2).out
}18五、线网19线网classMyModuleextendsModule{
valio=IO(newBundle{
valin=Input(UInt(8.W))
})
valmyNode=Wire(UInt(8.W))
myNode:=0.U;//无效
myNode:=io.in+1.U;
}通过工厂方法“Wire[T<:Data](t:T)”来定义线网可以对线网进行赋值,也可以把线网连接到其他电路节点,线网是组成组合逻辑的基本硬件类型。定义具有覆盖性,对同一个线网多次赋值,则只有最后一次赋值是有效的5.1Wire20Wire不提供位宽参数将启用自动推断。官方源代码注释:valw0=Wire(UInt())//widthisinferred
valw1=Wire(UInt(8.W))//widthissetto8
valw2=Wire(Vec(4,UInt()))//widthisinferred
valw3=Wire(Vec(4,UInt(8.W)))//widthofeachelementissetto8
classMyBundle{
valunknown=UInt()
valknown=UInt(8.W)
}
valw4=Wire(newMyBundle)
//Widthofw4.unknownisinferred
//Widthofw4.knownissetto821WireDefault例1:Non-LiteralElementinitializer-widthwillbeinferred对于non-literalchisel3.Bits,导线的宽度将被推断。WireDefault用于构建具有默认连接的硬件线路有单参数和多参数两种形式。
单参数使用参数来指定类型和默认连接:valx=Wire(UInt())
valy=Wire(UInt(8.W))
valw1=WireDefault(x)//widthwillbeinferred
valw2=WireDefault(y)//widthwillbeinferred5.2WireDefault22WireDefault例3:Aggregateinitializer:widthwillbesettomatchtheaggregate例2:Literalchisel3.Bitsinitializer:widthwillbesettomatch对于literalchisel3.Bits和所有非Bits参数,类型将从参数复制。valw1=WireDefault(1.U)//widthwillbeinferredtobe1
valw2=WireDefault(1.U(8.W))//widthissetto8classMyBundle{
valunknown=UInt()
valknown=UInt(8.W)
}
valw1=Wire(newMyBundle)
valw2=WireDefault(w1)
//Widthofw2.unknownisinferred
//Widthofw2.knownissetto823WireDefault带有两个参数的WireDefault的宽度推断语义与Wire的相匹配。WireDefault的第一个参数是类型模板,它定义了Wire的宽度,其方式与Wire的参数完全相同。其定义类似于:
双参数形式允许独立指定Wire的类型和默认连接。defWireDefault[T<:Data](t:T,init:T):T={
valx=Wire(t)
x:=init
x
}vala=Wire(UInt(8.W))
valb=WireDefault(UInt(10.W),a)wire[7:0]a;
wire[9:0]b={{2'd0},a};24六、寄存器(组)25寄存器6.1RegChisel有五种内建的寄存器,Reg、RegNext、RegInit、util包里的RegEnable和ShiftRegister普通的寄存器“Reg[T<:Data](t:T):T”可以在when语句里用全局reset信号进行同步复位(asBool),也可以进行条件赋值或无条件跟随入参必须是数据类型的对象26寄存器和Wire的构造方式非常类似valr0=Reg(UInt())//widthisinferred
valr1=Reg(UInt(8.W))
//widthissetto8
valr2=Reg(Vec(4,UInt()))
//widthisinferred
valr3=Reg(Vec(4,UInt(8.W)))
//widthofeachelementissetto8
classMyBundle{
valunknown=UInt()
valknown=UInt(8.W)
}
valr4=Reg(newMyBundle)
//Widthofr4.unknownisinferred
//Widthofr4.knownissetto827寄存器6.2RegNextvalfoo=Reg(UInt(4.W))//widthis4
valbar=RegNext(foo)//widthisunset
valfoo=Reg(UInt(4.W))//widthis4
valbar=Reg(chiselTypeOf(foo))
//widthis4
bar:=foo
classMyBundleextendsBundle{
valx=UInt(4.W)
}
valfoo=Wire(newMyBundle)
//thewidthoffoo.xis4
valbar=RegNext(foo)
//thewidthofbar.xis4“RegNext[T<:Data](next:T)”,没有复位信号另一个版本的apply工厂方法是“RegNext[T<:Data](next:T,init:T)”,是由复位信号控制RegNext经常用于构造延迟一个周期的信号。28寄存器例1:Non-LiteralElementinitializer-widthwillbeinferred对于non-literalchisel3.Bits、Reg的宽度将被推断6.3RegInit
复位到指定值的寄存器RegInit,也有两种构造方式:“RegInit[T<:Data](init:T)”“RegInit[T<:Data](t:T,init:T)”
单参数形式使用参数来指定类型和重置值valx=Wire(UInt())
valy=Wire(UInt(8.W))
valr1=RegInit(x)//widthwillbeinferred
valr2=RegInit(y)//widthwillbeinferred29寄存器例3:Aggregateinitializer:widthwillbesettomatchtheaggregate例2:Literalchisel3.Bitsinitializer:widthwillbesettomatch对于literalchisel3.Bits和所有非Bits参数,类型将从参数复制。valr1=RegInit(1.U)//widthwillbeinferredtobe1
valr2=RegInit(1.U(8.W))//widthissetto8classMyBundleextendsBundle{
valunknown=UInt()
valknown=UInt(8.W)
}
valw1=Reg(newMyBundle)
valw2=RegInit(w1)
//Widthofw2.unknownisinferred
//Widthofw2.knownissetto830寄存器带有两个参数的RegInit的宽度推断语义与Reg的宽度推断语义相匹配。RegInit的第一个参数是类型模板,它定义Reg的宽度的方式与Wire的完全相同。其定义类似于:defRegInit[T<:Data](t:T,init:T):T={
valx=Reg(t)
x:=init
x
}
双参数形式允许独立指定Reg的类型和默认连接。31第一个apply方法,不进行复位初始化。例:寄存器6.4RegEnableobjectRegEnable{
defapply[T<:Data]
(next:T,enable:Bool):T=
{
valr=Reg(chiselTypeOf(next))
when(enable){r:=next}
r
}
defapply[T<:Data]
(next:T,init:T,enable:Bool):T=
{
valr=RegInit(init)
when(enable){r:=next}
r
}
}valregWithEnableAndReset=RegEnable(nextVal,ena)valregWithEnableAndReset=RegEnable(nextVal,0.U,ena)第二个apply方法,进行复位初始化。例:32寄存器6.5ShiftRegister“ShiftRegister[T<:Data](in:T,n:Int,resetData:T,en:Bool)”第一个参数in是待移位的数据,第二个参数n是需要延迟的周期数,第三个参数resetData是指定的复位值,可以省略,第四个参数en是移位的使能信号,默认为true.B,也是通过两个apply方法实现的valregDelayTwo=ShiftRegister(nextVal,2,ena)valregDelayTwoReset=ShiftRegister(nextVal,2,0.U,ena)33寄存器使用withClockAndReset来构造异步时钟和异步复位信号,也可以用withClock和withReset单独控制异步时钟或异步复位信号classasyncRegextendsModule{
valio=IO(newBundle{
valasyncClk=Input(UInt(1.W))
valasyncRst=Input(UInt(1.W))
valout=Output(UInt(8.W))
})
valasyncRegInit=withClockAndReset(io.asyncClk.asBool().asClock(),
io.asyncRst.asBool().asAsyncReset())(RegInit(0.U(8.W)))
asyncRegInit:=asyncRegInit+1.U
io.out:=asyncRegInit
}6.6异步寄存器34寄存器如果把子类型Vec[T]作为参数传递进去,就会生成多个位宽相同、行为相同、名字前缀相同的寄存器。同样,寄存器组在Chisel代码里可以通过下标索引。
valreg0=RegNext(VecInit(io.a,io.a))
valreg1=RegNext(VecInit(io.a,io.a),VecInit(0.U,0.U))
valreg2=RegInit(VecInit(0.U(8.W),0.U(8.W)))
valreg3=Reg(Vec(2,UInt(8.W)))
valreg4=Reg(Vec(2,UInt(8.W)))
valreg5=RegEnable(VecInit(io.a+1.U,io.a+1.U),VecInit(0.U(8.W),0.U(8.W)),io.en)
valreg6=RegEnable(VecInit(io.a-1.U,io.a-1.U),io.en)6.7寄存器组35寄存器valreg7=ShiftRegister(VecInit(io.a,io.a),3,VecInit(0.U(8.W),0.U(8.W)),io.en)
valreg8=ShiftRegister(VecInit(io.a,io.a),3,io.en)
reg2(0):=io.a.andR
reg2(1):=io.a.andR
reg3(0):=io.a.orR
reg3(1):=io.a.orR
when(reset.asBool){
reg4(0):=0.U
reg4(1):=0.U
}.otherwise{
reg4(0):=1.U
reg4(1):=1.U
}36七、补充与总结37补充与总结7.1when条件赋值由于Scala已经占用了“if…elseif…else”语法,所以相应的Chisel控制结构改成了when语句,其语法如下:所有的判断条件都是返回Bool类型的传名参数,不要和Scala的Boolean类型混淆,也不存在Boolean和Bool之间的相互转换。对于UInt、SInt和Reset类型,可以用方法asBool转换成Bool类型来作为判断条件。when(condition1){definition1}
.elsewhen(condition2){definition2}
...
.elsewhen(conditionN){definitionN}
.otherwise{defaultbehavior}38补充与总结//mux2_when.scala
packagetest
importchisel3._
classMux2extendsModule{
valio=IO(newBundle{
valsel=Input(UInt(1.W))
valin0=Input(UInt(1.W))
valin1=Input(UInt(1.W))
valout=Output(UInt(1.W))
})
when(io.sel===1.U){
io.out:=io.in1
}.otherwise{
io.out:=io.in0
}
}通常,when用于给带使能信号的寄存器更新数据,组合逻辑不常用。对于有复位信号的寄存器,推荐使用RegInit来声明用when实现一个二选一多路选择器:39unlessimportchisel3.util._
unless(condition){definition}除了when结构,util包里还有一个与之对偶的结构“unless”,如果unless的判定条件为false.B,则一直执行,否则不执行7.2unless40总结数据类型必须配合硬件类型才能使用,它不能独立存在,因为编译器只会把硬件类型生成对应的Verilog代码。这是因为方法Vec期望第二个参数是数据类型,这样它才
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 外贸出口代理协议(2025年退税服务)
- 土地租赁合同(长期租赁2025年)
- 2026年安徽警官职业学院单招综合素质考试备考试题带答案解析
- 2026年广东机电职业技术学院高职单招职业适应性测试参考题库有答案解析
- 投资合同协议2025年
- 2026年福建卫生职业技术学院单招综合素质笔试备考题库带答案解析
- 2026年甘肃钢铁职业技术学院高职单招职业适应性测试备考题库有答案解析
- 2026年福建幼儿师范高等专科学校单招职业技能笔试备考题库带答案解析
- 2026年包头轻工职业技术学院高职单招职业适应性测试备考试题有答案解析
- 2026年抚州职业技术学院高职单招职业适应性考试参考题库带答案解析
- 猥亵私了协议书
- 《种子里孕育着新生命》课件
- 公司文件存储管理办法
- 即食鲜切果蔬制作服务规范(食品经营者)
- 船闸环保监理工作报告
- 工伤医疗垫付协议书
- 原发性肺癌诊疗指南2022版
- 《磁控溅射镀膜》课件
- 机械制造技术基础试题大全试题库历年考题带答案
- 天车维修协议书范本
- 甘蔗砍伐合同协议
评论
0/150
提交评论