赞
踩
LUT表是最基本的逻辑单元,入门书籍必有的内容,基本原理这里不说了。
一般的,有SLICEM和SLICEL两种,M代表存储,L代表逻辑,好记吧。
L的功能M也能实现,M比L更复杂,所以我们直接去看SLICEM。
图上面时直接从工具里面截的,这里面包括了:
6位读地址输入(A1-A6)
8位写地址输入(WA1-WA7)
写时钟(CLK)
写使能(WEN)
数据输入(DI1)
数据输出(O6)
移位寄存器输出(MC31)
除此之外,由于DI2输入线和O5输出的存在,这片LUT还可以被配置为32-depth,2-bit-data-wide的RAM。
为什么写是8位,读是6位呢?有疑惑就看datasheet或者user guide啊,翻出UG474,里面有张图,看了就明白了:
拿一个SLICEM的四个LUT搭一个256的单口RAM,看到了吧,写地址8位直接用,读地址用6位,然后高两bit,一个给F7MUX,一个给F8MUX,相当于做了两级二选一。
还有一个重点要说的是移位寄存器,移位寄存器用的最多的地方就是做delay 了。
下面是简单的两段代码:
always @(posedge clk )begin
shift_r <= {shift_r[62:0],rxp} ;
end
always @(posedge clk )begin
txp <= shift_r[63];
end
大概的意思就是将rxp输入延迟64个时钟周期,然后输出。在很多文档里面都说过了,LUT单元是可以直接生成移位寄存器的,当然必须是SLICEM里面的LUT的,我们看看最后生成的结果是啥样的:
有点不好看啊,我俩简单解释一下:
1.红线代表LTU读地址输入,读地址代表了移位寄存器输出的位数,写31就是延迟32位,可见所有的地址都被连接在一个高电平上,5h11111=31,一般情况下,是A[5:1]表征地址,A[0]固定为高
2.青色是时钟,这对于SLICEL来说是没有的,因为有了时钟,才可能同步操作;
3.蓝色是需要移位的数据,程序里面的rxp,直接输入到了LUT-B的数据DI1口
4.黄色从LUT-B的MC31输出的结果,一个LUT可以作为32位的移位寄存器,因为需要移位64次, 所以需要两个LUT级联才能完成完整的移位结果
5.白色是最后的输出,注意是从O6输出的,即级联之后64位移位后的结果,再过一级FF之后,就是txp 。
这种写法比较简单直观,也有一些同学想要规范,那我们调用一下官方的原语试试:
SRL16E #(
.INIT(16'h0000), // Initial contents of shift register
.IS_CLK_INVERTED(1'b0) // Optional inversion for CLK
)
SRL16E_inst (
.Q(SRL10_r), // 1-bit output: SRL Data
.CE(1), // 1-bit input: Clock enable
.CLK(clk), // 1-bit input: Clock
.D(rxp ), // 1-bit input: SRL Data
// Depth Selection inputs: A0-A3 select SRL depth
.A0(0),
.A1(1),
.A2(0),
.A3(1) //0x1010= 10
);
这是一个经典的16位寄存器的小模块,看看布线后成啥样:
1.红线代表LTU读地址输入,读地址代表了移位寄存器输出,一般情况下,是A[5:1]表征地址,但是我们看到黄色线代表的数据激怒的是DI2,也就是用了两个5输入LUT中的一个,所以真实的地址是4‘h1010 = 10,也就是移位10+1次,A[0]固定为高
2.青色是时钟;
3.黄色是输入,rxp ,注意是从DI2口输入的
4.白色是最后的输出,注意是从O6输出的,即10位移位后的结果,也就是SRL10_r。
7系列因为LUT表地址位增加,因此还支持32位移位的原语,我们来看看:
SRLC32E #(
.INIT(32'h00000000), // Initial contents of shift register
.IS_CLK_INVERTED(1'b0) // Optional inversion for CLK
)
SRLC32E_inst (
.Q(SRL20_r), // 1-bit output: SRL Data
.Q31(SRL31_r), // 1-bit output: SRL Cascade Data
.A(5'd20), // 5-bit input: Selects SRL depth
.CE(1), // 1-bit input: Clock enable
.CLK(clk), // 1-bit input: Clock
.D(rxp ) // 1-bit input: SRL Data
);
看看会是怎样布线的:
1.红线代表LTU读地址输入,读地址代表了移位寄存器输出,一般情况下,是A[5:1]表征地址,是5‘h10100 = 20,也就是移位20次,A[0]固定为高
2.青色是时钟;
3.黄色是输入,rxp ,注意是从DI1口输入的
4.白色时最后的输出,注意是从O6输出的,即20+1位移位后的结果,也就是SRL20_r。
5.咖啡色是32位移位后的结果,也就是SRL31_r
这个移位跟信号实际delay的关系,还要看个仿真才能看明白:
图要放大看,rxp_r信号delay了11个时钟节拍(计数器从750到761)得到信号SRL10_r,delay了21个时钟节拍得到了信号SRL20_r,delay了32个时钟节拍得到信号SRL31_r。
也就是delay的时钟节拍N,与配置的LUT地址A之间的关系为:
N = A + 1
说了这么多,总结一下。
注意了,知识点来了:
1.LUT作为移位寄存器配置时,要注意,delay的时钟节拍和LUT地址配置之间的关系!
2.LUT资源分两种(准确来说应该是SLICE分两种),M和L的区别要记得,同时也能看出作为SLICEM功能还是很多的,如果全拿来作分布式RAM太浪费了,当需要的RAM比较大的时候,可以考虑使用BlockRam。
3.写代码时能想到FPGA这些小结构的组成,将代码与结构契合度更紧密一些,无论是资源使用还是时序,都能得到非常明显地改善!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。