敏捷硬件开发语言Chisel与数字系统设计 课件 第8章 函数的应用_第1页
敏捷硬件开发语言Chisel与数字系统设计 课件 第8章 函数的应用_第2页
敏捷硬件开发语言Chisel与数字系统设计 课件 第8章 函数的应用_第3页
敏捷硬件开发语言Chisel与数字系统设计 课件 第8章 函数的应用_第4页
敏捷硬件开发语言Chisel与数字系统设计 课件 第8章 函数的应用_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

8.函数的应用一、用函数抽象组合逻辑二、用工厂方法简化模块的例化三、用Scala的函数简化代码四、Chisel的打印函数五、Chisel的对数函数六、与硬件相关的函数七、隐式类的应用八、递归函数的应用九、总结目录1一、用函数抽象组合逻辑2一、用函数抽象组合逻辑在Verilog中,可以利用任务或函数,将重复性的行为级设计进行提取。与Verilog一样,在Chisel中对于频繁使用的组合逻辑电路,可以定义成Scala的函数形式,然后通过函数调用的方式来使用它。定义位置:单例对象内供多个模块使用频繁使用任务(task)Scala函数

函数(function)VerilogChisel电路模块内3moduleUseFunc(

inputclock,

inputreset,

input[3:0]io_in,

outputio_out1,

outputio_out2

);

wire_io_out1_T_4=io_in[0]&io_in[1]

assignio_out1=io_in[0]&io_in[1]|~io_in[2]&io_in[3];assignio_out2=_io_out1_T_4&(io_in[2]&io_in[3]);

endmoduleclassUseFuncextendsModule{

valio=IO(newBundle{

valin=Input(UInt(4.W))

valout1=Output(Bool())

valout2=Output(Bool())

})

defclb(a:UInt,b:UInt,c:UInt,d:UInt):UInt=

(a&b)|(~c&d)

io.out1:=clb(io.in(0),io.in(1),io.in(2),io.in(3))

io.out2:=and(and(io.in(0),io.in(1)),and(io.in(2),io.in(3)))

}

objectand{

defapply(a:UInt,b:UInt):UInt=a&b}一、用函数抽象组合逻辑定义在单例对象中定义在电路模块里直接表示函数内容而没有生成verilog的函数4二、用工厂方法简化模块的例化5二、用工厂方法简化模块的例化在Scala里,往往在类的伴生对象里定义一个工厂方法,来简化类的实例化。同样,Chisel的模块也是Scala的类,也可以在其伴生对象里定义工厂方法来简化例化、连线模块。类new例化定义工厂方法直接例化工厂方法方法调用对外隐藏了类的实现细节6二、用工厂方法简化模块的例化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)

}

objectMux2{

defapply(sel:UInt,in0:UInt,in1:UInt)={

valm=Module(newMux2)

m.io.in0:=in0

m.io.in1:=in1

m.io.sel:=sel

m.io.out

}

}classMux4extendsModule{

valio=IO(newBundle{

valsel=Input(UInt(2.W))

valin0=Input(UInt(1.W))

valin1=Input(UInt(1.W))

valin2=Input(UInt(1.W))

valin3=Input(UInt(1.W))

valout=Output(UInt(1.W))

})

io.out:=Mux2(io.sel(1),

Mux2(io.sel(0),io.in0,io.in1),

Mux2(io.sel(0),io.in2,io.in3))

}在伴生对象中定义工厂方法直接调用工厂方法例化模块7三、用Scala的函数简化代码8三、用Scala的函数简化代码只要能通过Firrtl编译器的检查,Scala的函数就能在Chisel里使用,并生成Verilog代码。因此我们可以使用Scala的函数来简化代码。classDecoder(n:Int)extendsRawModule{

valio=IO(newBundle{

valsel=Input(UInt(n.W))

valout=Output(UInt((1<<n).W))

})

valx=for(i<-0until(1<<n))yieldio.sel===i.U

//Vector(io.sel===0.U,io.sel===1.U.......)

valy=for(i<-0until(1<<n))yield1.U<<i

//Vector(1,2,4......(1<<n))

io.out:=MuxCase(0.U,xzipy)

}Chisel写法classDecoder(n:Int)extendsRawModule{

valio=IO(newBundle{

valsel=Input(UInt(n.W))

valout=Output(UInt((1<<n).W))

})

valx=for(i<-0until(1<<n))yieldio.sel===i.U

//Vector(io.sel===0.U,io.sel===1.U.......)

valy=for(i<-0until(1<<n))yield1.U<<i

//Vector(1,2,4......(1<<n))

io.out:=MuxCase(0.U,xzipy)

}Verilog写法9always@(sel)begin

if(sel==3'b000)data_out=8'h1;

elseif(sel==3'b001)data_out=8'h2;

elseif(sel==3'b010)data_out=8'h4;

elseif(sel==3'b011)data_out=8'h8;

elseif(sel==3'b100)data_out=8'h10;

elseif(sel==3'b101)data_out=8'h20;

elseif(sel==3'b110)data_out=8'h40;

elseif(sel==3'b111)data_out=8'h80;

elsedata_out=8'h80;

end四、Chisel的打印函数10四、Chisel的打印函数Chisel提供了一个“printf”函数来打印信息,用于电路调试。它具有Scala和C两种风格。注意:printf函数只能用在Chisel定义的模块中必须要有时钟和复位信号printf转换成Verilog的系统函数“$fwrite”Scala里的printf函数要写成“Predef.printf”的完整路径11四、Chisel的打印函数Chisel自定义了一个p插值器,该插值器可以对字符串内的一些自定义表达式进行求值、Chisel类型转化成字符串类型等。简单类型聚合数据类型自定义打印信息4.1Scala风格12valmyUInt=33.U

//显示Chisel自定义的类型的数据

printf(p"myUInt=$myUInt")

//显示成十六进制

printf(p"myUInt=0x${Hexadecimal(myUInt)}")

//显示成二进制

printf(p"myUInt=${Binary(myUInt)}")

//显示成字符(ASCII码)

printf(p"myUInt=${Character(myUInt)}")四、Chisel的打印函数简单数据类型//myUInt=33//myUInt=0x21//myUInt=100001//myUInt=!13valmyVec=Vec(5.U,10.U,13.U)

printf(p"myVec=$myVec")

valmyBundle=Wire(newBundle{

vala=UInt()

valb=UInt()

})

myBundle.a:=3.U

myBundle.b:=11.U

printf(p"myBundle=$myBundle")四、Chisel的打印函数聚合数据类型//myVec=Vec(5,10,13)

//myBundle=Bundle(a->3,b->11)14四、Chisel的打印函数自定义打印信息classMessageextendsBundle{

valvalid=Bool()

valaddr=UInt(32.W)

vallength=UInt(4.W)

valdata=UInt(64.W)

overridedeftoPrintable:Printable={

valchar=Mux(valid,'v'.U,'-'.U)

p"Message:\n"+

p"valid:${Character(char)}\n"+

p"addr:0x${Hexadecimal(addr)}\n"+

p"length:$length\n"+

p"data:0x${Hexadecimal(data)}\n"

}}

valmyMessage=Wire(newMessage)

myMessage.valid:=true.B

myMessage.addr:="h1234".U

myMessage.length:=10.U

myMessage.data:="hdeadbeef".U

printf(p"$myMessage")Message:Message:

valid:vMessage:

valid:v

addr:0x00001234Message:

valid:v

addr:0x00001234

length:10Message:

valid:v

addr:0x00001234

length:10

data:0x00000000deadbeefclassMessageextendsBundle{

valvalid=Bool()

valaddr=UInt(32.W)

vallength=UInt(4.W)

valdata=UInt(64.W)

overridedeftoPrintable:Printable={

valchar=Mux(valid,'v'.U,'-'.U)

p"Message:\n"+

p"valid:${Character(char)}\n"+

p"addr:0x${Hexadecimal(addr)}\n"+

p"length:$length\n"+

p"data:0x${Hexadecimal(data)}\n"

}}

valmyMessage=Wire(newMessage)

myMessage.valid:=true.B

myMessage.addr:="h1234".U

myMessage.length:=10.U

myMessage.data:="hdeadbeef".U

printf(p"$myMessage")15valmyUInt=32.U

printf("myUInt=%x",myUInt)valmyUInt=33.U

printf(p"myUInt=0x${Hexadecimal(myUInt)}")四、Chisel的打印函数4.2C风格格式控制符含义%d十进制数%x十六进制数%b二进制数%c8位ASCⅡ字符%%百分号%n一个信号的名字%N聚合类里一个叶子信号的名字转义字符含义\n换行\t制表符\"双引号\'单引号\\斜杠Scala风格C风格16格式控制符含义%d十进制数%x十六进制数%b二进制数%c8位ASCⅡ字符%%百分号%n一个信号的名字%N聚合类里一个叶子信号的名字转义字符含义\n换行\t制表符\"双引号\'单引号\\斜杠五、Chisel的对数函数17五、Chisel的对数函数在二进制运算里,求以2为底的对数也是常用的运算,chisel3.util包里有一个单例对象Log2。作用:

计算并返回输入值以2为底的幂次,返回结果向下截断apply方法:defapply(x:Bits):UIntLog2(8.U)//等于3.U

Log2(13.U)//等于3.U(向下截断)

Log2(myUIntWire)//动态求值Log2(8.U)//等于3.U

Log2(13.U)//等于3.U(向下截断)

Log2(myUIntWire)//动态求值18println(log2Floor(3))

println(log2Ceil(3))

println(log2Up(3))

println(log2Down(1))五、Chisel的对数函数chisel3.util包里还有四个单例对象:log2Ceil、log2Floor、log2Up和log2Down,它们的apply方法的参数都是BigInt类型,返回结果都是Int类型。apply方法:defapply(in:BigInt):Int对象名log2Ceillog2Floorlog2Uplog2Down作用向上舍入向下舍入向上舍入且最小为1向下舍入且最小为1122119对象名log2Ceillog2Floorlog2Uplog2Down作用向上舍入向下舍入向上舍入且最小为1向下舍入且最小为1六、与硬件相关的函数20六、与硬件相关的函数chisel3.util包中的单例对象Reverse,可以把一个UInt类型的对象进行旋转,返回一个对应的UInt值。apply方法:defapply(in:UInt):UInt6.1位旋转Reverse("b1101".U)//等于"b1011".U

Reverse("b1101".U(8.W))//等于"b10110000".U

Reverse(myUIntWire)//动态旋转Reverse("b1101".U)//等于"b1011".U

Reverse("b1101".U(8.W))//等于"b10110000".U

Reverse(myUIntWire)//动态旋转21六、与硬件相关的函数单例对象Cat有两个apply方法,分别接收一个Bits类型的序列和Bits类型的重复参数,将它们拼接成一个UInt数。前面的参数在高位。apply方法:defapply[T<:Bits](a:T,r:T*):UIntdefapply[T<:Bits](r:Seq[T]):UInt6.2位拼接Cat("b101".U,"b11".U)//等于"b10111".U

Cat(Seq("b101".U,"b11".U))//等于"b10111".U

Cat(myUIntWire0,myUIntWire1)//动态拼接Cat("b101".U,"b11".U)//等于"b10111".U

Cat(Seq("b101".U,"b11".U))//等于"b10111".U

Cat(myUIntWire0,myUIntWire1)//动态拼接22六、与硬件相关的函数单例对象PopCount有两个apply方法,分别接收一个Bits类型的参数和Bool类型的序列,计算参数里“1”或“true.B”的个数,返回对应的UInt值。apply方法:defapply(in:Iterable[Bool]):UInt

defapply(in:Bits):UInt6.31计数器PopCount(Seq(true.B,false.B,true.B,true.B))//等于3.U

PopCount(Seq(false.B,false.B,true.B,false.B))//等于1.U

PopCount("b1011".U)//等于3.U

PopCount("b0010".U)//等于1.UPopCount(Seq(true.B,false.B,true.B,true.B))//等于3.U

PopCount(Seq(false.B,false.B,true.B,false.B))//等于1.U

PopCount("b1011".U)//等于3.U

PopCount("b0010".U)//等于1.U23六、与硬件相关的函数单例对象OHToUInt可以接收一个Bits类型或Bool序列类型的独热码参数,计算独热码里的“1”在第几位(从0开始),返回对应的UInt值。apply方法:defapply(in:Seq[Bool]):UInt

defapply(in:Bits):UInt6.4独热码转换器OHToUInt("b1000".U)//等于3.U

OHToUInt(Seq(true.B,false.B))//等于1.UOHToUInt("b1000".U)//等于3.U

OHToUInt(Seq(true.B,false.B))//等于1.U24六、与硬件相关的函数Verilog里可以用问号表示无关位,那么进行比较时就不会关心这些位。Chisel里有对应的BitPat类,可以指定无关位。apply方法:defapply(n:String):BitPat6.5无关位"b10101".U===BitPat("b101??")//等于true.B

"b10111".U===BitPat("b101??")//等于true.B

"b10001".U===BitPat("b101??")//等于false.B"b10101".U===BitPat("b101??")//等于true.B

"b10111".U===BitPat("b101??")//等于true.B

"b10001".U===BitPat("b101??")//等于false.B25六、与硬件相关的函数单例对象Fill可以对输入的数据进行重复apply方法:defapply(n:Int,x:UInt):UInt6.6数据重复Fill(2,"b1000".U)//等于"b10001000".U

Fill(2,"b1001".U)//等于"b10011001".UFill(2,"b1000".U)//等于"b10001000".U

Fill(2,"b1001".U)//等于"b10011001".U26六、与硬件相关的函数单例对象FillInterleaved,它可以对输入数据的每一位进行重复apply方法:defapply(n:Int,in:Seq[Bool]):UIntdefapply(n:Int,in:UInt]):UInt6.7位重复FillInterleaved(2,Seq(true.B,false.B,false.B,false.B))//等于"b11000000".U

FillInterleaved(2,"b1000".U)//等于"b11000000".UFillInterleaved(2,Seq(true.B,false.B,false.B,false.B))

//等于"b11000000".U

FillInterleaved(2,"b1000".U)

//等于"b11000000".U27七、隐式类的应用28七、隐式类的应用在Scala中我们可以通过在某个单例对象中,以关键字“implicit”开头创建一个隐式类,从而实现隐式转换。在Chisel中我们也可以使用隐式类来构建电路。objectmyAbs{

implicitclassAbsBits[T<:Bits](in:T){

defAbs={

Mux(in.head(1).asBool,(~in).asUInt+1.U,in.asUInt())

}

}

}

classBitsAbs(n:Int)extendsModule{

valio=IO(newBundle{

valin=Input(SInt(n.W))

valout=Output(UInt(n.W))

valin2=Input(UInt(n.W))

valout2=Output(UInt(n.W))

})

importmyAbs._

io.out:=io.in.Abs

io.out2:=io.in2.Abs

printf(p"Chiselprintf:in=${io.in}out=${io.out}in2=${io.in2}out2=${io.out2}\n")

}objectmyAbs{

implicitclassAbsBits[T<:Bits](in:T){

defAbs={

Mux(in.head(1).asBool,(~in).asUInt+1.U,in.asUInt())

}

}

}

classBitsAbs(n:Int)extendsModule{

valio=IO(newBundle{

valin=Input(SInt(n.W))

valout=Output(UInt(n.W))

valin2=Input(UInt(n.W)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论