1

我正在尝试创建一个涉及移位寄存器的数据路径,但我希望整个事情能够在等待新输入时停止。我看到标准库中有一个带有启用线的移位寄存器(尽管默认为true)。

问题是当我尝试使用它时,编译的verilog似乎并没有在启用低时真正停止移位寄存器。

考虑这个凿子代码:

package SR

import Chisel._

class SR extends Module {
  val io = new Bundle { 
    val in = UInt(INPUT, 8)
    val enable = Bool(INPUT)
    val out = UInt(OUTPUT, 8)
  }
  io.out:= ShiftRegister(io.in, 10, io.enable)
}

class SRTests(c: SR) extends Tester(c) {
}

object SR {
  def main(args: Array[String]): Unit = {
    val tutArgs = args.slice(1, args.length)
    chiselMainTest(tutArgs, () => Module(new SR())) {
      c => new SRTests(c) }
  }
}

我得到以下verilog:

module SR(input clk,
    input [7:0] io_in,
    input  io_enable,
    output[7:0] io_out
);

  reg [7:0] R0;
  reg [7:0] R1;
  reg [7:0] R2;
  reg [7:0] R3;
  reg [7:0] R4;
  reg [7:0] R5;
  reg [7:0] R6;
  reg [7:0] R7;
  reg [7:0] R8;
  reg [7:0] R9;
  wire[7:0] T10;

`ifndef SYNTHESIS
  integer initvar;
  initial begin
    #0.002;
    R0 = {1{$random}};
    R1 = {1{$random}};
    R2 = {1{$random}};
    R3 = {1{$random}};
    R4 = {1{$random}};
    R5 = {1{$random}};
    R6 = {1{$random}};
    R7 = {1{$random}};
    R8 = {1{$random}};
    R9 = {1{$random}};
  end
`endif

  assign io_out = R0;
  assign T10 = io_enable ? io_in : R9;

  always @(posedge clk) begin
    R0 <= R1;
    R1 <= R2;
    R2 <= R3;
    R3 <= R4;
    R4 <= R5;
    R5 <= R6;
    R6 <= R7;
    R7 <= R8;
    R8 <= R9;
    if(io_enable) begin
      R9 <= io_in;
    end
  end
endmodule

似乎移位寄存器只保持第一个值固定而不是整个值。例如,如果您在连续时钟周期中写入 1、2、3、4、5,但只为 1、2、3 保持启用高电平,则 3 将正确保持,但 1 和 2 最终会移出,整个移位寄存器将填充值 3。

我想要凿子教程中看到的移位寄存器示例的行为。问题是我需要长的、可参数化的移位寄存器,所以手写每个寄存器不是一种选择。我将非常感谢凿子代码的示例,该代码实现了具有启用行为的移位寄存器,如凿子教程中所见,但参数化为不同长度,如标准库中所见。

4

1 回答 1

0

您可以在Chisel存储库的 src/main/scala/ChiselUtil.scala 中看到 ShiftRegister 的源代码:

object ShiftRegister
{
  def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T =
  {
    // The order of tests reflects the expected use cases.
    if (n == 1) {
      RegEnable(in, en)
    } else if (n != 0) {
      RegNext(apply(in, n-1, en))
    } else {
      in
    }
  }
}

这是创建 RegNexts 的递归链,但在基本情况下创建了 RegEnable。例子:

RegNext(RegNext(RegNext(RegEnable(in, en))))

您可以将该代码复制到您的 hello world 中,将其重命名为object MyShiftRegister,然后修改该循环以满足您的需要。

我认为您正在寻找的是:

} else if (n != 0) {
  RegEnable(apply(in, n-1, en), en)
} ...

作为一般策略,我建议写出代码“展开”的样子,然后考虑如何将其“打包”成一段简洁且可参数化的 Scala 代码。

于 2014-10-08T09:15:45.540 回答