IC秋招总结:FIFO相关提问

秋招基本结束,来总结一下从实习面试到秋招面试以来面试会问到的FIFO相关的问题。

一、同步/异步FIFO面试提问汇总

  1. FIFO怎么实现跨时钟域?/为什么要用格雷码?
    —> 格雷码相邻只有1bit的跳变,不会出现多个bit同时出现亚稳态从而产生中间状态,所以可以直接打拍;而且就算出现了亚稳态,那也有空满去辅助,最多出现假空假满,不会出现数据错误。

  2. 多bit打两拍之后还有亚稳态吗?多bit直接打拍稳定下来之后和转格雷码对应的二进制一样吗?那为什么还要转格雷码呢?

    • 亚稳态不能消除,打拍只是让概率降低。
    • 多bit最后打拍完稳定下来应该结果和单bit合并起来是一样的。但主要问题在于多bit产生亚稳态和他们稳定下来的时间不同,中间可能会出现中间状态,从而导致其他判断逻辑出错
  3. 空满判断如何实现?(包括用格雷码和二进制判断的情况)
    这里要清楚指针的实现和空满的判断。

    • 指针是基于地址做循环,一般为了格雷码方便判断会多加一位,相当于FIFO深度扩倍。
    • 空满判断二进制(读写指针第一位相反其余相同则满,读写指针全相同是空。也可以说读写指针中间差一个FIFO深度就是满)和格雷码(读写指针前两位相反,其余相同则满,读写指针全相同是空。)
  4. 使用过程中FIFO的深度如何确定?(笔试经常出,面试也问到过,主要是考虑背对背传输的情况,要注意两边频率不同时的换算)

  5. 假如写很快,但读却很慢,那这样写了很多个之后才读,相当于读地址变一个的时候,写已经很多个了,那这样格雷码之间就不只有一位不一样了,逻辑会出问题吗?
    ---->不会。有没有亚稳态看的是这一时刻的几个多bit有几个在变,不应该一段时间不同的值去比较。

  6. 异步FIFO跨时钟域要设置什么约束?
    这个主要是考虑布局布线之后各个bit之间的延时会有差异,他们到同一个采样点的时间不同,那这样就不能保证其中只有一个bit在变化了。
    具体是要设max_delay,读到写,写到读都要设置。要设置的值,是launch域的一个周期,也就是从发的FF到采样的FF,几个bit的传输延时都不能超过T(设T/2更保险,T是最大不能超过的值了)。

  7. FIFO深度必须是2的幂次吗?可以是2n,怎么实现?
    不必须,2n也可以实现。参见 FIFO设计中与深度depth相关的问题
    思路就是,比如需要的深度5,那么因为判断空满地址要加倍,就需要10占4bit,而本身4bit最大到15,所以就从0-15里取中间的10个数。也就是前三个和后三个数都不要了,要3-12对应的格雷码。
    注意这样满判断的时候也会有区别。

  8. 读写的频差越大,会不会虚空虚满的越厉害
    会。首先明确虚满是在写时钟域。比如写的已经满了,读很慢,很久才知道已经不空了,然后写入一个数据再传过去,这样才不满了,中间间隔的时间都是虚满的时间。但是假如读的快一些,他就很快知道已经写入数据,从而可以读出。

  9. 能不能满在读域判断,写在写域判断?(芯动面试官问的,说可以,这样还不会出现虚空虚满的问题。我问那为什么平时我们不这样用,答要给代码留有余量)
    我其实没太明白,我自己理解满一定要在写时钟域产生,读域可以自己单独再生成一个满,当读的时候读域就里面知道已经不满了。但是如果满全部在读域,那就既要要先同步写地址,满即便直接组合逻辑不同步过去,也是晚两拍。
    还有一种可能,他说的是同步FIFO?那就没有同步时钟域的问题了,不懂了…

  10. 格雷码和二进制,二进制和格雷码的转化方式
    grey=bin^(bin>>1)
    格雷码转二进制(代码中不会用其实)

module gray_to_bin (bin, gray);
	parameter N= 4;
	input [N– 1:0] bin;
	output [N– 1:0] gray;
	reg [N– 1:10] bin;
		
	//1
	integer i;
	always @ (gray)
	for ( i = 0; i <= N; i = i + 1)
	bin[i] = ^(gray >> i);  		//右移一位并按位异或

    //2
	assign bin[N-1] = gray[N-1];	
	genvar i;
	generate //这里for循环从0开始其实也是一样的,因为for循环会把他们全部展开
	for(i = N-2; i >= 0; i = i - 1) begin: gray_2_bin   
		assign bin[i] = bin[i + 1] ^ gray[i];
	end
	endgenerate
	
endmodule

在这里插入图片描述

  1. 手撕同步/异步FIFO+深度为1的FIFO

二、FIFO手撕

1、同步FIFO

下面是同步FIFO代码实现,基于cnt计数。
| 注意其中会有三个关键参数,RAM的位宽深度和指针的位宽。

读写dat的位宽就是RAM宽度;指针的值最大到RAM深度-1,所以他的位宽就是clog2(RAM_DEPTH-1);计数要记到RAM深度,所以位宽比ptr宽一位。
module synfifo #(                             //注意这里要有#,里面都是逗号
    parameter WIDTH = 'd4,
    parameter DEPTH = 'd8
)(
    input                   clk,
    input                   rst_n,
    input                   wr_en,
    input                   rd_en,
    input       [WIDTH-1:0] wr_dat,    //这个位宽之前就写错了,注意不是$clog2(DEPTH)-1,这里是数据位宽,只有指针才要clog2
    output reg  [WIDTH-1:0] rd_dat,     //都写成对齐的形式,避免位宽和是否有reg出错
    output                  full,
    output                  empty 
);

//关于位宽经常容易出错。可以假设width是3,深度是16=2^4.
//写进去的数据位宽肯定是一样的
//指针的值是0-15,那么他的位宽只需要4,也就是$clog2(15)=$clog2(DEPTH -1)

localparam ADDR_WIDTH = $clog2(DEPTH-1); //注意这里要-1!多次复用的计算写成一个参数的形式

reg [WIDTH
### IntelliJ IDEA 中通义灵码 AI 功能介绍 IntelliJ IDEA 提供了一系列强大的工具来增强开发体验,其中包括与通义灵码 AI 相关的功能。这些功能可以帮助开发者更高效地编写代码并提高生产力。 #### 安装通义灵码插件 为了使用通义灵码的相关特性,在 IntelliJ IDEA 中需要先安装对应的插件: 1. 打开 **Settings/Preferences** 对话框 (Ctrl+Alt+S 或 Cmd+, on macOS)。 2. 导航到 `Plugins` 页面[^1]。 3. 在 Marketplace 中搜索 "通义灵码" 并点击安装按钮。 4. 完成安装后重启 IDE 使更改生效。 #### 配置通义灵码服务 成功安装插件之后,还需要配置通义灵码的服务连接信息以便正常使用其提供的各项能力: - 进入设置中的 `Tools | Qwen Coding Assistant` 菜单项[^2]。 - 填写 API Key 和其他必要的认证参数。 - 测试连接以确认配置无误。 #### 使用通义灵码辅助编程 一旦完成上述准备工作,就可以利用通义灵码来进行智能编码支持了。具体操作如下所示: ##### 自动补全代码片段 当输入部分语句时,IDE 将自动提示可能的后续逻辑,并允许一键插入完整的实现方案[^3]。 ```java // 输入 while 循环条件前半部分... while (!list.isEmpty()) { // 激活建议列表选择合适的循环体内容 } ``` ##### 解释现有代码含义 选中某段复杂的表达式或函数调用,右键菜单里会有选项可以请求通义灵码解析这段代码的作用以及优化意见。 ##### 生产测试案例 对于已有的业务逻辑模块,借助于通义灵码能够快速生成单元测试框架及初始断言集,减少手动构建的成本。 ```python def test_addition(): result = add(2, 3) assert result == 5, f"Expected 5 but got {result}" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值