敏捷硬件开发语言Chisel与数字系统设计 课件 第7章 多时钟域设计_第1页
敏捷硬件开发语言Chisel与数字系统设计 课件 第7章 多时钟域设计_第2页
敏捷硬件开发语言Chisel与数字系统设计 课件 第7章 多时钟域设计_第3页
敏捷硬件开发语言Chisel与数字系统设计 课件 第7章 多时钟域设计_第4页
敏捷硬件开发语言Chisel与数字系统设计 课件 第7章 多时钟域设计_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

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

文档简介

7.多时钟域设计一、没有隐式端口的模块二、定义一个时钟域和复位域三、使用时钟负沿和低有效复位四、示例:异步FIFO五、总结目录1一、没有隐式端口的模块2一、没有隐式端口的模块1.1RawModule继承自Module的模块类会获得隐式的全局时钟与同步复位信号,当我们不需要这两个隐式端口时,则可以选择继承自RawModule,这样在转换成Verilog时就没有隐式端口。3ModuleRawModule时钟隐式时钟无复位信号隐式同步复位无没有隐式端口的模块例子:含隐式端口importchisel3._

importchisel3.experimental._

importchisel3.stage.ChiselGeneratorAnnotation

classMyModuleextendsModule{

valio=IO(newBundle{

vala=Input(UInt(4.W))

valb=Input(UInt(4.W))

valc=Output(UInt(4.W))

})

io.c:=io.a&io.b

}moduleMyModule(

inputclock,

inputreset,

input[3:0]io_a,

input[3:0]io_b,

output[3:0]io_c

);

assignio_c=io_a&io_b;//@[MyRawModule.scala14:16]

endmodule一、没有隐式端口的模块4没有隐式端口的模块例子:无隐式端口importchisel3._

importchisel3.experimental._

importchisel3.stage.ChiselGeneratorAnnotation

classMyRawModuleextendsRawModule{

valio=IO(newBundle{

vala=Input(UInt(4.W))

valb=Input(UInt(4.W))

valc=Output(UInt(4.W))

})

io.c:=io.a&io.b

}moduleMyRawModule(

input[3:0]io_a,

input[3:0]io_b,

output[3:0]io_c

);

assignio_c=io_a&io_b;//@[MyRawModule.scala14:16]

endmodule一、没有隐式端口的模块5一、没有隐式端口的模块1.1RawModule这样的模块一般用于纯组合逻辑。由于其不再有隐式的时钟和复位信号,因此在其类内顶层不能出现使用时钟的相关操作。RawModule子类纯组合逻辑多时钟域语法时序逻辑6二、定义一个时钟域和复位域72.1withClockAndReset作用:创建一个新的时钟和复位域,作用范围仅限于它的传名参数的内部apply方法:defapply[T](clock:Clock,reset:Reset)(block:⇒T):T二、定义一个时钟域和复位域withClockAndReset是chisel3包里的一个单例对象8在Verilog中:定义时钟和复位信号的端口在always语句块中进行相应选择modulea(

inputclk,

inputrst_n

);

always(posedgeclkornegedgerst_n)

begin新的时钟和复位信号2.1withClockAndReset二、定义一个时钟域和复位域classMultiClockModuleextendsModule{

valio=IO(newBundle{

valclockB=Input(Clock())

valresetB=Input(Bool())

valstuff=Input(Bool())

})

valregClock1=RegNext(io.stuff)

withClockAndReset(io.clockB,io.resetB){

valregClockB=RegNext(io.stuff)

valm=Module(newChildModule)

}

valregClock2=RegNext(io.stuff)

}这个寄存器跟随当前模块的隐式全局时钟clock在该花括号内,所有时序元件都跟随时钟io.clockB和复位信号io.resetB这个寄存器跟随当前模块的隐式全局时钟clock92.1withClockAndReset二、定义一个时钟域和复位域classMultiClockModuleextendsModule{

valio=IO(newBundle{

valclockB=Input(Clock())

valresetB=Input(Bool())

valstuff=Input(Bool())

})

valclockB_child=withClockAndReset(io.clockB,io.resetB){

Module(newChildModule)

}

clockB_child.io.in:=io.stuff

}工厂方法:defapply[T](clock:Clock,reset:Reset)(block:⇒T):T例化其它模块在时钟域外对其赋值102.2withClock和withReset二、定义一个时钟域和复位域作用:分别用于构建只有独立时钟和只有独立复位信号的作用域apply方法:defapply[T](clock:Clock)(block:⇒T):Tdefapply[T](reset:Reset)(block:⇒T):TwithClock和withReset也是chisel3包里有单例对象11withClockAndResetwithClockwithReset独立时钟

独立复位信号

二、定义一个时钟域和复位域classChildModuleextendsModule{

valio=IO(newBundle{

valin=Input(Bool())

valclockChild=Input(Clock())

valout=Output(Bool())

})

withClock(io.clockChild){

//该寄存器跟随时钟io.clockChild,隐式复位信号reset

valregclock=RegNext(io.in,0.U)

io.out:=regclock

}

}classMultiClockTesterextendsModule{

valio=IO(newBundle{

valclockA=Input(Clock())

valresetA=Input(Bool())

valclockChild=Input(Clock())

valresetB=Input(Bool())

valstuff_in=Input(Bool())

valstuff_out=Output(Bool())

valoutregClock=Output(Bool())

valoutregClockA=Output(Bool())

valoutregClockB=Output(Bool())

})

//这个寄存器跟随当前模块的隐式全局时钟clock

valregClock=RegNext(io.stuff_in,0.U)

valclockA_child=withClockAndReset(io.clockA,io.resetA.asAsyncReset()){

//在该花括号内,所有时序元件都跟随时钟io.clockA

//所有寄存器的复位信号都是io.resetA

valregClockA=RegNext(io.stuff_in,0.U)

//这个寄存器跟随当前模块的隐式全局时钟clock

regClock:=regClockA

io.outregClockA:=regClockA

Module(newChildModule)

}clockA_child.io.clockChild:=io.clockChild

clockA_child.io.in:=io.stuff_in

io.stuff_out:=clockA_child.io.out

withReset(io.resetB){

//在该花括号内,所有时序元件都跟随时钟隐式时钟clock,复位信号都是io.resetB

valregClockB=RegNext(io.stuff_in,0.U)

io.outregClock:=regClock

io.outregClockB:=regClockB

}

}123122.2withClock和withReset二、定义一个时钟域和复位域一个寄存器只和它定义时所处的时钟域有关,即使在其他时钟域被赋值,那么它还是跟随自己被定义时的时钟。时钟域是可以嵌套的,当前的时钟域会覆盖掉上一层的时钟域。132.3复位信号的三种类型二、定义一个时钟域和复位域Reset是抽象类型,具体是同步复位还是异步复位需要根据上下文推断,也即既可以是同步,也可以异步。14复位信号BoolAsyncResetReset复位类型同步复位异步复位同步/异步当我们不希望其自动推断抽象类型的时候,可以在定义模块时通过混入以下特质,将reset的类型设置成我们想要的类型。混入RequireSyncReset特质可以将模块的隐式reset设置成同步复位信号。混入RequireAsyncReset

特质可以将模块的隐式reset设置成异步复位信号。二、定义一个时钟域和复位域classSyncResetModuleextendsMultiIOModulewithRequireSyncReset{

valSyncResetReg=RegInit(false.B)

}classAsyncResetModuleextendsMultiIOModulewithRequireAsyncReset{

valAsyncResetReg=RegInit(false.B)

}classSyncResetModuleextendsMultiIOModulewithRequireSyncReset{

valSyncResetReg=RegInit(false.B)//resetisoftypeBool

}classAsyncResetModuleextendsMultiIOModulewithRequireAsyncReset{

valAsyncResetReg=RegInit(false.B)//resetisoftypeAsyncReset

}15为了方便的修改任何复位信号的类型,我们还可以进行强制类型转换。使用reset.asBool()可以将复位信号从其他两种类型转换成Bool类型使用reset.asAsyncReset()可以将复位信号从其他两种类型转换成AsyncReset类型。二、定义一个时钟域和复位域16三、使用时钟负沿和低有效的复位信号17三、使用时钟负沿和低有效的复位信号Chisel:默认情况下,声明的时序元件都是以时钟的正沿和高有效的复位信号作为敏感变量。复位信号:只需要加上取反符号或逻辑非符号。时钟信号:需要先用asUInt方法把Clock类型转换成UInt类型,再用asBool转换成Bool类型,此时可以加上取反符号或逻辑非符号,最后再用asClock变回Clock类型。18Verilog:复位信号:使用取反符号或逻辑非符号。时钟信号:使用posedge或negedge。modulea(

inputclk,

inputrst_n

);

always(negedgeclk)

begin

if(!ret_n)classNegativeClkRstextendsRawModule{

valio=IO(newBundle{

valin=Input(UInt(4.W))

valmyClk=Input(Clock())

valmyRst=Input(Bool())

valout=Output(UInt(4.W))

})

withClockAndReset((~io.myClk.asUInt.asBool).asClock,~io.myRst){

valtemp=RegInit(0.U(4.W))

temp:=io.in

io.out:=temp

}

}三、使用时钟负沿和低有效的复位信号需要进行多次类型转换直接加上取反符号或逻辑非符号19四、示例:异步FIFO四、示例:异步FIFO下面是一个异步FIFO例子:数据位宽和深度都是参数化的,读、写地址指针的交互采用格雷码和两级寄存器采样,以便改善亚稳态。通过在Vivado2018.3里综合后,可以得到以BRAM为存储器的FIFO。21四、示例:异步FIFOclassFIFO(width:Int,depth:Int)extendsRawModule{

valio=IO(newBundle{

//write-domain

valdataIn=Input(UInt(width.W))

valwriteEn=Input(Bool())

valwriteClk=Input(Clock())

valfull=Output(Bool())

//read-domain

valdataOut=Output(UInt(width.W))

valreadEn=Input(Bool())

valreadClk=Input(Clock())

valempty=Output(Bool())

//reset

valsystemRst=Input(Bool())

})22四、示例:异步FIFOvalram=SyncReadMem(1<<depth,UInt(width.W))//2^depth

valwriteToReadPtr=Wire(UInt((depth+1).W))//toreadclockdomain

valreadToWritePtr=Wire(UInt((depth+1).W))//towriteclockdomain

//writeclockdomain

withClockAndReset(io.writeClk,io.systemRst){

valbinaryWritePtr=RegInit(0.U((depth+1).W))

valbinaryWritePtrNext=Wire(UInt((depth+1).W))

valgrayWritePtr=RegInit(0.U((depth+1).W))

valgrayWritePtrNext=Wire(UInt((depth+1).W))

valisFull=RegInit(false.B)

valfullValue=Wire(Bool())

valgrayReadPtrDelay0=RegNext(readToWritePtr)

valgrayReadPtrDelay1=RegNext(grayReadPtrDelay0)

binaryWritePtrNext:=binaryWritePtr+(io.writeEn&&!isFull).asUInt

binaryWritePtr:=binaryWritePtrNext

grayWritePtrNext:=(binaryWritePtrNext>>1).asUInt()^binaryWritePtrNext

grayWritePtr:=grayWritePtrNext

writeToReadPtr:=grayWritePtr

fullValue:=(grayWritePtrNext===Cat(~grayReadPtrDelay1(depth,depth-1),grayReadPtrDelay1(depth-2,0)))

isFull:=fullValue

when(io.writeEn&&!isFull){

ram.write(binaryWritePtr(depth-1,0),io.dataIn)

}

io.full:=isFull

}23四、示例:异步FIFO//readclockdomain

withClockAndReset(io.readClk,io.systemRst){

valbinaryReadPtr=RegInit(0.U((depth+1).W))

温馨提示

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

评论

0/150

提交评论