【注意】最后更新于 August 22, 2021,文中内容可能已过时,请谨慎使用。
使用方法
现在我们的需求是:在同一个 Generator 里可以使用端口定义相同、内部实现不同的子模块,且子模块可以通过参数进行配置。
首先定义一个特质 MyAdder
,它可以理解为 Mod1
和 Mod2
两个 Module
的接口定义。
Mod1
和 Mod2
是两个接口相同、功能不同的模块。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| // Provides a more specific interface since generic Module
// provides no compile-time information on generic module's IOs.
trait MyAdder {
def in1: UInt
def in2: UInt
def out: UInt
}
class Mod1 extends RawModule with MyAdder {
val in1 = IO(Input(UInt(8.W)))
val in2 = IO(Input(UInt(8.W)))
val out = IO(Output(UInt(8.W)))
out := in1 + in2
}
class Mod2 extends RawModule with MyAdder {
val in1 = IO(Input(UInt(8.W)))
val in2 = IO(Input(UInt(8.W)))
val out = IO(Output(UInt(8.W)))
out := in1 - in2
}
|
类 X
接收一个实现了 MyAdder
特质的对象作为参数。: =>
表示参数会延迟求值。
1
2
3
4
5
6
7
8
9
10
11
| class X[T <: BaseModule with MyAdder](genT: => T) extends Module {
val io = IO(new Bundle {
val in1 = Input(UInt(8.W))
val in2 = Input(UInt(8.W))
val out = Output(UInt(8.W))
})
val subMod = Module(genT)
io.out := subMod.out
subMod.in1 := io.in1
subMod.in2 := io.in2
}
|
生成对应 Verilog 代码,并进行比较。
1
2
| println(ChiselStage.emitVerilog(new X(new Mod1)))
println(ChiselStage.emitVerilog(new X(new Mod2)))
|
当类参数 genT = Mod1
时,生成了 X
和 Mod1
两个模块,并且在 X
中实例化了 Mod1
模块。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| module Mod1(
input [7:0] in1,
input [7:0] in2,
output [7:0] out
);
assign out = in1 + in2; // @[polymorphism-and-parameterization.md 174:16]
endmodule
module X(
input clock,
input reset,
input [7:0] io_in1,
input [7:0] io_in2,
output [7:0] io_out
);
wire [7:0] subMod_in1; // @[polymorphism-and-parameterization.md 192:24]
wire [7:0] subMod_in2; // @[polymorphism-and-parameterization.md 192:24]
wire [7:0] subMod_out; // @[polymorphism-and-parameterization.md 192:24]
Mod1 subMod ( // @[polymorphism-and-parameterization.md 192:24]
.in1(subMod_in1),
.in2(subMod_in2),
.out(subMod_out)
);
assign io_out = subMod_out; // @[polymorphism-and-parameterization.md 193:12]
assign subMod_in1 = io_in1; // @[polymorphism-and-parameterization.md 194:16]
assign subMod_in2 = io_in2; // @[polymorphism-and-parameterization.md 195:16]
endmodule
|
当类参数 genT = Mod2
时,X
中的子模块变成了 Mod2
(此处省略了重复的代码)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| module Mod2(
input [7:0] in1,
input [7:0] in2,
output [7:0] out
);
assign out = in1 - in2; // @[polymorphism-and-parameterization.md 182:16]
endmodule
module X(/*...*/);
/*...*/
Mod2 subMod ( // @[polymorphism-and-parameterization.md 192:24]
.in1(subMod_in1),
.in2(subMod_in2),
.out(subMod_out)
);
/*...*/
endmodule
|
更多
RawModule
/ BaseModule
/ Module
中:RawModule
没有隐式 clock
和 reset
端口;BaseModule
是其它 Module
的抽象基类(abstract base class);Module
是定义一个模块时通常会使用的类。MultiIOModule
比起 RawModule
多了隐式 clock
和 reset
端口。
参考资料