调试成功的简单异步FIFO--verilog实现+testbench

最近在写一个异步FIFO的时候,从网上找了许多资料,文章都写的相当不错,只是附在后面的代码都多多少少有些小错误。

于是自己写了一个调试成功的代码,放上来供大家参考。

非原创 原理参考下面:

原文 https://www.cnblogs.com/SYoong/p/6110328.html

上代码:

 1 module Asyn_FIFO
 2 #(
 3     parameter WIDTH = 8,
 4     parameter DEPTH = 4
 5 )
 6 (
 7     input  clk_wr,
 8     input  clk_rd,
 9     input  rst_n_rd,
10     input  rst_n_wr,
11     input  wr_en,
12     input  rd_en,
13     input  [WIDTH-1:0] data_wr,
14     output [WIDTH-1:0] data_rd,
15     output reg rd_empty,
16     output reg wr_full
17 );
18
19     //defination
20     reg  [WIDTH-1 : 0] mem [0 : (1<<DEPTH)-1];        //2^DEPTH numbers
21     reg  [DEPTH   : 0] wp, rp;
22     reg  [DEPTH   : 0] wr1_rp, wr2_rp, rd1_wp, rd2_wp;
23     reg  [DEPTH   : 0] wbin, rbin;
24
25
26     wire [DEPTH-1 : 0] waddr, raddr;
27     wire [DEPTH   : 0] wbin_next, rbin_next;        //bincode
28     wire [DEPTH   : 0] wgray_next, rgray_next;        //graycode
29
30     wire rd_empty_val, wr_full_val;
31
32     //output
33     assign data_rd = mem[raddr];
34
35     //input
36     always@(posedge clk_wr)
37         if(wr_en && !wr_full)
38             mem[waddr] <= data_wr;
39
40 /*----------generate waddr and raddr-------------------------*/
41     //gen raddr and read gray code
42     always@(posedge clk_rd or negedge rst_n_rd)
43         if(!rst_n_rd)
44             {rbin, rp} <= 0;
45         else
46             {rbin, rp} <= {rbin_next, rgray_next};
47
48     assign raddr = rbin[DEPTH-1 : 0];
49     assign rbin_next = rbin + (rd_en & ~rd_empty);
50     assign rgray_next = rbin_next ^ (rbin_next >> 1);
51
52     //gen waddr and write gray code
53     always@(posedge clk_wr or negedge rst_n_wr)
54         if(!rst_n_wr)
55             {wbin, wp} <= 0;
56         else
57             {wbin, wp} <= {wbin_next, wgray_next};
58
59     assign waddr = wbin[DEPTH-1 : 0];
60     assign wbin_next = wbin + (wr_en & ~wr_full);
61     assign wgray_next = wbin_next ^ (wbin_next >> 1);
62
63 /*---------------synchro rp and wp--------------------------*/
64     //synchro rp
65     always@(posedge clk_wr or negedge rst_n_wr)
66         if(!rst_n_wr)
67             {wr2_rp, wr1_rp} <= 0;
68         else
69             {wr2_rp, wr1_rp} <= {wr1_rp, rp}; //delay two clock
70
71     //synchro wp
72     always@(posedge clk_rd or negedge rst_n_rd)
73         if(!rst_n_rd)
74             {rd2_wp, rd1_wp} <= 0;
75         else
76             {rd2_wp, rd1_wp} <= {rd1_wp, wp};
77
78 /*---------------empty and full flags--------------------------*/
79     //gen rd_empty
80     assign rd_empty_val = (rd2_wp == rgray_next);
81     always@(posedge clk_rd or negedge rst_n_rd)
82         if(!rst_n_rd)
83             rd_empty <= 1‘b1;
84         else
85             rd_empty <= rd_empty_val;
86
87     //gen wr_full, two high bit do not equal
88     assign wr_full_val = ({~wr2_rp[DEPTH : DEPTH-1], wr2_rp[DEPTH-2 : 0]} == wgray_next);
89     always@(posedge clk_wr or negedge rst_n_wr)
90         if(!rst_n_wr)
91             wr_full <= 1‘b0;
92         else
93             wr_full <= wr_full_val;
94
95 endmodule

Asyn_FIFO.v

 1 module Asyn_FIFO_tb;
 2
 3     parameter WIDTH = 8;
 4
 5     reg clk_wr;
 6     reg clk_rd;
 7     reg rst_n_rd;
 8     reg rst_n_wr;
 9
10     reg  [WIDTH-1:0] data_wr;
11     reg  wr_en;
12     wire wr_full;
13
14     wire [WIDTH-1:0] data_rd;
15     reg  rd_en;
16     wire rd_empty;
17
18
19     Asyn_FIFO fifo_inst(
20     .clk_wr(clk_wr),
21     .rst_n_rd(rst_n_rd),
22     .rst_n_wr(rst_n_wr),
23     .wr_en(wr_en),
24     .data_wr(data_wr),
25     .clk_rd(clk_rd),
26     .rd_en(rd_en),
27     .data_rd(data_rd),
28     .rd_empty(rd_empty),
29     .wr_full(wr_full)
30     );
31
32     initial begin
33         rst_n_rd = 0;
34         rst_n_wr = 0;
35         clk_wr = 0;
36         clk_rd = 0;
37         wr_en = 0;
38         rd_en = 0;
39
40         #20
41         rst_n_rd = 1;
42         rst_n_wr = 1;
43
44         #80
45         wr_en = 1;
46         rd_en = 0;
47
48         #10000
49         wr_en = 0;
50         rd_en = 1;
51     end
52
53     always #10 clk_wr = ~clk_wr;
54     always #20 clk_rd = ~clk_rd;
55
56 /*     always @(posedge clk_rd)
57         rd_en <= ($random) % 2;
58
59     always @(posedge clk_wr)
60         wr_en <= ($random) % 2; */
61
62     always @(posedge clk_wr)
63         data_wr <= ($random) % 256;
64
65 endmodule

Asyn_FIFO_tb.v

注意wire、reg类型的赋值。

原文地址:https://www.cnblogs.com/HolmeXin/p/9448626.html

时间: 2024-08-30 06:52:43

调试成功的简单异步FIFO--verilog实现+testbench的相关文章

异步fifo的Verilog实现

 一.分析 由于是异步FIFO的设计,读写时钟不一样,在产生读空信号和写满信号时,会涉及到跨时钟域的问题,如何解决? 跨时钟域的问题:由于读指针是属于读时钟域的,写指针是属于写时钟域的,而异步FIFO的读写时钟域不同,是异步的,要是将读时钟域的读指针与写时钟域的写指针不做任何处理直接比较肯定是错误的,因此我们需要进行同步处理以后仔进行比较 解决方法:加两级寄存器同步 + 格雷码(目的都是消除亚稳态) 1.使用异步信号进行使用的时候,好的设计都会对异步信号进行同步处理,同步一般采用多级D触发器级联

异步FIFO的编程

对于异步FIFO.最基本的两个方面是地址控制和空.满标志位的产生.首先地址控制分别为读地址和写地址,每次读写时能读写地址应该加1.计数次数为ram深度的2倍.当读写地址相等时则空标志位有效,当读写地址最高位互补其余位相等时则满标志位有效. 存储部分採用双口RAM实现. 以下是详细的Verilog代码: module afifo(r_clk,w_clk,rst_n,data_in,data_out,we,re,empty,full); input r_clk,w_clk,rst_n,re,we;

异步FIFO

一.FIFO简介 FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,它与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址. 用途1: 异步FIFO读写分别采用相互异步的不同时钟.在现代集成电路芯片中,随着设计规模的不断扩大,一个系统中往往含有数个时钟,多时钟域带来的一个问题就是,如何设计异步时钟之间的接口电

《Color Transfer Based on Normalized Cumulative Hue Histograms》论文实现,已调试成功,可直接使用

 论文原理随后补充: 从网上找了别人实现的HistogramCT类,基本可用,一点小问题已经改好了,用的是opecv1.0 的函数,没有花时间去改成c++的接口,修改调试成功的code下载地址如下: http://download.csdn.net/detail/hyqsong/8601077 使用非常简单,如下: 参考图片是: 结果:

异步FIFO问题 二

同步FIFO, verilog: module fifo(clock,reset,read,write,fifo_in,fifo_out,fifo_empty,fifo_half,fifo_full); input clock,reset,read,write; input [15:0]fifo_in; output[15:0]fifo_out; output fifo_empty,fifo_half,fifo_full;//标志位 reg [15:0]fifo_out; reg [15:0]r

“500 oops socket” Debian 9 running via Linux Deploy上成功部署vsftpd的解决方案(201901原创)【成功完美简单极致】

"500 oops socket" Debian 9 running via Linux Deploy上成功部署vsftpd的解决方案(201901原创)[成功完美简单极致] #自从手机root后安装Linux Deploy开始安装了Debian9开始准备鼓捣ftp服务器(vsftpd). apt install vsftpd #之后整整一个月百度而来的猛如虎的各种操作各种坑, #且不说修改vsftpd.conf的各种参数, #下载源码修改编译,安装gdb调试,通过网络教程禁用子进程改

gdb调试多线程的简单命令

由于平时的编程当中经常会用到多线程,我想接触过多线程编程的人应该都会清楚多线程如果出了错,调起bug来是有多么麻烦,应为你某个地方出错了,有可能并不是这里的问题而是线程执行到这就切换到其他线程,而出错的是其他线程,我以前使用的办法是给某个线程sleep然后让内核自己调度去执行其他线程.很明显这种方法当有很多线程是并不是很使用,所以我就翻书学了几条调试多线程的简单gdb命令 1.测试所用的代码 1void *thread1(void *arg) 2{ 3 printf("New thread1\n

v3学院 FPGA专家 带你学习FPGA实现格雷码跨时钟域异步fifo

当由慢时钟域到快时钟域,肯定需要一个buffer做缓冲,这样才能完成时钟域的转换.一般这种情况都选择FIFO来做缓冲. 当读写FIFO的时钟不同那么称为异步FIFO,FIFO就是一个"环形存储器"读操作会把读指针指向下一个读数据,写操作会把写指针指向下一个写数据地址.当读指针追上写指针时称作读空,当写地址追上读地址时称作写满. 读空,写满标志的产生 格雷码地址编码产生 异步fifo整体逻辑框图 请扫二维码加入fpga圈 代码实现请持续关注,下次讲解! 本文章原创,来自v3学院 www.

异步FIFO设计的一些注意事项

异步FIFO的结构基本上是是按照下面的思路来设计: 1. 读写的指针分别用gray code sync到另外一个clock domain,sync的时候至少打2拍. 2. 读写指针最高位各加一个bit用来判断空和慢,对于FIFO来说,永远是读指针追写指针,当指针相同的时候,用加的这个最高bit来 判断是谁追上谁,继而判断空和满. 除了上面的设计要点,还有以下几点需要注意: 1. 当两个时候频率差别很大时 快时钟的读/写指针sync到慢时钟时,gray code就不是按照1次变化1个bit的方式进