## UInt/SInt
### 一、描述(Description)
`UInt`/`SInt`数据类型是一个能用在有/无符号计算中的bits向量
### 二、声明(Declaration)
声明整型的语法如下所示:([]中的是可填项)
| 语法 | 描述 | 返回类型 |
| :-----------------------------------------------------------------------------------------------------------: | :----------------------------------------------: | :----------: |
| UInt[()]
SInt[()] | 创建有/无符号整型, bits个数编译器推断得到 | UInt
SInt |
| UInt(x bits)
SInt(x bits) | 创建x bits的有/无符号整型 | UInt
SInt |
| U(value: Int[, xbits])
U(value: BigInt[, x bits])
S(value: Int[, x bits])
S(value: BigInt[, x bits]) | 创建有/无符号整型, 并赋值'value' | UInt
SInt |
| U"[[size']base]value"
S"[[size']base]value" | 创建有/无符号整型, 并赋值'value'(基:h, d, o, b) | UInt
SInt |
| U([x bits, ] element, ...)
S([x bits, ] element, ...) | 创建有/无符号整型, 赋值由element决定 | UInt
SInt |
```Scala
val myUInt = UInt(8 bits)
myUInt := U(2, 8 bits)
myUInt := U(2)
myUInt := U"0000_0101" //基默认二进制
myUInt := U"h1A" //x/h->基16, d->基10, o->基8, b->基2
myUInt := U"8'h1A"
myUInt := 2 //可以使用Scala Int作为字面值
val myBool := myUInt === U(7 -> true, (downto 0) -> false)
val myBool := myUInt === U(myUInt.range -> true)
//在赋值的时候, 可以去掉U/S, 也支持[default -> ???]
myUInt := (default -> true) //赋值“11111111”
myUInt := (myUInt.range -> true) //赋值“11111111
myUInt := (7 -> true, default -> false) //赋值“10000000”
myUInt := ((4 downto 1) -> true, default -> false) //赋值“00011110”
```
```Verilog
wire [7:0] myUInt;
reg [7:0] _zz_myBool;
wire myBool;
function [7:0] zz__zz_myBool(input dummy);
begin
zz__zz_myBool[7] = 1'b1;
zz__zz_myBool[6 : 0] = 7'h0;
end
endfunction
wire [7:0] _zz_1;
assign myUInt = 8'h02;
assign myUInt = 8'h02;
assign myUInt = 8'h05;
assign myUInt = 8'h1A;
assign myUInt = 8'h1A;
assign myUInt = 8'h02;
assign _zz_1 = zz__zz_myBool(1'b0);
always @(*) _zz_myBool = _zz_1;
assign myBool = (myUInt == _zz_myBool);
assign _zz_myBool[7 : 0] = 8'hff;
assign myBool = (myUInt == _zz_myBool);
assign myUInt = 8'hff;
assign myUInt = 8'hff;
assign myUInt = 8'h80;
assign myUInt = 8'h1E;
```
### 三、操作符(Operators)
下面是`UInt`和`SInt`支持的操作符:
1. 逻辑运算(Logic)##这里有问题##
| 操作符 | 描述 | 返回类型 |
| :------------------------: | :-----------------------: | :---------------------: |
| x ^ y | 逻辑异或 | Bool |
| ~x | 按位取非 | T(w(x) bits) |
| x & y | 按位与 | T(max(w(x), w(y)) bits) |
| x | y | 按位或 | T(max(w(x), w(y)) bits) |
| x ^ y | 按位异或 | T(max(w(x), w(y)) bits) |
| x.xorR | x的所有bits取异或 | Bool |
| x.orR | x的所有bits取或 | Bool |
| x.andR | x的所有bits取与 | Bool |
| x >> y | 算术右移, y: Int | T(w(x)-y bits) |
| x >> y | 算术右移, y: UInt | T(w(x) bits) |
| x << y | 算术左移, y: Int | T(w(x)+y bits) |
| x << y | 算术左移, y: UInt | T(w(x)+max(y) bits) |
| x \|>> y | 逻辑右移, y: Int/UInt | T(w(x) bits) |
| x \|<< y | 逻辑左移, y: Int/UInt | T(w(x) bits) |
| x.rotateLeft(y) | 逻辑循环左移, y: UInt/Int | T(w(x) bits) |
| x.rotateRight(y) | 逻辑循环右移, y: UInt/Int | T(w(x) bits) |
| x.clearAll[()] | 清除所有bits | |
| x.setAll[()] | 置位所有bits | |
| x.setAllTo(value: Boolean) | 根据给定Boolean值置位 | |
| x.setAllTo(value: Bool) | 根据给定Bool值置位 | |
> 备注:`x rotateLeft y`和`x rotateRight y`也是有效语句
> 备注:注意`x >> 2`和`x >> U(2)`的区别, 前者返回类型是`T(w(x)-2)`, 后者返回类型是`T(w(x))`, 其次更重要的是, 前者的2视为Int后者的U(2)视为硬件信号。
```Scala
val a, b, c = SInt(32 bits)
a := S(5)
b := S(10)
//比特级操作
c := ~(a & b)
assert(c.getWidth == 32)
//移位
val arithShift = UInt(8 bits) << 2 //结果10 bits
val logicShift = UInt(8 bits) |<< 2 //结果8 bits
assert(arithShift.getWidth == 10)
assert(logicShift.getWidth == 8)
//循环移位
val rotated = UInt(8 bits) rotateLeft 3
assert(rotated.getWidth == 8)
//当a全1, b也全1
when(a.andR) { b.setAll() }
```
Verilog:
```Verilog
wire [31:0] _zz_c;
wire [31:0] a;
reg [31:0] b;
wire [31:0] c;
wire [7:0] _zz_arithShift;
wire [9:0] arithShift;
wire [7:0] _zz_logicShift;
wire [7:0] logicShift;
wire [7:0] _zz_rotated;
wire [7:0] rotated;
wire when_MyTopLevel_l51;
assign _zz_c = (a & b);
assign a = 32'h00000005;
always @(*) begin
b = 32'h0000000a;
if(when_MyTopLevel_l51) begin
b = 32'hffffffff;
end
end
assign c = (~ _zz_c);
assign arithShift = ({2'd0,_zz_arithShift} <<< 2);
assign logicShift = (_zz_logicShift <<< 2);
assign rotated = {_zz_rotated[4 : 0],_zz_rotated[7 : 5]};
assign when_MyTopLevel_l51 = (&a);
```
2. 运算(Arithmetic)
| 操作符 | 描述 | 返回类型 |
| :-------: | :--------: | :-----------------------: |
| x+y | 加法 | T(max(w(x), w(y)) bits) |
| x+^y | 产生进位加 | T(max(w(x), w(y))+1 bits) |
| x+|y | 饱和判断加 | T(max(w(x), w(y)) bits) |
| x-y | 减法 | T(max(w(x), w(y)) bits) |
| x-^y | 产生借位减 | T(max(w(x), w(y))+1 bits) |
| x-\|y | 饱和判断减 | T(max(w(x), w(y)) bits) |
| x*y | 乘法 | T(max(w(x), w(y)) bits) |
| x/y | 除法 | T(w(x)bits) |
| x%y | 取模 | T(w(x)bits) |
```Scala
val a, b, c = UInt(8 bits)
a := U"xf0"
b := U"x0f"
c := a + b
assert(c === U"8'xff")
val d = a +^ b
assert(d === U"9'x0ff")
val e = a +| U"8'x20"
assert(e === U"8'xff")
```
Verilog:
```Verilog
wire [7:0] a;
wire [7:0] b;
wire [7:0] c;
wire [8:0] d;
wire [8:0] _zz_e;
reg [7:0] e;
wire when_UInt_l119;
reg [7:0] counter;
assign a = 8'hf0;
assign b = 8'h0f;
assign c = (a + b);
assign d = ({1'b0,a} + {1'b0,b});
assign _zz_e = ({1'b0,a} + {1'b0,8'h20});
assign when_UInt_l119 = (|_zz_e[8 : 8]);
always @(*) begin
if(when_UInt_l119) begin
e = 8'hff;
end else begin
e = _zz_e[7 : 0];
end
end
```
> 备注:需要注意的是, 该例程的仿真assert用的是`===`, 而相对的上一例程中细化assert用的是`==`
3. 对比操作(Comparison)
| 操作符 | 描述 | 返回类型 |
| :----: | :------: | :------: |
| x===y | 相等 | Bool |
| x=/=y | 不相等 | Bool |
| x>y | 大于 | Bool |
| x>=y | 大于等于 | Bool |
| x b) {
c := U"10"
} elsewhen (a =/= b) {
c := U"01"
} elsewhen (a === U(0)) {
c.setAll()
} otherwise {
c.clearAll()
}
```
Verilog:
```Verilog
wire [7:0] a;
wire [7:0] b;
reg [1:0] c;
wire when_MyTopLevel_l39;
wire when_MyTopLevel_l41;
wire when_MyTopLevel_l43;
reg [7:0] counter;
assign a = 8'h05;
assign b = 8'h0a;
assign when_MyTopLevel_l39 = (b < a);
always @(*) begin
if(when_MyTopLevel_l39) begin
c = 2'b10;
end else begin
if(when_MyTopLevel_l41) begin
c = 2'b01;
end else begin
if(when_MyTopLevel_l43) begin
c = 2'b11;
end else begin
c = 2'b00;
end
end
end
end
ssign when_MyTopLevel_l41 = (a != b);
assign when_MyTopLevel_l43 = (a == 8'h0);
```
4. 类型转换(Type cast)
| 操作符 | 描述 | 返回类型 |
| :--------: | :------------------: | :---------------: |
| x.asBits | 二进制转换成Bits | Bits(w(x) bits) |
| x.asUInt | 二进制转换成UInt | UInt(w(x) bits) |
| x.asSInt | 二进制转换成SInt | SInt(w(x) bits) |
| x.asBools | 转换成Bool数组 | Vec(Bool, w(x)) |
| S(x:T) | 把数据转换成SInt | SInt(w(x) bits) |
| U(x:T) | 把数据转换成UInt | UInt(w(x) bits) |
| x.intoSInt | 扩展符号位转换成SInt | SInt(w(x)+1 bits) |
将`Bool`, `Bits`, `SInt`转化成`UInt`可以用`U(something)`, 将类型转化为SInt的时候可以用`S(something)`。
```Scala
//把SInt转换成Bits
val myBits = mySInt.asBits
//创建一个Bool量
val myVec = myUint.asBools
//把Bits转换成SInt
val mySInt = S(myBits)
```
Verilog:
```Verilog
wire [7:0] mySInt;
wire [7:0] myUInt;
wire [7:0] myBits;
wire myVec_0;
wire myVec_1;
wire myVec_2;
wire myVec_3;
wire myVec_4;
wire myVec_5;
wire myVec_6;
wire myVec_7;
assign myBits = mySInt;
assign myVec_0 = myUInt[0];
assign myVec_1 = myUInt[1];
assign myVec_2 = myUInt[2];
assign myVec_3 = myUInt[3];
assign myVec_4 = myUInt[4];
assign myVec_5 = myUInt[5];
assign myVec_6 = myUInt[6];
assign myVec_7 = myUInt[7];
assign mySInt = myBits;
```
1. 提取比特位(Bit extraction)
| 操作符 | 描述 | 返回类型 |
| :-----------------: | :----------------------------------------------: | :-----------: |
| x(y) | 读第y bits的值 | Bool |
| x(offset, width) | 读bit区域, offset: UInt, width: Int | T(width bits) |
| x(range) | 读某范围内bits, 例如myBits(4 downto 2) | T(range bits) |
| x(y):=z | 赋值某bit, y:Int/UInt | Bool |
| x(offset, width):=z | 赋值bit区域, offset:UInt, width:Int | T(width bits) |
| x(range):=z | 赋值某范围内bits, 例如myBits(4 downto 2):=U"010" | T(range bits) |
```Scala
//取第4bit数据
val myBool = myUInt(4)
//把第1bit赋值为True
mySInt(1) := True
//范围内赋值
val myUInt_8bits = myUInt_16bits(7 downto 0)
val myUInt_7bits = myUInt_16bits(0 to 6)
val myUInt_6bits = myUInt_16bits(0 until 6)
mySInt_8bits(3 downto 0) := mySInt_4bits
```
Verilog:
```Verilog
wire [7:0] myUInt;
reg [7:0] mySInt;
wire [15:0] myUInt_16bits;
reg [7:0] mySInt_8bits;
wire [3:0] mySInt_4bits;
wire myBool;
wire [7:0] myUInt_8bits;
wire [6:0] myUInt_7bits;
wire [5:0] myUInt_6bits;
assign myUInt_16bits = {8'd0, myUInt};
assign myBool = myUInt[4];
assign myUInt_8bits = myUInt_16bits[7 : 0];
assign myUInt_7bits = myUInt_16bits[6 : 0];
assign myUInt_6bits = myUInt_16bits[5 : 0];
always @(*) begin
mySInt_8bits[3 : 0] = mySInt_4bits;
mySInt_8bits[7 : 4] = 4'b0000;
end
always @(posedge clk or posedge reset) begin
if(reset) begin
mySInt <= 8'h0;
end else begin
mySInt[1] <= 1'b1;
end
end
```
5. Misc
| 操作符 | 描述 | 返回类型 |
| :---------------------------: | :--------------------------------------------------------------------: | :--------------------: |
| x.getWidth | 返回bit位数 | Int |
| x.msb | 返回最高有效位 | Bool |
| x.lsb | 返回最低有效位 | Bool |
| x.range | 返回区间范围(x.high到0) | Range |
| x.high | 返回x的上限 | Int |
| x##y | 数据拼接, x->高位, y->低位 | Bits(w(x)+w(y) bits) |
| x@@y | 数据拼接, x:T, y:Bool/SInt/UInt | T(w(x)+w(y) bits) |
| x.subdivideln(y slices) | 把x切片成y份, y:Int | Vec(T,y) |
| x.subdivideln(y bits) | 把x按y bits切片, y:Int | Vec(T,w(x)/y) |
| x.resize(y) | 返回x的长度变换后的复制, UInt长度增大补零, SInt长度增大补符号位, y:Int | T(y bits) |
| x.resized | 返回按需自动确定长度的x | T(w(x) bits) |
| myUInt.twoComplement(en:Bool) | 用补码把UInt转换成SInt | SInt(w(myUInt)+1) |
| mySInt.abs | 返回UInt类型的绝对值 | UInt(w(mySInt),bits) |
| mySInt.abs(en:Bool) | 如果en是True返回UInt类型的绝对值 | UInt(w(mySInt),bits) |
| mySInt.sign | 返回最高有效位 | Bool |
| x.expand | 返回1bit拓展后的x | T(w(x)+1 bits) |
| mySInt.absWithSym | 返回对称收缩1 bit的UInt的绝对值 | UInt(w(mySInt)-1 bits) |
```Scala
myBool := mySInt.lsb //等价于mySInt(0)
//拼接
val mySInt = mySInt_1 @@ mySInt_1 @@ myBool
val myBits = mySInt_1 ## mySInt_1 ## myBool
//分块
val sel = UInt(2 bits)
val mySIntWord = mySInt_128bits.subdivideIn(32 bits)(sel)
//sel = 0 => mySIntWord = mySInt_128bits(128 downto 96)
//sel = 1 => mySIntWord = mySInt_128bits(95 downto 64)
//sel = 2 => mySIntWord = mySInt_128bits(63 downto 32)
//sel = 3 => mySIntWord = mySInt_128bits(31 downto 0)
//如果想要反向访问数据:
val myVector = mySInt_128bits.subdivideIn(32 bits).reverse
val mySIntWord = myVector(sel)
//变换大小
myUInt_32bits := U"32'x11223344"
myUInt_8bits := myUInt_32bits.resized //长度自动推断(myUInt_8bits=0x44)
myUInt_8bits := myUInt_32bits.resize(8) //变换为8 bits(myUInt_8bits=0x44)
//取补码
mySInt := myUInt.twoComplement(myBool)
//取绝对值
mySInt_abs := mySInt.abs
```
Verilog:
```Verilog
wire [15:0] _zz_mySInt;
reg [31:0] _zz_mySIntWord;
wire [31:0] _zz_mySIntWord_1;
wire [31:0] _zz_mySIntWord_2;
wire [31:0] _zz_mySIntWord_3;
wire [31:0] _zz_mySIntWord_4;
wire myBool;
wire [7:0] mySInt_1;
wire [127:0] mySInt_128bits;
wire [16:0] mySInt;
wire [16:0] myBits;
wire [1:0] sel;
wire [31:0] mySIntWord;
wire [31:0] myUInt_32bits;
wire [7:0] myUInt_8bits;
wire [7:0] myUInt;
wire [16:0] mySInt_abs;
assign _zz_mySInt = {mySInt_1,mySInt_1};
assign _zz_mySIntWord_1 = mySInt_128bits[31 : 0];
assign _zz_mySIntWord_2 = mySInt_128bits[63 : 32];
assign _zz_mySIntWord_3 = mySInt_128bits[95 : 64];
assign _zz_mySIntWord_4 = mySInt_128bits[127 : 96];
always @(*) begin
case(sel)
2'b00 : _zz_mySIntWord = _zz_mySIntWord_1;
2'b01 : _zz_mySIntWord = _zz_mySIntWord_2;
2'b10 : _zz_mySIntWord = _zz_mySIntWord_3;
default : _zz_mySIntWord = _zz_mySIntWord_4;
endcase
end
assign myBool = mySInt[0];
assign mySInt = {_zz_mySInt,myBool};
assign myBits = {{mySInt_1,mySInt_1},myBool};
assign mySIntWord = _zz_mySIntWord;
assign myUInt_32bits = 32'h11223344;
assign myUInt_8bits = myUInt_32bits[7:0];
assign myUInt = 8'h28;
assign mySInt_abs = 17'h0;
assign _zz_mySInt = ({myBool,(myBool ? (~ myUInt) : myUInt)} + _zz_mySInt_1);
assign _zz_mySInt_2 = myBool;
assign _zz_mySInt_1 = {8'd0, _zz_mySInt_2};
assign _zz_mySInt_abs = (mySInt[8] ? _zz_mySInt_abs_1 : mySInt);
assign _zz_mySInt_abs_1 = (~ mySInt);
assign _zz_mySInt_abs_3 = mySInt[8];
assign _zz_mySInt_abs_2 = {8'd0, _zz_mySInt_abs_3};
assign mySInt_abs = (_zz_mySInt_abs + _zz_mySInt_abs_2);
```
### 四、定点数操作(FixPoint operations)
对于定点数, 我们可以把它分成两个部分:
+ 低位操作(四舍五入)
+ 高位操作(饱和运算)
1. 低位操作(Lower bit operations)

| SpinalHDL舍入类型 | Wikipedia舍入类型 | API | 数学算法 | 返回(align=false) | 支持程度 |
| :---------------: | :---------------: | :---------: | :--------------------: | :---------------: | :------: |
| FLOOR | RoundDown | floor | floor(x) | w(x)-n bits | Yes |
| FLOORTOZERO | RoundToZero | floorToZero | sign*floor(abs(x)) | w(x)-n bits | Yes |
| CEIL | RoundUp | ceil | ceil(x) | w(x)-n+1 bits | Yes |
| CEILTOINF | RoundToInf | ceilToInf | sign*ceil(abs(x)) | w(x)-n+1 bits | Yes |
| ROUNDUP | RoundHalfUp | roundUp | floor(x+0.5) | w(x)-n+1 bits | Yes |
| ROUNDDOWN | RoundHalfDown | roundDown | ceil(x-0.5) | w(x)-n+1 bits | Yes |
| ROUNDTOZERO | RoundHalfToZero | roundToZero | sign*ceil(abs(x)-0.5) | w(x)-n+1 bits | Yes |
| ROUNDTOINF | RoundHalfToInf | roundToInf | sign*floor(abs(x)+0.5) | w(x)-n+1 bits | Yes |
| ROUNDTOEVEN | RoundHalfToEven | roundToEven | | | |
| ROUNDTOODD | RoundHalfToOdd | roundToOdd | | | |
> 备注:RoundToEven和RoundToOdd模式都非常特殊, 常用在高精度大数据统计领域, SpinalHDL还没有支持它们。
你会发现ROUNDUP, ROUNDDOWN, ROUNDTOZERO, ROUNDTOINF, ROUNDTOEVEN, ROUNDTOODD在行为上非常相似, ROUNDTOINF所最常见的, 不同编程语言中的四舍五入方法可能不同。
| 编程语言 | 默认四舍五入类型 | 举例 | 评估 |
| :--------: | :--------------: | :----------------------------------------------------------: | :-----------------: | |
| Matlab | ROUNDTOINF | round(1.5)=2, round(2.5)=3
round(-1.5)=-2, round(-2.5)=-3 | round to +-Infinity |
| python2 | ROUNDTOINF | round(1.5)=2, round(2.5)=3
round(-1.5)=-2, round(-2.5)=-3 | round to +-Infinity |
| python3 | ROUNDTOEVEN | round(1.5)=round(2.5)=2
round(-1.5)=round(-2.5)=-2 | close to Even |
| Scala.math | ROUNDTOUP | round(1.5)=2, round(2.5)=3
round(-1.5)=-1, round(-2.5)=-2 | always to +Infinity |
| SpinalHDL | ROUNDTOINF | round(1.5)=2, round(2.5)=3
round(-1.5)=-2, round(-2.5)=-3 | round to +-Infinity |
> 备注:在SpinalHDL中ROUNDTOINF默认是RoundType(`round = roundToInf`)
```Scala
val A = SInt(16 bits)
val B = A.roundToInf(6) //默认'align=false', 会得到11 bits
val B = A.roundToInf(6, align = true) //舍去进位, 得到10 bits
val B = A.floor(6 bits) //返回10 bits
val B = A.floorToZero(6 bits) //返回10 bits
val B = A.ceil(6 bits) //带进位故返回11 bits
val B = A.ceil(6 bits, align = true) //舍去进位, 得到10 bits
val B = A.ceilToInf(6 bits)
val B = A.roundUp(6 bits)
val B = A.roundDown(6 bits)
val B = A.roundToInf(6 bits)
val B = A.roundToZero(6 bits)
val B = A.round(6 bits) //SpinalHDL用roundToInf作为默认rounding模式
val B0 = A.roundToInf(6 bits, align = true) //---+
//--> equal
val B1 = A.roundToInf(6 bits, align = false).sat(1) //---+
```
Verilog:
```Verilog
//这里只举一个例子,其他的可自行生成
//val B = A.roundToInf(6, align = true) 当前版本默认align = true,与文档有所不同 有符号数两边近似
wire [16:0] _zz__zz_when_SInt_l337_2;
wire [16:0] _zz__zz_when_SInt_l337_2_1;
wire [5:0] _zz_when_SInt_l191;
wire [10:0] _zz__zz_B_3;
wire [10:0] _zz__zz_B_3_1;
wire [16:0] _zz__zz_B;
wire [16:0] _zz__zz_B_1;
wire [16:0] _zz__zz_B_2;
wire [1:0] _zz_when_SInt_l131;
wire [0:0] _zz_when_SInt_l137;
wire [15:0] A;
reg [10:0] _zz_B;
wire [15:0] _zz_B_1;
wire [15:0] _zz_when_SInt_l337;
wire [15:0] _zz_when_SInt_l337_1;
wire [16:0] _zz_when_SInt_l337_2;
wire [15:0] _zz_B_2;
wire when_SInt_l337;
reg [10:0] _zz_B_3;
wire when_SInt_l191;
reg [9:0] B;
wire when_SInt_l130;
wire when_SInt_l131;
wire when_SInt_l137;
reg [7:0] counter;
assign _zz__zz_when_SInt_l337_2 = {_zz_when_SInt_l337_1[15],_zz_when_SInt_l337_1}; //A符号位拓展1bit
assign _zz__zz_when_SInt_l337_2_1 = {_zz_when_SInt_l337[15],_zz_when_SInt_l337}; //前6bit为0,其余为1的符号位拓展, 即-2^5
assign _zz_when_SInt_l191 = _zz_when_SInt_l337_2[5 : 0]; //A-0.5的小数部分
assign _zz__zz_B_3 = _zz_when_SInt_l337_2[16 : 6]; //A-0.5的整数部分
assign _zz__zz_B_3_1 = 11'h001; //1
assign _zz__zz_B = ($signed(_zz__zz_B_1) + $signed(_zz__zz_B_2)); //符号位拓展后的A+2^5, 相当于A+0.5
assign _zz__zz_B_1 = {_zz_B_2[15],_zz_B_2}; //A符号位拓展1bit
assign _zz__zz_B_2 = {_zz_B_1[15],_zz_B_1}; //2^5符号位拓展1bit
assign _zz_when_SInt_l131 = _zz_B[10 : 9]; //溢出判断位
assign _zz_when_SInt_l137 = _zz_B[9 : 9]; //符号位
assign _zz_B_1 = {{10'h0,1'b1},5'h0}; //16‘b0000_0000_0010_0000, 即2^5
assign _zz_when_SInt_l337 = {11'h7ff,5'h0}; //前5bit为0,其余为1. 即-2^5
assign _zz_when_SInt_l337_1 = A[15 : 0];
assign _zz_when_SInt_l337_2 = ($signed(_zz__zz_when_SInt_l337_2) + $signed(_zz__zz_when_SInt_l337_2_1)); //符号位拓展后的A-2^5, 相当于A-0.5
assign _zz_B_2 = A[15 : 0]; //A
assign when_SInt_l337 = _zz_when_SInt_l337_2[16]; //A-0.5符号位
assign when_SInt_l191 = (|_zz_when_SInt_l191); //A-0.5小数部分是否为0
always @(*) begin
if(when_SInt_l191) begin
_zz_B_3 = ($signed(_zz__zz_B_3) + $signed(_zz__zz_B_3_1)); //非0的话A-0.5的整数部分+1
end else begin
_zz_B_3 = _zz_when_SInt_l337_2[16 : 6]; //0的话结果为 A-0.5 整数部分
end
end
always @(*) begin
if(when_SInt_l337) begin //负数时取
_zz_B = _zz_B_3;
end else begin
_zz_B = (_zz__zz_B >>> 6); //非负时A+0.5整数部分
end
end
assign when_SInt_l130 = _zz_B[10];
assign when_SInt_l131 = (! (&_zz_when_SInt_l131));
always @(*) begin
if(when_SInt_l130) begin
if(when_SInt_l131) begin
B = 10'h200;
end else begin
B = _zz_B[9 : 0];
end
end else begin
if(when_SInt_l137) begin
B = 10'h1ff;
end else begin
B = _zz_B[9 : 0];
end
end
end
assign when_SInt_l137 = (|_zz_when_SInt_l137);
```
> 备注:只有`floor`和`floorToZero`没有`align`选项, 它们不需要进位bit(align=true)。其他近似算法都默认带进位信息。
| API | UInt/SInt | 描述 | Return(align=false) | Return(align=true) |
| :---------: | :-------: | :-------------------------: | :-----------------: | :----------------: |
| floor | Both | | w(x)-n bits | w(x)-n bits |
| floorToZero | SInt | 与无符号floor相等 | w(x)-n bits | w(x)-n bits |
| ceil | Both | | w(x)-n+1 bits | w(x)-n bits |
| ceilToInf | SInt | 与无符号ceil相等 | w(x)-n+1 bits | w(x)-n bits |
| roundUp | Both | 仅为了HW | w(x)-n+1 bits | w(x)-n bits |
| roundDown | Both | | w(x)-n+1 bits | w(x)-n bits |
| roundToInf | SInt | 最常用 | w(x)-n+1 bits | w(x)-n bits |
| roundToZero | SInt | 无符号时等于roundDown | w(x)-n+1 bits | w(x)-n bits |
| round | Both | 在SpinalHDL中默认roundToInf | w(x)-n+1 bits | w(x)-n bits |
> 备注:尽管`roundToInf`很常用, `roundUp`有着最小的开销和最好的时序, 并且几乎没有性能损失。因此强烈推荐使用`roundUp`
2. 高位操作(High bit operations)

| 函数 | 操作 | 正数操作 | 负数操作 |
| :------: | :---: | :---------------------------------: | :----------------------------------: |
| sat | 饱和 | when(Top[w-1, w-n].orR)set maxValue | when(Top[w-1, w-n].andR)set minValue |
| trim | 舍弃 | N/A | N/A |
| symmetry | 对称 | N/A | minValue=-maxValue |
对称仅对`SInt`有效
```Scala
val A = SInt(8 bits)
val B = A.sat(3 bits) //高3 bits饱和的5 bits返回值
val B = A.sat(3) //与上式同理
val B = A.trim(3 bits) //高3 bits舍弃的5bits返回值
val C = A.symmetry //像(-128~127 to -127~127)一样返回8 bits
val C = A.sat(3).symmetry //像(-16~15 to -15~15)一样返回5 bits
```
Verilog:
```Verilog
//饱和
wire [3:0] _zz_when_SInt_l131;
wire [2:0] _zz_when_SInt_l137;
wire [7:0] A;
reg [4:0] B;
wire when_SInt_l130;
wire when_SInt_l131;
wire when_SInt_l137;
assign _zz_when_SInt_l131 = A[7 : 4];
assign _zz_when_SInt_l137 = A[6 : 4];
assign when_SInt_l130 = A[7];
assign when_SInt_l131 = (! (&_zz_when_SInt_l131));
always @(*) begin
if(when_SInt_l130) begin
if(when_SInt_l131) begin
B = 5'h10;
end else begin
B = A[4 : 0];
end
end else begin
if(when_SInt_l137) begin
B = 5'h0f;
end else begin
B = A[4 : 0];
end
end
end
assign when_SInt_l137 = (|_zz_when_SInt_l137);
//trim舍弃
wire [7:0] A;
wire [4:0] B;
assign B = A[4 : 0];
//对称
wire [7:0] _zz_B;
wire [7:0] _zz_B_1;
wire [7:0] A;
wire [7:0] B;
assign _zz_B = 8'h80;
assign _zz_B_1 = 8'h81;
assign B = (($signed(A) == $signed(_zz_B)) ? _zz_B_1 : A);
```
3. fixTo函数(fixTo function)
针对`UInt`/`SInt`提供了两种定点方法:

强烈推荐在RTL工程中使用`fixTo`, 有了这个函数你就不需要处理进位alignment和bit宽度的计算问题, 如同上图Way1那样。
Fix函数关于自动处理饱和:
| 函数 | 描述 | 返回类型 |
| :----------------------------------: | :-----------------: | :---------------: |
| fixTo(section, roundType, symmetric) | Factory FixFunction | section.size bits |
```Scala
val A = SInt(16 bits)
val B = A.fixTo(10 downto 3) //默认的RoundType是ROUNDTOINF, sym=false
val B = A.fixTo(8 downto 0, RoundType.ROUNDUP)
val B = A.fixTo(9 downto 3, RoundType.CEIL, sym = false)
val B = A.fixTo(16 downto 1, RoundType.ROUNDTOINF, sym = true)
val B = A.fixTo(10 downto 3, RoundType.FLOOR) //向下取整3 bits, 舍弃进位5 bits @ highest
val B = A.fixTo(20 downto 3, RoundType.FLOOR) //向下取整3 bits,拓展进位2 bits @ highest
```
Verilog:
```Verilog
wire [7:0] fixTo_dout;
wire [15:0] A;
SInt16fixTo10_3_ROUNDTOINF fixTo (
.din (A[15:0] ), //i
.dout (fixTo_dout[7:0]) //o
);
module SInt16fixTo10_3_ROUNDTOINF (
input [15:0] din,
output [7:0] dout
);
wire [16:0] _zz__zz_dout_4;
wire [16:0] _zz__zz_dout_4_1;
wire [2:0] _zz_when_SInt_l191;
wire [13:0] _zz__zz_dout_6;
wire [13:0] _zz__zz_dout_6_1;
wire [16:0] _zz__zz_dout;
wire [16:0] _zz__zz_dout_1;
wire [16:0] _zz__zz_dout_2;
wire [6:0] _zz_when_SInt_l131;
wire [5:0] _zz_when_SInt_l137;
reg [13:0] _zz_dout;
wire [15:0] _zz_dout_1;
wire [15:0] _zz_dout_2;
wire [15:0] _zz_dout_3;
wire [16:0] _zz_dout_4;
wire [15:0] _zz_dout_5;
wire when_SInt_l337;
reg [13:0] _zz_dout_6;
wire when_SInt_l191;
reg [7:0] _zz_dout_7;
wire when_SInt_l130;
wire when_SInt_l131;
wire when_SInt_l137;
assign _zz__zz_dout_4 = {_zz_dout_3[15],_zz_dout_3};
assign _zz__zz_dout_4_1 = {_zz_dout_2[15],_zz_dout_2};
assign _zz_when_SInt_l191 = _zz_dout_4[2 : 0];
assign _zz__zz_dout_6 = _zz_dout_4[16 : 3];
assign _zz__zz_dout_6_1 = 14'h0001;
assign _zz__zz_dout = ($signed(_zz__zz_dout_1) + $signed(_zz__zz_dout_2));
assign _zz__zz_dout_1 = {_zz_dout_5[15],_zz_dout_5};
assign _zz__zz_dout_2 = {_zz_dout_1[15],_zz_dout_1};
assign _zz_when_SInt_l131 = _zz_dout[13 : 7];
assign _zz_when_SInt_l137 = _zz_dout[12 : 7];
assign _zz_dout_1 = {{13'h0,1'b1},2'b00};
assign _zz_dout_2 = {14'h3fff,2'b00};
assign _zz_dout_3 = din[15 : 0];
assign _zz_dout_4 = ($signed(_zz__zz_dout_4) + $signed(_zz__zz_dout_4_1));
assign _zz_dout_5 = din[15 : 0];
assign when_SInt_l337 = _zz_dout_4[16];
assign when_SInt_l191 = (|_zz_when_SInt_l191);
always @(*) begin
if(when_SInt_l191) begin
_zz_dout_6 = ($signed(_zz__zz_dout_6) + $signed(_zz__zz_dout_6_1));
end else begin
_zz_dout_6 = _zz_dout_4[16 : 3];
end
end
always @(*) begin
if(when_SInt_l337) begin
_zz_dout = _zz_dout_6;
end else begin
_zz_dout = (_zz__zz_dout >>> 3);
end
end
assign when_SInt_l130 = _zz_dout[13];
assign when_SInt_l131 = (! (&_zz_when_SInt_l131));
always @(*) begin
if(when_SInt_l130) begin
if(when_SInt_l131) begin
_zz_dout_7 = 8'h80;
end else begin
_zz_dout_7 = _zz_dout[7 : 0];
end
end else begin
if(when_SInt_l137) begin
_zz_dout_7 = 8'h7f;
end else begin
_zz_dout_7 = _zz_dout[7 : 0];
end
end
end
assign when_SInt_l137 = (|_zz_when_SInt_l137);
assign dout = _zz_dout_7;
```