棋子 · 1月24日

老李带你看菜谱— stx_cookbook 之 加法器 (一)

一转眼距离老李上次更新又过去了三年多,十分抱歉,上次停更是因为老李工作和家庭的原因。承蒙各位的抬爱,目前这个号还有人在继续关注。目前老李回归,争取保持一定的更新节奏,也是给自己的一个要求,希望和大家一同进步。

今天咱们来看一个cookbook,翻译过来是菜谱,当然老李不是要当美食博主,而是指FPGA 大厂Altera (目前已经被Intel收购)在2011年公开的基于Stratix系列FPGA的一份学习资料,叫做stx_cookbook。这个文档之所以有学习价值,是因为它是少有的来自大厂既有文档又有公开verilog源代码的资料,而且其中包含的内容包含了很多小模块的设计:小到加法器、乘法器,再到复杂一点的仲裁器,多路选自器,再到更复杂的CRC, ECC,甚至还包含了加密单元等,可谓干货满满。老李的目标就是通过一系列的文章,把这个资料里的模块搞清楚吃透,从而达到提升自己前端设计能力的目的。

我们先来看最基本的第一章 — 加法器

相信所有学过数字电路的同学对于加法器都不陌生,加法操作也可能是数字逻辑运算当中最常见的操作之一。我们废话不多说,边看代码边学习。放代码之前先把公司的版权信息复制过来


// Copyright 2007 Altera Corporation. All rights reserved.  
// Altera products are protected under numerous U.S. and foreign patents, 
// maskwork rights, copyrights and other intellectual property laws.  
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design 
// License Agreement (either as signed by you or found at www.altera.com).  By
// using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation.  In the event that you do
// not agree with such terms and conditions, you may not use the reference 
// design file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an 
// accommodation and therefore all warranties, representations or guarantees of 
// any kind (whether express, implied or statutory) including, without 
// limitation, warranties of merchantability, non-infringement, or fitness for
// a particular purpose, are specifically disclaimed.  By making this reference
// design file available, Altera expressly does not recommend, suggest or 
// require that this reference design file be used in combination with any 
// other product not provided by Altera.
/////////////////////

////////////////////////////////////////////////////////
///////////////////////////////////////////////
//
// This is the basic "+" operator version.  It is
// easy to use and gives the synthesis tool an 
// unambiguous message of which bits belong together.
// The synthesis tool has permission to minimize and 
// restructure "+" operations freely.  For example to 
// change "1+a+1" to "a+2".  This is the method 
// recommended by Altera and 3rd party synthesis.
//
module word_adder_plain (a,b,s);
parameter WIDTH = 8;
input [WIDTH-1:0] a,b;
output [WIDTH-1:0] s;
assign s = a + b;
endmodule

首先上来,作者在注释里也说了,加法运算在Verilog里就用+这个运算符来做就行,综合工具是可以对+来选取相应的逻辑门进行综合,这其实也是综合工具推荐的方式。其实对于ASIC的综合工具来说也是同理,我们写的RTL code里,绝大多数时候都不需要对加法运算进行特别的拆分,目前主流的综合工具DC/Genus都能够对加法运算优化的很好,只有你在做位宽非常宽的信号加法运算时可能需要关心一下时序收敛问题。

当然对于上面的code,经常跑lint的小伙伴应该能够发现一个bug,那就是a+b的结果由于进位的可能,结果s需要比a和b的位数要多一位。

在这个basic_adder.v里,后面还有一段代码利用FPGA上的资源直接例化了一个加法器。从这个例子中我们可以看到FPGA和ASIC还是有很大的不同的。


///////////////////////////////////////////////
//
// This is a standard Full Adder cell expressed
// in a WYSIWYG gate.  This form is preferable
// to comb logic because it explicitly marks the
// carry in and carry out.  It is also a good
// way to express complex logic functions on the 
// input side of the adder, and shared chains 
// (ternary addition).   This view gives access
// to all architecture capabilities, but is somewhat
// cumbersome to use.  Unlike the "+" operator
// a WYSIWYG add will not be restructured or 
// mimnimized except in extreme cases.
//
module full_add (a,b,cin,s,cout);
input a,b,cin;
output s,cout;
stratixii_lcell_comb w (
    .dataa(1'b1),
    .datab(1'b1),
    .datac(1'b1),
    .datad(a),
    .datae(1'b1),
    .dataf(b),
    .datag(1'b1),
    .cin(cin),
    .sharein(1'b0),
    .sumout(s),
    .cout(cout),
    .combout(),
    .shareout()
);
defparam w .shared_arith = "off";
defparam w .extended_lut = "off";
defparam w .lut_mask = 64'h000000ff0000ff00 ;
//
// Note : LUT mask programming is generally done by
//   synthesis software, but they can be set by hand.  This
//   explanation is for the interested person, and by 
//   no means necessary to follow.
//
// The lut mask is a truth table expressed in 64 bit hex.  
// In basic adder mode these two blocks are active.
//         vvvv    vvvv 
// 64'h000000ff0000ff00 
// 
// Each 4 hex digit block represents a function of up to 4 inputs.
// The left hand block uses "ABCF" and the right hand "ABCD" with
// A being the least significant.  For each of the 16 possible input
// values the function output is stored in the corresponting bit.
//
//    e.g.  ffff  = vcc  (all ones)
//ff00  = "D"  (most significant)
//aaaa  = "A"  (1010..binary, the least significant)
//          6666  = "A xor B"
//
// These functions will be the two inputs to the adder chain.  
// In this case the inputs D and F pass through.  Detailed
// information on the programming of WYSIWYG cells is available
// through the Altera University Program (for CAD tools
// research).  
//
endmodule

这段代码的注释里面说,下面这种直接例化WYSIWYG gate的方式是另外一种写法。问题来了,什么是WYSIWYG? 老李第一次看到这个词还以为是和Synopsys 的designWare类似的概念,即以为是Altera FPGA的库,实际确实上也可以这么理解,WYSIWYG其实是What You See Is What You Get (即所见即所得)的英文缩写,在这里这个1比特的全加器里例化了一个StratixII的基本单元(primitive cell),这个基本单元在Altera FPGA里叫做adaptive logic module (ALM),你可以将它理解为FPGA帮你先设计好了一个单元库,但这个单元要比简单的与或非门之类的要复杂,也更加灵活,里面有设计好的LUT (Lookup Table),加法器,mux,flop stage等,利用不同的输入组合以及不同的查找表,可以实现较为复杂但是时序又比较有保证的电路。下图是一个high level的diagram.

image.png

其实FPGA的综合工具在将RTL的行为级代码综合为FPGA网表时,底层也是这些ALM单元,这里的写法其实就是跳过了综合这一步,直接告诉FPGA去例化这个模块,来实现全加器的功能。那么我们继续看这个例化是怎么实现的呢?

这个cookbook的这一章开头就放了一个简化版的ALM图。

image.png

里面有3个LUT4,其中上面两个LUT4的输出接了一个加法器,和Cin一起得出了sumout和cout。那么我们现在来理解一下LUT是怎么回事。4输入的LUT说白了其实就是个4输入的真值表

image.png

如果我们将F0 OUT来从高到低排列组成一个数,那就是0’b1111_1111_0000_0000, 也就是对应的0xFF00,这就是LUT的参数。注意对于第一个LUT来说,例化的时候dataa, datab, datac端口都连了1’b1,那么其实LUT有效的就是第8行和第16行,因为datad接的是实际的信号a。本质上这个LUT实现的功能就是F = datad,即F = a。

然后我们再看第二个LUT,它接了dataa, datab, datac, dataf. 在这里dataf端口连的是信号b

image.png

同样的道理,有效的依然只是第8行和第16行,只不过LUT实现的功能是F = ~dataf = ~b. 这个LUT的参数是0x00FF。那么为什么要取反呢,注意看ALM的logic cell框图,在加法器的第二个输入前是有个反相器的,所以这里LUT输出是b的反,再反一次就还是b了,最终本质上就是a + b + cin经过加法器得到s和cout。

关于这个stratixii_lcell_comb cell, 老李没有找到详细的端口例化资料。老李找到了另外一个系列Cycloneii FPGA的lcell资料,里面的逻辑类似,只是没有stratix的cell的端口多,有感兴趣的小伙伴可以直接Bing搜索Cycloneii_le_wys.pdf应该就能找到。 

这里再解释一下代码注释中的这一段

// The lut mask is a truth table expressed in 64 bit hex.  
// In basic adder mode these two blocks are active.
//         vvvv    vvvv 
// 64'h000000ff0000ff00 
// 

为什么是64位呢?其实stratixii的ALM里面不只有3个LUT,其实它是很灵活的,全部的full diagram如下。64位其实对应了所有6个LUT。

640.png

接下来的code实现了一个多位的全加法器,利用上面的单比特全加器,本质上是一个行波进位加法器。如果学过数字电路设计的同学应该记得,行波进位加法器是最慢的了,还有一大堆比这个快得多的加法器的实现办法,这里只是举个实例,实际使用中无论是FPGA还是ASIC,大家尽量不要这样去单纯例化全加器,而是交给综合工具让它去选择最适合的加法器。


///////////////////////////////////////////////
//
// This is a word adder constructed from the 
// slices declared above.
//
module word_adder_sliced (a,b,s);
parameter WIDTH = 8;
input [WIDTH-1:0] a,b;
output [WIDTH-1:0] s;
wire [WIDTH:0] cin;
assign cin[0] = 1'b0;
genvar i;
generate
for (i=0; i<WIDTH; i=i+1) 
begin : al
full_add fa (.a(a[i]),.b(b[i]),.cin(cin[i]),.s(s[i]),.cout(cin[i+1]));
end
endgenerate
endmodule

最后指出一点,上述代码中对于参数的例化用了defparam的语法,defparam在实际工程中已经不推荐使用了,SystemVerilog的语法指南已经把它归类为过时语法,很多EDA工具已经开始不再支持,希望大家在实际工作中还是使用.()的形式来对参数进行例化。

作者:硅谷老李
文章来源:IC加油站

推荐阅读

更多IC设计干货请关注IC设计专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
15908
内容数
1261
主要交流IC以及SoC设计流程相关的技术和知识
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息