版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
4.Chisel常用的硬件原語一、多路選擇器二、優(yōu)先編碼器三、仲裁器四、隊(duì)列五、ROM六、RAM七、計(jì)數(shù)器八、線性反饋移位寄存器九、狀態(tài)機(jī)2目
錄一、多路選擇器3多路選擇器二輸入多路選擇器”Mux(sel,in1,in2)”sel是Bool類型;in1和in2的類型相同,都是Data的任意子類型。當(dāng)sel為true.B時(shí),返回in1,否則返回in2可內(nèi)嵌Mux,構(gòu)成n輸入,例:
“Mux(c1,a,Mux(c2,b,Mux(...,default)))”1.1Mux4多路選擇器1.2MuxCasen輸入多路選擇器”MuxCase(default,Array(c1->a,c2->b,...))”第一個(gè)參數(shù)是默認(rèn)情況下返回的結(jié)果;第二個(gè)參數(shù)是一個(gè)數(shù)組,數(shù)組的元素是對偶“(成立條件,被選擇的輸入)”。5多路選擇器MuxCase的變體,類似查找表“MuxLookup(idx,default,Array(0.U->a,1.U->b,...))”相當(dāng)于把MuxCase的成立條件依次換成從0開始的索引值它的展開相當(dāng)于:“MuxCase(default,Array((idx===0.U)->a,(idx===1.U)->b,...))”1.3MuxLookup6多路選擇器1.4Mux1H獨(dú)熱碼多路選擇器如果零個(gè)或多個(gè)選擇信號有效,則行為變?yōu)槎鄠€(gè)被選擇數(shù)字之和Mux1H三種常用的定義形式(等價(jià)):valhotValue=Mux1H(io.selector,Seq(2.U,4.U,8.U,11.U))
valhotValue=Mux1H(Seq(io.selector(0),io.selector(1),
io.selector(2),io.selector(3)),Seq(2.U,4.U,8.U,11.U))
valhotValue=Mux1H(Seq(
io.selector(0)->2.U,
io.selector(1)->4.U,
io.selector(2)->8.U,
io.selector(3)->11.U
))io.selectorSeq(2.U,4.U,8.U,11.U)00012.U00104.U01008.U100011.U7多路選擇器1.5PriorityMux當(dāng)多個(gè)選擇信號有效時(shí),按照定義時(shí)的順序,返回更靠前的被選數(shù)據(jù)。有以下三種定義形式(等價(jià)):valpriorityValue=PriorityMux(io.selector,Seq(2.U,4.U,8.U,11.U))
valpriorityValue=PriorityMux(Seq(io.selector(0),io.selector(1),
io.selector(2),io.selector(3)),
Seq(2.U,4.U,8.U,11.U))
valpriorityValue=PriorityMux(Seq(
io.selector(0)->2.U,
io.selector(1)->4.U,
io.selector(2)->8.U,
io.selector(3)->11.U,
))io.selectorSeq(2.U,4.U,8.U,11.U)xxx12.Uxx104.Ux1008.U100011.U8二、優(yōu)先編碼器9優(yōu)先編碼器2.1PriorityEncoderPriorityEncoder("b1010".U)
PriorityEncoder(Seq(false.B,true.B,false.B,true.B))作用是對多個(gè)輸入信號中優(yōu)先級最高的一個(gè)信號進(jìn)行編碼。有以下兩種定義形式:以上兩種形式是等價(jià)的,返回值類型都是UInt,值為1.U。入?yún)ⅲ築its返回值:UIntxxx10.Uxx101.Ux1002.U10003.U10優(yōu)先編碼器2.2PriorityEncoderOH有以下兩種定義形式:PriorityEncoderOH("b1010".U)
PriorityEncoderOH(Seq(false.B,true.B,true.B,false.B))它和第一種編碼器的區(qū)別在于該編碼器會把編碼結(jié)果轉(zhuǎn)換成獨(dú)熱碼。第一種形式返回一個(gè)UInt的數(shù)據(jù)2.U,第二種形式返回一個(gè)Seq:Seq(false.B,true.B,false.B,false.B)。入?yún)ⅲ築its返回值:Uintxxx10001xx100010x10001001000100011三、仲裁器12仲裁器3.1ready-valid接口Arbiter使用的是標(biāo)準(zhǔn)的ready-valid接口,該類型的端口在單一數(shù)據(jù)信號的基礎(chǔ)上又添加了ready和valid信號以使用ready-valid握手協(xié)議。它包含3個(gè)信號:ready:高有效時(shí)表示數(shù)據(jù)接收者consumer已經(jīng)準(zhǔn)備好接收信號,由consumer驅(qū)動。valid:高有效時(shí)表示數(shù)據(jù)生產(chǎn)者producer已經(jīng)準(zhǔn)備好待發(fā)送的數(shù)據(jù)了,由producer驅(qū)動。bits:是要在producer與consumer之間傳輸?shù)臄?shù)據(jù)。13仲裁器使用單例對象Decoupled可創(chuàng)建ready-valid接口,有以下兩種形式:
Decoupled(...):可以傳入任意的數(shù)據(jù)類型,然后返回一個(gè)ready-valid接口,此時(shí)ready是input信號,valid和bits都是output信號。因此它是屬于數(shù)據(jù)生產(chǎn)者producer的端口。
Flipped(Decoupled(...)):Flipped()會將ready-valid接口的信號方向進(jìn)行取反,因此此時(shí)ready是output信號,valid和bits都是input信號。因此它是屬于數(shù)據(jù)接收者consumer的端口。14仲裁器producerDecoupled(...)readyvalidbitsconsumerFlipped(Decoupled(...))readyvalidbits15仲裁器3.2優(yōu)先仲裁器優(yōu)先仲裁器的輸入通道的優(yōu)先級是固定的,每次都是選擇多個(gè)有效通道中優(yōu)先級最高的。創(chuàng)建Arbiter對象的方式為newArbiter(gen:T,n:Int)gen是傳輸?shù)臄?shù)據(jù)的類型,n是待仲裁對象的個(gè)數(shù),也即數(shù)據(jù)發(fā)送者producer的個(gè)數(shù)。數(shù)據(jù)接收者consumer的個(gè)數(shù)為默認(rèn)為1。16仲裁器Arbiter內(nèi)部使用ArbiterIO定義端口,而ArbiterIO內(nèi)部又使用Decoupled()創(chuàng)建最終所需的ready-valid接口,定義如下:classArbiterIO[T<:Data](privatevalgen:T,valn:Int)extendsBundle{
valin=Flipped(Vec(n,Decoupled(gen)))
valout=Decoupled(gen)
valchosen=Output(UInt(log2Ceil(n).W))
}”log2Ceil(n)”是實(shí)現(xiàn)的是以2為底的對數(shù)函數(shù)的計(jì)算,把結(jié)果向上取整返回17仲裁器producer0readyvalidbitsconsumerreadyvalidbitsArbiterin(0).validin(0).bitsin(0).readyin(1).validin(1).bitsin(1).readyout.bitsout.readyout.validchosenproducer1readyvalidbitschosen18仲裁器例:
classMyArbiterextendsModule{
valio=IO(newBundle{
valin=Flipped(Vec(2,Decoupled(UInt(8.W))))
valout=Decoupled(UInt(8.W))
valchosen=Output(UInt())
})
valarbiter=Module(newArbiter(UInt(8.W),2))
//2to1PriorityArbiter
arbiter.io.in<>io.in
io.out<>arbiter.io.out
io.chosen:=arbiter.io.chosen
}Verilog代碼中生成了兩個(gè)module,第一個(gè)moduleArbiter對應(yīng)的是例化的優(yōu)先仲裁器Arbiter,第二個(gè)moduleMyArbiter對應(yīng)的是頂層模塊MyArbiter。19仲裁器每次都從不同的起點(diǎn)開始仲裁,采用輪詢方式查看各個(gè)通道是否有請求,優(yōu)先選擇先查到的有效通道。由于起點(diǎn)是依次變化的,所以每個(gè)通道總體來說具有相同的優(yōu)先級。它的創(chuàng)建與調(diào)用方式和Arbiter是一樣的,只是內(nèi)部實(shí)現(xiàn)的仲裁邏輯不同。3.3循環(huán)仲裁器RRArbiter20四、隊(duì)列21隊(duì)列objectEnqIO{
defapply[T<:Data](gen:T):DecoupledIO[T]=Decoupled(gen)
}
objectDeqIO{
defapply[T<:Data](gen:T):DecoupledIO[T]=Flipped(Decoupled(gen))
}Chisel內(nèi)建了隊(duì)列Queue,它會創(chuàng)建一個(gè)使用ready-valid接口的FIFOQueue內(nèi)部使用QueueIO定義端口,QueueIO最終仍然是使用Decoupled()創(chuàng)建所需的ready-valid接口,定義如下:4.1隊(duì)列的接口22隊(duì)列classQueueIO[T<:Data](privatevalgen:T,valentries:Int)extendsBundle
{
valenq=Flipped(EnqIO(gen))
valdeq=Flipped(DeqIO(gen))
valcount=Output(UInt(log2Ceil(entries+1).W))
}enq是用來寫數(shù)據(jù)的端口,因此它和數(shù)據(jù)生產(chǎn)者producer連接;deq是用來讀數(shù)據(jù)的端口,因此它和數(shù)據(jù)接收者consumer連接;count表示此時(shí)Queue中的數(shù)據(jù)個(gè)數(shù)23隊(duì)列producerreadyvalidbitsconsumerreadyvalidbitsQueueenq.validenq.bitsenq.readyout.bitsout.readyout.validcountenqdeqcountcount24隊(duì)列4.2使用隊(duì)列Queue(enq:ReadyValidIO[T],entries:Int=2):返回的是DecoupledIO[T]類型的讀數(shù)據(jù)端口,也即上述的deq,因此我們不能在代碼中訪問enq和count。第一種形式的使用案例:classMyQueueextendsModule{
valio=IO(newBundle{
valin=Flipped(Decoupled(UInt(8.W)))
valout=Decoupled(UInt(8.W))
})
valq=Queue(io.in,2)
io.out<>q
}25隊(duì)列第二種形式的使用案例:classMyQueueextendsModule{
valio=IO(newBundle{
valin=Flipped(Decoupled(UInt(8.W)))
valout=Decoupled(UInt(8.W))
valcnt=Output(UInt(4.W))
})
valq=Module(newQueue(UInt(8.W),entries=16))
q.io.enq<>io.in
io.out<>q.io.deq
io.cnt:=q.io.count
}newQueue(gen:T,entries:Int):第一個(gè)參數(shù)是存儲的數(shù)據(jù)的類型,第二個(gè)參數(shù)是存儲的數(shù)據(jù)的深度。返回一個(gè)Queue對象,該對象包含QueueIO屬性,因此我們可以在代碼中訪問QueueIO的enqdeqcount這三種端口信號。26隊(duì)列各自生成的Verilog中,子模塊Queue的端口定義分別如下:moduleQueue(
inputclock,
inputreset,
outputio_enq_ready,
inputio_enq_valid,
input[7:0]io_enq_bits,
inputio_deq_ready,
outputio_deq_valid,
output[7:0]io_deq_bits,
output[4:0]io_count
);moduleQueue(
inputclock,
inputreset,
outputio_enq_ready,
inputio_enq_valid,
input[7:0]io_enq_bits,
inputio_deq_ready,
outputio_deq_valid,
output[7:0]io_deq_bits
);都有所需的兩對ready-valid握手信號,并且這兩對信號方向相反在第種一形式中,是不會有io_count端口的,因?yàn)槲覀儫o法使用QueueIO中的count27隊(duì)列io.deq.valid:=!empty
io.enq.ready:=!Full4.3empty和full屬性由于在classQueue中有如下定義:我們就可以通過io.deq.valid和io.enq.ready間接地訪問empty和full信號28五、ROM29ROMclassROMextendsModule{
valio=IO(newBundle{
valsel=Input(UInt(2.W))
valout=Output(UInt(8.W))
})
valrom=VecInit(1.U,2.U,3.U,4.U)
io.out:=rom(io.sel)
//Vec[T]類的apply方法可接收Int和UInt類型的索引值
}通過工廠方法“VecInit[T<:Data](elt0:T,elts:T*)”或“VecInit[T<:Data](elts:Seq[T])”來創(chuàng)建一個(gè)只讀存儲器參數(shù)就是ROM里的常量數(shù)值,對應(yīng)的Verilog代碼就是給讀取ROM的線網(wǎng)或寄存器賦予常量值,例如:30六、RAM31RAM6.1異步讀RAM第一種RAM是同步(時(shí)序)寫,異步(組合邏輯)讀的RAM,通過工廠方法“Mem[T<:Data](size:Int,t:T)”來構(gòu)建。valasyncMem=Mem(16,UInt(32.W))由于現(xiàn)代的FPGA和ASIC技術(shù)大多不再支持異步讀RAM,所以這種RAM會被綜合成寄存器陣列。32RAM6.2同步讀寫RAM同步(時(shí)序)讀、寫,通過工廠方法“SyncReadMem[T<:Data](size:Int,t:T)”來構(gòu)建,這種RAM會被綜合成實(shí)際的SRAM。例:valsyncMem=SyncReadMem(16,UInt(32.W))
寫RAM的語法是:valmem=SyncReadMem(16,UInt(32.W))
when(wr_en){
mem.write(address,dataIn)
out:=DontCare
}
//“DontCare”告訴Chisel的未連接線網(wǎng)檢測機(jī)制,寫入RAM時(shí)讀端口
//的行為無需關(guān)心33RAM讀RAM的語法是:out:=mem.read(address,rd_en)
讀、寫使能信號都可以省略,使用賦值語句,也可以實(shí)現(xiàn)讀寫:valmem=SyncReadMem(1024,UInt(width.W))
io.dataOut:=DontCare
when(io.enable){
valrdwrPort=mem(io.addr)
when(io.write){rdwrPort:=io.dataIn}
.otherwise{io.dataOut:=rdwrPort}
}34RAM當(dāng)讀寫操作有效的條件互斥時(shí),RAM會被推斷為單端口RAM。如:valmem=SyncReadMem(1024,UInt(width.W))
io.dataOut:=DontCare
when(io.enable){
when(io.write){mem.write(io.addr,io.dataIn)}
.otherwise{io.dataOut:=mem.read(io.addr)}
}反之,如果讀寫操作有效的條件不互斥,那么會被推斷為雙口RAM。如:valmem=SyncReadMem(1024,UInt(width.W))
//Createonewriteportandonereadport
mem.write(io.addr,io.dataIn)
io.dataOut:=mem.read(io.addr2,io.enable)35RAM6.3帶寫掩碼的RAMRAM通常都具備按字節(jié)寫入的功能,當(dāng)寫掩碼的比特位有效時(shí),對應(yīng)的字節(jié)才會寫入。當(dāng)構(gòu)建RAM的數(shù)據(jù)類型為Vec[T]時(shí),就會推斷出該RAM具有寫掩碼。此時(shí),需要定義一個(gè)Seq[Bool]類型的寫掩碼信號。構(gòu)建一個(gè)帶寫掩碼的單端口RAM,classMaskRAMextendsModule{
valio=IO(newBundle{
valaddr=Input(UInt(10.W))
valdataIn=Input(UInt(32.W))
valen=Input(Bool())
valwe=Input(UInt(1.W))
valmask=Input(Vec(4,Bool()))
valdataOut=Output(UInt(32.W))
})36RAM而write方法有一個(gè)重載版本,就是第三個(gè)參數(shù)是接收寫掩碼信號的。當(dāng)下標(biāo)為0的寫掩碼比特是true.B時(shí),最低的那個(gè)字節(jié)會被寫入,依次類推。syncRAM.write(io.addr,dataIn_temp,io.mask)valsyncRAM=SyncReadMem(1024,Vec(4,UInt(8.W)))編譯器會把Vec[T]的元素逐個(gè)展開,而不是合并成壓縮數(shù)組的形式。因此本代碼對應(yīng)的Verilog的RAM主體定義成4個(gè)reg,Vivado綜合出來的電路是四小塊BRAM,而不是一大塊BRAM。37RAM6.4從文件讀取數(shù)據(jù)到RAM單例對象loadMemoryFromFile的apply方法可以在Chisel層面上從txt文件讀取數(shù)據(jù)到RAM里。第一個(gè)參數(shù)接收一個(gè)自定義的RAM對象。第二個(gè)參數(shù)是文件的名字及路徑,用字符串表示。第三個(gè)參數(shù)表示讀取的方式為十六進(jìn)制或二進(jìn)制。注意,沒有十進(jìn)制和八進(jìn)制。defapply[T<:Data](
memory:MemBase[T],
fileName:String,
hexOrBinary:MemoryLoadFileType.FileType=MemoryLoadFileType.Hex
):Unit38RAM例://loadmem.scala
packagechapter04
importchisel3._
importchisel3.util.experimental.loadMemoryFromFile
classLoadMemextendsModule{
valio=IO(newBundle{
valaddress=Input(UInt(3.W))
valvalue=Output(UInt(8.W))
})
valmemory=Mem(8,UInt(8.W))
io.value:=memory.read(io.address)
loadMemoryFromFile(memory,"~/chisel-workspace/chisel-template/mem.txt")
}
39七、計(jì)數(shù)器40計(jì)數(shù)器第一個(gè)參數(shù)為true.B時(shí)計(jì)數(shù)器從0開始每個(gè)時(shí)鐘上升沿加1自增,為false.B時(shí)則計(jì)數(shù)器保持不變;第二個(gè)參數(shù)n是一個(gè)Int類型的具體正數(shù),當(dāng)計(jì)數(shù)到n時(shí)歸零。在Chisel.util包里定義了一個(gè)自增計(jì)數(shù)器原語Counter,其apply方法共有三個(gè)重載版本7.1apply方法一apply(cond:Bool,n:Int):(UInt,Bool)41計(jì)數(shù)器classMyCounterextendsModule{
valio=IO(newBundle{
valen=Input(Bool())
valout=Output(UInt(8.W))
valvalid=Output(Bool())
})
val(a,b)=Counter(io.en,233)
io.out:=a
io.valid:=b
}該方法返回一個(gè)二元組:第一個(gè)元素是計(jì)數(shù)器當(dāng)前的計(jì)數(shù)值,類型為UInt。第二個(gè)元素是判斷當(dāng)前計(jì)數(shù)值是否等于n的結(jié)果,類型為Bool。apply(cond:Bool,n:Int):(UInt,Bool)42計(jì)數(shù)器defapply(r:Range,enable:Bool=true.B,reset:Bool=false.B):(UInt,Bool)7.2apply方法二r:是一個(gè)scala.collection.immutable.Range類型的參數(shù),用來提供一個(gè)計(jì)數(shù)的范圍。enable:有效時(shí)表示該clk使能計(jì)數(shù)器計(jì)數(shù)。reset:有效時(shí)表示該clk使計(jì)數(shù)器復(fù)位到初始值,這里的初始值是提供的計(jì)數(shù)范圍的起始值。如果不提供,那么默認(rèn)跟隨隱式復(fù)位信號,如果提供,那么就會有多個(gè)復(fù)位信號。43計(jì)數(shù)器importchisel3._
importchisel3.util._
importscala.collection.immutable.Range
classMyCounterextendsModule{
valio=IO(newBundle{
valen=Input(Bool())
valout=Output(UInt(8.W))
valvalid=Output(Bool())
})
val(a,b)=Counter(Range(0,233),io.en)
io.out:=a
io.valid:=b
}defapply(r:Range,enable:Bool=true.B,reset:Bool=false.B):(UInt,Bool)44計(jì)數(shù)器apply(n:Int):Counter7.3apply方法三和上述兩個(gè)方法不同,該方法返回的是一個(gè)Counter對象,有如下的屬性和方法可以使用:definc():Bool隨時(shí)鐘使計(jì)數(shù)器+1,返回值表示計(jì)數(shù)器是否在下一個(gè)時(shí)鐘周期結(jié)束defn:Int無參函數(shù),返回計(jì)數(shù)器的計(jì)數(shù)最大值ndefrange:Range無參函數(shù),返回計(jì)數(shù)器的計(jì)數(shù)范圍,類型為Rangedefreset():Unit使計(jì)數(shù)器復(fù)位到初始值0valvalue:UInt表示計(jì)數(shù)器此時(shí)的計(jì)數(shù)值,因?yàn)槭莢al類型,所以只能讀取45計(jì)數(shù)器classMyCounterextendsModule{
valio=IO(newBundle{
valen=Input(Bool())
valout=Output(UInt(8.W))
valvalid=Output(Bool())
})
valcnt=Counter(233)
when(io.en){
cnt.inc()
}
vala=cnt.value
valb=cnt.value===cnt.n.U
io.out:=a
io.valid:=b
}apply(n:Int):Counter46八、線性反饋移位寄存器47線性反饋移位寄存器defapply(width:Int,increment:Bool=true.B,seed:Option[BigInt]=Some(1)):UInt要產(chǎn)生偽隨機(jī)數(shù),可使用線性反饋移位寄存器原語LFSR:第一個(gè)參數(shù)width是移位寄存器的位寬。第二個(gè)參數(shù)increment是一個(gè)Bool類型的使能信號,用于控制寄存器是否移位,缺省值為true.B。第三個(gè)參數(shù)seed是一個(gè)隨機(jī)種子,是可選值類型。LFSR在chisel3.util.random包里。48線性反饋移位寄存器例如:importchisel3._
importchisel3.util.random.LFSR
classLFSR16extendsModule{
valio=IO(newBundle{
valen=Input(Bool())
valout=Output(UInt(16.W))
})
io.out:=LFSR(16,io.en,Some(1))
}49九、狀態(tài)機(jī)50狀態(tài)機(jī)defapply(n:Int):List[UInt]用Enum特質(zhì)及其伴生對象。伴生對象里的apply方法定義如下:它會根據(jù)參數(shù)n返回對應(yīng)元素?cái)?shù)的List[UInt],每個(gè)元素都是不同的,所以可以作為枚舉值來使用。最好把枚舉狀態(tài)的變量名也組成一個(gè)列表,然后用列表的模式匹配來進(jìn)行賦值。檢測持續(xù)時(shí)間超過兩個(gè)時(shí)鐘周期的高電平:classDetectTwoOnesextendsModule{
valio=IO(newBundle{
valin=Input(Bool())
valout=Output(Bool())
})
valsNone::sOne1::sTwo1s::Nil=Enum(3)
valstate=RegInit(sNone)
51狀態(tài)機(jī)
io.out:=(state===sTwo1s)
switch(state){
is(sNone){
when(io.in){
state:=sOne1
}
}
is(sOne1){
when(io.in){
state:=sTwo1s
}.otherwise{
state:=sNone
}
}
is(sTwo1s){
when(!io.in){
state:=sNone
}
}
}
}有了枚舉值后,可以通過“switch…is…is”語句來使用。其中,switch里是相應(yīng)的狀態(tài)寄存器,而每個(gè)is分支的后面則是枚舉值及相應(yīng)的定義。52十、常見電路的描述方式53常見電路的描述方式10.1如何定義向量54Vec[T]
T必須是Data的子類,而且每個(gè)元素的類型、位寬必須一樣。
其伴生對象里的apply工廠方法,接收兩個(gè)參數(shù),第一個(gè)是Int類型,表示元素的個(gè)數(shù),第二個(gè)是元素。VecInit[T]其接收一個(gè)Seq[T]作為參數(shù)來構(gòu)造向量,常用于初始化寄存器組、ROM、RAM等,或者用來構(gòu)造多個(gè)模塊。valmyVec=Wire(Vec(3,UInt(32.W)))valVec1=VecInit(1.U,2.U,3.U,4.U)
valVec2=VecInit(Seq.fill(8)(0.U(8.W)))重復(fù)參數(shù):序列:常見電路的描述方式10.2混合向量55混合向量MixedVec[T]:包含的元素可以不全都一樣,比如位寬不一樣。MixedVecInit[T]的單例對象,以重復(fù)參數(shù)或者序列作為參數(shù)來構(gòu)造。對于可以傳入序列的向量,可以通過Scala的函數(shù)來生成。valVec1=MixedVec(UInt(8.W),UInt(16.W),UInt(32.W))
valVec2=MixedVec(Array(UInt(8.W),UInt(16.W),UInt(32.W)))valVec1=MixedVecInit(1.U,2.U,3.U,4.U)
valVec2=MixedVecInit(Seq.fill(8)(0.U(8.W)))valmixVec=MixedVec((1to10)map{i=>UInt(i.W)})
valmixVecinit=MixedVecInit(Seq.fill(8)(0.U(8.W)))重復(fù)參數(shù):序列:重復(fù)參數(shù):序列:序列:序列:常見電路的描述方式10.3Vec和UInt的互相轉(zhuǎn)換56使用asBools將UInt轉(zhuǎn)換成Vec。使用asUInt將Vec轉(zhuǎn)換成Uint。importchisel3._
classFooextendsRawModule{
valuint=0xc.U
valvec=VecInit(uint.asBools)
printf(p"$vec")//Vec(0,0,1,1)
//Test
assert(vec(0)===false.B)
assert(vec(1)===false.B)
assert(vec(2)===true.B)
assert(vec(3)===true.B)}importchisel3._
classFooextendsRawModule{
valvec=VecInit(true.B,false.B,true.B,true.B)
valuint=vec.asUInt
printf(p"$uint")//13
//Test
//(rememberleftmostBoolinVecisloworderbit)
assert(0xd.U===uint)}常見電路的描述方式10.4向量的維度與索引以及修改向量的某幾位57賦值:索引:valmyVec=Wire(Vec(3,UInt(32.W)))
myVec(0)(5)
myVec(0)(3,0)valVec1=Wire(Vec(3,UInt(32.W)))
Vec1(0):=1.U(32.W)
Vec1(1):=1.U(32.W)
Vec1(2):=1.U(32.W)
valVec2=Wire(Vec(3,UInt(32.W)))
Vec2(0):=1.U(32.W)
Vec2(1):=1.U(32.W)
Vec2(2):=1.U(32.W)
Vec1(0):=Cat(Vec2(0)(31,4),1.U(4.W))valVec1=Wire(Vec(3,UInt(32.W)))
Vec1(0):=1.U(32.W)
Vec1(1):=1.U(32.W)
Vec1(2):=1.U(32.W)
valVec2=Wire(Vec(3,UInt(32.W)))
Vec2(0):=1.U(32.W)
Vec2(1):=1.U(32.W)
Vec2(2):=1.U(32.W)
valbools=VecInit(Vec1(0).asBools)
valseq=1.U(4.W).asBools
for(i<-0until4){
bools(i):=seq(i)}
Vec2(0):=bools.asUInt
Vec1(0):=Vec2(0)常見電路的描述方式10.5子字賦值58子字賦值:先調(diào)用Bits類型的asBools方法,再配合VecInit構(gòu)成一個(gè)向量asBools方法:根據(jù)調(diào)用對象的0、1排列返回一個(gè)相應(yīng)的Seq[Bool]對象。classTestModuleextendsModule{
valio=IO(newBundle{
valin=Input(UInt(10.W))
valbit=Input(Bool())
valout=Output(UInt(10.W))
})
valbools=VecInit(io.in.asBools)
bools(0):=io.bit
io.out:=bools.asUInt
}常見電路的描述方式10.6BitPat59在Chisel里有對應(yīng)的BitPat類,可以指定無關(guān)位。在其伴生對象里,一個(gè)apply方法可以接收一個(gè)字符串來構(gòu)造BitPat對象,字符串里用問號表示無關(guān)位。dontCare方法接收一個(gè)Int類型的參數(shù),構(gòu)造等值位寬的全部無關(guān)位。"b10101".U===BitPat("b101??")//等于true.B
"b10111".U===BitPat("b101??")//等于true.B
"b10001".U===BitPat("b101??")//等于false.BvalmyDontCare=BitPat.dontCare(4)//等于BitPat("b????")常見電路的描述方式10.7Lookup/ListLookup60Lookup:defapply[T<:Bits](addr:UInt,default:T,mapping:Seq[(BitPat,T)]):TListLookup:
它的apply方法與上面的類似,區(qū)別在于返回結(jié)果是一個(gè)T類型的列表。Lookup(2.U,//addressforcomparison
10.U,//default
Array(BitPat(2.U)->20.U,
BitPat(3.U)->30.U)
)//返回20.UListLookup(2.U,//addressforcomparison
List(10.U,11.U,12.U),//default
Array(BitPat(2.U)->List(20.U,21.U,22.U),
BitPat(3.U)->List(30.U,31.U,32.U))
)//返回List(20.U,21.U,22.U)常見電路的描述方式10.8PopCount61單例對象PopCount:兩個(gè)apply方法,分別接收一個(gè)Bits類型的參數(shù)和Bool類型的序列計(jì)算參數(shù)里“1”或“true.B”的個(gè)數(shù),返回對應(yīng)的UInt值。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.U
PopCount(myUIntWire)//動態(tài)計(jì)數(shù)常見電路的描述方式10.9OHToUInt62OHToUInt的apply方法可以接收一個(gè)Bits類型或Bool序列類型的獨(dú)熱碼參數(shù),計(jì)算獨(dú)熱碼里的“1”在第幾位(從0開始),返回對應(yīng)的UInt值。如果不是獨(dú)熱碼,則行為不確定。單例對象UIntToOH,它的apply方法是根據(jù)輸入的UInt類型參數(shù),返回對應(yīng)位置的獨(dú)熱碼,獨(dú)熱碼也是UInt類型。UIntToOH(3.U)//等于"b1000".U
UIntToOH(7.U)//等于"b1000_0000".UOHToUInt("b1000".U)//等于3.U
OHToUInt("b1000_0000".U)//等于7.U常見電路的描述方式10.10Scala高級語法應(yīng)用63Tuple:包含不同類型的對象
以一個(gè)二元組為例,由于函數(shù)counter只有一個(gè)返回語句,但如果想返回多個(gè)表達(dá)式或?qū)ο?,如cntReg和nextVal,就可以把它們包在一個(gè)元組里返回。classMemFifo[T<:Data](gen:T,depth:Int)extendsFifo(gen:T,depth:Int){
defcounter(depth:Int,incr:Bool):(UInt,UInt)={
valcntReg=RegInit(0.U(log2Ceil(depth).W))
valnextVal=Mux(cntReg===(depth-1).U,0.U,cntReg+1.U)
when(incr){
cntReg:=nextVal
}
(cntReg,nextVal)
}
}常見電路的描述方式10.10Scala高
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年黑龍江農(nóng)業(yè)職業(yè)技術(shù)學(xué)院單招綜合素質(zhì)考試備考試題帶答案解析
- 2026年安徽新聞出版職業(yè)技術(shù)學(xué)院單招職業(yè)技能筆試模擬試題帶答案解析
- 2026年安徽林業(yè)職業(yè)技術(shù)學(xué)院高職單招職業(yè)適應(yīng)性測試參考題庫帶答案解析
- 投資合作2025年協(xié)議
- 停車場租賃居間合同2025年服務(wù)內(nèi)容明細(xì)
- 2026年池州職業(yè)技術(shù)學(xué)院單招職業(yè)技能筆試備考題庫帶答案解析
- 稅務(wù)代理服務(wù)協(xié)議2025年稅務(wù)代理監(jiān)督條款
- 2026年湖南藝術(shù)職業(yè)學(xué)院單招綜合素質(zhì)筆試參考題庫帶答案解析
- 2026年貴州裝備制造職業(yè)學(xué)院單招綜合素質(zhì)考試模擬試題帶答案解析
- 2026年寶雞職業(yè)技術(shù)學(xué)院高職單招職業(yè)適應(yīng)性測試備考試題有答案解析
- 斜弱視眼科學(xué)
- 電商平臺需求規(guī)格說明書-通用版本
- 眼底熒光造影護(hù)理配合
- 2023年電大會計(jì)本人力資源管理復(fù)習(xí)資料
- GB/T 3372-2010拖拉機(jī)和農(nóng)業(yè)、林業(yè)機(jī)械用輪輞系列
- GB/T 25146-2010工業(yè)設(shè)備化學(xué)清洗質(zhì)量驗(yàn)收規(guī)范
- 相關(guān)控規(guī)-申花單元
- 90萬噸煤礦人員配備
- 安川伺服說明書
- 酒精度檢測原始記錄
- 中國私募基金募集與運(yùn)營法律實(shí)務(wù)指南(私募股權(quán)卷)
評論
0/150
提交評論