最近做些RTL代碼連線正確性檢查的一些事情,在對(duì)于Verilog代碼進(jìn)行連接性檢查,只能依賴仿真的形式,過(guò)程深感不便。且在一個(gè)大型工程里,比如檢測(cè)一個(gè)fifo的overflow是否都連接到了debug接口上通過(guò)仿真就是一個(gè)很耗時(shí)的事情。作為SpinalHDL的堅(jiān)定支持者,這種類型的工作交給代碼自己做,在SpinalHDL里so easy。
》連接性檢查所謂的連接性檢查,無(wú)非就是A、B兩個(gè)信號(hào),判斷下兩者之間有沒(méi)有驅(qū)動(dòng)關(guān)系。比如說(shuō)我們認(rèn)為A應(yīng)該驅(qū)動(dòng)B,在仿真里Force A為一個(gè)值,然后delay一段時(shí)間看B是否有變更為對(duì)應(yīng)的值。如果針對(duì)某一類連線規(guī)則,在Verilog里通過(guò)這種仿真的形式一根根進(jìn)行檢查是一個(gè)很耗時(shí)的事情。然而在SpinalHDL里,采用LatencyAnalysis,搞什么仿真,輕輕松幾行代碼定義下規(guī)則就可以搞定了。如上面的判斷A是否有驅(qū)動(dòng)B,僅需通過(guò)下面的一行代碼即可:
LatencyAnalysis(A,B)
其會(huì)自動(dòng)分析A到B之間的路徑并返回其寄存器級(jí)數(shù)。即使跨時(shí)鐘域也能輕松搞定。
》Example通過(guò)在代碼里制定連接性檢查規(guī)則,根本不需要仿真,生成RTL代碼的時(shí)候就可以直接順便把這件事給做了。以下面的例子為例:
importspinal.core._
importspinal.lib._
object connectCheck{
def fifoPortCheck(componecnt:Component,portBoolean={
for(elem <- componecnt.children) {
??????elem match {
????????casefifo: StreamFifo[BaseType]=> {
println(s"Start Check ${componecnt.getName()} ${fifo.getName()} ${fifo.io.pop.valid.getName} to ${port.getName()} connection")
LatencyAnalysis(fifo.io.pop.valid,port)>=0
}
case_=>true
}
fifoPortCheck(elem,port)
}
true
}
}
caseclasstest1() extendsComponent{
val io=newBundle{
val data0=out Bool()
}
noIoPrefix()
val fifoInst=Array.fill(10)(StreamFifo(UInt(8bits),16))
fifoInst.foreach(fifo=>{
fifo.io.push.valid.clear()
fifo.io.push.payload.clearAll()
fifo.io.pop.ready.clear()
})
val test2Inst=test2()
io.data0:=fifoInst.map(_.io.pop.valid).reduce(_|_)|test2Inst.io.data0
connectCheck.fifoPortCheck(this,io.data0)
}
caseclasstest2() extendsComponent{
val io=newBundle{
val data0=out Bool()
}
noIoPrefix()
val fifoInst=Array.fill(10)(StreamFifo(UInt(8bits),16))
fifoInst.foreach(fifo=>{
fifo.io.push.valid.clear()
fifo.io.push.payload.clearAll()
fifo.io.pop.ready.clear()
})
io.data0:=fifoInst.map(_.io.pop.valid).reduce(_|_)
}
這里test2里面定義了10個(gè)StreamFifo,所有fifo的pop.valid通過(guò)或的形式連接到io.data0上。然后在test1里例化了test2和10個(gè)StreamFifo,將10個(gè)StreamFifo的pop.valid和test2的data0通過(guò)或的形式驅(qū)動(dòng)io.data0。
假定我們?cè)谠O(shè)計(jì)里定義如下規(guī)則:
-
test1下面的所有模塊的Stream Fifo的pop.valid都需要連接到test1的輸出端口io.data0上。
這里我們定義了一個(gè)fifoPortCheck函數(shù)用于做這件事,它會(huì)遍歷指定component下面的所有StreamFifo,通過(guò)LatencyAnalysis判斷其pop.valid是否與指定port之間是否存在連接關(guān)系。
如此,在生成代碼時(shí)便會(huì)有下面的檢查信息顯示:
這不比仿真來(lái)的快的多么,也無(wú)需發(fā)現(xiàn)錯(cuò)誤自己挨個(gè)去找各模塊的負(fù)責(zé)人,只需統(tǒng)一制定好規(guī)則,每個(gè)人自己就能檢查,喝口水的功夫~。
現(xiàn)在我們把test1里面的test2Inst的data0拿掉不讓他驅(qū)動(dòng)test1的io.data0:
caseclasstest1() extendsComponent{
val io=newBundle{
val data0=out Bool()
}
noIoPrefix()
val fifoInst=Array.fill(10)(StreamFifo(UInt(8bits),16))
fifoInst.foreach(fifo=>{
fifo.io.push.valid.clear()
fifo.io.push.payload.clearAll()
fifo.io.pop.ready.clear()
})
val test2Inst=test2()
io.data0:=fifoInst.map(_.io.pop.valid).reduce(_|_)
connectCheck.fifoPortCheck(this,io.data0)
}
生成RTL代碼時(shí)就會(huì)報(bào)錯(cuò):
告知test2Inst中的StreamFifo并沒(méi)有驅(qū)動(dòng)test1中的io.data0,規(guī)則不過(guò),根本不讓你生成Verilog代碼,仿真靠邊站~
效率就是這么提升的~
-
寄存器
+關(guān)注
關(guān)注
31文章
5434瀏覽量
124514 -
驅(qū)動(dòng)
+關(guān)注
關(guān)注
12文章
1918瀏覽量
86940 -
代碼
+關(guān)注
關(guān)注
30文章
4900瀏覽量
70751
原文標(biāo)題:連線對(duì)不對(duì),仿真靠邊站,讓代碼自己做
文章出處:【微信號(hào):Spinal FPGA,微信公眾號(hào):Spinal FPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
評(píng)論