FMC 使用指南
Writer:何凯旋
本指南用 zynq-7000 系列 ZC706 开发板进行示例。
一、ZC706 开发板实物图
其中位于最上方的标号 30、31 的区域便是两个 FMC 接口,分别为 HPC 与 LPC。
二、FMC 载卡实物图
三、载卡与载板连接图
四、FMC 介绍
FMC ( FPGA Mezzanine Card ) 简而言之,是具有特定功能的子卡模块。
FPGA 夹层卡 (FMC) 标准由包括 FPGA 厂商和最终用户在内的公司联盟
开发,属于 ANSI 标准,旨在为基础板(载卡)上的 FPGA 提供标准的夹层卡
尺寸、连接器和模块接口。I/O 接口与 FPGA 分离,不仅简化了 I/O 接口模
块设计,同时还能最大化载卡的重复使用率。
FMC 标准定义了单宽度(69 毫米 x 76.5 毫米) 和双宽度(139 毫米 x
76.5 毫米)两种尺寸。单宽度模块支持到载卡的单个连接器。双宽度模块主要面
向需要更高带宽、更大前面板空间或较大 PCB 面积的应用,支持多达两个连接
器。FMC 标准提供两种尺寸,能够更加灵活地根据空间、I/O 要求或者这两者
的要求对板进行精心优化。
选定尺寸之后,板设计人员就要在两种不同连接器间做出选择,以用作
FMC 标准到载卡上 FPGA 的接口:一种是具有 160 个引脚的低引脚数 (LPC)
连接器,另一种则是具有 400 个引脚的高引脚数 (HPC) 连接器。这两种连接
器均支持高达 2 Gb/s 的单端和差分信号传输速率,且到 FPGA 串行连接器的
信号传输速率高达 10 Gb/s。
除了 68 个用户定义的单端信号或者 34 个用户定义的差分对外,LPC 连
接器还提供了 1 个串行收发器对、时钟、JTAG 接口和 1 个作为基础智能平台
管理接口 (IPMI) 命令可选支持的 I2C 接口。而 HPC 连接器则提供了 160
个用户定义的单端信号(或者 80 个用户定义的差分对)、10 个串行收发器对以
及更多时钟。
五、开发工具介绍(Vivado)
ISE 是 Vivado 之前的上一代开发工具,自 14.7 版本(对应 Vivado 2013.3)
后已经停止开发了。 Vivado 是 ISE 后的新一代开发工具,运行时间更短,对复
杂设计更容易收敛。如果没有特殊设计要求,建议基于 Zynq 的设计都从 Vivado
开始。Vivado 有很多不错的 tutorial,UG940 和 embedded 相关,建议仔细
看看。
六、Vivado 开发流程示例
本示例为将几个信号通过 ZC706 上的 FMC 接口输出到载卡上。
1. 源代码:
module top(clk,CLKW,D3,D2,D1,D0,CLK_RESET,CLK_COMPUTE);
input clk;
output CLKW,D3,D2,D1,D0,CLK_RESET,CLK_COMPUTE;
reg CLKW,D3,D2,D1,D0,CLK_RESET,CLK_COMPUTE;
integer counter = 0;
parameter N = 20;
integer counter1 = 0;
reg clk_div = 0;
initial
begin
CLKW <= 1;
D3 <= 0;
D2 <= 0;
D1 <= 0;
D0 <= 0;
CLK_RESET <= 1;
CLK_COMPUTE <= 0;
end
always@(posedge clk)
begin
if (counter1 == N-1)
begin
counter1 <= 0;
end
else
begin
counter1 <= counter1+1;
end
end
always@(posedge clk)
begin
if (counter1 == N-1)
clk_div <= !clk_div;
end
always@(posedge clk_div)
begin
if(counter==2)
begin
CLKW<=0;
D3<=1;
D2<=1;
D1<=1;
D0<=1;
end
else if(counter==3)
begin
CLK_RESET<=0;
end
else if(counter==4)
begin
CLK_COMPUTE<=1;
end
else counter<=counter;
counter<=counter+1;
end
endmodule
2. 测试代码以及波形
module test;
wire CLKW,D3,D2,D1,D0,CLK_RESET,CLK_COMPUTE;
reg clk=0;
top uut(
.clk(clk),
.CLKW(CLKW),
.D3(D3),
.D2(D2),
.D1(D1),
.D0(D0),
.CLK_RESET(CLK_RESET),
.CLK_COMPUTE(CLK_COMPUTE));
always #1 clk=~clk;
endmodule