【芯片前端】“异步FIFO全解析”的BUG——格雷码连续性

简介: 【芯片前端】“异步FIFO全解析”的BUG——格雷码连续性

前言

在前几天写完【芯片前端】保持代码手感——异步FIFO全解析之后自我感觉非常良好,觉得异步fifo的问题我已经全部拿捏了,没想到今天突然想到一个我自己代码里的bug。


代码中的BUG

事情的源头在同步fifo里,深度任意可配的同步fifo里使用了两个非饱和的cnt计数器记录读写地址指针,waddr和raddr均比实际地址多一位,最高位用来指示套圈情况。当waddr和raddr的最高位相同时,fifo_cnt = waddr-raddr;当waddr和raddr的最高位相反时,fifo_cnt = DEPTH + waddr[ADDR_WIDTH-1:0]   - raddr[ADDR_WIDTH-1:0]。最高位作为标志位,当低位计数到DEPTH-1时,高位翻转,代码大意如下:

assign waddr_d_h = (waddr[DP_WD-1:0] == DEPTH-1) ? ~waddr[DP_WD] : waddr[DP_WD];
assign waddr_d_l = (waddr[DP_WD-1:0] == DEPTH-1) ? 0 : waddr[DP_WD-1:0] + 1;
always @(posedge clk or negedge rst_n)begin
  if(~rst_n)    waddr <= 0;
  else if(wenc) waddr <= {waddr_d_h, waddr_d_l};
end


假设fifo深度设为10,那么waddr的跳转为:

高比特

低比特

指针数值

0

0000

0

0

0001

1

...

...

...

0

1001

9

1

0000

(套圈)0

1

0001

(套圈)1

...

...


1

1001

(套圈)9

0

0000

0


在同步fifo里这样做是没有问题的,但是问题出现在,把这个代码代入到异步fifo中的时候。



异步fifo中使用格雷码对addr进行跨异步,关键处理是二进制 - 格雷码 - 跨异步 - 二进制处理路径 。而之所以能够使用格雷码跨异步是因为格雷码相邻的两个数只相差1bit,而深度为10的异步fifo,存在'b01001('d9) -> 'b10000('d16)的跳转,这个就不是相邻跳转了,相应的格雷码变化也不是单比特的跳转:01101 -> 11000,显然的这会导致空满判断出现逻辑错误。

BUG修复

这个问题的关键就在于不饱和计数在边界的跳变导致的格雷码不连续,所以先观察格雷码。十进制0~15对应的二进制和格雷码如下表:

十进制

二进制

格雷码

0

0000

0000

1

0001

0001

2

0010

0011

3

0011

0010

4

0100

0110

5

0101

0111

6

0110

0101

7

0111

0100

8

1000

1100

9

1001

1101

10

1010

1111

11

1011

1110

12

1100

1010

13

1101

1011

14

1110

1001

15

1111

1000


显而易见的一条规律是,相邻两个数只有1bit不一样。进一步可以发现,3->0,7->0,15->0的编码也是“连续的”,即只有1bit不同。为了更好地观察规律,我们做出格雷码的码盘来观察,码盘如下图,红色为1白色为0,同心圆内为高比特,外部为低比特,如十进制2的格雷码为0011,对应的图就是“白白红红”。



盯一会码盘就会发现码盘的“对称性”和“连续性”,比如说1和14、2和13、6和9、7和8在码盘上处于轴对称的位置,而格雷码编码值恰好相差1bit。


那么也就是说,如果当前的值是5,那么下一个数想要保持格雷码连续性,就只能跳4、6或者10:

十进制5=格雷码:0111

十进制4=格雷码:0110


十进制6=格雷码:0101


十进制10=格雷码;1111


显然,此时只能跳10才能满足最高位作为标志位,当低位计数到DEPTH-1时,高位翻转的条件,也就是说我们实际要由5('b0101) -> 8('b1000)变成了由5('b0101) -> 10('b1010),所以说实际多条了两个数,因此实际cnt的值是10 - 偏移量,此时的偏移量是2,fifo的深度为6(所以低位计数计到5)。


那么继续推导,当深度配置为5,那么低位满4(格雷码:0110)跳转为11(格雷码:1110),实际的cnt值是11 - 3 = 8('d1000),偏移量为3。进一步的我就不推了,根据码盘也可以发现,偏移量 = 2^N - 配置深度,低位计满跳转值 = 2^N + 偏移量。用代码表示这几个参数:

parameter DEPTH = 11;
parameter WIDTH = $clog2(DEPTH);//4
parameter DEPTH_TO2 = 2 ^ WIDTH;//16
parameter SHIFT = DEPTH_TO2 - DEPTH;//16-11=5


还是以深度11为例,看一下这种策略下的指针跳转:

高比特

低比特

数值(二进制)

数值(格雷码)

实际指针数值

0

0000

0

0_0000

0

0

0001

1

0_0001

1

...

...

...

...

...

0

1010

10

0_1111

10

1

0101

21

1_1111

1_0101-101('d5)=1_0000,0

1

0110

22

1_1101

1_0110-101=1_0001,1

...

...

...

...

...

1

1111

31

1_0000

1_1111-101=1_1010,10

0

0000

0

0_0000

0


OK,策略上没有问题,进一步的异步FIFO代码组织放到下次,今天太晚了。  


相关文章
|
存储 前端开发 安全
前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
本文全面解析前端三种数据存储方式:Cookie、LocalStorage与SessionStorage。涵盖其定义、使用方法、生命周期、优缺点及典型应用场景,帮助开发者根据登录状态、用户偏好、会话控制等需求,选择合适的存储方案,提升Web应用的性能与安全性。(238字)
779 0
|
8月前
|
Web App开发 前端开发 JavaScript
前端性能优化利器:图片懒加载实战解析
前端性能优化利器:图片懒加载实战解析
|
10月前
|
存储 前端开发 JavaScript
调用DeepSeek API增强版纯前端实现方案,支持文件上传和内容解析功能
本方案基于DeepSeek API增强版,提供纯前端实现的文件上传与内容解析功能。通过HTML和JavaScript,用户可选择文件并调用API完成上传及解析操作。方案支持多种文件格式(如PDF、TXT、DOCX),具备简化架构、提高响应速度和增强安全性等优势。示例代码展示了文件上传、内容解析及结果展示的完整流程,适合快速构建高效Web应用。开发者可根据需求扩展功能,满足多样化场景要求。
3145 64
|
9月前
|
存储 前端开发 JavaScript
|
7月前
|
人工智能 JSON 前端开发
如何解决后端Agent和前端UI之间的交互问题?——解析AG-UI协议的神奇作用
三桥君指出AG-UI协议通过SSE技术实现智能体与前端UI的标准化交互,解决流式传输、实时进度显示、数据同步等开发痛点。其核心功能包括结构化事件流、多Agent任务交接和用户中断处理,具有"一次开发到处兼容"、"UI灵活可扩展"等优势。智能体专家三桥君认为协议将AI应用从聊天工具升级为实用软件,适用于代码生成、多步骤工作流等场景,显著提升开发效率和用户体验。
1746 0
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
472 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
8月前
|
JSON 前端开发 安全
前端开发中常用的鉴权方式解析与实践要点
本文深入探讨了前端开发中常用的鉴权方式,包括HTTP基本鉴权、Session-Cookie鉴权、Token验证、JWT(JSON Web Tokens)、单点登录(SSO)和OAuth等。文章首先明确了认证、授权、鉴权和权限控制的概念及关系,随后详细解析每种鉴权方式的工作原理、优缺点及适用场景。例如,HTTP基本鉴权简单但安全性低,适合内部网络;Session-Cookie鉴权易受CSRF攻击,适用于同域Web应用;Token和JWT无状态且扩展性好,适合分布式系统;SSO提升用户体验,适用于多系统统一登录;OAuth安全方便,适合第三方授权接入。
866 2
|
11月前
|
消息中间件 JavaScript 前端开发
最细最有条理解析:事件循环(消息循环)是什么?为什么JS需要异步
度一教育的袁进老师谈到他的理解:单线程是异步产生的原因,事件循环是异步的实现方式。 本质是因为渲染进程因为计算机图形学的限制,只能是单线程。所以需要“异步”这个技术思想来解决页面阻塞的问题,而“事件循环”是实现“异步”这个技术思想的最主要的技术手段。 但事件循环并不是全部的技术手段,比如Promise,虽然受事件循环管理,但是如果没有事件循环,单一Promise依然能实现异步不是吗? 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您
|
前端开发 JavaScript API
前端:事件循环/异步
前端开发中的事件循环和异步处理是核心机制,用于管理任务执行、性能优化及响应用户操作,确保网页流畅运行。事件循环负责调度任务,而异步则通过回调、Promise等实现非阻塞操作。
|
机器学习/深度学习 编解码 前端开发
探索无界:前端开发中的响应式设计深度解析####
【10月更文挑战第29天】 在当今数字化时代,用户体验的优化已成为网站与应用成功的关键。本文旨在深入探讨响应式设计的核心理念、技术实现及最佳实践,揭示其如何颠覆传统布局限制,实现跨设备无缝对接,从而提升用户满意度和访问量。通过剖析响应式设计的精髓,我们将一同见证其在现代Web开发中的重要地位与未来趋势。 ####
284 7

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    779
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    353
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    274
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    241
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    349
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    497
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    296
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    162
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    286
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    311
  • 推荐镜像

    更多
  • DNS