专栏首页用户7494468的专栏Verilog设计实例(5)详解全类别加法器(二)

Verilog设计实例(5)详解全类别加法器(二)

  • 写在前面
  • 正文
    • 超前进位加法器
  • 参考资料
  • 交个朋友

Verilog设计实例(5)详解全类别加法器(二)


写在前面

  • Verilog设计实例(4)详解全类别加法器(一)[1]
  • 个人博客首页[2]
  • 注:学习交流使用!

正文

超前进位加法器

超前加法器由许多级联在一起的全加法器组成。 它仅通过简单的逻辑门就可以将两个二进制数相加。 下图显示了连接在一起以产生4位超前进位加法器的4个全加器。 超前进位加法器类似于纹波提前加法器。 不同之处在于,超前进位加法器能够在完全加法器完成其运算之前计算进位。 这比起波纹加法器具有优势,因为它能够更快地将两个数字加在一起。 缺点是需要更多逻辑。 您会发现在设计FPGA和ASIC时,执行速度和使用的资源之间通常会达到平衡。

4位超前进位加法器

所谓超前进位,就是在加法运算得到结果之前,得到进位,如何判断是否进位呢? 以上图为例给出三步判断:

  1. 如果Ai与Bi都为1,则一定进位,否则不一定进位;由此确定一定进位的情况,可以用与门实现。伪代码表示为:Gi = Ai & Bi;
  2. 第一步确定了一定进位的情况,这一步确定可能进位的情况,也就是Ai或Bi有一个1,可以使用或门判断,伪代码为:Pi = Ai | Bi;
  3. 这一步进一步确定第二部不确定的情况,如果低一位(进位用Ci表示,则低为可以表示为C_i-1)确定了进位,并且Pi为1,则一定进位,也即Ci = 1。

最后得到进位公式为: C_{i+1} = G_i | ( P_i & C_i )

由此得到的伪代码为:

  // Create the Generate (G) Terms:  Gi=Ai*Bi
  assign w_G[0] = i_add1[0] & i_add2[0];
  assign w_G[1] = i_add1[1] & i_add2[1];
  assign w_G[2] = i_add1[2] & i_add2[2];
  assign w_G[3] = i_add1[3] & i_add2[3];
 
  // Create the Propagate Terms: Pi=Ai+Bi
  assign w_P[0] = i_add1[0] | i_add2[0];
  assign w_P[1] = i_add1[1] | i_add2[1];
  assign w_P[2] = i_add1[2] | i_add2[2];
  assign w_P[3] = i_add1[3] | i_add2[3];
 
  // Create the Carry Terms:
  assign w_C[0] = 1'b0; // no carry input
  assign w_C[1] = w_G[0] | (w_P[0] & w_C[0]);
  assign w_C[2] = w_G[1] | (w_P[1] & w_C[1]);
  assign w_C[3] = w_G[2] | (w_P[2] & w_C[2]);
  assign w_C[4] = w_G[3] | (w_P[3] & w_C[3]);

4位超前进位加法器

逻辑设计

由上述原理,得到的逻辑设计Verilog代码为:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Reborn Lee
// Module Name: carry_lookahead_adder_4_bit
// Additional Comments:
// https://blog.csdn.net/Reborn_Lee
//////////////////////////////////////////////////////////////////////////////////
`include "full_adder.v"
 
module carry_lookahead_adder_4_bit 
  (
   input [3:0]  i_add1,
   input [3:0]  i_add2,
   output [4:0] o_result
   );
     
  wire [4:0]    w_C;
  wire [3:0]    w_G, w_P, w_SUM;
   
  full_adder full_adder_bit_0
    ( 
      .i_bit1(i_add1[0]),
      .i_bit2(i_add2[0]),
      .i_carry(w_C[0]),
      .o_sum(w_SUM[0]),
      .o_carry()
      );
 
  full_adder full_adder_bit_1
    ( 
      .i_bit1(i_add1[1]),
      .i_bit2(i_add2[1]),
      .i_carry(w_C[1]),
      .o_sum(w_SUM[1]),
      .o_carry()
      );
 
  full_adder full_adder_bit_2
    ( 
      .i_bit1(i_add1[2]),
      .i_bit2(i_add2[2]),
      .i_carry(w_C[2]),
      .o_sum(w_SUM[2]),
      .o_carry()
      );
   
  full_adder full_adder_bit_3
    ( 
      .i_bit1(i_add1[3]),
      .i_bit2(i_add2[3]),
      .i_carry(w_C[3]),
      .o_sum(w_SUM[3]),
      .o_carry()
      );
   
  // Create the Generate (G) Terms:  Gi=Ai*Bi
  assign w_G[0] = i_add1[0] & i_add2[0];
  assign w_G[1] = i_add1[1] & i_add2[1];
  assign w_G[2] = i_add1[2] & i_add2[2];
  assign w_G[3] = i_add1[3] & i_add2[3];
 
  // Create the Propagate Terms: Pi=Ai+Bi
  assign w_P[0] = i_add1[0] | i_add2[0];
  assign w_P[1] = i_add1[1] | i_add2[1];
  assign w_P[2] = i_add1[2] | i_add2[2];
  assign w_P[3] = i_add1[3] | i_add2[3];
 
  // Create the Carry Terms:
  assign w_C[0] = 1'b0; // no carry input
  assign w_C[1] = w_G[0] | (w_P[0] & w_C[0]);
  assign w_C[2] = w_G[1] | (w_P[1] & w_C[1]);
  assign w_C[3] = w_G[2] | (w_P[2] & w_C[2]);
  assign w_C[4] = w_G[3] | (w_P[3] & w_C[3]);
   
  assign o_result = {w_C[4], w_SUM};   // Verilog Concatenation
 
endmodule // carry_lookahead_adder_4_bit

注:头文件中包含的全加器为:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Reborn Lee
// Module Name: full_adder
// https://blog.csdn.net/Reborn_Lee
//////////////////////////////////////////////////////////////////////////////////


module full_adder(
 input  i_bit1,
  input  i_bit2,
  input  i_carry,
 output o_sum,
  output o_carry

    );


assign o_sum   = i_bit1 ^ i_bit2 ^ i_carry;
assign o_carry = ((i_bit1 ^ i_bit2) & i_carry) | (i_bit1 & i_bit2);


// More clear method
 
//   wire   w_WIRE_1;
//   wire   w_WIRE_2;
//   wire   w_WIRE_3;
       
//   assign w_WIRE_1 = i_bit1 ^ i_bit2;
//   assign w_WIRE_2 = w_WIRE_1 & i_carry;
//   assign w_WIRE_3 = i_bit1 & i_bit2;
 
//   assign o_sum   = w_WIRE_1 ^ i_carry;
//   assign o_carry = w_WIRE_2 | w_WIRE_3;


  // The third method
 // assign {o_carry, o_sum} = i_bit1 + i_bit2 + i_carry;
 
 

endmodule


功能仿真

`timescale 1ns/1ps
module carry_lookahead_adder_4_bit_tb;

   reg [3:0]  i_add1;
   reg [3:0]  i_add2;
   wire [4:0] o_result;


   initial begin
    i_add1 = 'd5;
 i_add2 = 'd11;

 # 10
 i_add1 = 'd6;
 i_add2 = 'd15;

 # 10
 i_add1 = 'd11;
 i_add2 = 'd13;

 # 10
 i_add1 = 'd15;
 i_add2 = 'd15;

 #10 $finish;
   end


 // Monitor values of these variables and print them into the log file for debug
   initial
      $monitor ("i_add1 = %b, i_add2 = %b, o_result = %b", i_add1, i_add2, o_result);


   carry_lookahead_adder_4_bit inst_carry_lookahead_adder_4_bit(
    .i_add1(i_add1),
    .i_add2(i_add2),
    .o_result(o_result)
    );

endmodule

仿真波形及数据

4bit超前进位加法器仿真图

i_add1 = 0101, i_add2 = 1011, o_result = 10000
i_add1 = 0110, i_add2 = 1111, o_result = 10101
i_add1 = 1011, i_add2 = 1101, o_result = 11000
i_add1 = 1111, i_add2 = 1111, o_result = 11110

任意位宽的超前进位加法器

逻辑设计

使用参数化的方式定义位宽为 WIDTH,且使用generate for循环语句来进行全加器例化以及进位产生,设计文件如下:

 
`include "full_adder.v"
 
module carry_lookahead_adder
  #(parameter WIDTH = 3)
  (
   input [WIDTH-1:0] i_add1,
   input [WIDTH-1:0] i_add2,
   output [WIDTH:0]  o_result
   );
     
  wire [WIDTH:0]     w_C;
  wire [WIDTH-1:0]   w_G, w_P, w_SUM;
 
  // Create the Full Adders
  genvar             ii;
  generate
    for (ii=0; ii<WIDTH; ii=ii+1) 
      begin
        full_adder full_adder_inst
            ( 
              .i_bit1(i_add1[ii]),
              .i_bit2(i_add2[ii]),
              .i_carry(w_C[ii]),
              .o_sum(w_SUM[ii]),
              .o_carry()
              );
      end
  endgenerate
 
  // Create the Generate (G) Terms:  Gi=Ai*Bi
  // Create the Propagate Terms: Pi=Ai+Bi
  // Create the Carry Terms:
  genvar             jj;
  generate
    for (jj=0; jj<WIDTH; jj=jj+1) 
      begin
        assign w_G[jj]   = i_add1[jj] & i_add2[jj];
        assign w_P[jj]   = i_add1[jj] | i_add2[jj];
        assign w_C[jj+1] = w_G[jj] | (w_P[jj] & w_C[jj]);
      end
  endgenerate
   
  assign w_C[0] = 1'b0; // no carry input on first adder
 
  assign o_result = {w_C[WIDTH], w_SUM};   // Verilog Concatenation
  • 注意要对第一个进位进行置0,因为第一个全加器没有进位。

功能仿真

功能仿真同上一个tb文件类似,这里不在赘余了。


参考资料

  • 参考资料1[3]
  • 参考资料2[4]

参考资料

[1]

相关博文: https://blog.csdn.net/Reborn_Lee/article/details/106561857

[2]

个人博客首页: https://blog.csdn.net/Reborn_Lee

[3]

参考资料1: https://en.wikipedia.org/wiki/Carry-lookahead_adder

[4]

参考资料2: https://www.nandland.com/vhdl/modules/carry-lookahead-adder-vhdl.html

[5]

FPGA/IC技术交流2020: https://blog.csdn.net/Reborn_Lee/article/details/105844330

本文分享自微信公众号 - FPGA LAB(gh_af38c08c9983),作者:李锐博恩

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • FPGA/ASIC笔试面试题集锦(1)知识点高频复现练习题

    本文其实就是整合了一下去年秋招时总结的笔试题或者各大平台的练习题,只不过去年由于边笔试面试边总结,比较粗糙,这里再次整理润色一下,前人栽树,方便后人乘凉!注:个...

    Reborn Lee
  • FPGA基础知识极简教程(3)从FIFO设计讲起之同步FIFO篇

    缩写FIFO代表 First In First Out。FIFO在FPGA和ASIC设计中无处不在,它们是基本的构建模块之一。而且它们非常方便!FIFO可用于以...

    Reborn Lee
  • 有关遗传算法的一个简单入门的例子(java语言实现)

    摘要:本报告提出了一个能体现遗传算法原理的例子,并侧重于java语言的编程实现,结果较好地完成了算法的要求。基因遗传算法是一种灵感源于达尔文自然进化理论的启发式...

    Reborn Lee
  • 1-SII--SharedPreferences完美封装

    张风捷特烈
  • 技术前沿 : 大数据下的用户与价值分析。

    大数据下,用户分析的核心是什么? ——解决实际问题   确定用户分析目的,具体是为了降低成本?增加收入?优化用户体验?提升营销效果?用户针对性管理? 确定目的...

    小莹莹
  • 【数据挖掘】客户价值分析

    使用RFM方法(最近购买日Recency, 各期购买频率Frequency, 各期平均单次购买金额Monetary)能够科学地预测老客户(有交易客户)今后的购买...

    陆勤_数据人网
  • Flutter lesson 7: Flutter组件之基础组件(三)

    上一节我们介绍了Row, Column, Image, Text四个基础组件,这一节我们来看看下面几个组件。

    踏浪
  • RFID 破解基础详解

    在我们平时生活中有各种各样的卡,比如 ID 卡、IC 卡、RFID 卡、NFC 卡、Mifare 系列卡(可能银行卡、公交卡、饭卡、水卡、门禁卡、电梯卡.......

    信安之路
  • [打造自己的监控系统]使用Django批量监控Oracle长会话

    关于监控系统我们前面介绍了很多,学会了如何使用Django新建网站以及获取数据监控数据至MySQL或redis

    bsbforever
  • 火遍抖音的八卦时钟matlab源代码来了

    在浏览抖音的时候看见一款名叫“八卦时钟”的视频,看起来很炫酷,于是小编决定亲自动手采用matlab来实现。

    艾木樨

扫码关注云+社区

领取腾讯云代金券