Scala Chisel实现Carry Select Adder(进位选择加法器)报错求解
代码核心错误点
- 数组越界:你实例化的rca和mux数量是
n/m组(每组2个rca对应1个mux),但循环写了for (i <- 0 until n),当n大于n/m时,直接访问数组不存在的下标,这是抛出elaboration异常的直接原因,循环次数应该对应进位选择块的总数。 - 位截取错误:你对a、b的位截取写的是
(i*m+m,i*m),正确的高位应该是i*m + m -1,否则会多截取一位不存在的信号,也会触发elaboration错误。 - 多路选择器位宽错误:你实现的二选一多路选择器只需要1位sel信号即可,但你实例化时给Multiplexer传的参数是
m+1,导致sel位宽是m+1位,逻辑完全错误,需要把sel单独设为1位位宽,不要和数据位宽绑定。 - 硬件逻辑混淆:你写的
if(muxs(i).sel == 0)是Scala语法,只会在代码编译时判断,不会生成硬件选择电路。进位选择的进位传递逻辑需要用Chisel的Mux生成硬件选择逻辑。 - 位宽匹配错误:每个mux输出是m位的块求和结果,你把它直接赋值给1位的
Sum(i),位宽完全不匹配,需要按块拼接sum结果。 - 进位链逻辑错误:第一级块的mux sel是输入的cin,后续每个块的sel是前一个块输出的进位(即前一个块选中的rca的cout),你现有逻辑把所有sel都连到io.cin,完全不符合进位选择加法器的结构。
- 输出缺少最高进位:io.sum是n+1位,你现有逻辑只拼接了n位的求和结果,没有包含最后一级块输出的进位。
修正后代码
1. 修正Multiplexer定义
class Multiplexer(val n:Int) extends Module { val io = IO(new Bundle { val a = Input(UInt(n.W)) val b = Input(UInt(n.W)) val sel = Input(UInt(1.W)) // 修正:sel固定为1位,二选一不需要和数据同宽 val out = Output(UInt(n.W)) }) io.out := Mux(io.sel.asBool, io.a, io.b) }
2. 修正CarrySelectAdder定义
class CarrySelectAdder(val n:Int, val m:Int) extends Module { require(n % m == 0, "总位宽n必须是块位宽m的整数倍,非整除场景可自行补充边角块逻辑") val blockNum = n / m 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+1).W)) }) // 每个块对应2个rca,分别预计算cin=0和cin=1的结果 val rcas = Array.fill(blockNum, 2){Module(new RcaAdder(m)).io} // 每个块对应1个sum选择器、1个进位选择器 val sumMuxs = Array.fill(blockNum){Module(new Multiplexer(m)).io} val carryMuxs = Array.fill(blockNum){Module(new Multiplexer(1)).io} val sumBlocks = Wire(Vec(blockNum, UInt(m.W))) val carryChain = Wire(Vec(blockNum + 1, UInt(1.W))) // 第一级进位为输入cin carryChain(0) := io.cin for (i <- 0 until blockNum) { // 给当前块的两个rca赋值输入 rcas(i)(0).a := io.a(i*m + m - 1, i*m) rcas(i)(0).b := io.b(i*m + m - 1, i*m) rcas(i)(0).cin := 0.U rcas(i)(1).a := io.a(i*m + m - 1, i*m) rcas(i)(1).b := io.b(i*m + m - 1, i*m) rcas(i)(1).cin := 1.U // 根据前一级进位选当前块的sum sumMuxs(i).a := rcas(i)(1).sum sumMuxs(i).b := rcas(i)(0).sum sumMuxs(i).sel := carryChain(i) sumBlocks(i) := sumMuxs(i).out // 根据前一级进位选当前块的输出进位,作为下一级选择信号 carryMuxs(i).a := rcas(i)(1).cout carryMuxs(i).b := rcas(i)(0).cout carryMuxs(i).sel := carryChain(i) carryChain(i+1) := carryMuxs(i).out } // 拼接低位到高位的sum,加上最高进位得到最终结果 io.sum := Cat(carryChain(blockNum), sumBlocks.reverse.asUInt) }
你的原有测试代码无需修改,测试用例n=6、m=3符合整除要求,可直接运行。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

