verilog 多种方法实现多位加法器

一位全加器原理
在这里插入图片描述

法1 串行一位加法器法

一位全加器

module adder_1bit(
    input din_one, //第一个加数
    input din_two, //第二个加数
    input cin,     //进位输入
    
    output sum,    //和输出
    output cout    //进位输出
    );
    

//利用连续赋值语句实现全加操作    
   assign sum = din_one ^ din_two ^ cin;
   assign cout = (din_one & din_two) | (din_two & cin) | (din_one & cin);    
endmodule

2bit

module adder_2bit(
    input [1 : 0] din_one,  //第一个加数
    input [1 : 0] din_two,  //第二个加数
    input cin,              //进位输入
    
    output [1 : 0] sum,     //和输出
    output cout             //进位输出
    );
    
    wire cin_0bit;          //低位加法的进位输出

//实例化adder_1bit实现低位加法    
    adder_1bit U1_low_bit(
        .din_one(din_one[0]),
        .din_two(din_two[0]),
        .cin(cin),
        .sum(sum[0]),
        .cout(cin_0bit)
        );
    
//实例化adder_1bit实现高位加法       
    adder_1bit U2_high_bit(
        .din_one(din_one[1]),
        .din_two(din_two[1]),
        .cin(cin_0bit),
        .sum(sum[1]),
        .cout(cout)
        );
        

//利用模块实例化语句实现2位全加操作    
endmodule

4bit

module adder_4bit(
    input [3 : 0] din_one,  //第一个加数
    input [3 : 0] din_two,  //第二个加数
    input cin,              //进位输入
    
    output [3 : 0] sum,     //和输出
    output cout             //进位输出
    );
    
    wire cin_0bit;          //低位加法的进位输出

//实例化adder_1bit实现低位加法    
    adder_2bit U1_low_bit(
        .din_one(din_one[1 : 0]),
        .din_two(din_two[1 : 0]),
        .cin(cin),
        .sum(sum[1 : 0]),
        .cout(cin_0bit)
        );
    
//实例化adder_1bit实现高位加法       
    adder_2bit U2_high_bit(
        .din_one(din_one[3 : 2]),
        .din_two(din_two[3 : 2]),
        .cin(cin_0bit),
        .sum(sum[3 : 2]),
        .cout(cout)
        );
        

//利用模块实例化语句实现2位全加操作    
endmodule

法2 并行加法器

思路 :直接用加法运算符“+”实现。直接表示

/*******************8位加法器 ***********************/
module adder_nonpipe(cout, sum, ina, inb, cin, enable);
 
output cout;
output [7:0] sum;
input [7:0] ina, inb;
input cin, enable;
 
reg cout;
reg [7:0] sum;
reg [7:0] tempa, tempb;
reg tempc;
 
always @(posedge enable)
begin
    tempa <= ina;
    tempb <= inb;
    tempc <= cin;
end
 
always @(posedge enable)
begin
    {cout,sum} <= tempa + tempb + tempc;
end
 
endmodule

法3 参数化

module N_bit_add(
    clk    ,
    rst_n  ,
    //其他信号,举例dout
    A ,
    B ,
    Cin ,
    dout ,
    sout
    );
    //参数定义
    parameter      DATA_W =         8;

    //输入信号定义
    input               clk    ;

    input               rst_n  ;
    input               Cin  ;
    input[DATA_W-1:0]        A ;
    input[DATA_W-1:0]        B ;
    //输出信号定义
    output[DATA_W-1:0]  dout   ;
    output              sout   ;

    //进位位,S[7]为输出最后进位
    reg   [DATA_W-1:0]  S   ;


    genvar i;
    generate for(i=0;i<DATA_W;i=i+1)
        begin:one_bit_add
            if(i==0)begin
                assign dout[i]=A[i]^B[i]^Cin;
                assign S[i]=(A[i]&B[i])|(A[i]&Cin)|(Cin&B[i]);
            end
            else begin
                assign dout[i]=A[i]^B[i]^S[i-1];
                assign S[i]=(A[i]&B[i])|(A[i]&Cin;)|(Cin&B[i]);
            end
            
        end
    endgenerate
    assign sout=S[7];

    endmodule


法4流水线

 1 /*******************8位2级流水加法器*************************/
 2 module adder_pipeline(cout, sum, ina, inb, cin, enable);
 3 
 4 output cout;
 5 output [7:0] sum;
 6 input [7:0] ina, inb;
 7 input cin, enable;
 8 
 9 reg cout;
10 reg [7:0] sum;
11 
12 reg [3:0] tempa, tempb, firsts;
13 reg firstc;
14 always @(posedge enable)
15 begin
16     {firstc,firsts} = ina[3:0] + inb[3:0] + cin;
17     tempa = ina[7:4];        //高4位输入寄存,使其与sum低4位在下级流水线同步输入。
tempb = inb[7:4];        //否则sum的高4位,与低四位分两个时钟周期输出
18 end
19 
20 always @(posedge enable)
21 begin
22     {cout,sum[7:4]} = tempa + tempb + firstc;
23     sum[3:0] = firsts;       //不能合并为{cout, sum} = {tempa + tempb + firstc, firsts}; 位宽不匹配
24 end
25 
26 endmodule

四级流水线

module adder_pipeline(rst_n,
                                clk,
                                a,
                                b,
                                cin,
                                sum
                                     );
     
parameter     DATA_SIZE = 8;
     
input rst_n;
input clk;
input [DATA_SIZE - 1 : 0] a;
input [DATA_SIZE - 1 : 0] b;    
input cin;

output [DATA_SIZE : 0] sum;

reg [DATA_SIZE - 1 : 0] a_r;
reg [DATA_SIZE - 1 : 0] b_r;
reg cin_r;

reg [DATA_SIZE : 0] sum;

reg [1:0] stage0_sum;
reg stage0_cout;
reg [DATA_SIZE - 1 : 0] stage0_a_r;
reg [DATA_SIZE - 1 : 0] stage0_b_r;

//reg [4:0] stage1_sum;
reg [3:0] stage1_sum;
reg stage1_cout;
reg [DATA_SIZE - 1 : 0] stage1_a_r;
reg [DATA_SIZE - 1 : 0] stage1_b_r;

//reg [6:0] stage2_sum;
reg [5:0] stage2_sum;
reg stage2_cout;
reg [DATA_SIZE - 1 : 0] stage2_a_r;
reg [DATA_SIZE - 1 : 0] stage2_b_r;

//reg [8:0] stage3_sum;
reg [7:0] stage3_sum;
reg stage3_cout;

always@(posedge clk)
    if(!rst_n)
        begin
            a_r <= 8'd0;
            b_r <= 8'd0;
            cin_r <= 1'b0;
        end
    else
        begin
            a_r <= a;
            b_r <= b;
            cin_r <= cin;
        end

always@(posedge clk)
    if(!rst_n)
        begin
            {stage0_cout,stage0_sum} <= 3'd0;
            stage0_a_r <= 8'd0;
            stage0_b_r <= 8'd0;        
        end
    else
        begin
            //{stage0_cout,stage0_sum} <= a_r[1:0] + b_r[1:0] + cin_r;    
            {stage0_cout,stage0_sum} <= {1'b0,a_r[1:0]} + {1'b0,b_r[1:0]} + cin_r;                
            stage0_a_r <= a_r;
            stage0_b_r <= b_r;        
        end
        
always@(posedge clk)
    if(!rst_n)
        begin
            {stage1_cout,stage1_sum} <= 5'd0;
            stage1_a_r <= 8'd0;
            stage1_b_r <= 8'd0;    
        end
    else
        begin
            //{stage1_cout,stage1_sum} <= { {a_r[3:2] + b_r[3:2] + stage0_cout},{stage0_sum} };
            //{stage1_cout,stage1_sum} <= { {{1'b0,a_r[3:2]} + {1'b0,b_r[3:2]} + stage0_cout},{stage0_sum} };    
            //{stage1_cout,stage1_sum} <= { {1'b0,a_r[3:2]} + {1'b0,b_r[3:2]} + stage0_cout,stage0_sum };
            //{stage1_cout,stage1_sum} = { {a_r[3],a_r[3:2]} + {b_r[3],b_r[3:2]} + stage0_cout,stage0_sum };
            {stage1_cout,stage1_sum} <= { {1'b0,stage0_a_r[3:2]} + {1'b0,stage0_b_r[3:2]} + stage0_cout,stage0_sum };
            stage1_a_r <= stage0_a_r;
            stage1_b_r <= stage0_b_r;
        end        

always@(posedge clk)
    if(!rst_n)
        begin
            {stage2_cout,stage2_sum} <= 7'd0;
            stage2_a_r <= 8'd0;
            stage2_b_r <= 8'd0;    
        end
    else
        begin
            {stage2_cout,stage2_sum} <= { {1'b0,stage1_a_r[5:4]} + {1'b0,stage1_b_r[5:4]} + stage1_cout,stage1_sum };            
            stage2_a_r <= stage1_a_r;
            stage2_b_r <= stage1_b_r;
        end        

always@(posedge clk)
    if(!rst_n)
        begin
            {stage3_cout,stage3_sum} <= 9'd0;
        end
    else
        begin
            {stage3_cout,stage3_sum} <= { {stage2_a_r[7],stage2_a_r[7:6]} + {stage2_b_r[7],stage2_b_r[7:6]} + stage2_cout,stage2_sum };    
        end

always@(posedge clk)
    if(!rst_n)
        begin
            sum <= 9'd0;
        end
    else
        begin
            sum <= {stage3_cout,stage3_sum};        
        end
        
endmodule

testbench

 `timescale 1 ns/1 ns

 module tb();

 //时钟周期,单位为ns,可在此修改时钟周期。
 parameter CYCLE    = 20;

 //复位时间,此时表示复位3个时钟周期的时间。
 parameter RST_TIME = 3 ;

 parameter DATA_W    = 4;


 //时钟和复位
 reg clk  ;
 reg rst_n;

 //uut的输入信号
 reg[DATA_W-1:0]  A  ;
 reg[DATA_W-1:0]  B  ;

 reg              Cin;
     //uut的输出信号
     wire      sout;
     wire[DATA_W-1:0] dout;

         //待测试的模块例化
         N_bit_add #(.DATA_W(4))uut(
             .clk          (clk     ), 
             .rst_n        (rst_n   ),
             .A               (A    ),
             .B               (B    ),
	         .Cin               (Cin),
             .dout          (dout   ),
             .sout          (sout   )
             );


             //生成本地时钟50M
             initial begin
                 clk = 0;
                 forever
                 #(CYCLE/2)
                 clk=~clk;
             end

             //产生复位信号
             initial begin
                 rst_n = 1;
                 #2;
                 rst_n = 0;
                 #(CYCLE*RST_TIME);
                 rst_n = 1;
             end
             integer i;
             //输入信号a赋值方式
             initial begin
	        	i=0;
                  #1;
                 //赋初值
	          	Cin=0;
	        	 A= 0;
                 #(10*CYCLE);
                 //开始赋值
                 for (i=0;i<16;i=i+1)begin
                     A=i;
                     #(CYCLE/2);
                 end
             end
	             integer j;	
             initial begin
	        	j=0;
                 #1;
                 //赋初值
		         B = 0;
                 #(10*CYCLE);
                 //开始赋值
                 for (j=0;j<16;j=j+1)begin
                     B=j;
                     #(CYCLE/2);
                 end
             end
     endmodule


ref
https://www.cnblogs.com/youngforever/archive/2013/06/08/3127204.html

  • 8
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值