【芯片前端】保持代码手感——握手型同步FIFO设计

简介: 【芯片前端】保持代码手感——握手型同步FIFO设计

前言

工作中做了太久方案,还是要继续对代码手感的保持,这次完成握手型同步FIFO的RTL设计,设计规格如下:


  • 写入与读出均采用握手型接口;
  • 支持2的整数次与非整数次深度;
  • 对外输出逻辑时序较优;

RTL设计

对外接口

握手型同步FIFO,接口如下:

module sync_fifo #(
  parameter DEPTH = 8,
  parameter WIDTH = 32
)(
  input         clk,
  input         rst_n,
  input           in_valid,
  input  [WIDTH -1:0] in_data,
  output          in_ready,
  output          out_valid,
  output [WIDTH -1:0] out_data,
  input           out_ready
);
localparam DP_WD = $clog2(DEPTH);
endmodule


根据我的设计要求,对外输出的in_ready和out_valid必须为寄存器输出,以保证时序最优。out_data最好也要作为寄存器输出,但是out_data必然会有MUX逻辑,在深度较浅时时序会比较好,深度太深MUX逻辑带来的时序就不能忽略了。


逻辑设计

同步FIFO的设计思路在 【芯片前端】保持代码手感——同步FIFO 中已经盘过了,这次注重握手逻辑的规划,对于涉及过得设计思路不再赘述。


写入/读出ADDR逻辑

写入计数器主要调整了触发器en端的逻辑,把输入握手作为使能信号:

//==================================================================
//写入计数器
//==================================================================
reg  [DP_WD   :0]waddr;
wire             wenc;
wire             waddr_d_h;
wire [DP_WD -1:0]waddr_d_l;
assign wenc = in_valid && in_ready;
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


读出计数器同理:

//==================================================================
//读出计数器
//==================================================================
reg  [DP_WD   :0]raddr;
wire             renc;
wire             raddr_d_h;
wire [DP_WD -1:0]raddr_d_l;
assign renc = out_valid && out_ready;
assign raddr_d_h = (raddr[DP_WD-1:0] == DEPTH-1) ? ~raddr[DP_WD] : raddr[DP_WD];
assign raddr_d_l = (raddr[DP_WD-1:0] == DEPTH-1) ? 0 : raddr[DP_WD-1:0] + 1;
always @(posedge clk or negedge rst_n)begin
  if(~rst_n)    raddr <= 0;
  else if(renc) raddr <= {raddr_d_h, raddr_d_l};
end


FIFO深度计数器

fifo深度的计算我做了一些调整,fifi_cnt也作为寄存器输出,主要是我需要用fifi_cnt_d这个变量,所以是在数据读写的当拍产生fifi_cnt_d这个逻辑:

//==================================================================
//深度计数器
//==================================================================
reg  [DP_WD :0]fifo_cnt_q;
wire [DP_WD :0]waddr_d = wenc ? {waddr_d_h, waddr_d_l} : waddr;
wire [DP_WD :0]raddr_d = renc ? {raddr_d_h, raddr_d_l} : raddr;
wire [DP_WD :0]fifo_cnt_d = (waddr_d[DP_WD] == raddr_d[DP_WD]) ? (waddr_d[DP_WD-1:0] - raddr_d[DP_WD-1:0]):
                                   (waddr_d[DP_WD-1:0] + DEPTH - raddr_d[DP_WD-1:0]);
wire fifo_cnt_en = (wenc ^ renc);
always @(posedge clk or negedge rst_n)begin
  if(~rst_n)    fifo_cnt_q <= 0;
  else if(fifo_cnt_en) fifo_cnt_q <= fifo_cnt_d;
end


数据寄存

数据寄存,寄存器不复位降功耗,出口有一个多路的MUX,WIDTH*DEPTH越大,逻辑越深绕线越难:

//==================================================================
//数据寄存
//==================================================================
reg [WIDTH -1:0]data[DEPTH];
always @(posedge clk or negedge rst_n)begin
  if(wenc) data[waddr[DP_WD-1:0]] <= in_data;
end
assign out_data = data[raddr[DP_WD-1:0]];


对外逻辑的产生

in_ready实际就是常用FIFO的full信号取反,out_valid就是empty的取反,因此单纯做逻辑是不难的。但是为了实现寄存器输出,最后我选择了这样的逻辑:

//==================================================================
//对外逻辑
//==================================================================
//assign in_ready  = (fifo_cnt_q < DEPTH);
//assign out_valid = (fifo_cnt_q > {DP_WD{1'b0}});
wire in_ready_en;
wire in_ready_d;
reg  in_ready_q;
assign in_ready_en = (out_valid && out_ready) || in_ready;
assign in_ready_d  = (fifo_cnt_d < DEPTH);
always @(posedge clk or negedge rst_n)begin
  if(~rst_n)          in_ready_q <= 1;
  else if(in_ready_en)in_ready_q <= in_ready_d;
end
wire out_valid_en;
wire out_valid_d;
reg  out_valid_q;
assign out_valid_en = (in_valid && in_ready) || out_valid;
assign out_valid_d  = (fifo_cnt_d > {DP_WD{1'b0}});
always @(posedge clk or negedge rst_n)begin
  if(~rst_n)           out_valid_q <= 0;
  else if(out_valid_en)out_valid_q <= out_valid_d;
end
assign in_ready  = in_ready_q;
assign out_valid = out_valid_q;


仿真

使用auto_verification进行仿真,得到波形图:



相关文章
|
8天前
|
前端开发 JavaScript
前端界的革命:掌握这些新技术,让你的代码简洁到让人惊叹!
前端技术的快速发展带来了许多令人惊叹的新特性。ES6及其后续版本引入了箭头函数、模板字符串等简洁语法,极大减少了代码冗余。React通过虚拟DOM和组件化思想,提高了代码的可维护性和效率。Webpack等构建工具通过模块化和代码分割,优化了应用性能和加载速度。这些新技术正引领前端开发的革命,使代码更加简洁、高效、可维护。
12 2
|
8天前
|
前端开发 JavaScript 测试技术
前端工程师的必修课:如何写出优雅、可维护的代码?
前端工程作为数字世界的门面,编写优雅、可维护的代码至关重要。本文从命名规范、模块化设计、注释与文档、遵循最佳实践四个方面,提供了提升代码质量的方法。通过清晰的命名、合理的模块划分、详细的注释和持续的学习,前端工程师可以写出高效且易于维护的代码,为项目的成功打下坚实基础。
16 2
|
13天前
|
监控 前端开发 JavaScript
前端开发的终极奥义:如何让你的代码既快又美,还不易出错?
【10月更文挑战第31天】前端开发是一个充满挑战与机遇的领域,本文从性能优化、代码美化和错误处理三个方面,探讨了如何提升代码的效率、可读性和健壮性。通过减少DOM操作、懒加载、使用Web Workers等方法提升性能;遵循命名规范、保持一致的缩进与空行、添加注释与文档,让代码更易读;通过输入验证、try-catch捕获异常、日志与监控,增强代码的健壮性。追求代码的“快、美、稳”,是每个前端开发者的目标。
30 3
|
15天前
|
前端开发 JavaScript 开发者
前端开发的终极技巧:如何让你的代码既简洁又高效,还能减少bug?
【10月更文挑战第30天】前端开发充满挑战与创新,如何编写简洁高效且少bug的代码是开发者关注的重点。本文介绍五大技巧:1. 模块化,提高代码复用性;2. 组件化,降低代码耦合度;3. 使用现代框架,提高开发效率;4. 统一代码规范,降低沟通成本;5. 利用工具,优化代码质量。掌握这些技巧,让前端开发更高效。
30 1
|
22天前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
28 1
|
1月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
130 2
|
1月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
38 0
|
1月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。
|
1月前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
1月前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。