https://mp.weixin.qq.com/s/SEcVjGRL1YloGlEPSoHr3A
位数为参数的加法器。通过FullAdder级联实现。
参考链接:
https://github.com/ucb-bar/chisel-tutorial/blob/release/src/main/scala/examples/Adder.scala
1. 引入Chisel3
2. 继承自Module类
这里的n是构造方法的参数,表示加法器的位数。
3. 定义输入输出接口
根据位数n,创建各项输入输出接口。
(UInt(n.W))
a. 使用n.W表示位宽为n位;
b. 使用UInt创建无符号整型数;
c. 使用Input/Output表示接口方向;
关键字表明定义的变量是所属匿名Bundle子类的数据成员;
4. 内部连接
创建n个全加器,并与输入和输出接口相连。
)
a. 这个写法实际上是用了一点trick,以缩短后续代码。实际上FA是指FullAdder,但这里创建的却不是全加器,而是全加器的io。
如果是全加器,写法应该如下:
FullAdder()))
但这样写,后续使用时,需要加上io:
(i)
因为后续使用时都是使用全加器的io,而不使用全加器。所以直接使用FAs指代FAs的io,也无可厚非。
b. 这里使用了Scala的call-by-name机制
Array.fill()方法的签名为:
]
包含两个参数列表,第一个为数组元素的个数;第二个参数使用“=> T”表明该参数为call-by-name参数,使用时如同这个参数是一个函数,这个函数返回类型为T的返回值。
的意思:
i. 创建一个数组;
i. 数组元素的个数为n;
。即每次创建数组元素时,都调用这段代码;
.W)))
a. 创建一个Vec[UInt]
b. 使用Wire()绑定Vec[UInt]
WireBinding不是只读绑定,可以作为“:=”的左值。
c. carry(i)返回元素UInt
carry(i)可以作为左值使用:
Cin
= Wire(Vec(n, Bool()))
略
5. 生成Verilog
可以直接点运行符号运行。
也可以使用sbt shell执行:
生成Verilog如下:
略
6. 测试
略
7. 附录
Adder.scala:
import chisel3._ //A n-bit adder with carry in and carry out class Adder(val n:Int) extends Module { val io = IO(new Bundle { val A = Input(UInt(n.W)) val B = Input(UInt(n.W)) val Cin = Input(UInt(1.W)) val Sum = Output(UInt(n.W)) val Cout = Output(UInt(1.W)) }) //create an Array of FullAdders // NOTE: Since we do all the wiring during elaboration and not at run-time, // i.e., we don't need to dynamically index into the data structure at run-time, // we use an Array instead of a Vec. val FAs = Array.fill(n)(Module(new FullAdder()).io) // val FAs = Array.fill(n)(Module(new FullAdder())) val carry = Wire(Vec(n+1, UInt(1.W))) val sum = Wire(Vec(n, Bool())) //first carry is the top level carry in carry(0) := io.Cin //wire up the ports of the full adders for (i <- 0 until n) { FAs(i).a := io.A(i) FAs(i).a := io.A(i) FAs(i).b := io.B(i) FAs(i).cin := carry(i) carry(i+1) := FAs(i).cout sum(i) := FAs(i).sum.toBool() } // for (i <- 0 until n) { // FAs(i).io.a := io.A(i) // FAs(i).io.a := io.A(i) // FAs(i).io.b := io.B(i) // FAs(i).io.cin := carry(i) // carry(i+1) := FAs(i).io.cout // sum(i) := FAs(i).io.sum.toBool() // } io.Sum := sum.asUInt io.Cout := carry(n) } object AdderMain { def main(args: Array[String]): Unit = { chisel3.Driver.execute(Array("--target-dir", "generated/Adder"), () => new Adder(4)) } }