Josh 的学习笔记之 Verilog(Part 5——RTL 设计与编码指导)

本文深入探讨RTL级设计的基本规律,涵盖面积与速度的平衡、同步设计原则、代码风格、组合逻辑注意事项、时钟设计及RTL代码优化技巧。通过具体案例解析,阐述设计原则与实践技巧,助力提升设计质量和效率。

本文约 34,000 字,阅读需约 65 分钟。

《Part 4——RTL 概念与常用 RTL 建模》中,通过具体的 RTL 建模建立了一些对 RTL 级描述的一些感性认识,本文将较深入地探讨一些 RTL 设计的基本规律。RTL 设计规律与方法是一个非常大的论题,在此不可能面面俱到,希望通过本文的介绍,引起大家的注意。如果大家能在日后的工作实践中,不断积累,有意识地积累基本设计原则、设计思想,将取得事半功倍的效果!


1. 一般性指导原则

RTL 级设计的评判标准有很多,如时序性能、所占面积、可测试性、可重要性、功耗、时钟域的分配、复位信号设计、是否与所用 EDA 工具匹配等。如果设计目标是在 FPGA 或 CPLD 等可编程逻辑器件上实现,则还需考虑是否能发挥这些 PLD 的结构特点等。根据以上所述这些目标的组合和优先级可以派生出很多不同的设计原则。这里仅仅讨论一般意义的指导原则。

这里抛砖引玉地提出 4 个基本设计原则,这些指导原则范畴非常广,不仅仅是要学习它们,更重要的是理解,并在今后的工作实践中充实、完善。

  1. 面积和速度的平衡与互换原则

    面积和速度的平衡与互换原则提出了 RTL 设计的两个基本目标,并探讨了这两个目标对立统一的矛盾关系。

  2. 硬件原则

    硬件原则重点在于提醒读者转化软件设计的思路,理解 HDL 语言设计的本质。

  3. 系统原则

    系统原则希望读者能够通过全局、整体上把握设计,从而提高设计质址,优化设计效果。

  4. 同步设计原则

    同步设计原则是设计时序稳定的基本要求,也是高速 RTL 设计的通用法则。

1.1 面积和速度的平衡与互换原则

这里“面积”是指一个设计所消耗的目标器件(如 FPGA/CPLD/ASIC 等)的硬件资源数量:对于 FPGA,可以用所消耗的触发器(FF)和查找表(LUT)来衡扯;对于 CPLD,常用宏单元(MC)衡量;对于 ASIC 可以用设计的系统门衡量。“速度”指设计在芯片上稳定运行时所能够达到的最高频率,这个频率由设计的时序状况决定,与设计满足的时钟周期、PAD to PAD Time、Clock Setup Time、Clock Hold Time 和 Clock-to-Output Delay 等众多时序特征量密切相关。面积(Area)和速度(Speed)这两个指标贯穿着 RTL 设计的始终,是设计质量评价的终极标准。这里就讨论一下设计中关于面积和速度的基本原则:面积和速度的平衡与互换。

面积和速度是一对对立统一的矛盾体。要求一个设计同时具备设计面积最小,运行频率最高,这是不现实的。科学的设计目标应该是在满足设计时序要求(包含对设计最高频率的要求)的前提下,占用最小的芯片面积,或者在所规定的面积下,使设计的时序余量更大、频率更高。这两种目标充分体现了面积和速度的平衡思想。关于面积和速度的要求,不应该简单地理解为工程师水平的提高和设计完美性的追求,而应该认识到它们是和产品的质量、成本直接相关的。如果设计的时序余量比较大,运行的频率比较高,则意味着设计的健壮性更强,整个系统的质量更有保证;另一方面,设计所消耗的面积更小,则意味着在单位芯片上实现的功能模块更多,需要的芯片数量更少,整个系统的成本也随之大幅度削减。

作为矛盾的两个组成部分,面积和速度的地位是不一样的。相比之下,满足时序、工作频率的要求更重要一些,当两者冲突时,采用速度优先的准则。

面积和速度的互换是 RTL 设计的一个重要思想。从理论上讲,一个设计如果时序余量较大,所能跑的频率远远高于设计要求,那么就能通过功能模块复用减少整个设计消耗的芯片面积,这就是用速度的优势换面积的节约;反之,如果一个设计的时序要求很高,普通方法达不到设计频率,那么一般可以通过将数据流串/并转换,并行复制多个操作模块,对整个设计采取“乒乓操作”和“串/并转换”的思想进行处理,在芯片输出模块处再对数据进行“并/串转换”。从宏观上看,整个芯片满足了处理速度的要求,这相当于用面积复制换取速度的提高。面积和速度互换的具体操技巧很多,比如模块复用、“乒乓操作”、“串/并转换”等,需要在工作中不断积累。下面举例说明如何使用“速度换面积”和“面积换速度”。

1.1.1 “用速度的优势换面积的节约”举例

WCDMA(宽带码分多址)系统中使用到了快速哈达码(FHT)运算, FHT 由 4 步相同的算法完成,如图 5-1 所示。

5-1-FHT 原理图

图5-1 FHT 原理图

FHT 单步算法如下:

O u t [ 2 i ] = I n [ 2 i ] + I n [ 2 i + 8 ] , i = 0 ∼ 7 O u t [ 2 i + 1 ] = I n [ 2 i + 1 ] − I n [ 2 i + 1 + 8 ] , i = 0 ∼ 7 \begin{aligned} &\mathrm{Out}[2i]=\mathrm{In}[2i] + \mathrm{In}[2i+8],&i=0\sim7\\ &\mathrm{Out}[2i+1]=\mathrm{In}[2i+1] - \mathrm{In}[2i+1+8],&i=0\sim7 \end{aligned} Out[2i]=In[2i]+In[2i+8],Out[2i+1]=In[2i+1]In[2i+1+8],i=07i=07

考虑流水线式数据处理的要求,最自然的设计方法就是设计不同端口宽度的 4 个单步 FHT,并用将这 4 个单步模块串联起来,从而完成数据流的流水线处理。该 FHT 实现方式的代码如下:

/******************************
该模块是 FHT 的顶层,调用 4 个不同端口宽度的单步 FHT 模块,完成整个 FHT 算法
******************************/

// fhtpart.v
module fhtpart(
    Clk,Reset,FhtStarOne,FhtStarTwo,FhtStarThree,FhtStarFour,
    I0,I1,I2,I3,I4,I5,I6,I7,I8,
    I9,I10,I11,I12,I13,I14,I15,
    Out0,Out1,Out2,Out3,Out4,Out5,Out6,Out7,Out8,
    Out9,Out10,Out11,Out12,Out13,Out14,Out15
    );

input           Clk;                // 设计的主时钟
input           Reset;              // 异步复位
input           FhtStarOne,FhtStarTwo,FhtStarThree,FhtStarFour;
                                    // 4 个单步算法的时序控制信号
                                    
// FHT 的 16 个输入
input   [11:0]  I0,I1,I2,I3,I4,I5,I6,I7,I8;
input   [11:0]  I9,I10,I11,I12,I13,I14,I15; 
                                    
// FHT 的 16 个输出
output  [15:0]  Out0,Out1,Out2,Out3,Out4,Out5,Out6,Out7;
output  [15:0]  Out8,Out9,Out10,Out11,Out12,Out13,Out14,Out15;

// 第 1 次 FHT 单步运算的输出
wire    [12:0]  m0,m1,m2,m3,m4,m5,m6,m7,m8,m9;
wire    [12:0]  m10,m11,m12,m13,m14,m15;

// 第 2 次 FHT 单步运算的输出
wire    [13:0]  mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7,mm8,mm9;
wire    [13:0]  mm10,mm11,mm12,mm13,mm14,mm15;

// 第 3 次 FHT 单步运算的输出
wire    [14:0]  mmm0,mmm1,mmm2,mmm3,mmm4,mmm5,mmm6,mmm7,mmm8,mmm9;
wire    [14:0]  mmm10,mmm11,mmm12,mmm13,mmm14,mmm15;

// 第 4 次 FHT 单步运算的输出
wire    [15:0]  Out0,Out1,Out2,Out3,Out4,Out5,Out6,Out7,Out8,Out9;
wire    [15:0]  Out10,Out11,Out12,Out13,Out14,Out15;

// 第 1 次 FHT 单步运算
fht_unit1 fht_unit1(
    Clk,Reset,FhtStarOne,
    I0,I1,I2,I3,I4,I5,I6,I7,I8,I9,I10,I11,I12,
    I13,I14,I15,
    m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,
    m13,m14,m15
    );

// 第 2 次 FHT 单步运算
fht_unit2 fht_unit2(
    Clk,Reset,FhtStarTwo,
    m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,
    m13,m14,m15,
    mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7,mm8,mm9,mm10,mm11,mm12,
    mm13,mm14,mm15
    );

// 第 3 次 FHT 单步运算
fht_unit3 fht_unit3(
    Clk,Reset,FhtStarThree,
    mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7,mm8,mm9,mm10,mm11,mm12,
    mm13,mm14,mm15,
    mmm0,mmm1,mmm2,mmm3,mmm4,mmm5,mmm6,mmm7,mmm8,mmm9,mmm10,mmm11,mmm12,
    mmm13,mmm14,mmm15
    );

// 第 4 次 FHT 单步运算
fht_unit4 fht_unit4(
    Clk,Reset,FhtStarFour,
    mmm0,mmm1,mmm2,mmm3,mmm4,mmm5,mmm6,mmm7,mmm8,mmm9,mmm10,mmm11,mmm12,
    mmm13,mmm14,mmm15,
    Out0,Out1,Out2,Out3,Out4,Out5,Out6,Out7,Out8,Out9,Out10,Out11,Out12,
    Out13,Out14,Out15
    );

endmodule

单步 FHT 运算举例如下(仅举例第 1 步的模块):

/******************************
第 1 次 FHT 单步运算
******************************/

// fht_unit1.v
module fht_unit1(
    Clk,Reset,FhtStar,
    In0,In1,In2,In3,In4,In5,In6,In7,In8,In9,In10,In11,In12,
    In13,In14,In15,
    Out0,Out1,Out2,Out3,Out4,Out5,Out6,Out7,Out8,Out9,Out10,Out11,Out12,
    Out13,Out14,Out15
    );

input           Clk;        // 设计的主时钟
input           Reset;      // 异步复位
input           FhtStar;    // 单步 FHT 运算控制信号

// 单步 FT运算输入
input   [11:0]  In0,In1,In2,In3,In4,In5,In6,In7,In8,In9;
input   [11:0]  In10,In11,In12,In13,In14,In15;
                            
// 单步 FT运算输出
output  [12:0]  Out0,Out1,Out2,Out3,Out4,Out5,Out6,Out7,Out8,Out9;
output  [12:0]  Out10,Out11,Out12,Out13,Out14,Out15;

reg     [12:0]  Out0,Out1,Out2,Out3,Out4,Out5;
reg     [12:0]  Out6,Out7,Out8,Out9,Out10,Out11;
reg     [12:0]  Out12,Out13,Out14,Out15;

// 补码运算
wire    [11:0]  In8Co  =~ In8+1;
wire    [11:0]  In9Co  =~ In9+1;
wire    [11:0]  In10Co =~ In10+1;
wire    [11:0]  In11Co =~ In11+1;
wire    [11:0]  In12Co =~ In12+1;
wire    [11:0]  In13Co =~ In13+1;
wire    [11:0]  In14Co =~ In14+1;
wire    [11:0]  In15Co =~ In15+1;

always @(posedge Clk or negedge Reset) begin
    if(!Reset) begin
        Out0<=0 ; Out1<=0 ; Out2<= 0; Out3<= 0;
        Out4<=0 ; Out5<=0 ; Out6<= 0; Out7<= 0;
        Out8<=0 ; Out9<=0 ; Out10<=0; Out11<=0;
        Out12<=0; Out13<=0; Out14<=0; Out15<=0;
    end
    end
    else begin
        if(FhtStar) begin
            Out0  <= {In0[11],In0 } + {In8[11],In8 };
            Out1  <= {In0[11],In0 } + {In8Co[11],In8Co };
            Out2  <= {In1[11],In1 } + {In9[11],In9 };
            Out3  <= {In1[11],In1 } + {In9Co[11],In9Co };
            Out4  <= {In2[11],In2 } + {
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值