如何使Chisel生成触发器启用?

时间:2017-01-12 11:32:03

标签: chisel

我们正在实现一个处理器管道,并希望有效的方法来阻止它。如果我们控制了电路,那么我们将使用具有使能输入的锁存器。要停止,只需禁用锁存器,然后他们不会在下一个时钟边沿更新,它们将保持不变直到再次启用。

但是,如何在Chisel中做到这一点?目前还不清楚"什么时候"声明将转化为。有助于幕后的黑魔法,以及如何控制终端电路的提示将不胜感激。

3 个答案:

答案 0 :(得分:0)

when语句基本上只是帮助构建多路复用树的简写方法。例如:

class SimpleWhen extends Module {
  val io = IO(new Bundle {
    val cond = Input(Bool())
    val a = Input(UInt(32.W))
    val b = Input(UInt(32.W))
    val z = Output(UInt(32.W))
  })

  when (io.cond) { io.z := io.a }
  .otherwise { io.z := io.b }
}

如果我们从中生成Verilog,我们得到(在Chisel 3中):

module SimpleWhen(
  input   clock,
  input   reset,
  input   io_cond,
  input  [31:0] io_a,
  input  [31:0] io_b,
  output [31:0] io_z
);
  wire  _T_11;
  wire [31:0] _GEN_1;
  assign io_z = _GEN_1;
  assign _T_11 = io_cond == 1'h0;
  assign _GEN_1 = _T_11 ? io_b : io_a;
endmodule

正如人们所料,此模块基本上只根据条件abcond之间进行多路复用。

对于更有趣的寄存器用例:

class RegEnableTest extends Module {
  val io = IO(new Bundle {
    val en = Input(Bool())
    val a = Input(Valid(UInt(32.W)))
    val b = Input(Valid(UInt(32.W)))
    val out = Output(UInt(32.W))
  })

  val regNext = Wire(UInt(32.W))
  val myReg = Reg(UInt(32.W))
  when (io.en) { myReg := regNext }
  regNext := myReg

  when (io.a.valid) { regNext := io.a.bits }
  when (io.b.valid) { regNext := io.b.bits }

  io.out := myReg
}

此处我们有一个注册表myReg,只有在输入en为高时才会更新。生成的Verilog是:

module RegEnableTest(
  input   clock,
  input   reset,
  input   io_en,
  input   io_a_valid,
  input  [31:0] io_a_bits,
  input   io_b_valid,
  input  [31:0] io_b_bits,
  output [31:0] io_out
);
  wire [31:0] regNext;
  reg [31:0] myReg;
  reg [31:0] _GEN_1;
  wire [31:0] _GEN_0;
  wire [31:0] _GEN_2;
  assign io_out = myReg;
  assign regNext = _GEN_2;
  assign _GEN_0 = io_en ? regNext : myReg;
  assign _GEN_2 = io_b_valid ? io_b_bits : io_a_bits;
// ... Randomization removed for clarity ...
  always @(posedge clock) begin
    if (io_en) begin
      myReg <= regNext;
    end
  end
endmodule

myReg仅在io.en为高时更新。使用RegEnable(https://chisel.eecs.berkeley.edu/api/index.html#chisel3.util.RegEnable $)

可以使这段代码更加简洁

答案 1 :(得分:0)

以下是如何使用RegEnable来实现它,这是一个帮助对象构造启用的寄存器: https://github.com/ucb-bar/chisel3/blob/master/src/main/scala/chisel3/util/Reg.scala

import chisel3._
import chisel3.util._

class RegEnableTest extends Module {
  val io = IO(new Bundle {
    val en = Input(Bool())
    val a = Input(Valid(UInt(32.W)))
    val b = Input(Valid(UInt(32.W)))
    val out = Output(UInt(32.W))
  })

  val regNext = Wire(UInt(32.W))
  val myReg = RegEnable(regNext,io.en)

  when (io.a.valid) { regNext := io.a.bits }
  when (io.b.valid) { regNext := io.b.bits }

  io.out := myReg
}

这会产生以下verilog(编辑以删除不需要的宏)

module RegEnableTest(
  input   clock,
  input   reset,
  input   io_en,
  input   io_a_valid,
  input  [31:0] io_a_bits,
  input   io_b_valid,
  input  [31:0] io_b_bits,
  output [31:0] io_out
);
  wire [31:0] regNext;
  reg [31:0] myReg;
  reg [31:0] _GEN_1;
  wire [31:0] _GEN_0;
  wire [31:0] _GEN_2;
  assign io_out = myReg;
  assign regNext = _GEN_2;
  assign _GEN_0 = io_en ? regNext : myReg;
  assign _GEN_2 = io_b_valid ? io_b_bits : io_a_bits;

  always @(posedge clock) begin
    if (io_en) begin
      myReg <= regNext;
    end
  end
endmodule

答案 2 :(得分:0)

或者你可以这样做:

  val regNext = Wire(UInt(32.W))

  when (io.a.valid) { regNext := io.a.bits }
  when (io.b.valid) { regNext := io.b.bits }

  io.out := RegEnable(regNext,io.en)

但是状态在verilog代码中没有好名字

  assign io_out = _T_30;
  assign regNext = _GEN_1;
  assign _GEN_1 = io_b_valid ? io_b_bits : io_a_bits;
  assign _GEN_2 = io_en ? regNext : _T_30;

  always @(posedge clock) begin
    if (io_en) begin
      _T_30 <= regNext;
    end
  end
  endmodule