尝试Xilinx FPGA上的BUFGCE
最近在学习 Firesim ,其中对我自己科研很重要的一个功能便是 FASED 提供了 Memory Timing Model 的模拟。因为之前和别人合作论文曾被审稿人提出过 100MHz FPGA 使用 1600MHz 的内存,使得内存的延迟非常低,其性能表现像是一个大的 LLC Cache 而不是真实的内存,导致访存性能与真实 ASIC 上实际使用存在差异,但对于我目前的某个科研项目来说,真实的访存性能非常重要,为了防止重蹈覆辙,决定学习一些先进仿真技术。
然而我们不难想到,模拟一个真实的 Memmory Timing Model 离不开整个RTL的暂停,这一功能对于 Firesim 实现在其 MIDAS(Golden Gate) 中,在 FPGA 物理上我们考虑两种做法:
- 关掉寄存器的 CE
- 使用 Clock Gating 的方式关闭时钟,使其部分停止运行
其中,不难想到1会导致非常多的fanout问题(一般FPGA对Clock的fanout有特殊处理,和逻辑资源不同),而2则是在ASIC中节能的一种方式,也是最为常见的RTL暂停方法,同样MIDAS也是这么使用的。由于我过去没有自己写过BUFGCE,因此很好奇其具体Implementation的样子,因此做了一个尝试。
首先写了一个简单的counter模块:
module counter(
input clock,
input resetn,
input en,
output [63:0] value,
output probe_clock
);
reg [63:0] out_reg;
assign value = out_reg;
wire post_gate_clock;
assign probe_clock = post_gate_clock;
BUFGCE BUFGCE_inst (
.O(post_gate_clock), // 1-bit output: Clock output
.CE(en), // 1-bit input: Clock enable input for I0
.I(clock) // 1-bit input: Primary clock
);
always @(posedge post_gate_clock) begin
if (!resetn) out_reg <= 0;
else out_reg <= out_reg + 1;
end
endmodule
其内部使用了一个BUFGCE对时钟进行控制。而Xilinx FPGA到7-Series到Ultrascale+都提供了BUFGCE和BUFGCE_1原语,区别仅仅在于BUFGCE会在CE=0时将时钟停在0,而BUFGCE_1会在CE=0时将时钟停在1。
然后,我简单用Block Design做了一个包含MMCM、VIO、ILA的顶层设计:
其中,我把ila的时钟设定为200MHz,这样我可以采集到counter输出的100MHz时钟的变化。
布线观测
然后我们观察probe_clock的网线,可以发现其连接着输出寄存器的时钟。
再观察我们的时钟使能信号,可以发现其实现是直接连接到BUFGCE进行控制,说明BUFGCE并非使用大量的fanout寄存器CE进行模拟。
时序观测
我也通过ila对时序进行了观测,BUFGCE的默认CE类型为同步(SYNC),还可以设置为异步(ASYNC)以及HARDSYNC,我这里使用默认的SYNC情况,通过VIO注入同步的en=0,观察变化:
可以看出,在同步地设置en=0后,下一周期clock就暂停在了0位置。
再测试从en=0恢复到en=1:
可以看出,在en升高的下一拍,时钟立刻恢复。