SpinalEnum
一、描述(Description)
Enumeration
类型代表一组值组成的列表
二、声明(Declaration)
枚举数据类型的声明方式如下:
object Enumeration extends SpinalEnum {
val element0, element1, ..., elementN = newElement()
}
对于上述例子, 使用默认的编码方式。原生的枚举类型用于VHDL, 二进制编码用于Verilog。
能够通过下述方式强制使用枚举编码:
object Enumeration extends SpinalEnum(defaultEncoding=encodingOfYourChoice) {
val element0, element1, ..., elementN = newElement()
}
备注:如果想为给定的模块定义枚举类型的输入/输出, 应该用如下方式定义:
in(MyEnum())
或者out(MyEnum)
编码(Encoding)
SpinalHDL支持下述的枚举编码方式:
编码方式 | Bit位宽 | 描述 |
---|---|---|
native | 这是默认编码方式, 使用VHDL枚举系统 | |
binarySequential | log2Up(stateCount) | 以声明的顺序使用Bits存储状态(值从0到n-1) |
binaryOneHot | stateCount | 使用Bits来存储状态, 每个bit对应一个状态 |
定制化的编码方式能用静态和动态的方式实现:
/*
*静态编码方式
*/
object MyEnumStatic extends SpinalEnum {
val e0, e1, e2, e3 = newElement()
defaultEncoding = SpinalEnumEncoding("staticEncoding")(
e0 -> 0,
e1 -> 2,
e2 -> 3,
e3 -> 7
)
/*
*用函数动态编码: _ * 2 + 1
*e.g. : e0 => 0 * 2 + 1 = 1
* e1 => 1 * 2 + 1 = 3
* e2 => 2 * 2 + 1 = 5
* e3 => 3 * 2 + 1 = 7
*/
val encoding = SpinalEnumEncoding("dynamicEncoding", _ * 2 + 1)
object MyEnumDynamic extends SpinalEnum(encoding) {
val e0, e1, e2, e3 = newElement()
}
}
举例(Example)
初始化枚举信号并给它赋值:
object UartCtrlTxState extends SpinalEnum { val sIdle, sStart, sData, sParity, sStop = newElement() } val stateNext = UartCtrlTxState() stateNext := UartCtrlTxState.sIdle //你也可以import枚举类型使其元素可视化, 需要放在package里 import UartCtrlTxState._ stateNext := sIdle
Verilog:
localparam UartCtrlTxState_sIdle = 3'd0; localparam UartCtrlTxState_sStart = 3'd1; localparam UartCtrlTxState_sData = 3'd2; localparam UartCtrlTxState_sParity = 3'd3; localparam UartCtrlTxState_sStop = 3'd4; wire [2:0] stateNext; `ifndef SYNTHESIS reg [55:0] stateNext_string; `endif `ifndef SYNTHESIS always @(*) begin case(stateNext) UartCtrlTxState_sIdle : stateNext_string = "sIdle "; UartCtrlTxState_sStart : stateNext_string = "sStart "; UartCtrlTxState_sData : stateNext_string = "sData "; UartCtrlTxState_sParity : stateNext_string = "sParity"; UartCtrlTxState_sStop : stateNext_string = "sStop "; default : stateNext_string = "???????"; endcase end `endif assign stateNext = UartCtrlTxState_sIdle;
三、操作符(Operators)
以下是可供Enumeration
类型使用的操作符:
比较运算(Comparison)
|操作符|描述|返回类型| |x===y|相等|Bool| |x=/=y|不相等|Bool|
import UartCtrlTxState._ val stateNext = UartCtrlTxState() stateNext := sIdle when(stateNext === sStart) { ... } switch(stateNext) { is(sIdle) { ... } is(sStart) { ... } ... }
类型(Types)
为了使用你的enum, 例如在函数里, 你需要它的类型。
enum中值的类型(例如sIdle的类型):
spinal.core.SpinalEnumElement[UartCtrlTxState.type]
或者等价地, 也可以如下方式
UartCtrlTxState.E
bundle的类型(例如stateNext的类型):
spinal.core.SpinalEnumCraft[UartCtrlTxState.type]
或者等价地, 也可以用如下方式
UartCtrlTxState.C
类型转换(Type cast)
操作符 | 描述 | 返回类型 |
---|---|---|
x.asBits | 二进制转换为Bits | Bits(w(x) bits) |
x.asUInt | 二进制转换为UInt | UInt(w(x) bits) |
x.asSInt | 二进制转换为SInt | SInt(w(x) bits) |
e.assignFromBits(bits) | Bits转换为enum | MyEnum() |
import UartCtrlTxState._
val stateNext = UartCtrlTxState()
myBits := sIdle.asBits
stateNext.assignFromBits(myBits)
Verilog:
localparam UartCtrlTxState_sIdle = 3'd0;
localparam UartCtrlTxState_sStart = 3'd1;
localparam UartCtrlTxState_sData = 3'd2;
localparam UartCtrlTxState_sParity = 3'd3;
localparam UartCtrlTxState_sStop = 3'd4;
wire [2:0] myBits;
wire [2:0] stateNext;
wire [2:0] _zz_stateNext;
reg [7:0] counter;
`ifndef SYNTHESIS
reg [55:0] stateNext_string;
reg [55:0] _zz_stateNext_string;
`endif
`ifndef SYNTHESIS
always @(*) begin
case(stateNext)
UartCtrlTxState_sIdle : stateNext_string = "sIdle ";
UartCtrlTxState_sStart : stateNext_string = "sStart ";
UartCtrlTxState_sData : stateNext_string = "sData ";
UartCtrlTxState_sParity : stateNext_string = "sParity";
UartCtrlTxState_sStop : stateNext_string = "sStop ";
default : stateNext_string = "???????";
endcase
end
always @(*) begin
case(_zz_stateNext)
UartCtrlTxState_sIdle : _zz_stateNext_string = "sIdle ";
UartCtrlTxState_sStart : _zz_stateNext_string = "sStart ";
UartCtrlTxState_sData : _zz_stateNext_string = "sData ";
UartCtrlTxState_sParity : _zz_stateNext_string = "sParity";
UartCtrlTxState_sStop : _zz_stateNext_string = "sStop ";
default : _zz_stateNext_string = "???????";
endcase
end
`endif
assign myBits = UartCtrlTxState_sIdle;
assign _zz_stateNext = myBits;
assign stateNext = _zz_stateNext;