chisel - Chisel3 每个时钟周期比较 UInt 位 [运行长度编码器]
问题描述
我正在构建一个运行长度编码器模块,但遇到了问题。
原始比特流作为 uint8 存储在内存中:11111100 -> 252、00000110 -> 6 等
我将原始比特流的每个块加载到一个寄存器中val in = Reg(UInt(8.W))
,然后我想将第 1 位与第 2 位进行比较,然后将第 2 位与第 3 位进行比较,依此类推,以计算运行的长度。这是我的状态机的一部分。
switch(state) {
// code here ...
is(step1) {
logic.io.current_bit := in(7)
logic.io.next_bit := in(6)
// code here ...
}
is(step2) {
current_bit := in(6)
next_bit := in(5)
// code here ...
}
// ... more steps ...
is(step7) {
current_bit := in(1)
next_bit := in(0)
// code here ...
}
// code here ...
}
我有一个名为逻辑的组合电路,它决定两个连续位的相等性,以及下一个状态是步骤 n+1 还是存储运行的长度。我认为有很多代码冗余,但我想不出另一种方式。
有没有办法输入 in(x) ,其中 x 是我的状态机中定义的数字?
关于如何以更优雅的方式做到这一点的任何想法?
编辑:
模块输入/输出:
val io = IO(new Bundle {
val valid = Input(Bool()) // enables-disables the module
val mem_addr_load = Input(UInt(mem_addr_length.W)) // memory position to load the uints
val mem_addr_store = Input(UInt(mem_addr_length.W)) // memory position to store the uints
val mem_in = Input(UInt(8.W)) // uint input - loads 252 so it translates 11111100 bitstream
val mem_out = Output(UInt(8.W)) // store the run's length using 8-bit runs (up to 255 consecutive same bits)
val mem_addr = Output(UInt(mem_addr_length.W)) // memory position that the module wants to access (store/load)
val writeEn = Output(Bool()) // signifies that there are data to be written in the memory
val ready = Output(Bool()) // signifies that the process is over
})
模块功能:压缩内存内容
Memory contents (IN)
|11101111|11111111|11111111|11111111|10111110|00000000|00111111|11111111|11111111|11111111|11111111|11111111|11111111|11111100|
Memory contents (OUT)
|00000011|00000001|00011101|00000001|00000101|00001011|00111000|00000010|
| 4x1 | 1x0 | 29x1 | 1x0 | 5x1 | 11x0 | 56x1 | 2x0 |
解决方案
有没有办法输入 in(x) ,其中 x 是我的状态机中定义的数字?
您可以在设计中使用寄存器/线路进行位提取。例如,is
状态机中的每个:
is(step7) {
current_bit := in(1)
next_bit := in(0)
// code here ...
}
可以折叠成类似的东西
current_bit := in(state)
next_bit := in(state - 1.U)
(以整理一些细节为准)
我会考虑的另一件事是使用更多的聚合。我并不完全理解内存接口,但可以将其表示为:
val io = IO(new Bundle {
val mem = new Bundle {
val addr = Output(UInt(mem_addr_length.W))
val dataIn = Input(UInt(8.W))
val dataOut = Output(UInt(8.W))
val writeEn = Output(Bool())
}
})
使用某种形式的解耦(即现成有效)设计通常也更容易。例如,在这种情况下,我可能会有一个外部模块来与内存接口(如您编辑中的模块 I/O),以及一个内部模块来进行编码。例如。
val io = IO(new Bundle {
val in = Decoupled(UInt(8.W)) // note Decoupled is defined in chisel3.util._
val out = Decoupled(UInt(8.W))
})
经常解耦有助于减少问题规模
根据您的资源与延迟限制,您还可以考虑在每个周期对输入的多个位进行编码。这就是在编写生成器时可以提供一个有趣问题的东西。
人们可以认为这种编码本质上是一个可以实现为 ROM 的真值表。您可以通过几个维度对其进行参数化,包括每个周期编码的最大位数以及每个周期的最大编码运行数(尽管我怀疑对于每个周期单个字节的内存接口,没有理由让它大于1)。
推荐阅读
- c# - 我可以将 ContextMenuStrip 上的多个项目绑定到同一个函数吗?
- sql - 甲骨文今年即将生日
- python - 求aiohttp响应/连接关闭行为的解释
- dynamics-crm - Dynamics 365 – 实体 ER 图表 (Visio) 使用 SDK 中的元数据图表控制台
- typescript - 带有模块分辨率的打字稿的开玩笑设置
- php - 在php中显示数组和对象之间的差异
- javafx-8 - 为什么我不能在表中选择?我和其他人一样
- python - 如何创建一个只有一篇文章的页面?
- python - 如何过滤出今天日期在计算日期范围内的对象?
- python - 如何打印刮痕深度