SpinalHDL之RegIf(下篇)

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

SpinalHDL学习笔记总纲链接如下:

SpinalHDL 学习笔记_spinalhdl blackbox-CSDN博客

目录:

6.典型例子

7.中断生成器

8.默认读取值

6.典型例子

批量创建 REG-Address 和字段寄存器:

import spinal.lib.bus.regif._
class RegBank extends Component {
val io = new Bundle {
val apb = slave(Apb3(Apb3Config(16, 32)))
val stats = in Vec(Bits(16 bit), 10)
val IQ = out Vec(Bits(16 bit), 10)
}
val busif = Apb3BusInterface(io.apb, (0x000, 100 Byte), regPre = "AP")
(0 to 9).map { i =>
//here use setName give REG uniq name for Docs usage
val REG = busif.newReg(doc = s"Register${i}").setName(s"REG${i}")
val real = REG.field(SInt(8 bit), AccessType.RW, 0, "Complex real")
val imag = REG.field(SInt(8 bit), AccessType.RW, 0, "Complex imag")
val stat = REG.field(Bits(16 bit), AccessType.RO, 0, "Accelerator status")
io.IQ(i)( 7 downto 0) := real.asBits
io.IQ(i)(15 downto 8) := imag.asBits
stat := io.stats(i)
}
def genDocs() = {
busif.accept(CHeaderGenerator("regbank", "AP"))
busif.accept(HtmlGenerator("regbank", "Interupt Example"))
busif.accept(JsonGenerator("regbank"))
busif.accept(RalfGenerator("regbank"))
busif.accept(SystemRdlGenerator("regbank", "AP"))
}
this.genDocs()
}
SpinalVerilog(new RegBank())

7.中断生成器

手动写中断:

class cpInterruptExample extends Component {
val io = new Bundle {
val tx_done, rx_done, frame_end = in Bool()
val interrupt = out Bool()
val apb = slave(Apb3(Apb3Config(16, 32)))
}
val busif = Apb3BusInterface(io.apb, (0x000, 100 Byte), regPre = "AP")
val M_CP_INT_RAW = busif.newReg(doc="cp int raw register")
val tx_int_raw = M_CP_INT_RAW.field(Bool(), W1C, doc="tx interrupt enable␣
,→register")
val rx_int_raw = M_CP_INT_RAW.field(Bool(), W1C, doc="rx interrupt enable␣
,→register")
val frame_int_raw = M_CP_INT_RAW.field(Bool(), W1C, doc="frame interrupt enable register")
val M_CP_INT_FORCE = busif.newReg(doc="cp int force register\n for debug use")
val tx_int_force = M_CP_INT_FORCE.field(Bool(), RW, doc="tx interrupt␣
,→enable register")
val rx_int_force = M_CP_INT_FORCE.field(Bool(), RW, doc="rx interrupt␣
,→enable register")
val frame_int_force = M_CP_INT_FORCE.field(Bool(), RW, doc="frame interrupt␣
,→enable register")
val M_CP_INT_MASK = busif.newReg(doc="cp int mask register")
val tx_int_mask = M_CP_INT_MASK.field(Bool(), RW, doc="tx interrupt mask␣
,→register")
val rx_int_mask = M_CP_INT_MASK.field(Bool(), RW, doc="rx interrupt mask␣
,→register")
val frame_int_mask = M_CP_INT_MASK.field(Bool(), RW, doc="frame interrupt␣
,→mask register")
val M_CP_INT_STATUS = busif.newReg(doc="cp int state register")
val tx_int_status = M_CP_INT_STATUS.field(Bool(), RO, doc="tx interrupt␣
,→state register")
val rx_int_status = M_CP_INT_STATUS.field(Bool(), RO, doc="rx interrupt␣
,→state register")
val frame_int_status = M_CP_INT_STATUS.field(Bool(), RO, doc="frame interrupt␣
,→state register")
rx_int_raw.setWhen(io.rx_done)
tx_int_raw.setWhen(io.tx_done)
frame_int_raw.setWhen(io.frame_end)
rx_int_status := (rx_int_raw || rx_int_force) && (!rx_int_mask)
tx_int_status := (tx_int_raw || rx_int_force) && (!rx_int_mask)
frame_int_status := (frame_int_raw || frame_int_force) && (!frame_int_mask)
io.interrupt := rx_int_status || tx_int_status || frame_int_status
}

这是一项非常繁琐且重复的工作,更好的方法是使用“生成器 (factory)”范例来自动生成每个信号的文档。现在 InterruptFactory 可以做到这一点。

创建中断的简单方法:

class EasyInterrupt extends Component {
val io = new Bundle {
val apb = slave(Apb3(Apb3Config(16,32)))
val a, b, c, d, e = in Bool()
}
val busif = BusInterface(io.apb,(0x000,1 KiB), 0, regPre = "AP")
busif.interruptFactory("T", io.a, io.b, io.c, io.d, io.e)
busif.accept(CHeaderGenerator("intrreg","AP"))
busif.accept(HtmlGenerator("intrreg", "Interupt Example"))
busif.accept(JsonGenerator("intrreg"))
busif.accept(RalfGenerator("intrreg"))
busif.accept(SystemRdlGenerator("intrreg", "AP"))
}

 

IP 级中断生成器

寄存器

访问类型

描述

RAW

W1C

中断原始状态 (int raw) 寄存器,由 int 事件设置,总线写 1 时清零

FORCE

RW

中断强制寄存器,用于软件调试

MASK

RW

中断掩码寄存器, 1:关闭; 0:打开;默认 1 中断关闭

STATUS

RO

中断状态,只读, status = raw && ! mask

 

Spinal 用法:

busif.interruptFactory("T", io.a, io.b, io.c, io.d, io.e) 

SYS 级中断合并

寄存器

访问类型

描述

MASK

RW

中断掩码寄存器, 1:关闭; 0:打开;默认 1 中断关闭

STATUS

RO

中断状态, RO, status = int_level && ! mask

 

busif.interruptLevelFactory("T", sys_int0, sys_int1)

Spinal 的生成器

总线接口方法

描述

InterruptFactory(regNamePre: String,triggers: Bool*)

为 脉 冲 事 件 创 建RAW/FORCE/MASK/STATUS

InterruptFactoryNoForce(regNamePre: String,
triggers: Bool*)

为 脉 冲 事 件 创 建RAW/MASK/STATUS

InterruptFactory(regNamePre: String,triggers: Bool*)

为 level_int 合 并 创 建MASK/STATUS

InterruptFactoryAt(addrOffset: Int,regNamePre: String, triggers: Bool*)

在 addrOffset 处 为 脉 冲 事 件 创 建RAW/FORCE/MASK/STATUS

InterruptFactoryNoForceAt(addrOffset: Int,
regNamePre: String, triggers: Bool*)

在 addrOffset 处 为 脉 冲 事 件 创 建RAW/MASK/STATUS

InterruptFactoryAt(addrOffset: Int,regNamePre: String, triggers: Bool*)

在 addrOffset 处为 level_int 合并创建MASK/STATUS

示例:

class RegFileIntrExample extends Component {
val io = new Bundle {
val apb = slave(Apb3(Apb3Config(16,32)))
val int_pulse0, int_pulse1, int_pulse2, int_pulse3 = in Bool()
val int_level0, int_level1, int_level2 = in Bool()
val sys_int = out Bool()
val gpio_int = out Bool()
}
val busif = BusInterface(io.apb, (0x000,1 KiB), 0, regPre = "AP")
io.sys_int := busif.interruptFactory("SYS",io.int_pulse0, io.int_pulse1, io.
,→int_pulse2, io.int_pulse3)
io.gpio_int := busif.interruptLevelFactory("GPIO",io.int_level0, io.int_level1,␣
,→io.int_level2, io.sys_int)
def genDoc() = {
busif.accept(CHeaderGenerator("intrreg","Intr"))
busif.accept(HtmlGenerator("intrreg", "Interupt Example"))
busif.accept(JsonGenerator("intrreg"))
busif.accept(RalfGenerator("intrreg"))
busif.accept(SystemRdlGenerator("intrreg", "Intr"))
this
}
this.genDoc()
}

8.默认读取值

当软件读取保留地址时,当前的策略是正常返回, readerror=0。为了方便软件调试,可以配置回读值,默

认为 0。

busif.setReservedAddressReadValue(0x0000EF00)

 

default: begin
busif_rdata <= 32'h0000EF00 ;
busif_rderr <= 1'b0 ;
end

  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

千穹凌帝

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

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

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

打赏作者

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

抵扣说明:

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

余额充值