超前进位加法器无法生成正确和与进位位问题排查
超前进位加法器错误排查与修正
问题描述
设计的4位超前进位加法器无法生成正确的和(sum)与进位(carry)位,以下是原代码及测试平台,需排查问题:
原全加器模块
`timescale 1ns / 1ps module FA(A,B,carry_in,sum,carry_out); input A,B, carry_in; output sum, carry_out; assign sum = A ^ B ^ carry_in; assign carry_out = (A^B) | ((carry_in) & ( A | B)); endmodule
原超前进位加法器模块
module CLAA #( parameter WIDTH = 4 ) ( input [WIDTH-1:0] A, input [WIDTH-1:0] B, output [WIDTH:0] sum ); wire [WIDTH:0] t_carry; wire [WIDTH-1:0] t_genr; wire [WIDTH-1:0] t_prop; wire [WIDTH-1:0] t_sum; // create Full adders using genvar genvar i; generate for (i=0; i< WIDTH; i=i+1) begin FA FA_Instantiation ( .A(A[i]), .B(B[i]), .carry_in(t_carry[i]), .sum(t_sum[i]), .carry_out() ); end endgenerate // creating generate and propagate terms // Gi = Ai & Bi // Pi = Ai | Bi genvar j; generate for ( j=0; j< WIDTH; j=j+1) begin assign t_genr = A[j] & B[j]; assign t_prop = A[j] | B[j]; assign t_carry[j+1] = t_genr[j] | ( t_prop[j] & t_carry[j]); end endgenerate assign t_carry[0] = 1'b0; assign sum = {t_carry[WIDTH],t_sum}; //$display("t_sum is %b",t_sum); endmodule
原测试平台
module carry_lookahead_adder_tb (); parameter WIDTH = 4; reg [WIDTH-1:0] A = 0; reg [WIDTH-1:0] B = 0; wire [WIDTH:0] sum; CLAA #(.WIDTH(WIDTH)) carry_lookahead_inst ( .A(A), .B(B), .sum(sum) ); initial begin $monitor (" A is %b, B is %b, sum is %b", A, B ,sum); end initial begin #10; A = 3'b000; B = 3'b001; #10; A = 3'b010; B = 3'b010; #10; A = 3'b101; B = 3'b110; #10; A = 3'b111; B = 3'b111; #10; end endmodule
错误点分析
全加器进位输出公式错误
全加器的carry_out正确逻辑应为:当A和B同时为1,或者其中一个为1且进位输入为1时产生进位。原代码的(A^B) | (carry_in & (A|B))不符合该逻辑,正确公式应为(A & B) | (carry_in & (A ^ B))。超前进位模块中生成与传播信号错误
- 原代码给
t_genr和t_prop赋值时未指定索引,直接对整个数组赋值,会导致所有位被最后一次循环的值覆盖,需改为对每一位单独赋值。 - 传播信号
Pi的定义应为Ai ^ Bi(当Ai和Bi不同时,进位输入会被传播到下一位),原代码写成Ai | Bi是错误的。
- 原代码给
进位信号初始化顺序问题
原代码中t_carry[0] = 1'b0的赋值在进位计算循环之后,虽然Verilog连续赋值是并行的,但为逻辑清晰,应将初始进位放在进位计算之前。测试平台位宽不匹配
测试平台中WIDTH=4,但赋值时使用3'b(3位),会导致A、B的高位默认补0,不符合4位加法器的测试预期,应改为4'b。
修正后的代码
修正后的全加器
`timescale 1ns / 1ps module FA(A,B,carry_in,sum,carry_out); input A,B, carry_in; output sum, carry_out; assign sum = A ^ B ^ carry_in; // 修正进位输出逻辑 assign carry_out = (A & B) | (carry_in & (A ^ B)); endmodule
修正后的超前进位加法器
module CLAA #( parameter WIDTH = 4 ) ( input [WIDTH-1:0] A, input [WIDTH-1:0] B, output [WIDTH:0] sum ); wire [WIDTH:0] t_carry; wire [WIDTH-1:0] t_genr; wire [WIDTH-1:0] t_prop; wire [WIDTH-1:0] t_sum; // 初始化输入进位 assign t_carry[0] = 1'b0; // 例化全加器 genvar i; generate for (i=0; i< WIDTH; i=i+1) begin FA FA_Instantiation ( .A(A[i]), .B(B[i]), .carry_in(t_carry[i]), .sum(t_sum[i]), .carry_out() // 超前进位模式下,全加器的进位输出无需使用 ); end endgenerate // 生成与传播信号计算 genvar j; generate for ( j=0; j< WIDTH; j=j+1) begin // 为每一位单独赋值生成信号 assign t_genr[j] = A[j] & B[j]; // 修正传播信号为异或 assign t_prop[j] = A[j] ^ B[j]; // 计算每一位的进位 assign t_carry[j+1] = t_genr[j] | (t_prop[j] & t_carry[j]); end endgenerate // 拼接最终结果:最高位进位 + 各位和 assign sum = {t_carry[WIDTH], t_sum}; endmodule
修正后的测试平台
module carry_lookahead_adder_tb (); parameter WIDTH = 4; reg [WIDTH-1:0] A = 0; reg [WIDTH-1:0] B = 0; wire [WIDTH:0] sum; CLAA #(.WIDTH(WIDTH)) carry_lookahead_inst ( .A(A), .B(B), .sum(sum) ); initial begin $monitor ("A = %b, B = %b, sum = %b", A, B, sum); end initial begin #10; A = 4'b0000; B = 4'b0001; #10; A = 4'b0010; B = 4'b0010; #10; A = 4'b0101; B = 4'b0110; #10; A = 4'b0111; B = 4'b0111; #10; // 增加全1测试,验证进位 A = 4'b1111; B = 4'b1111; #10; $finish; end endmodule
测试结果说明
修正后运行测试平台,输出应为:
A = 0000, B = 0001, sum = 00001 A = 0010, B = 0010, sum = 00100 A = 0101, B = 0110, sum = 01011 A = 0111, B = 0111, sum = 01110 A = 1111, B = 1111, sum = 11110
所有结果符合4位加法器的预期,最高位进位正确。
内容的提问来源于stack exchange,提问作者krishna Sai Kanthan
相关产品推荐
相关产品推荐

