Chisel 学习笔记(五)

Chisel 学习笔记(五)

Chisel中的时序逻辑

寄存器reg

val register = Reg(UInt(12.W))

class RegisterModule extends Module {
  val io = IO(new Bundle {
    val in  = Input(UInt(12.W))
    val out = Output(UInt(12.W))
  })
  
  val register = Reg(UInt(12.W))
  register := io.in + 1.U
  io.out := register
}

还可以通过RegNext来实例化出来一个寄存器

class RegNextModule extends Module {
  val io = IO(new Bundle {
    val in  = Input(UInt(12.W))
    val out = Output(UInt(12.W))
  })
  
  // register bitwidth is inferred from io.out
  io.out := RegNext(io.in + 1.U)
}

step(n)可以改变n次时钟,常用于测试中

class RegisterModuleTester(c: RegisterModule) extends PeekPokeTester(c) {
  for (i <- 0 until 100) {
    poke(c.io.in, i)
    step(1)
    expect(c.io.out, i+1)
  }
}

可以通过RegInit来让寄存器中初始附带特定值

val myReg = RegInit(UInt(12.W), 0.U)
val myReg = RegInit(0.U(12.W))

有如下例子

classclass  RegInitModuleRegInit  extends Module {
  val io = IO(new Bundle {
    val in  = Input(UInt(12.W))
    val out = Output(UInt(12.W))
  })
  
  val register = RegInit(0.U(12.W))
  register := io.in + 1.U
  io.out := register
}

必须要使用RegInit,否则寄存器里的初值未知

可以在测试时使用reset(n)来使reset信号有效n个周期

精确时钟和复位

Chisel中对于寄存器有默认的同步复位reset和时钟clk,但如果想自己加入额外的复位信号和额外的时钟信号,就要用到withClock/withReset/withClockAndReset
withClock(a){}意味着在a的上升沿会触发什么
withReset(a){}意味着在标准时钟上升沿a有效时复位
withClockAndReset(a,b){}意味着在a的上升沿,b有效时复位

class ClockExamples extends Module {
  val io = IO(new Bundle {
    val in = Input(UInt(10.W))
    val alternateReset    = Input(Bool())
    val alternateClock    = Input(Clock())
    val outImplicit       = Output(UInt())
    val outAlternateReset = Output(UInt())
    val outAlternateClock = Output(UInt())
    val outAlternateBoth  = Output(UInt())
  })

  val imp = RegInit(0.U(10.W))
  imp := io.in
  io.outImplicit := imp

  withReset(io.alternateReset) {
    // everything in this scope with have alternateReset as the reset
    val altRst = RegInit(0.U(10.W))
    altRst := io.in
    io.outAlternateReset := altRst
  }

  withClock(io.alternateClock) {
    val altClk = RegInit(0.U(10.W))
    altClk := io.in
    io.outAlternateClock := altClk
  }

  withClockAndReset(io.alternateClock, io.alternateReset) {
    val alt = RegInit(0.U(10.W))
    alt := io.in
    io.outAlternateBoth := alt
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    println("Generating the Adder hardware")
    chisel3.Driver.execute(Array("--target-dir", "generated"), () => new ClockExamples)
  }
}

生成的verilog中相关部分如下

module ClockExamples( // @[:@3.2]
  input        clock, // @[:@4.4]
  input        reset, // @[:@5.4]
  input  [9:0] io_in, // @[:@6.4]
  input        io_alternateReset, // @[:@6.4]
  input        io_alternateClock, // @[:@6.4]
  output [9:0] io_outImplicit, // @[:@6.4]
  output [9:0] io_outAlternateReset, // @[:@6.4]
  output [9:0] io_outAlternateClock, // @[:@6.4]
  output [9:0] io_outAlternateBoth // @[:@6.4]
);
  reg [9:0] imp; // @[Passthrough.scala 137:20:@8.4]
  reg [31:0] _RAND_0;
  reg [9:0] _T_23; // @[Passthrough.scala 143:25:@11.4]
  reg [31:0] _RAND_1;
  reg [9:0] _T_26; // @[Passthrough.scala 149:25:@14.4]
  reg [31:0] _RAND_2;
  reg [9:0] _T_29; // @[Passthrough.scala 155:22:@17.4]
  reg [31:0] _RAND_3;
  assign io_outImplicit = imp; // @[Passthrough.scala 139:18:@10.4]
  assign io_outAlternateReset = _T_23; // @[Passthrough.scala 145:26:@13.4]
  assign io_outAlternateClock = _T_26; // @[Passthrough.scala 151:26:@16.4]
  assign io_outAlternateBoth = _T_29; // @[Passthrough.scala 157:25:@19.4]

  always @(posedge clock) begin
    if (reset) begin
      imp <= 10'h0;
    end else begin
      imp <= io_in;
    end
    if (io_alternateReset) begin
      _T_23 <= 10'h0;
    end else begin
      _T_23 <= io_in;
    end
  end
  always @(posedge io_alternateClock) begin
    if (reset) begin
      _T_26 <= 10'h0;
    end else begin
      _T_26 <= io_in;
    end
    if (io_alternateReset) begin
      _T_29 <= 10'h0;
    end else begin
      _T_29 <= io_in;
    end
  end
endmodule
原文地址:https://www.cnblogs.com/JamesDYX/p/10073208.html