SpinalHDL之RegIf(上篇)

本文作为SpinalHDL学习笔记第二十一篇,介绍SpinalHDL RegIf相关API。

SpinalHDL 学习笔记_spinalhdl blackbox-CSDN博客

RegIf寄存器接口搭建器功能:

• 自动寻址、字段分配和冲突检测

• 28 种寄存器访问类型(涵盖 UVM 标准定义的 25 种类型)

• 自动生成文档

目录:

1.自动分配

2.28种访问类型

3.自动生成文档

4.特殊访问用途

1.自动分配

自动地址分配:

class RegBankExample extends Component {
val io = new Bundle {
apb = slave(Apb3(Apb3Config(16,32)))
}
val busif = Apb3BusInterface(io.apb,(0x0000, 100 Byte))
val M_REG0 = busif.newReg(doc="REG0")
val M_REG1 = busif.newReg(doc="REG1")
val M_REG2 = busif.newReg(doc="REG2")
val M_REGn = busif.newRegAt(address=0x40, doc="REGn")
val M_REGn1 = busif.newReg(doc="REGn1")
busif.accept(HtmlGenerator("regif", "AP"))
// busif.accept(CHeaderGenerator("header", "AP"))
// busif.accept(JsonGenerator("regif"))
// busif.accept(RalfGenerator("regbank"))
// busif.accept(SystemRdlGenerator("regif", "AP"))
}

 自动字段分配:

val M_REG0 = busif.newReg(doc="REG1")
val fd0 = M_REG0.field(Bits(2 bit), RW, doc= "fields 0")
M_REG0.reserved(5 bits)
val fd1 = M_REG0.field(Bits(3 bit), RW, doc= "fields 0")
val fd2 = M_REG0.field(Bits(3 bit), RW, doc= "fields 0")
//auto reserved 2 bits
val fd3 = M_REG0.fieldAt(pos=16, Bits(4 bit), doc= "fields 3")
//auto reserved 12 bits

冲突检测:

val M_REG1 = busif.newReg(doc="REG1")
val r1fd0 = M_REG1.field(Bits(16 bits), RW, doc="fields 1")
val r1fd2 = M_REG1.field(Bits(18 bits), RW, doc="fields 1")
...
cause Exception
val M_REG1 = busif.newReg(doc="REG1")
val r1fd0 = M_REG1.field(Bits(16 bits), RW, doc="fields 1")
val r1fd2 = M_REG1.fieldAt(pos=10, Bits(2 bits), RW, doc="fields 1")
...
cause Exception

2.28种访问类型

其中大部分来自 UVM 规范:

访问类型

描述

来源

RO

w:无影响, r:无影响

UVM

RW

w:保持原样, r:无影响

UVM

RC

w:无影响, r:清除所有比特

UVM

RS

w:无影响, r:置位所有比特

UVM

WRC

w:保持原样, r:清除所有比特

UVM

WRS

w:保持原样, r:置位所有比特

UVM

WC

w:清除所有比特, r:无影响

UVM

访问类型

描述

来源

WS

w:置位所有比特, r:无影响

UVM

WSRC

w:置位所有比特, r:清除所有比特

UVM

WCRS

w:清除所有比特, r:置位所有比特

UVM

W1C

w: 1/0 对匹配位清除/无影响, r:无影响

UVM

W1S

w: 1/0 对匹配位置位/无影响, r:无影响

UVM

W1T

w: 1/0 对匹配位翻转/无影响, r:无影响

UVM

W0C

w: 1/0 对匹配位清除/无影响, r:无影响

UVM

W0S

w: 1/0 对匹配位置位/无影响, r:无影响

UVM

W0T

w: 1/0 对匹配位翻转/无影响, r:无影响

UVM

W1SRC

w: 1/0 对匹配位置位/无影响, r:清除所有比特

UVM

W1CRS

w: 1/0 对匹配位清除/无影响, r:置位所有比特

UVM

W0SRC

w: 1/0 对匹配位置位/无影响, r:清除所有比特

UVM

W0CRS

w: 1/0 对匹配位清除/无影响, r:置位所有比特

UVM

WO

w:保持原样, r:错误

UVM

WOC

w:清除所有比特, r:错误

UVM

WOS

w:置位所有比特, r:错误

UVM

W1

w:硬复位后第一个 w 保持原样,其他 w 无影响, r:无影响

UVM

WO1

w:硬复位后第一个 w 保持原样,其他 w 无影响, r:错误

UVM

NA

w:保留, r:保留

新的

W1P

w: 1/0 对匹配位脉冲 (pulse)/无影响, r:无影响

新的

W0P

w: 0/1 对匹配位脉冲 (pulse)/无影响, r:无影响

新的

HSRW

w:硬件置位,软件 RW

新的

RWHS

w:软件 RW、硬件置位

新的

ROV

w:只读值,用于硬件版本

新的

CSTM

w:用户自定义类型,用于文档

新的

3.自动生成文档

文档类型:

文 档 类型

用法

状态

HTML

busif.accept(HtmlGenerator("regif", title = "XXX registerfile"))

Y

CHeader

busif.accept(CHeaderGenerator("header", "AP"))

Y

JSON

busif.accept(JsonGenerator("regif"))

Y

RALF(UV

M)busif.accept(RalfGenerator("header"))

Y

SystemRDL

busif.accept(SystemRdlGenerator("regif", "addrmap_name",
Some("name"), Some("desc")))

Y

Latex(pdf)

N

docx

N

生成的 HTML 文档:

 

4.特殊访问用途

案例 1: RO 用法

RO 与其他类型不同。它不创建寄存器,需要外部信号来驱动它,注意,请不要忘记驱动它。

val io = new Bundle {
val cnt = in UInt(8 bit)
}
val counter = M_REG0.field(UInt(8 bit), RO, 0, "counter")
counter := io.cnt

val xxstate = M_REG0.field(UInt(8 bit), RO, 0, "xx-ctrl state").asInput

val overflow = M_REG0.field(Bits(32 bit), RO, 0, "xx-ip paramete")
val ovfreg = Reg(32 bit)
overflow := ovfreg

val inc = in Bool()
val couter = M_REG0.field(UInt(8 bit), RO, 0, "counter")
val cnt = Counter(100, inc)
couter := cnt

案例 2: ROV 用法

ASIC 设计常常需要一些固化的版本信息。与 RO 不同,它不会产生有线信号

旧方法:

val version = M_REG0.field(Bits(32 bit), RO, 0, "xx-device version")
version := BigInt("F000A801", 16)

新方法:

M_REG0.field(Bits(32 bit), ROV, BigInt("F000A801", 16), "xx-device version")(Symbol("Version"))

案例 3: HSRW/RWHS 在某些情况下的硬件设置类型,此类寄存器不仅可以由软件配置,还可以由硬件信号设置

val io = new Bundle {
val xxx_set = in Bool()
val xxx_set_val = in Bits(32 bit)
}
val reg0 = M_REG0.fieldHSRW(io.xxx_set, io.xxx_set_val, 0, "xx-device version") //0x0000
val reg1 = M_REG1.fieldRWHS(io.xxx_set, io.xxx_set_val, 0, "xx-device version") //0x0004
always @(posedge clk or negedge rstn)
if(!rstn) begin
reg0 <= '0;
reg1 <= '0;
end else begin
if(hit_0x0000) begin
reg0 <= wdata ;
end
if(io.xxx_set) begin //HW have High priority than SW
reg0 <= io.xxx_set_val ;
end
if(io.xxx_set) begin
reg1 <= io.xxx_set_val ;
end
if(hit_0x0004) begin //SW have High priority than HW
reg1 <= wdata ;
end
end

案例 4: CSTM 虽然 SpinalHDL 包含 25 种寄存器类型和 6 种扩展类型,但在实际应用中仍然对私有寄存器类型有各种需求。因此,我们保留 CSTM 类型以实现可扩展性。 CSTM 仅用于生成软件接口,不生成实际电路

val reg = Reg(Bits(16 bit)) init 0
REG.registerAtOnlyReadLogic(0, reg, CSTM("BMRW"), resetValue = 0, "custom field")
when(busif.dowrite) {
reg := reg & ~busif.writeData(31 downto 16) | busif.writeData(15 downto 0) & busif.writeData(31 downto 16)
}

案例 5: parasiteField

这用于软件在多个地址上共享同一寄存器,而不是生成多个寄存器实体

示例 1:时钟门软件使能

val M_CG_ENS_SET = busif.newReg(doc="Clock Gate Enables") //0x0000
val M_CG_ENS_CLR = busif.newReg(doc="Clock Gate Enables") //0x0004
val M_CG_ENS_RO = busif.newReg(doc="Clock Gate Enables") //0x0008
val xx_sys_cg_en = M_CG_ENS_SET.field(Bits(4 bit), W1S, 0, "clock gate enalbes, write 1 set" )
M_CG_ENS_CLR.parasiteField(xx_sys_cg_en, W1C, 0, "clock gate enalbes, write 1 clear" )
M_CG_ENS_RO.parasiteField(xx_sys_cg_en, RO, 0, "clock gate enables, read only")

示例 2:使用软件的带强制 (force) 接口的中断原始 (raw) 状态寄存器

val RAW = this.newRegAt(offset,"Interrupt Raw status Register\n set when event \
,→n clear raw when write 1")
val FORCE = this.newReg("Interrupt Force Register\n for SW debug use \n write 1␣
,→set raw")
val raw = RAW.field(Bool(), AccessType.W1C, resetValue = 0, doc = s"raw,␣
,→default 0" )
FORCE.parasiteField(raw, AccessType.W1S, resetValue = 0, doc = s
,→"force, write 1 set, debug use" )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千穹凌帝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值