Menu Close

Xilinx7系列FPGA SRL16E原语

文章 Xilinx专用设计代码风格中提到从FPGA器件特征角度出发,尽可能的多使用已经存在的芯片结构,来优化资源的利用。本文将介绍Xilinx 7系列FPGA中原语 SRL16E的结构背景和使用。SRL16E原语调用的是移位寄存器,而移位寄存器位于FPGA中的配置逻辑块(CLB,Configurable Logic Block),本文将先简单介绍CLB。

 

1. 7系列FPGA中配置逻辑块(CLB)简介

CLB(Configurable Logic Block)是7系列FPGA的基本内部结构。一般来说,设计工程师不需要考虑 CLB 资源的逻辑分配,因为智能的综合器会自动实现。 但是了解CLB的特点可以帮助工程师在设计RTL时更有效的使用FPGA器件资源,包括CLB中查找表(LUT,Look-up table)的不同功能、进位(carry)传递的物理方向、可用触发器(flip-flop)的数量,分布和触发器的可用性,高效的移位寄存器等。由于CLB相关的特点过于复杂,本文将专注于介绍CLB中移位寄存器的特点。

一个CLB块包括两个SLICE。7系列FPGA中有两种SLICE,分别为SLICEL和SLICEM。SLICEL大约是SLICEM数量的两倍左右,以FII-PRX100-D所使用的7A100T芯片为例,其中SLICEM有4750个,SLICEL有11100个。所以CLB有两种SLICE组合:SLICEL + SLICEL,SLICEL + SLICEM。相较于SLICEL,SLICEM中的LUT可以用于distributed 64-bit RAM或是32-bit 移位寄存器(一个SRL32可以分为两个SRL16),注意移位寄存器不需要使用SLICEM中的触发器。在Vivado工程综合后,选中SYSTHESIS,点击菜单Window -> Device,即可以观察到如图1,图2所示的界面,找到FPGA主体CLB区。

图1 打开Device

 

图2 CLB

 

SLICEM和SLICEL的位置示意如图3所示,左边的SLICE是SLICEM,右边的SLICE是SLICEL。可以看出两个SLICE的组成基本一致:8个D触发器,一些逻辑门,MUX和四个LUT6。但是注意从图3中也可以看出,SLICEM中的LUT6的接口更多,SLICEL中LUT6的接口比较少。

 

图3 SLICEM和SLICEL

 

2. SRL16E原语用法

本文主要介绍移位寄存器中SRL16E原语的用法,7系列FPGA中移位寄存器的原语只有SRL16E和SRLC32E两种。在学会SRL16E原语的用法后,很容易触类旁通理解SRLC32E原语的用法。

SRL16E原语的端口示意图如图4所示:

图4 SRL16E原语示意图

相关的端口解释如表1所示。

表1:

端口 输入/输出 位宽 描述
CE 输入  1 高电平有效时钟使能
CLK 输入  1 移位寄存器的时钟
D 输入  1 数据输入
Q 输出  1 数据输出
A0 输入  1 A0-A3的值确定移位寄存器的深度,深度=8*A3 + 4*A2 + 2*A1 + A0 + 1,例A3-A0为4’b1100,移位寄存器的深度为13
A1 输入  1
A2 输入  1
A3 输入  1

 

表1中的端口具体含义需要结合图5理解SRL16E的原理。为了简化理解,这里将CE上拉,也就是说时钟永远是有效的。可以看出,A3-A0是选择输出Q的位置,图5中所示A3-A0是4’b1001,那么移位寄存器的值从D端输入,到Q端输出会需要延迟10个时钟周期,如图7所示(如果A3-A0 是4’b0000,那么需要1个时钟周期的D端到Q端延时)。移位寄存器的特点是最后输出的Q端会反馈给第一个触发器的D端,如图6所示。注意,在使用SRL16E原语时,移位寄存器中的初始值为INIT,16-bit宽,如果没有明确指出,默认为0。INIT值会作为初始值装载在对应移位寄存器的D端口,举例说明如果INIT值为16’b1100_0110_1001_0001,因为只选择到了第10个移位寄存器,所以参与移位的值只有10’b10_1001_0001,之后D端的值只随着移位寄存器的时钟节拍不断移位。

图5 SRL16E原理示意图

 

图6 SRL16E内部移位寄存器连接示意图

 

图7 当A3-A0为4’b1001

 

SRL16E原语的例化如下所示:

// SRL16E: 16-bit shift register LUT with clock enable operating
// on posedge of clock (Mapped to a SliceM LUT6)
// 7 Series

SRL16E #(   
    .INIT(16'h2300) // Initial Value of Shift Register
) SRL16E_inst (   
    .Q(Q),       // SRL data output   
    .A0(A0),     // Select[0] input   
    .A1(A1),     // Select[1] input   
    .A2(A2),     // Select[2] input   
    .A3(A3),     // Select[3] input   
    .CE(CE),     // Clock enable input
    .CLK(CLK),   // Clock input   
    .D(D)        // SRL data input
);
// End of SRL16E_inst instantiation

 

3. 使用SRL16E原语实例

例:使用SRL16E原语做一个8分频器。

实现代码如下:

`timescale 1ns / 1ps
module  top #
(
    parameter [31:0] N = 8
)
(
    input  clk,
    output clk_out
);

localparam DIV_COE =  { {(N/2){1'b0}}, {(N/2){1'b1}} };    
wire [3:0] a = N - 1;
SRL16E #(
    .INIT(DIV_COE) 			// Initial Value of Shift Register
) SRL16E_inst (
    .Q(clk_out),       		// SRL data output   
    .A0(a[0]),
    .A1(a[1]),
    .A2(a[2]),
    .A3(a[3]),
    .CE(1'b1),     			// Clock enable input
    .CLK(clk),   			// Clock input
    .D(clk_out)        		// SRL data input
);

endmodule

其中clk是原时钟,clk_out是经过8分频后的时钟。

 

仿真工程比较简单,只需要提供实体程序一个时钟即可,如下所示:

`timescale 1ns / 1ps


module tb(

    );
    reg clk = 0;
    wire flag;
    
    always #5 clk = ~clk;
    
    
    top top_inst(
    .clk(clk),
    .clk_out(flag)
    );
    
endmodule

 

仿真波形如下所示:

图8  8分频仿真波形

在实体文件中,对于分频系数采用了参数化的设计,但是注意:如果只使用一个SRL16E原语,最大可实现的分频是16分频,并且只能实现偶数分频。如果需要奇数分频,参见文章verilog 奇数,偶数分频逻辑。如果只需要做偶数分频的话,可以对比简单的时钟使能分频(使用多个触发器),使用移位寄存器分频(SRL16E)的好处是不需要使用触发器,资源使用极少,如图9所示,如上文提到SLICEM中的移位寄存器不需要使用额外的触发器。

图9   SRL16E资源使用

为了进行直观的对比,使用时钟使能分频的实例如下所示:

`timescale 1ns / 1ps



module top(
    input clk,
    output reg clk_out= 0
    );
    
    
    reg[1:0] div_8 = 0;
    
    always @ (posedge clk)
    begin
        if(&div_8)
            div_8 <= 0;
        div_8 <= div_8 + 1;
    end
    

    
    always @ (*)
        if(div_8 == 3)
            clk_out = ~clk_out;
        else
            clk_out = clk_out;
endmodule

综合后使用的FPGA资源如下图所示:

图10(1) 时钟使能分频资源使用

 

注意8分频理论上需要3个触发器,之所以图10中只显示出了2个触发器,是因为代码综合后生成了一个latch + 2个触发器。latch使用了一个触发器的资源,只不过在综合的时候,没有报告出来,在布线中,可以看到,如下图所示:

图10(2) 布线后资源情况

如果需要实现16分频,那么使用时钟使能分频使用的资源会更多,如下图所示:

图11   16分频时钟使能分频资源使用

 

然而,由于16分频仍然可以由一个SRL16E原语实现,所以使用移位寄存器的资源没有改变,如下图所示:

图12   16分频SRL16E资源使用

 

由此可见,SRL16E在时钟分频上优化利用FPGA资源,在资源紧张的情况下,应当作为首选实现方法。

4. 扩展讨论

EDA工具会自动将简单的延迟转换为 SRL16E 原语。但是除此之外,设计工程师应该将不直接使用延迟的工程,巧妙的利用SRL16E实现。下面列举了一些移位寄存器的应用:

  • 作为随机数生成器, 如LFSR(Linear Feedback Shift Register,线性反馈移位寄存器), Pseudo-Random Noise Generator等
  • 线性帧同步器(Serial Frame Synchronizer),将一整个帧存储在移位寄存器中,并对帧内每一位数据测试起始位和结束位Pattern
  • 使用累加器代替加法树(Adder Tree)实现运行平均值(running average)。运行平均值是一个简单的具有平滑或低通响应FIR滤波器
  • 脉冲产生器和时钟分频器,由于实现的移位寄存器都在一个SLICE中,并且都是使用同一时钟,时钟偏斜(skew,偏斜指时钟在因为途径寄存器不同或是负载不同,导致到达时间的空间变化)不会发生,而且可以支持超过350 MHz的时钟频率
  • 简易FIFO
Posted in FPGA, FPGA, FPGA 教材教案, FPGA硬件资源, Verilog, Verilog, Vivado, Vivado, 元器件, 开发工具, 开发工具, 开发语言, 教材与教案, 文章, 编程语言, 资料区

2 Comments

  1. 8班王飞飞

    老师您好,在阅读本篇文章时,有几点疑问请老师解答:
    1、文中有一句话“使用移位寄存器(SRL16E)分频的好处是不需要使用触发器,资源使用极少”,图9 SRL16E资源使用的表中也确实没有出现FF(触发器)的资源使用数据。可是移位寄存器(SRL16E)本身是由16个D触发器(也就是FF)组成的,对吗?是否可以理解为单纯使用SRL16E自身的FF资源就可以实现分频需求,同时SRL16E的FF资源如果不使用的话,也是一种浪费,这样理解对吗?
    2、下方使用“时钟使能分频”实现8或者16分频的方式中,图10、图11中展示的FF资源使用情况,都少计算了一个clk_out 寄存器,仅仅统计的div_8的2bit(2个寄存器)、div_16的3bit(3个寄存器),是否应该加上clk_out寄存器呢?

    • William

      1. 你的理解是正确的。

      2. 之所以8分频只使用了2个触发器是因为代码综合后生成了一个latch + 2个触发器。latch使用了一个触发器的资源,只不过在综合的时候,没有报告出来,在布线中,可以看到,如下图所示:
      latch

      同学学习课程非常仔细,给你点赞!

发表回复

相关链接