书接上文,SpinalHDL在Bool的基础上,定义了Bits数据类型,本篇就Bits的初始化及使用方式结合SpinalHDL Doc做一个总结。
Bits:初始化 Bits意味这一组有Bool类型组成的向量,类似与我们在Verilog中的多比特位宽变量。在SpinalHDL中,声明一个Bits变量可采用如下形式(“[]”中为可选项): 相较于Veriog,Bits变量的初始化给了更多灵活的方式用于针对不同的场景:// Declarationval myBits = Bits() // the size is inferredval myBits1 = Bits(32 bits)val myBits2 = B(25, 8 bits)val myBits3 = B"8'xFF" // Base could be x,h (base 16) // d (base 10) // o (base 8) // b (base 2)val myBits4 = B"1001_0011" // _ can be used for readability
// Elementval myBits5 = B(8 bits, default -> True) // "11111111"val myBits6 = B(8 bits, (7 downto 5) -> B"101", 4 -> true, 3 -> True, default -> false) // "10111000"val myBits7 = Bits(8 bits)myBits7 := (7 -> true, default -> false) // "10000000" (For assignment purposes, you can omit the B)
操作符 针对Bits变量,SpinalHDL提供了一系列的操作运算符,如下表所示:
这里值得注意的是:&、|、^操作符中x,y的宽度必须保持一致,否则在生成RTL代码时将提示不能正常编译(可使用resized方法自动扩展剪裁位宽),相当于把RTL中的位宽不匹配警报消除在设计阶段。
对于逻辑右移操作,同时x>>y,y变量类型的不同所产生的结果也不同,看下述代码:
class BitsInst extends Component { val data_in1=in Bits(16 bits) val data_out1=out Bits() val data_out2=out Bits() data_out1:=data_in1>>3 data_out2:=data_in1>>U(3)} 其生成的RTL代码为: module BitsInst ( input [15:0] data_in1, output [12:0] data_out1, output [15:0] data_out2); assign data_out1 = (data_in1 >>> 3); assign data_out2 = (data_in1 >>> 2'b11);endmodule 可以看到 ,data_out1位宽为13个bit,而data_out2位宽为16个比特。结合定义,对比可以看出:若y为Int类型(scala原生类型),所谓的移位操作更像是截断处理,而若y为UInt类型,则和Verilog中的移位操作含义基本相同。此外,虽然生成的RTL代码里采用的是>>>,但由于是无符号数,故而与逻辑右移相同。 由于SpinalHDL会检测":="左右两侧位宽是否相同,所以若在编写时使用错误在生成rtl时即可发现,不会等到仿真时摸不着头脑。
比较操作符 比较操作符Bits变量和Bool变量相同: when(myBits === 3) {}
when(myBits_32 =/= B"32'x44332211") {}
类型转换 Bits类型可以与其他类型之间进行相互转换,SpinalHDL提供的方法如下:val mySInt = myBits.asSInt// create a Vector of boolval myVec = myBits.asBools// Cast a SInt to Bitsval myBits = B(mySInt) 部分赋值/提取操作符
与Verilog/Systemverilog相同,Bits也支持部分读取/赋值操作:
val myBool = myBits(4)val myBits2= Bits(2 bits)// assignmyBits(1) := TruemyBits2:=myBits(2,2 bits)myBits2:=myBits(U(2),2 bits)// Rangeval myBits_8bits = myBits_16bits(7 downto 0)val myBits_7bits = myBits_16bits(0 to 6)val myBits_6bits = myBits_16Bits(0 until 6)
myBits_8bits(3 downto 0) := myBits_4bits 对于x(offset,width bits),其意味着从offset比特位开始,向上截取width比特位宽,上述示例第5行等效于myBits2:=myBits(3 downto 2)。
其他方法
为方便代码设计,SpinalHDL针对Bits也提供了一些其他方法: myBool := myBits.lsb // Equivalent to myBits(0)
// ConcatenationmyBits_24bits := bits_8bits_1 ## bits_8bits_2 ## bits_8bits_3
// Subdivideval sel = UInt(2 bits)val myBitsWord = myBits_128bits.subdivideIn(32 bits)(sel) // sel = 0 => myBitsWord = myBits_128bits(127 downto 96) // sel = 1 => myBitsWord = myBits_128bits( 95 downto 64) // sel = 2 => myBitsWord = myBits_128bits( 63 downto 32) // sel = 3 => myBitsWord = myBits_128bits( 31 downto 0)
// If you want to access in reverse order you can do: val myVector = myBits_128bits.subdivideIn(32 bits).reverse val myBitsWord = myVector(sel)
// ResizemyBits_32bits := B"32'x112233344"myBits_8bits := myBits_32bits.resized // automatic resize (myBits_8bits = 0x44)myBits_8bits := myBits_32bits.resize(8) // resize to 8 bits (myBits_8bits = 0x44)myBits_8bits := myBits_32bits.resizeLeft(8) // resize to 8 bits (myBits_8bits = 0x11
本帖来源微信公从号:Spinal FPGA
网页地址: 链接
|