虚拟机:VMware -14.0.0.24051
环 境:ubuntu 18.04.1
脚 本:makefile(点击查看)
应用工具:vcs 和 verdi


写在前面

  1. 这个专栏的内容记录的是个人学习过程,博文中贴出来的代码是调试前的代码,方便bug重现。
  2. 调试后的程序提供下载,【下载地址】
  3. 发现了一个Verilog宝藏刷题网站,网站提供在线仿真环境(点击直达),同时新开了一个<刷题记录>专栏,持续打卡中…

路 线:

  • 【verilog实战】同步FIFO设计(附源码RTL/TB)
  • 【Verilog实战】异步FIFO设计(附源码RTL/TB)
  • 【Verilog实战】UART通信协议,半双工通信方式(附源码RTL/TB)
  • 【Verilog实战】SPI协议接口设计(附源码RTL/TB)
  • 【Verilog实战】AMBA 3 APB接口设计(附源码RTL/TB)
  • 【Verilog实战】AMBA AHB接口设计(附源码RTL/TB)
  • 【Verilog实战】AMBA AXI接口设计(附源码RTL/TB)
  • 【Verilog实战】UART2APB bridge 设计(附源码RTL/TB)
  • 【Verilog实战】AHB2APB bridge 设计(附源码RTL/TB)

文章目录

  • 一、学习内容
  • 二、基本概念
  • 三、Spec
  • (1) Function description
  • (2) Feature list
  • (3) Block diagram
  • (4) Interface description
  • (5) Timing
  • 四、RTL design
  • 五、分析和小结
  • (1)分析
  • (2)小结
  • ✍✍☛ [题库入口](https://www.nowcoder.com/link/pc_csdncpt_xlin_verilog)

一、学习内容

  1. 同步FIFO的写时钟和读时钟为同一个时钟,FIFO内部所有逻辑都是同步逻辑,常常用于交互数据缓冲。
  2. 典型同步FIFO有三部分组成: (1) FIFO写控制逻辑; (2)FIFO读控制逻辑;(3)FIFO 存储实体(如Memory、Reg)。
  3. FIFO写控制逻辑主要功能:产生FIFO写地址、写有效信号,同时产生FIFO写满、写错等状态信号;
  4. FIFO读控制逻辑主要功能:产生FIFO读地址、读有效信号,同时产生FIFO读空、读错等状态信号

二、基本概念

  1. 同步FIFO的“同步”是什么意思?
  2. FIFO是什么,有什么用?
  3. 接口都有什么
  • 同步:时钟间有确定的倍数关系或确定的相位关系
  • FIFO:Frist-in-first-out,先进先出,是一种数据缓存器,实现速率匹配。

      既然是数据缓冲器,那么缓冲器的大小,存储深度,读写地址和存储器空满状态都需要确定。
      一般FIFO使用循环指针(计数溢出自动归零)。一般可以称写指针为头head,读指针为尾tail。初始化时,读写指针指向同一数据地址。

  上图可见,FIFO初始化时,WP和RP指针指向同一数据单元。WP指向下一个将要写入的数据单元,RP指向将要读出的数据单元,两者是一个追赶过程。可以设置一个计数器,只写,来一个数据,写一个,写地址,+1,计数器+1,写满为止;只读,来一个,读出一个数据,读地址+1,计数器-1;同时读写,计数器值不变,读写地址均+1。

三、Spec

(1) Function description

  同步FIFO实现了对write/read的控制,其接口解决了接口两端数据速率不匹配的问题。

(2) Feature list

  • 支持存储宽度、深度可配置
  • 时钟工作频率为1MHz

(3) Block diagram

  模块主要分为读/写接口、读/写指针、读写指针的比较逻辑和array存储阵列四部分。

  1. 读/写接口:为模块提供读写数据和读写使能信号;
  2. 读写指针:主要标志读写指针当前array的地址
  3. 比较逻辑:
  • 使用element counter(elem_cnt)记录FIFO RAM 中的数据个数:
    ▷ 等于0时,给出empty信号;等于BUF_LENGTH时,给出full信号
  • elem_cnt:
    ▷ 写而未满时增加1
    ▷ 读而未空时减1
    ▷ 同时发生读写操作时,elem_cnt不变

(4) Interface description

(5) Timing

  分为三部分,写操作,读操作,读写操作。


四、RTL design

  • DUT模块
module sync_fifo
#(parameter DATA_WIDTH = 32,parameter DATA_DEPTH = 8 ,parameter PTR_WIDTH  = 3
//parameter PTR_WIDTH  = $clog2(DATA_DEPTH)
)
(input  wire                    clk_i   ,input  wire                    rst_n_i ,//write interfaceinput  wire                    wr_en_i  ,input  wire  [DATA_WIDTH-1:0]  wr_data_i,//read interfaceinput  wire                    rd_en_i  ,output reg   [DATA_WIDTH-1:0]  rd_data_o,//Flags_ooutput reg                     full_o   ,output reg                     empty_o
);reg  [DATA_WIDTH-1:0]  regs_array  [DATA_DEPTH-1:0];reg  [PTR_WIDTH-1 :0]  wr_ptr                      ;reg  [PTR_WIDTH-1 :0]  rd_ptr                      ;reg  [PTR_WIDTH   :0]  elem_cnt                    ;reg  [PTR_WIDTH   :0]  elem_cnt_nxt                ;//Flagswire                   full_comb                   ;wire                   empty_comb                  ;/*---------------------------------------------------\--------------- write poiter addr ----------------
\---------------------------------------------------*/
always @ (posedge clk_i or negedge rst_n_i) beginif (!rst_n_i) beginwr_ptr <= 3'b0;endelse if (wr_en_i && !full_o) beginwr_ptr <= wr_ptr + 3'b1;end
end/*---------------------------------------------------\-------------- read poiter addr ------------------
\---------------------------------------------------*/
always @ (posedge clk_i or negedge rst_n_i) beginif (!rst_n_i) beginrd_ptr <= 3'b0;endelse if (rd_en_i && !empty_o) beginrd_ptr <= rd_ptr + 3'b1;end
end/*---------------------------------------------------\--------------- element counter ------------------
\---------------------------------------------------*/always @ (posedge clk_i or negedge rst_n_i) beginif (!rst_n_i) beginelem_cnt <= 4'b0;endelse if (wr_en_i && rd_en_i && !full_o && !empty_o) beginelem_cnt <= elem_cnt;endelse if(wr_en_i && !full_o) beginelem_cnt <= elem_cnt + 1'b1;endelse if(rd_en_i && !empty_o) beginelem_cnt <= elem_cnt - 1'b1;end
end/*---------------------------------------------------\------------- generate the flags -----------------
\---------------------------------------------------*/
always @(*) beginif(!rst_n_i) beginelem_cnt_nxt = 1'b0;endelse if(elem_cnt != 4'd0 && rd_en_i && !empty_o) beginelem_cnt_nxt = elem_cnt - 1'b1; endelse if(elem_cnt != 4'd8 && wr_en_i && !full_o) beginelem_cnt_nxt = elem_cnt + 1'b1; endelse beginelem_cnt_nxt = elem_cnt;end
endassign full_comb  = (elem_cnt_nxt == 4'd8);
assign empty_comb = (elem_cnt_nxt == 4'd0);always @ (posedge clk_i or negedge rst_n_i) beginif (!rst_n_i) beginfull_o <= 1'b0;endelse beginfull_o <= full_comb;end
endalways @ (posedge clk_i or negedge rst_n_i) beginif (!rst_n_i) beginempty_o <= 1'b1;endelse beginempty_o <= empty_comb;end
end/*---------------------------------------------------\-------------------- read data -------------------
\---------------------------------------------------*/
always @ (posedge clk_i or negedge rst_n_i) beginif (!rst_n_i) beginrd_data_o <= 32'b0;endelse if(rd_en_i && !empty_o) beginrd_data_o <= regs_array[rd_ptr];end
end/*---------------------------------------------------\------------------- write data -------------------
\---------------------------------------------------*/
reg [PTR_WIDTH:0] i;always @ (posedge clk_i or negedge rst_n_i) beginif (!rst_n_i) beginfor(i=0;i<DATA_DEPTH;i=i+1) beginregs_array[i] <= 32'b0;endendelse if(wr_en_i && !full_o) beginregs_array[wr_ptr] <= wr_data_i;end
endendmodule

  • tb
module tb_sync_fifo;reg          clk_i    ;reg          rst_n_i  ;reg          wr_en_i  ;reg  [31:0]  wr_data_i;reg          rd_en_i  ;reg  [31:0]  rd_data_o;wire         full_o   ;reg          empty_o  ;initial beginrst_n_i   = 1  ;clk_i     = 0  ;rd_en_i   = 0  ;wr_en_i   = 0  ;wr_data_i = 32'b0;#2 rst_n_i = 0 ;#5 rst_n_i = 1 ;
endinitial begin#10 wr_en_i = 1;rd_en_i = 0;#10 wr_en_i = 0;rd_en_i = 1;#10 wr_en_i = 1;rd_en_i = 0;#3  rd_en_i = 1;#10repeat(100) begin#5 wr_en_i = {$random}%2;rd_en_i = {$random}%2;end
endinitial #2000 $finish;always #0.5 clk_i     = ~clk_i       ;
always #1   wr_data_i = {$random}%10;
sync_fifo u_sync_fifo
(.clk_i    (clk_i    ),.rst_n_i  (rst_n_i  ),.wr_en_i  (wr_en_i  ),.wr_data_i(wr_data_i),.rd_en_i  (rd_en_i  ),.rd_data_o(rd_data_o),.full_o   (full_o   ),.empty_o  (empty_o  )
);initial begin$fsdbDumpfile("sync_fifo.fsdb");$fsdbDumpvars                  ;$fsdbDumpMDA                   ;
end
endmodule

五、分析和小结

(1)分析

  • 写阶段

  复位之后,进行写操作,直至写满,产生满标志后,不再写入新数据。


  • 读阶段

  进行读操作,直至读空,产生空标志后,不再读出新数据。


  • 同时读写阶段

  先进行写操作,写入三个新数据之后,同时进行读写操作,期间写入新数据和读出数据,但是elem_cnt计数器不再变化,动态平衡。

(2)小结

  设计思路:先分析需求,定义接口,画出具体的实现框图;按照协议和理解,画出相应时序图;看图写程序,验证仿真波形是否与时序图对应。
  同步FIFO设计要点是什么时候产生空满标志位,即怎么衡量array被写满或者被读空。在这里,我使用了4bit的elem_cnt表示,通过elem_cnt的值表示当前array存储阵列的资源使用情况。0表示没有数据,即空状态;8表示写满,因为array的存储深度就是8。在spec中提到实现FIFO可配置,在这里只实现了宽度为32bit,深度为8的同步fifo设计,初步验证仿真波形与时序图相对应。


✍✍☛ 题库入口

  经过一段时间的沉淀,发现入行IC行业,自己的底子还是很差,写的文章质量参差不齐,也没能解答大家的疑问。还是要实打实从基础学起,由浅入深。因此决定推倒重来,通过补充/完善基础知识的同时,通过题库刷题不断提高自己的设计水平,题库推荐给大家(点击直达),<题库记录>栏目不定期更新,欢迎前来讨论。2022.08.29 记


作者:xlinxdu
版权:本文版权归作者所有
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。

01 【Verilog实战】同步FIFO的设计(附源码RTL/TB)相关推荐

  1. 02【Verilog实战】异步FIFO设计(附源码RTL/TB)

    脚 本:makefile 工 具:vcs 和 verdi 文 章:1. 同步FIFO的设计和功能验证(附源码)     2. Verilog的亚稳态现象和跨时钟域处理方法 写在前面 这个专栏的内容记录 ...

  2. 04【Verilog实战】SPI协议底层硬件接口设计(附源码RTL/TB)

    脚  本:makefile 工  具:vcs 和 verdi 写在前面 这个专栏的内容记录的是个人学习过程,博文中贴出来的代码是调试前的代码,方便bug重现. 调试后的程序提供下载,[下载地址] 发现 ...

  3. 05【Verilog实战】AMBA 3 APB接口设计(附源码RTL/TB)

    官方手册:点击下载 脚  本:makefile 工  具:vcs & verdi 写在前面 这个专栏的内容记录的是个人学习过程,博文中贴出来的代码是调试前的代码,方便bug重现. 调试后的程序 ...

  4. Linux嵌入式驱动开发01——第一个驱动Hello World(附源码)

    文章目录 全系列传送门 引言 驱动介绍 Hello World 1. 包含头文件 2. 驱动模块的入口和出口 3. 声明信息 4. 功能实现 完整代码 编译 第一种方法 第二种方法 编译成模块 第一步 ...

  5. 原生前端实现响应式个人简历网站设计(附源码)

    目录 网站站点 所用技术 实现功能 视频展示 源码 网站站点 胜烨的个人网站 所用技术 HTML css JavaScript 实现功能 响应式界面设计 捕捉用户操作 明暗模式 服务器部署 视频展示 ...

  6. Python实战例子(32个附源码)

    Python是一种高级编程语言,具有简洁.清晰的语法,易于理解和使用,因此受到广泛的欢迎.尤其在数据科学.人工智能.机器学习.自然语言处理等领域,Python已成为最受欢迎的编程语言之一.Python ...

  7. 基于SSM框架图书管理系统开发与设计(附源码资料)-毕业设计

    文章目录 1. 适用人群 2. 你将收获 3.项目简介 4.技术实现 5.系统功能 5.1.管理员身份登录 5.1.1.登录 5.1.2.管理员登录首页 5.1.3.借阅管理 5.1.4.图书管理 5 ...

  8. discuz论坛整合ucenter免激活,同步登录,同步退出解决方案(附源码)

    UCenter作为整合用户的这样一个开源插件,对于PHP开发的,甚至其它开发语言如.net,java.asp等开发人员解决多个项目整合到一起,用户进行同步登录,同步退出等,同步消息等都是非常有用的.下 ...

  9. 100个Python实战练手项目(附源码+素材),学习必备

    前言: 不管学习哪门语言都希望能做出实际的东西来,这个实际的东西当然就是项目啦,不用多说大家都知道学编程语言一定要做项目才行. 这里整理了最新32个Python实战项目列表,都有完整且详细的视频教程和 ...

最新文章

  1. 重磅 | TensorFlow 2.0即将发布,所有tf.contrib将被弃用
  2. jquery选择器 之 获取父级元素、同级元素、子元素
  3. K8S面试大通关!赶紧收藏!
  4. maven仓库配置和 修改阿里云镜像
  5. Redis-15Redis基础配置文件
  6. 79. 单词搜索(dfs)
  7. WCF 第四章 绑定 netMsmqBinding
  8. discuz!5.5.0安装方法及常见问题解决
  9. 小学学校计算机教室使用计划,小学电脑室工作计划
  10. nssl1469-W【dp】
  11. oracle复杂的子查询,Oracle 子查询(复杂select语句)
  12. 【Hadoop】Hadoop SocketChannelImpl UnresolvedAddressException
  13. android 列表上拉加载更多,Android 下拉刷新,上拉加载更多控件–支持ListView,GridView和ScrollView...
  14. java.lang math 类
  15. 微信小程序原生自定义组件布局问题
  16. ESD问题案例分析-智能手表为例
  17. go语言interface用法
  18. java中 什么意思?比如130
  19. model.most_similar
  20. Android Backup功能之全面实战

热门文章

  1. python圣斗士(十七):令人欲罢不能的正则
  2. python实现将深度学习应用于医学图像以辅助医疗
  3. 一键收藏网页上的文章,浏览器书签方便日常查找和管理
  4. Win10 schtasks 不稳定问题
  5. C51单片机数码管动态显示
  6. 09——规范数据库设计
  7. Ubuntu系统电池管理软件TLP(Thinkpad设置电池充电阈值)
  8. 典型分布式计算技术的分析和比较
  9. alibaba人一起写过的技术丛书
  10. 使用vue实现简单的图书管理