FPGA/IC笔试——杂七杂八
1:什么是同步逻辑和异步逻辑?(汉王)
- 同步逻辑是时钟之间有固定的因果关系。异步逻辑是各时钟之间没有固定的因果关系。
- 同步时序逻辑电路的特点:各触发器的时钟端全部连接在一起, 并接在系统时钟端, 只有当时钟脉冲到来时, 电路的状态才能改变。 改变后的状态将一直保持到下一个时钟脉冲的到来,此时无论外部输入 x 有无变化,状态表中的每个状态都是稳定的。
- 异步时序逻辑电路的特点:电路中除可以使用带时钟的触发器外,还可以使用不带时钟的触发器和延迟元件作为存储元件, 电路中没有统一的时钟, 电路状态的改变由外部输入的变化直接引起。
2:同步电路和异步电路的区别:
- 同步电路: 存储电路中所有触发器的时钟输入端都接同一个时钟脉冲源,因而所有触发器的状态的变化都与所加的时钟脉冲信号同步。
- 异步电路: 电路没有统一的时钟, 有些触发器的时钟输入端与时钟脉冲源相连, 只有这些触发器的状态变化与时钟脉冲同步,而其他的触发器的状态变化不与时钟脉冲同步。
3:时序设计的实质:
时序设计的实质就是满足每一个触发器的建立 /保持时间的要求。
4:建立时间与保持时间的概念?
- 建立时间:触发器在时钟上升沿到来之前,其数据输入端的数据必须保持不变的最小时间。
- 保持时间:触发器在时钟上升沿到来之后,其数据输入端的数据必须保持不变的最小时间。
5:为什么触发器要满足建立时间和保持时间?
因为触发器内部数据的形成是需要一定的时间的,如果不满足建立和保持时间,触发器将进入亚稳态,进入亚稳态后触发器的输出将不稳定,在0和1之间变化,这时需要经过一个恢复时间,其输出才能稳定,但稳定后的值并不一定是你的输入值。这就是为什么要用两级触发器来同步异步输入信号。这样做可以防止由于异步输入信号对于本级时钟可能不满足建立保持时间而使本级触发器产生的亚稳态传播到后面逻辑中,导致亚稳态的传播。足建立保持时间而使本级触发器产生的亚稳态传播到后面逻辑中,导致亚稳态的传播。
换个方式理解:需要建立时间是因为触发器的 D 端像一个锁存器在接受数据, 为了稳定的设置前级门的状态需要一段稳定时间; 需要保持时间是因为在时钟沿到来之后,触发器要通过反馈来锁存状态,从后级门传到前级门需要时间。
6:什么是亚稳态?为什么两级触发器可以防止亚稳态传播?
这也是一个异步电路同步化的问题。亚稳态是指触发器无法在某个规定的时间段内到达一个可以确认的状态。 使用两级触发器来使异步电路同步化的电路其实叫做一位同步器 ,他只能用来对一位异步信号进行同步。 两级触发器可防止亚稳态传播的原理: 假设第一级触发器的输入不满足其建立保持时间, 它在第一个脉冲沿到来后输出的数据就为亚稳态, 那么在下一个脉冲沿到来之前, 其输出的亚稳态数据在一段恢复时间后必须稳定下来, 而且稳定的数据必须满足第二级触发器的建立时间, 如果都满足了, 在下一个脉冲沿到来时, 第二级触发器将不会出现亚稳态,因为其输入端的数据满足其建立保持时间。
同步器有效的条件:第一级触发器进入亚稳态后的恢复时间 + 第二级触发器的建立时间 <= 时钟周期 。
更确切地说, 输入脉冲宽度必须大于同步时钟周期与第一级触发器所需的保持时间之和。 最保险的脉冲宽度是两倍同步时钟周期。所以,这样的同步电路对于从较慢的时钟域来的异步信号进入较快的时钟域比较有效,对于进入一个较慢的时钟域,则没有作用。
7:系统最高速度计算(最快时钟频率)和流水线设计思想:
同步电路的速度是指同步系统时钟的速度,同步时钟愈快,电路处理数据的时间间隔越短,电路在单位时间内处理的数据量就愈大。
假设 Tco 是触发器的输入数据被时钟打入到触发器到数据到达触发器输出端的延时时间 (Tco=Tsetpup+Thold) ; Tdelay 是组合逻辑的延时; Tsetup 是D触发器的建立时间。
假设数据已被时钟打入 D 触发器,那么数据到达第一个触发器的Q输出端需要的延时时间是 Tco ,经过组合逻辑的延时时间为 Tdelay ,然后到达第二个触发器的D端, 要希望时钟能在第二个触发器再次被稳定地打入触发器, 则时钟的延迟必须大于 Tco +Tdelay +Tsetup ,也就是说最小的时钟周期 Tmin =Tco +Tdelay +Tsetup , 即最快的时钟频率 Fmax =1/Tmin 。
FPGA 开发软件也是通过这种方法来计算系统最高运行速度 Fmax 。因为 Tco 和 Tsetup 是由具体的器件工艺决定的,故设计电路时只能改变组合逻辑的延迟时间 Tdelay ,所以说缩短触发器间组合逻辑的延时时间是提高同步电路速度的关键所在。 由于一般同步电路都大于一级锁存, 而要使电路稳定工作, 时钟周期必须满足最大延时要求。 故只有缩短最长延时路径, 才能提高电路的工作频率。 可以将较大的组合逻辑分解为较小的 N 块, 通过适当的方法平均分配组合逻辑, 然后在中间插入触发器,并和原触发器使用相同的时钟, 就可以避免在两个触发器之间出现过大的延时, 消除速度瓶颈,这样可以提高电路的工作频率。这就是所谓 "流水线 "技术的基本设计思想,即原设计速度受限部分用一个时钟周期实现, 采用流水线技术插入触发器后, 可用 N 个时钟周期实现,因此系统的工作速度可以加快, 吞吐量加大。 注意, 流水线设计会在原数据通路上加入延时,另外硬件面积也会稍有增加。
8:时序约束的概念和基本策略?
- 时序约束主要包括周期约束, 偏移约束, 静态时序路径约束三种。 通过附加时序约束可以综合布线工具调整映射和布局布线,使设计达到时序要求。
- 附加时序约束的一般策略是先附加全局约束, 然后对快速和慢速例外路径附加专门约束。
- 附加全局约束时, 首先定义设计的所有时钟, 对各时钟域内的同步元件进行分组, 对分组附加周期约束,然后对 FPGA/CPLD 输入输出 PAD 附加偏移约束、对全组合逻辑的 PAD TO PAD 路径附加约束。
- 附加专门约束时,首先约束分组之间的路径,然后约束快、慢速例外路径和多周期路径,以及其他特殊路径。
9:附加约束的作用?
- 1:提高设计的工作频率(减少了逻辑和布线延时);
- 2:获得正确的时序分析报告;(静态时序分析工具以约束作为判断时序是否满足设计要求的标准, 因此要求设计者正确输入约束,以便静态时序分析工具可以正确的输出时序报告)
- 3:指定 FPGA/CPLD 的电气标准和引脚位置。
10: FPGA 设计工程师努力的方向:
SOPC ,高速串行 I/O,低功耗,可靠性,可测试性和设计验证流程的优化等方面。随着芯片工艺的提高,芯片容量、集成度都在增加, FPGA 设计也朝着高速、高度集成、低功耗、高可靠性、高可测、可验证性发展。芯片可测、可验证,正在成为复杂设计所必备的条件,尽量在上板之前查出 bug ,将发现 bug 的时间提前,这也是一些公司花大力气设计仿真平台的原因。另外随着单板功能的提高、成本的压力,低功耗也逐渐进入FPGA 设计者的考虑范围,完成相同的功能下,考虑如何能够使芯片的功耗最低,据说altera 、 xilinx都在根据自己的芯片特点整理如何降低功耗的文档。高速串行 IO 的应用,也丰富了 FPGA的应用范围,如 xilinx 的 v2pro 中的高速链路也逐渐被应用。
11:对于多位的异步信号如何进行同步?
对以一位的异步信号可以使用一位同步器进行同步(使用两级触发器),而对于多位的异步信号,可以采用如下方法:
- 1:可以采用保持寄存器加握手信号的方法(多数据,控制,地址);
- 2:特殊的具体应用电路结构 ,根据应用的不同而不同;
- 3:异步 FIFO 。(最常用的缓存单元是 DPRAM )
12: FPGA 和 CPLD 的区别?
13:锁存器( latch )和触发器( flip-flop)区别?
电平敏感的存储器件称为锁存器。可分为高电平锁存器和低电平锁存器,用于不同时钟之间的信号同步。
有交叉耦合的门构成的双稳态的存储原件称为触发器。分为上升沿触发和下降沿触发。可以认为是两个不同电平敏感的锁存器串连而成。前一个锁存器决定了触发器的建立时间,后一个锁存器则决定了保持时间。
14: FPGA 芯片内有哪两种存储器资源?
FPGA 芯片内有两种存储器资源: 一种叫 BLOCK RAM, 另一种是由 LUT 配置成的内部存储器(也就是分布式 RAM )。
BLOCK RAM 由一定数量固定大小的存储块构成的,使用BLOCK RAM 资源不占用额外的逻辑资源,并且速度快。但是使用的时候消耗的 BLOCK RAM 资源是其块大小的整数倍。
15:什么是时钟抖动?
时钟抖动是指芯片的某一个给定点上时钟周期发生暂时性变化,也就是说时钟周期在不同的周期上可能加长或缩短。它是一个平均值为 0 的平均变量。
16: FPGA 设计中对时钟的使用?(例如分频等)
FPGA 芯片有固定的时钟路由,这些路由能有减少时钟抖动和偏差。需要对时钟进行相位移动或变频的时候, 一般不允许对时钟进行逻辑操作, 这样不仅会增加时钟的偏差和抖动, 还会使时钟带上毛刺。 一般的处理方法是采用 FPGA 芯片自带的时钟管理器如 PLL,DLL或 DCM ,或者把逻辑转换到触发器的 D 输入(这些也是对时钟逻辑操作的替代方案)。
17: FPGA 设计中如何实现同步时序电路的延时?
首先说说异步电路的延时实现: 异步电路一半是通过加 buffer 、 两级与非门等来实现延时(我还没用过所以也不是很清楚),但这是不适合同步电路实现延时的。在同步电路中,对于比较大的和特殊要求的延时,一半通过高速时钟产生计数器,通过计数器来控制延时;对于比较小的延时,可以通过触发器打一拍,不过这样只能延迟一个时钟周期。
18: FPGA 中可以综合实现为 RAM/ROM/CAM 的三种资源及其注意事项?
三种资源: BLOCK RAM ,触发器( FF),查找表( LUT );
注意事项:
- 1:在生成 RAM 等存储单元时,应该首选 BLOCK RAM 资源;其原因有二:
Ⅰ:使用BLOCK RAM 等资源, 可以节约更多的 FF 和 4-LUT 等底层可编程单元。 使用 BLOCK RAM可以说是 ―不用白不用, 是最大程度发挥器件效能, 节约成本的一种体现;
Ⅱ: BLOCK RAM是一种可以配置的硬件结构, 其可靠性和速度与用 LUT 和 REGISTER 构建的存储器更有优势。
- 2:弄清 FPGA 的硬件结构,合理使用 BLOCK RAM 资源;
- 3:分析 BLOCK RAM 容量,高效使用 BLOCK RAM 资源;
- 4:分布式 RAM 资源(DISTRIBUTE RAM )
19: Xilinx 中与全局时钟资源和 DLL 相关的硬件原语:
常用的与全局时钟资源相关的 Xilinx 器件原语包括:BUFG,IBUFGDS,BUFG,BUFGP,BUFGCE,BUFGMUX,BUFGDLL,DCM 等。
关于各个器件原语的解释可以参考《 FPGA 设计指导准则》 p50 部分。
20: HDL 语言的层次概念?
HDL 语言是分层次的、类型的,最常用的层次概念有系统与标准级、功能模块级,行为级,寄存器传输级和门级。
系统级,算法级, RTL 级(行为级 ),门级,开关级。
21:查找表的原理与结构?
查找表(look-up-table )简称为 LUT , LUT 本质上就是一个 RAM 。目前 FPGA 中多使用 4 输入的 LUT ,所以每一个 LUT 可以看成一个有 4 位地址线的 16x1 的 RAM 。 当用户通过原理图或 HDL 语言描述了一个逻辑电路以后, PLD/FPGA 开发软件会自动计算逻辑电路的所有可能的结果,并把结果事先写入 RAM, 这样,每输入一个信号进行逻辑运算就等于输入一个地址进行查表,找出地址对应的内容,然后输出即可。
22: IC 设计前端到后端的流程和 EDA 工具?
设计前端也称逻辑设计,后端设计也称物理设计,两者并没有严格的界限,一般涉及到与工艺有关的设计就是后端设计。
- 1:规格制定:客户向芯片设计公司提出设计要求。
- 2:详细设计:芯片设计公司( Fabless )根据客户提出的规格要求,拿出设计解决方案和具体实现架构, 划分模块功能。目前架构的验证一般基于 systemC 语言,对价后模型的仿真可以使用 systemC 的仿真工具。例如: CoCentric 和 Visual Elite 等。
- 3: HDL 编码:设计输入工具: ultra , visual VHDL 等
- 4:仿真验证: modelsim
- 5:逻辑综合: synplify
- 6:静态时序分析: synopsys 的 Prime Time
- 7:形式验证: Synopsys 的 Formality.
23:寄生效应在 IC 设计中怎样加以克服和利用(这是我的理解,原题好像是说,IC 设计过程中将寄生效应的怎样反馈影响设计师的设计方案)?
所谓寄生效应就是那些溜进你的 PCB 并在电路中大施破坏、令人头痛、原因不明的小故障。 它们就是渗入高速电路中隐藏的寄生电容和寄生电感。 其中包括由封装引脚和印制线过长形成的寄生电感; 焊盘到地、 焊盘到电源平面和焊盘到印制线之间形成的寄生电容; 通孔之间的相互影响,以及许多其它可能的寄生效应。
理想状态下,导线是没有电阻,电容和电感的。而在实际中,导线用到了金属铜,它有一定的电阻率,如果导线足够长,积累的电阻也相当可观。两条平行的导线,如果互相之间有电压差异,就相当于形成了一个平行板电容器(你想象一下)。通电的导线周围会形成磁场(特别是电流变化时),磁场会产生感生电场,会对电子的移动产生影响,可以说每条实际的导线包括元器件的管脚都会产生感生电动势,这也就是寄生电感。
在直流或者低频情况下,这种寄生效应看不太出来。而在交流特别是高频交流条件下,影响就非常巨大了。根据复阻抗公式,电容、电感会在交流情况下会对电流的移动产生巨大阻碍,也就可以折算成阻抗。这种寄生效应很难克服,也难摸到。只能通过优化线路,尽量使用管脚短的惇SMT元器件来减少其影响,要完全消除是不可能的。
24:用Verilog写一段代码,实现消除一个glitch。
(1)滤掉小于1个周期glitch的原理图如下:
1 module digital_filter_(clk_in,rst,host_rst,host_rst_filter);
2 input clk_in;
3 input rst;
4 input host_rst;
5 output host_rst_filter;
6 reg host_rst_d1;
7 reg host_rst_d2;
8
9 always@(posedge clk_in or negedge rst)
10 begin
11 if(~rst)
12 begin
13 host_rst_d1 <= 1'b1;
14 host_rst_d2 <= 1'b1;
15 end
16 else
17 begin
18 host_rst_d1 <= host_rst;
19 host_rst_d2 <= host_rst_d1;
20 end
21 end
22
23 assign host_rst_filter = host_rst_d1 | host_rst_d2;
24 endmodule
(2)滤掉大于1个周期且小于2个周期glitch的原理图如下:
25:计算最小周期。
Tco:寄存器时钟输入到数据输出的时间
Tdata:寄存器间的走线延迟
Tsu :建立时间
Tskew:时钟偏斜
|
|
26、F = A & ~A
有竞争不一定产生冒险,如红线处。有冒险一定存在竞争。
27、异步FIFO深度计算
如果数据流连续不断则FIFO深度无论多少,只要读写时钟不同源同频则都会丢数;
FIFO用于缓冲块数据流,一般用在写快读慢时,
FIFO深度 / (写入速率 - 读出速率) = FIFO被填满时间 应大于 数据包传送时间= 数据量 / 写入速率
例:A/D采样率50MHz,dsp读A/D读的速率40MHz,要不丢失地将10万个采样数据送入DSP,在A/D在和DSP之间至少加多大容量(深度)的FIFO才行?
100,000 / 50MHz = 1/ 500 s = 2ms
(50MHz - 40MHz) * 1/500 = 20k既是FIFO深度。
28、画出用D触发器实现2倍分频的逻辑电路
![](https://img2020.cnblogs.com/blog/2336314/202106/2336314-20210622112819012-555525398.png)
将D触发器的Q非端接到数据输入端D即可实现二分频,说白了就是CLK时钟信号的一个周期。
四分频电路:
![](https://img2020.cnblogs.com/blog/2336314/202106/2336314-20210622112915474-1707216779.png)
29、在同步电路设计中,电路时序模型如下∶T1为触发器时钟到输出延时,T2和T4为连线延时,T3为组合路径延时,T5为时钟网络延时,假设时钟周期为Tcycle ,Tsetup,Thold分别为触发器建立保持时间,为保证正确采样(改路径为multi-cycle路径),下列必须满足的是︰D
![](https://img2020.cnblogs.com/blog/2336314/202107/2336314-20210720100900079-729535103.png)
A.T1+T2+T3+T4<Tcycle-Tsetup+T5,T1+T2+T3+T4>Thold
B.T1+T2+T3+T4<Tcycle-Tsetup,T1+T2+T3+T4+T5>Thold
C.T1+T2+T3+T4+T5<Tcycle-Tsetup,T1+T2+T3+T4>Thold
D.T1+T2+T3+T4<Tcycle-Tsetup+T5,T1+T2+T3+T4> Thold+T5
30、下列降低功耗的措施,哪个可以降低峰值功耗:B
A.大幅度提高HVT比例
B.静态模块级clock gating
C.power gating
D.Memory shut down
解析:
峰值往往出现在时钟翻转的瞬间,hvt只能降低静态功耗;
clock gating可以用效降低动态功耗,因为减少了不必要的时钟翻转;
power gating,通常是也是减少待机电流。因为正常工作时各种power domain都是打开的;
memory shutdown与power gating是一个意思。只是一个关memory模块的电,一个是关逻辑模块的电。
31、下图是长除法的CRC4电路,其对应的多项式 G(x)=x^4+x^3+1
四个寄存器从左向右依次输出:x^1(reg3)、x^2(reg2)、x^3 、x^4
32、用Verilog中设计模块以满足以下要求。
(1)频率为100MHz的时钟
(2)对时钟敏感的4位宽信号,限制该信号在8到15的范围内随机化16次。
`timescale 1ns/1ps module random1(); reg clk; reg [3:0] out_rand; initial begin clk = 0; forever #5 clk = ~clk; end //always #5 clk = ~clk; integer i; initial begin for(i = 0;i < 16; i = i + 1) begin @(posedge clk) begin out_rand = 4'b1000+ {$random}%8; end end end endmodule
33、分析如下电路功能
分析:看这个电路图,下面四个触发器和上面1个触发器构成,下面四个触发器的连接关系好像是分频器的连接,我们要分析这个电路的功能,就要画出每一个触发器的波形图,触发器的默认复位输出是0,当然Q反为1。
可见是一个八分频输出,当然这不重要。重要的是Y,当A为高电平的时候够长,我就能检测到A的高电平。
A的高电平时间必须大于等于7个时钟周期,否则,当成毛刺过滤掉。那么我不禁想这个电路到底什么功能呢?滤波电路!对于A的高电平时候小于7个时钟,我们就当做毛刺滤掉了。
module freq_div( input clk, input A, output reg Y ); wire A1; assign A1 = A; reg Q1_n, Q2_n ,Q3_n, Q4; always@(posedge clk or negedge A) begin if(~A) begin Q1_n <= 1'b1; end else begin Q1_n <= ~Q1_n; end end always@(posedge Q1_n or negedge A) begin if(~A) Q2_n <= 1'b1; else Q2_n <= ~Q2_n; end always@(posedge Q2_n or negedge A) begin if(~A) Q3_n <= 1'b1; else Q3_n <= ~Q3_n; end always@(posedge Q3_n or negedge A) begin if(~A) Q4 <= 1'b0; else Q4 <= ~Q4; end always@(posedge Q4 or negedge A) begin if(~A) Y <= 1'b0; else Y <= A1; end endmodule
34、Given the following FIFO and rules, how deep does the FIFO need to beto prevent underflow or overflow?(75 entries)
RULES:
1) frequency(clk_A) = frequency(clk_B)/4
2) period(en_B) = period(clk_A)*100
3) duty_cycle(en_B) = 25%
35、Y=AB+CD为了检测D是否错误,则AB=0且C=1,所以选 C
36、时序建立
固有建立时间为:Tsu_valid = Tsu - T_offset + Tpd + Tpd1 = 2 - 1.2 + 1.2 + 0.9 = 2.9ns
固有保持时间为:Th_valid = Th + T_offset - Tpd - Tpd1 = 1.5 + 1.2 - 1.2 - 0.9 = 0.6ns.
而系统的最高频率呢?
先求系统的最小周期,考虑两个触发器之间的路径:
Tmin = Tco + Tpd + Tsu = 1.8 + 1.2 + 2 = 5ns,那么系统最高频率为200MHz。
37、序列发生器,循环产生如下序列:0010_1101_11。
可以用状态机写,但是更好的办法是:
循环左移,输出高位。
module seq_gen( input clk, input rst_n, output reg q ); reg [9:0]q_r; always@(posedge clk or negedge rst_n) begin if(~rst_n) begin q <= 0; q_r <= 10'b0010_1101_11; end else begin q <= q_r[9]; q_r <= {q_r[8:0], q_r[9]}; end end endmodule
38、CDC(Clock Domain Conversion)跨时钟域:
分单bit和多bit传输,其中:
单bit(慢时钟域到快时钟域):用快时钟打两拍,直接采一拍大概率也是没问题的,两拍的主要目的是消除亚稳态;
单bit(快时钟域到慢时钟域):握手、异步FIFO、异步双口RAM;快时钟域的信号脉宽较窄,慢时钟域不一定能采到,可以通过握手机制让窄脉冲展宽,慢时钟域采集到信号后再“告诉”快时钟域已经采集到信号,确保能采集到;
多bit:异步FIFO、异步双口RAM、握手、格雷码;
单bit(慢时钟域到快时钟域): | 快的一定能采到慢的,用快时钟打两拍; |
---|---|
单bit(快时钟域到慢时钟域): | 快时钟域的信号脉宽较窄,慢时钟域不一定能采到,可以通过握手机制让窄脉冲展宽,慢时钟域采集到信号后再“告诉”快时钟域已经采集到信号,确保能采集到; |
39、(大疆2020芯片开发工程师A卷)对12.918做无损定点化,需要的最小位宽是多少位?位宽选择11位时的量化误差是多少?
A. 12位,0.0118
B. 13位,0.0039
C. 12位,0.0039
D. 13位,0.0118
答案:C,12位,误差0.0039
解析:12.918,定点量化时对整数部分和小数部分分别量化。
(1)整数部分12,最少使用4位量化,4-bit表示范围0~15;
(2)小数部分0.918,假设12.918整体使用12位量化,整数已使用4-bit,则小数部分还能使用8-bit量化,能够表示2的8次方共计256个刻度,每个刻度的间隔是1/256 = 0.00390625,这个值也就是量化精度。
小数0.918需要多少个刻度来表示呢? 0.918/(1/256) = 0.918*256 = 235.008,四舍五入取整,则使用235个刻度来表示,误差是0.008个刻度,误差大小是0.008*(1/256) = 0.00003125。
量化误差小于量化精度的一半,认为是“无损量化”。由于量化后误差0.00003125肯定是小于精度0.00390625的一半,所以这个误差小到可以认为是无损量化。
当使用11位量化时,同理:
(1)整数部分12,最少仍需要4位量化,4-bit表示范围0~15;
(2)小数0.918,只能使用剩下的7-bit量化,能够表示2的7次方共计128个刻度,每个刻度的间隔是1/128。
小数0.918需要多少个刻度来表示呢? 0.918/(1/128) = 0.918*128 = 117.504,四舍五入取整,则使用118个刻度来表示,误差是-0.496个刻度,误差大小是-0.496*(1/128) = -0.003875,保留四位小数并取正数,0.0039。
40、(大疆2020芯片工程师A卷,单选)1个16K x 8位的存储器,其地址线和数据线总和是
A、46
B、17
C、48
D、22
答案: D
解析:
地址线:16K = 1K*16 = 1024*16 = (2^10)*(2^4) = 2^14,即需要 14 根地址线;
数据线:8 位数据需要 8 根数据线;
所以一共需要 22 根线。
未完待续。。。
参考资料:
[1] OpenS Lee:FPGA开源工作室(公众号)