【SpinalHDL快速入门】4.2、基本类型之Bits-LMLPHP

1.1、描述

Bits类型对应于一个不传达任何算术含义的位向量

1.2、声明

声明位向量的语法如下:(方括号中的所有内容都是可选项)

【SpinalHDL快速入门】4.2、基本类型之Bits-LMLPHP

// Declaration
val myBits = Bits() // the size is inferred
val 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

// Element【这个赋值方式有点意思,之前其他语言都没见过】
val 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)

1.3、运算符

以下运算符可用于 Bits 类型:

1.3.1、逻辑运算(Logic)

【SpinalHDL快速入门】4.2、基本类型之Bits-LMLPHP

// Bitwise operator
val a, b, c = Bits(32 bits)
c := ~(a & b) // Inverse(a AND b)

val all_1 = a.andR // Check that all bits are equal to 1

// Logical shift
val bits_10bits = bits_8bits << 2 // shift left (results in 10 bits)
val shift_8bits = bits_8bits |<< 2 // shift left (results in 8 bits)

// Logical rotation
val myBits = bits_8bits.rotateLeft(3) // left bit rotation

// Set/clear
val a = B"8’x42"
when(cond) {
	a.setAll() // set all bits to True when cond is True
}

注意:

  • 1、 这里值得注意的是:&、|、^操作符中x,y的宽度必须保持一致,否则在生成RTL代码时将提示不能正常编译(可使用resized方法自动扩展剪裁位宽),相当于把RTL中的位宽不匹配警报消除在设计阶段。

  • 2、对于逻辑右移操作:x>>y,y变量类型的不同所产生的结果也不同。y为UInt时和Verilog是比较符合的,移位前后位数不变。实验代码如下:

有点意思的东西,可以琢磨一下

SpinalHDL代码:

package test

import spinal.core._


case 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) //类型转换为UInt,默认是Int
}

object MyTopLevelApp extends App{
  SpinalConfig().generateSystemVerilog(BitsInst())
}
// Generator : SpinalHDL v1.6.0    git head : 73c8d8e2b86b45646e9d0b2e729291f2b65e6be3
// Component : BitsInst



module BitsInst (
  input      [15:0]   data_in1,
  output     [12:0]   data_out1,
  output     [15:0]   data_out2
);

  assign data_out1 = (data_in1 >>> 3); //默认Int移位后进行截断,不会高位补0
  assign data_out2 = (data_in1 >>> 2'b11); //移位后还是原来的位数,高位补0

endmodule

1.3.2、比较(Comparison)

【SpinalHDL快速入门】4.2、基本类型之Bits-LMLPHP

when(myBits === 3) {
}

when(myBits_32 =/= B"32’x44332211") {
}

1.3.3、类型转换(Type cast)

【SpinalHDL快速入门】4.2、基本类型之Bits-LMLPHP

将 Bool、UInt 或 SInt 转换为 Bits,您可以使用 B(something):

// cast a Bits to SInt
val mySInt = myBits.asSInt

// create a Vector of bool
val myVec = myBits.asBools

// Cast a SInt to Bits
val myBits = B(mySInt)

1.3.4、部分赋值/提取操作符(Bit extraction)

【SpinalHDL快速入门】4.2、基本类型之Bits-LMLPHP

// get the element at the index 4
val myBool = myBits(4)

// assign
myBits(1) := True

// Range
val 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

有点意思的东西,可以琢磨一下

Range的三种表示范围

【SpinalHDL快速入门】4.2、基本类型之Bits-LMLPHP

  • 简而言之:todownto是左右闭区间,until是左闭右开区间。

1.3.5、杂项(Misc)

【SpinalHDL快速入门】4.2、基本类型之Bits-LMLPHP

println(myBits_32bits.getWidth) // 32

myBool := myBits.lsb // Equivalent to myBits(0)

// Concatenation
myBits_24bits := bits_8bits_1 ## bits_8bits_2 ## bits_8bits_3

// Subdivide
val sel = UInt(2 bits)
val myBitsWord = myBits_128bits.subdivideIn(32 bits)(sel) //根据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)

// Resize(有点意思!!!)
myBits_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)

resized 有点意思的东西,可以琢磨一下

1.3.6、MaskedLiteral

MaskedLiteral值是带有“-”的位向量,表示不关心的值。【下面的M就表示MaskedLiteral】

val myBits = B"1101
val test1 = myBits === M"1-01" // True
val test2 = myBits === M"0---" // False
val test3 = myBits === M"1--1" // True
06-07 03:11