文章 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原语的例化如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// 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分频器。
实现代码如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
`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分频后的时钟。
仿真工程比较简单,只需要提供实体程序一个时钟即可,如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
`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资源使用
为了进行直观的对比,使用时钟使能分频的实例如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
`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