欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > SpinalHDL之错误修复(中篇)

SpinalHDL之错误修复(中篇)

2024/10/25 2:29:36 来源:https://blog.csdn.net/m0_59092412/article/details/140306488  浏览:    关键词:SpinalHDL之错误修复(中篇)

本文作为SpinalHDL学习笔记第十一篇,记录使用SpinalHDL一些代码错误的修复方法。

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

SpinalHDL 学习笔记_spinalhdl blackbox-CSDN博客

目录:

6.锁存器检测 (Latch detected)

7.无驱动检测 (No driver on)

8.空指针异常 (NullPointerException)

9.超出范围的常数 (Out of Range Constant)

10.定义为组件输入的寄存器 (Register defned as component input)

6.锁存器检测 (Latch detected)

SpinalHDL 将检查在综合期间没有组合信号会引入锁存器。换句话说,这是检查有没有组合信号被部分赋值。

示例:

class TopLevel extends Component {
val cond = in(Bool())
val a = UInt(8 bits)
when(cond) {
a := 42
}
}

会报错:

LATCH DETECTED from the combinatorial signal (toplevel/a : UInt[8 bits]), defined␣
,→at
***
Source file location of the toplevel/io_a definition via the stack trace
***

 一个可能的修复方法是:

class TopLevel extends Component {
val cond = in(Bool())
val a = UInt(8 bits)
a := 0
when(cond) {
a := 42
}
}

 

因多路复用器产生的错误

检测到锁存器的另一个原因通常是不详尽、缺少默认值的 mux/muxList 语句:

val u1 = UInt(1 bit)
u1.mux(
0 -> False,
// case for 1 is missing
)

可以通过添加缺失的条件(或默认条件)来修复:

val u1 = UInt(1 bit)
u1.mux(
0 -> False,
default -> True
)

例如对于通用位宽代码,使用 muxListDc 通常是更好的解决方案,因为对于不需要默认值的情况,这不会生成错误:

val u1 = UInt(1 bit)
// automatically adds default if needed
u1.muxListDc(Seq(0 -> True))

7.无驱动检测 (No driver on)

SpinalHDL 将检查所有对设计有影响的组合信号是否被赋值。

示例:

class TopLevel extends Component {
val result = out(UInt(8 bits))
val a = UInt(8 bits)
result := a
}

会报错:

NO DRIVER ON (toplevel/a : UInt[8 bits]), defined at
***
Source file location of the toplevel/a definition via the stack trace
***

一个可能的修复方法是:

class TopLevel extends Component {
val result = out(UInt(8 bits))
val a = UInt(8 bits)
a := 42
result := a
}

8.空指针异常 (NullPointerException)

NullPointerException 是 Scala 运行时报告的错误,当变量在初始化之前被访问时可能会发生这种错误。

示例:

class TopLevel extends Component {
a := 42
val a = UInt(8 bits)
}

会报错:

Exception in thread "main" java.lang.NullPointerException
***
Source file location of the a := 42 assignment via the stack trace
***

 一个可能的修复方法是:

class TopLevel extends Component {
val a = UInt(8 bits)
a := 42
}

SpinalHDL 不是一种语言,它是一个 Scala 库,这意味着它遵循与 Scala 通用编程语言相同的规则。当运行上面的 SpinalHDL 硬件描述生成相应的 VHDL/Verilog RTL 时, SpinalHDL 硬件描述将作为 Scala程序执行,并且 a 将是一个空引用,直到程序执行 val a = UInt(8 bits) ,因此试图在此之前赋值给它将导致 NullPointerException 。

9.超出范围的常数 (Out of Range Constant)

SpinalHDL 会检查,当一个值和一个常量对比时,该值是否具有更宽的位数。

示例:

val value = in UInt(2 bits)
val result = out(value < 42)

会报错:

OUT OF RANGE CONSTANT. Operator UInt < UInt
- Left operand : (toplevel/value : in UInt[2 bits])
- Right operand : (U"101010" 6 bits)
is checking a value against a out of range constant

在某些情况下,由于设计参数化,将值与更大的常量进行比较并获得静态已知的 True/False 结果是有意义的。可以选择将与超出范围的常量进行比较的一个实例列入专门的白名单。

val value = in UInt(2 bits)
val result = out((value < 42).allowOutOfRangeLiterals)

或者,可以允许整个设计对超出范围的常量进行比较。

SpinalConfig(allowOutOfRangeLiterals = true)

10.定义为组件输入的寄存器 (Register defned as component input)

在 SpinalHDL 中,用户不被允许定义一个将寄存器作为输入的组件。原因是为了防止用户试图用寄存器信号作为子组件的输入驱动时出现意外。如果确实需要一个寄存器输入,用户可以在 io 线束中先定义一个非寄存器输入, 随后在组件内部对其添加寄存器。

示例:

class TopLevel extends Component {
val io = new Bundle {
val a = in(Reg(UInt(8 bits)))
}
}

会报错:

REGISTER DEFINED AS COMPONENT INPUT : (toplevel/io_a : in UInt[8 bits]) is defined␣
,→as a registered input of the toplevel component, but isn't allowed.
***
Source file location of the toplevel/io_a definition via the stack trace
***

一个可能的修复方法是:

class TopLevel extends Component {
val io = new Bundle {
val a = in UInt(8 bits)
}
}

如果需要一个寄存器信号 a ,可以这样做:

class TopLevel extends Component {
val io = new Bundle {
val a = in UInt(8 bits)
}
val a = RegNext(io.a)
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com