凿标准库移位寄存器的行为是否适用于使能线

时间:2014-10-06 23:30:10

标签: chisel

我正在尝试创建一个涉及移位寄存器的数据路径,但我希望在等待新输入时能够停止整个事情。我看到标准库中有一个带有启用行的移位寄存器(虽然默认为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。

我想要像凿子教程中看到的移位寄存器示例一样的行为。问题是我需要长的,可参数化的移位寄存器,因此不能手动编写每个寄存器。我非常感谢一个凿子代码的例子,它实现了一个带有启用行为的移位寄存器,就像在凿子教程中看到的那样,但是参数化不同,如标准库中所见。

1 个答案:

答案 0 :(得分: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世界中,将其重命名为object MyShiftRegister,然后根据您的需要修改该循环。

我认为你在寻找的是:

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

作为一般策略,我建议写出代码的样子&#34; un-rolled&#34;然后考虑如何打包它#34;转换为简洁且可参数化的Scala代码。