对于SpinalHDL电路描述,信号的赋值不免有些小伙伴带有些许迷茫,本篇抽丝剥茧,一块儿来梳理。
是val还是var?
先来看两个语法:
对于变量a,声明为val,在对其进行第二次赋值时发现会报错,而声明为var的变量则正常。在Scala里,对于val和var的定义:
**val:不可变变量类型。
var:可变变量类型
这似乎与我们在其他语言中所接触的有些冲突,变量是不可变的为什么还叫变量呢?Scala是一门函数式编程语言,而在函数式编程里,其所倡导的往往是变量的赋值仅有一次,对于其他地方不会对该变量进行重新赋值,这也是引入val类型的原因,颇有些C语言中const类型的意味。
而下面的语句:
这里变量c声明为val,其意味着c所指向的地址不可变更,但我们仍可以修改其指向的内容,这也正式为什么我们能对c(0)赋值,而无法再将c指向一个新声明的Array。
声明师=,赋值靠:=
有了上面的了解,再回到SpinalHDL电路描述里,我们在描述电路时,无论是寄存器还是Mem、这些都是电路对象,其声明有且仅应当只有一次,因而我们在定义变量时,往往这么来定义:
在Scala里一切皆为class,这里我们声明a为一个UInt对象、b为一个RegNext(a)对象,即这里声明a、b均为8比特的寄存器,而寄存器本身一旦定义了是不可变的,为val类型。想一想倘若一会儿将a声明为8bit寄存器,一会儿声明为9比特寄存器,像Verilog中这么写:
想必没人会在Verilog中这么来写吧。同理,在SpinalHDL里,我们声明一个电路对象时,自然是=。
虽然电路对象不可改,就像声明了a是8bit,其一定是8bit,但这8bit所代表的值是可以改变的!!!这也正是我们描述电路里的赋值。
SpinalHDL里为电路对象的赋值提供了三种形式:
我们是为电路对象所代表的值进行赋值,而不是改变电路对象本身(把电路对象指向另一个对象,想一想是否和上面Array的赋值有点儿类似),因而这里我们是不能用=(=在Scala中本身也是一个方法,是改变变量指向的位置,玩不可行),因而所要采用的是SpinalHDL中提供的:=或者\=来给电路对象所代表的含义进行赋值:
由于只有声明为Reg类型的变量才会被当成寄存器类型,这里即可放心使用“:=”。
小结
劝君莫惧Scala,我们在电路描述里用到的语法特性并不多,若有systemverilog的基础那么对于这类软件语言入门没那么可怕,毕竟又不是去转大数据不是么?
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !