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