0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

在SpinalHDL中如何像軟件調(diào)用方法那樣優(yōu)雅地例化端口

FPGA之家 ? 來源:FPGA之家 ? 作者:FPGA之家 ? 2022-06-13 10:01 ? 次閱讀

在編寫Verilog代碼時(shí)最痛苦的事情便是例化模塊時(shí)端口的連接,這時(shí)候的你我便成了連線工程師,本節(jié)就在SpinalHDL中如何像軟件調(diào)用方法那樣優(yōu)雅地例化端口進(jìn)行探討。

前言

習(xí)慣了寫Verilog的小伙伴們在做大型工程時(shí)是否有遇到過連續(xù)數(shù)天時(shí)間化身“連線工程師”去例化模塊、為端口賦值連接的場景(關(guān)鍵是這些工作量老板他也不認(rèn))。盡管在SystemVerilog中提供了Interface接口的概念,但是從事FPGA的小伙伴都清楚無論是Xilinx的Vivado還是Intel Quartus雖然支持SystemVerilog但遠(yuǎn)沒有做到像軟件代碼編輯器那般做到自動聯(lián)想與提示。最近分析一個(gè)Intel的大型源碼工程其中用到了大量的SystemVerilog中的interface及struct,但自動關(guān)聯(lián)提示做的真是一團(tuán)糟,導(dǎo)致閱讀體驗(yàn)真是差的一匹…… 本文以一個(gè)簡單的加法器的例子來看如何在SpinalHDL中如何避免成為連線工程師。 加法器端口列表如下所示:
端口名 方向 位寬 說明
valid_in input 1 輸入有效標(biāo)志
data1 input 8 輸入數(shù)據(jù)
data2 input 8 輸入數(shù)據(jù)
sum output 8
sum_valid output 1 和有效標(biāo)志

初階

剛開始接觸SpinalHDL時(shí)這個(gè)加法器我們可能會這么來寫:


class add(dataWidth:Int) extends Component{  val validIn=in Bool()  val data1=in UInt(dataWidth bits)  val data2=in UInt(dataWidth bits)  val sum=out UInt(dataWidth bits)  val sumValid=out Bool()  sum:=RegNextWhen(data1+data2,validIn)  sumValid:=RegNext(validIn,False)}

這里針對端口的實(shí)現(xiàn)形式和我們在Verilog中的方式基本相同。那么當(dāng)我們在例化這個(gè)模塊時(shí),我們可能會這么來寫:


class addInst(dataWidth:Int) extends Component {  val io=new Bundle{    val validIn_0=in Bool()    val data1_0=in UInt(dataWidth bits)    val data2_0=in UInt(dataWidth bits)    val sum_0=out UInt(dataWidth bits)    val sumValid_0=out Bool()
    val validIn_1=in Bool()    val data1_1=in UInt(dataWidth bits)    val data2_1=in UInt(dataWidth bits)    val sum_1=out UInt(dataWidth bits)    val sumValid_1=out Bool()  }  val add0=new add(dataWidth)  val add1=new add(dataWidth)  add0.validIn<>io.validIn_0  add0.data1<>io.data1_0  add0.data2<>io.data2_0  add0.sum<>io.sum_0  add0.sumValid<>io.sumValid_0    add1.validIn<>io.validIn_1  add1.data1<>io.data1_1  add1.data2<>io.data2_1  add1.sum<>io.sum_1  add1.sumValid<>io.sumValid_1}

這里例化了兩個(gè)加法器,可以看到,這里如同我們寫Verilog代碼般一根根連線,當(dāng)有眾多模塊需要去例化時(shí)還是蠻痛苦的。

中階

在SystemVerilog中提供了Interface的概念用于封裝接口,在SpinalHDL中,我們可以借助軟件面向?qū)ο蟮乃枷氚呀涌诮o抽象出來:


case class sumPort(dataWidth:Int=8) extends Bundle with IMasterSlave{  case class dataPort(dataWidth:Int=8) extends Bundle{    val data1=UInt(dataWidth bits)    val data2=UInt(dataWidth bits)  }  val dataIn=Flow(dataPort(dataWidth))  val sum=Flow(UInt(dataWidth bits))
  override def asMaster(): Unit = {    master(dataIn)    slave(sum)  }}

這里我們將加法器的端口抽象成sumPort端口。其中包含兩個(gè)Flow類型:dataIn、sum。并聲明當(dāng)作為master端口時(shí)dataIn為master、sum為slave。這樣,我們的加法器便可以這么來寫:


case class add2(dataWidth:Int=8)extends Component{  val io=new Bundle{    val sumport=slave(sumPort(dataWidth))  }  io.sumport.sum.payload:=RegNextWhen(io.sumport.dataIn.data1+io.sumport.dataIn.data2,io.sumport.dataIn.valid)  io.sumport.sum.valid:=RegNext(io.sumport.dataIn.valid,False)}

而我們在例化時(shí),便可以簡潔地例化:


class addInst1(dataWidth:Int) extends Component{  val io=new Bundle{    val sumport0=slave(sumPort(dataWidth))    val sumport1=slave(sumPort(dataWidth))  }  val addInst_0=add2(dataWidth)  val addInst_1=add2(dataWidth)  io.sumport0<>addInst_0.io.sumport  io.sumport1<>addInst_1.io.sumport}

如此我們便能簡潔地例化加法器。雖然這里地做法思想和SystemVerilog中地思想基本一致,但好處是我們能夠在IDEA中像閱讀軟件代碼那般快速地跳轉(zhuǎn)和定位,相較于廠商工具中那樣分析工程地痛苦實(shí)在是好太多。

高階

在中階例,我們采用了類似SystemVerilog中Interface及struct概念,但可以發(fā)現(xiàn),我們這里依舊存在連線行為。一個(gè)模塊例化一次要連線一次,要例化N次還是要……

在軟件代碼中,調(diào)用一個(gè)方法或者模塊往往一行代碼了事:聲明調(diào)用函數(shù)并將參數(shù)放在括號列表里。那么在這里,我們能否像軟件調(diào)用那樣一行代碼搞定呢?

可以的!由于SpinalHDL是基于Scala的,因此我們可以將端口列表當(dāng)成參數(shù)列表來傳遞。這里我們先為我們的加法器定義一個(gè)伴生對象:


object add2{  def apply(dataWidth: Int,port Unit = {    val addInst=new add2(dataWidth)    addInst.io.sumport<>port  }}

這里我們?yōu)榧臃ㄆ鱝dd2定義了一個(gè)伴生對象(伴生對象聲明為object,名字與類名相同)。并在其中定義了一個(gè)apply方法,傳入兩個(gè)參數(shù):位寬dataWidth及端口port,并在apply實(shí)現(xiàn)中完成模塊例化及端口連接(一次連線,終身使用)。隨后我們在例化時(shí)便可以像軟件調(diào)用方法那樣例化模塊了:


class addInst1(dataWidth:Int) extends Component{  val io=new Bundle{    val sumport0=slave(sumPort(dataWidth))    val sumport1=slave(sumPort(dataWidth))  }  add2(dataWidth,io.sumport0)  add2(dataWidth,io.sumport0)}

一行代碼搞定一個(gè)模塊的一次例化和端口連接!

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 加法器
    +關(guān)注

    關(guān)注

    6

    文章

    183

    瀏覽量

    30046
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4701

    瀏覽量

    68126
  • 編輯器
    +關(guān)注

    關(guān)注

    1

    文章

    799

    瀏覽量

    31022

原文標(biāo)題:SpinalHDL—像軟件調(diào)用方法般例化模塊

文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    三相維也納電路,是否需要單項(xiàng)那樣加一個(gè)pfc芯片?

    本人接了一個(gè)項(xiàng)目,需要輸入端380-525vac輸入,但是輸出要達(dá)到600-800vdc,電流14-17a,想用三相維也納電路,但現(xiàn)在迷茫如何看電路pf值是否得到了矯正,需不需要單項(xiàng)那樣加一個(gè)pfc芯片,因?yàn)橐獙?shí)現(xiàn)軟啟動,過
    發(fā)表于 10-17 09:31

    ad端口的幾種類型

    Altium Designer(簡稱AD)等電子設(shè)計(jì)自動(EDA)軟件,端口(Port)是設(shè)計(jì)原理圖時(shí)用于連接和表示信號流動的重要元素
    的頭像 發(fā)表于 09-29 10:11 ?570次閱讀

    請問studio可以裸機(jī)一樣調(diào)用定時(shí)器中斷嗎?

    studio可以裸機(jī)一樣調(diào)用定時(shí)器中斷嗎?我調(diào)用后顯示出錯(cuò)了,使用hal庫還需要添加什么嗎
    發(fā)表于 09-13 08:18

    求助各位關(guān)于Verilog當(dāng)中模塊、端口與引腳 的問題

    初學(xué)者。我刷HDLbits的時(shí)候做到了這道題 答案: 答案給的是定義了wire型的信號,并借這個(gè)來進(jìn)行端口連接。而我的疑問在于: 1.模塊化時(shí),如果采用按名字的方式進(jìn)行
    發(fā)表于 07-15 20:38

    STM32的IO口能不能51的IO口那樣直接控制Px口輸出?

    大家好,STM32的IO口能不能51的IO口那樣直接控制Px口輸出?比如我要用51控制器段數(shù)碼管,只要給Px口送十六進(jìn)制數(shù)值就可以了?請問STM32可以嗎?
    發(fā)表于 04-07 07:59

    淺析SpinalHDLPipeline的復(fù)位定制

    之前有系列文章介紹了SpinalHDLPipeline的使用,最近在一個(gè)功能模塊真實(shí)的使用了這個(gè)lib。
    的頭像 發(fā)表于 03-17 17:31 ?941次閱讀
    淺析<b class='flag-5'>SpinalHDL</b><b class='flag-5'>中</b>Pipeline<b class='flag-5'>中</b>的復(fù)位定制

    verilog端口類型有哪三種

    Verilog ,端口類型有三種:輸入端口(input)、輸出端口(output)和雙向端口
    的頭像 發(fā)表于 02-23 10:28 ?1717次閱讀

    verilog調(diào)用模塊端口對應(yīng)方式

    Verilog是一種硬件描述語言(HDL),廣泛應(yīng)用于數(shù)字電路設(shè)計(jì)和硬件驗(yàn)證。Verilog,模塊是構(gòu)建電路的基本單元,而模塊端口對應(yīng)方式則用于描述模塊之間信號傳遞的方式。本文將介紹
    的頭像 發(fā)表于 02-23 10:20 ?1401次閱讀

    #2024,立Flag了嘛? #win平臺搭建SpinalHDL開發(fā)環(huán)境

    1、軟件下載 首先列出我們需要安裝的軟件:IDEA(社區(qū)版就行,不需要采用特殊的方法去PJ)、JDK17(也是免費(fèi)的); 2、軟件安裝 2.1、IntelliJ IDEA安裝 其他的按
    發(fā)表于 01-21 10:52

    如何在同步的 Rust 方法調(diào)用異步代碼 | Tokio 使用的幾點(diǎn)教訓(xùn)

    同步的 Rust 方法調(diào)用異步代碼經(jīng)常會導(dǎo)致一些問題,特別是對于不熟悉異步 Rust runtime 底層原理的初學(xué)者。
    的頭像 發(fā)表于 12-24 16:23 ?1204次閱讀

    HamronyOS自動測試框架使用指南

    錯(cuò)誤,即用執(zhí)行超時(shí) 可能原因 1.用執(zhí)行異步接口,但執(zhí)行過程沒有執(zhí)行到 done 函數(shù),導(dǎo)致用執(zhí)行一直沒有結(jié)束,直到超時(shí)結(jié)束。 2.用
    發(fā)表于 12-19 10:26

    Linux系統(tǒng)調(diào)用腳本的常見方法

    linux系統(tǒng)中有多種方法可以系統(tǒng)啟動后調(diào)用腳本,接下來介紹幾種常見的方法
    的頭像 發(fā)表于 12-13 18:16 ?949次閱讀

    SpinalHDL 1.9.4版本的PackedBundle、PackedWordBundle的使用

    ? ? 聊一聊SpinalHDL 1.9.4版本的PackedBundle、PackedWordBundle的使用 位域的提取與封裝 ????邏輯設(shè)計(jì)里,但凡牽涉到協(xié)議,一般都避免不了協(xié)議字段
    的頭像 發(fā)表于 11-11 15:35 ?1061次閱讀
    <b class='flag-5'>SpinalHDL</b> 1.9.4版本<b class='flag-5'>中</b>的PackedBundle、PackedWordBundle的使用

    ARM能51單片機(jī)那樣用idata Xdata等定義變量嗎?

    ARM能51單片機(jī)那樣用idata Xdata等定義變量嗎
    發(fā)表于 11-06 07:49

    時(shí)間序列的基礎(chǔ)模型自然語言處理那樣存在嗎

    時(shí)間序列預(yù)測領(lǐng)域最近的幾年有著快速的發(fā)展,比如N-BEATS、N-HiTS、PatchTST和TimesNet。 大型語言模型(LLM)最近在ChatGPT等應(yīng)用程序變得非常流行,因?yàn)樗鼈兛梢?/div>
    的頭像 發(fā)表于 11-03 10:15 ?578次閱讀
    時(shí)間序列的基礎(chǔ)模型<b class='flag-5'>像</b>自然語言處理<b class='flag-5'>那樣</b>存在嗎