当前位置:   article > 正文

【FPGA学习】对FIFO的理解及双FIFO流水操作实验_fifo中的数据读取后还在吗

fifo中的数据读取后还在吗

目录

   1、 FIFO概述

 1.1、FIFO分类

 1.2、 fifo模型(Native interface)

 1.3、 IP信号列表

1.4、注意事项

1.5、fifo读写关键时序

1.5.1、写操作

1.5.2、读操作

1.6、 应用

2、双fifo流水操作实验

2.1、模块总体架构

2.2、实现思路:

 2.3、fifo_ctrl模块端口描述

2.4、代码实现

double_fifo_ctrl

urat_rx

top_fifo

testbench

data.txt

2.5、仿真结果

 2.5.1modelsim仿真结果     

 2.5.2、ChipSocpe  Pro抓取

2.6、调试助手测试结果


   1、 FIFO概述

        FIFO(First input First Output) ,即先入先出,本质上是一个RAM,FIOF和RAM的共同点在于都是能储存数据,都有控制读和写的信号,不同点在于FIOF没有地址,因此不能任意指定读取某个数据,数据只能按照数据输入的顺序输出,且读写可以同时进行。

        如果将数据把fifo的深度写满,数据将不能在进去,也不会覆盖原来的数据,读取fifo的数据也只能读一遍,读完一遍fifo就空了,需要再往fifo写数据才能读出新的数据,否则读出的数据一直是最后一次读fifo时的数据。

 1.1、FIFO分类

        FIFO的类型区分主要根据FIFO在实现时利用的是芯片中的哪些资源,其分类主要有以下四种:

        shift register FIFO:通过寄存器来实现的,由于片内FF资源比较珍贵,所以这种方式的fifo要考虑周全后使用。

        built-in FIFO:这种类型的FIFO只有7系列之后(包括UltraScale)才有。是一种集成的FIFO硬核,他不支持almost_full标志

        Block Ram FIFO:通过块RAM的资源配置形成的FIFO,其本质是Block RAM+一些外设电路。

        Distributed Ram FIFO:通过分布式RAM配置形成的FIFO,与BRAM类似,只是RAM的类型不一样。

 1.2、 fifo模型(Native interface)

 1.3、 IP信号列表

列部分常使用的端口

信号名

位宽

说明

端口

wr_clk 

1

写时钟,提供给写端口使用的时钟

input

wr_en 

1

写使能,高电平有效,在每个写时钟上升沿被捕捉,捕捉一次写入一次数据

input

 full

1

满信号,高有效

在FIFO内部写数据个数 = FIFO写深度的第一个时钟上升沿置高,在FIFO内部写数据个数 < FIFO写深度的第一个时钟上升沿拉低。

在full有效时,FIFO会关闭写功能,如果此时wr_en有效,full会置高overflow即输出满溢信号,FIFO中的数据没有变化,往满FIFO中写不会覆盖之前的数据。

output

din[N:0]

1~1024

写入的数据,当wr_en高被捕捉时,din被写入到FIFO中

input

almost_full

1

预满信号,高有效

FIFO内部写数据个数 = FIFO深度 - 1的第一个写时钟上升沿置高,

FIFO内部写数据个数 < FIFO深度 - 1的第一个写时钟上升沿拉低 output wr_rst 1 写复位,高有效,

写复位信号有效后的第一个写时钟上升沿,FIFO被清空,并不再响应写使能,

直到写复位信号失效后下一个写时钟上升沿(包括)开始再去响应写使能

input

rd_clk 

1

读时钟

对于同步FIFO,FIFO读写时钟合一

对于异步FIFO,FIFO会有分开的写时钟和读时钟

input

rd_en 

1

读使能,高有效,在每个读时钟上升沿被捕捉,捕捉一次读出一次数据

input

empty

1

空信号,高有效,

FIFO内部读数据个数 = 0的第一个读时钟上升沿置高,

直到FIFO内部读数据个数 > 0的第一个读时钟上升沿拉低。

在empty有效时,FIFO会关闭功能,如果此时rd_en有效,FIFO会置高underflow即输出空溢信号,FIFO内部的数据没有变化,读取空FIFO不是破坏性的。

output 

 dout

可设定位宽 =

din位宽 *(1/8,1/4,1/2,1,2,4,8)

读数据,读数据位宽 * 读深度 = FIFO容量 = 写数据位宽 * 写深度,

对于FWFT FIFO,dout预先有效,在读使能被捕捉的同时更新下一个读数据,

对于Standard FIFO,在读使能被捕捉的时钟过后的第二个时钟上升沿,dout才是读出的数据

output

almost_empty

1

预空信号,高有效

FIFO内部读数据个数 = 1的第一个读时钟上升沿置高,

FIFO内部读数据个数 > 1的第一个读时钟上升沿被拉低

output

参考链接:https://blog.csdn.net/weixin_42837669/article/details/121734888

1.4、注意事项

        在FPGA配置完成后,读写操作开始之前,FIFO必须被复位,有同步/异步两种复位可用。

        Xilinx建议,不要通过改变clk来改变FIFO的读写行为,而应该去控制读写使能信号,当时钟未稳定时,不要去操作FIFO,当时钟稳定后,先对FIFO进行复位,然后再去操作FIFO。

        虽然写满和读空行为都不是破坏性的,但仍然强烈建议不要在FIFO满时置高写使能,不要在FIFO空时置高读使能。也就是wr_en的用户逻辑需要考虑full信号,rd_en的用户逻辑需要考虑empty信号。

1.5、fifo读写关键时序

1.5.1、写操作

          写数据只有在din输入同时wr_ack被拉高(在被写入成功的下一个时钟上升沿拉高)时才写入到FIFO中。这里wr_ack是对数据接收的应答,断言时表示接收成功。当然也可以不使能wr_ack,只是wr_ack的存在会让数据的写入更加安全。​
        almost_full在fifo只能再写入一个数据时被拉高(full前一拍),当fifo写满时,如果wr_en仍为高,则溢出信号overflow在一个时钟上升沿被拉高,需要注意的一个关键点是,FIFO被写满时,即使再输入数据,写入请求还是会被忽略的,FIFO中的数据保持不变

        在FIFO被写满时,如果开始读操作,full信号会被拉低,此时数据又可以再次写入FIFO。

1.5.2、读操作

         当read使能且FIFO不是空的时候,数据开始从FIFO读出。同时valid信号被断言表示数据有效。读操作只有在FIFO有数据时才能成功,当FIFO是空的时,此时读信号会被忽略,同时underflow会被拉高表示下溢,数据输出不会发生任何变化

 读操作分为Standard Read 和First_Word Fall_Through 两种模式,

         First_Word Fall_Through模式广泛的用于数据缓冲应用,其特点是相对读使能0延迟输出读数据,它的原理是第一个数据不需要读使能就能自动呈现在读端口

        Standard Read模式用于输出端时序特性要求比较高的场合,特点是相对读使能输出1拍延迟,也可以时钟多拍延迟这样经过寄存器的打拍提高输出寄存器间的时序特性

        当读操作和写操作同时发生在empty置高时,写操作可以正常执行,读操作会被忽略,在下个时钟,empty和underflow被拉低后,才能继续进行读操作。

         ​ 标准读模式下,当empty为低时,表示FIFO中有数据可读。此时使能rd_en,在下个时钟上升沿即开始读取数据,同时valid被拉高表示读取数据有效。当读到FIFO只剩一个数据时,almost_empty被拉高;当读完所有数据时,empty拉高。此时如果再进行读取,则underflow被拉高言,表示下溢,同时valid拉低表示数据无效。

        在FWFT模式下,数据总是能被提前获取的,可以这么理解,在我们还不需要读取FIFO的数据的时候,其实我们不在乎FIFO中第一个数据是什么,但FWFT模式下,第一个数据提前进入了准备发送的状态,即我们可以dout处看到即将输出的数据是什么,而当我们开始读的时候,下一个数据就进入准备状态,也被我们提前获取了。

​         比较两种模式下的flag信号。almost_empty是在FIFO中还剩下一个数据是被拉高,empty是在把最后一个数据读取完了之后被拉高。在SR模式下,empty是在把最后一个数据读出来的同时拉高,在FWFT模式下,empty是在获取最后一个数据后才拉高,因为我们是提前知道最后一个数据,此时的数据还是停留在FIFO中,只有把它读出来了,FIFO才是空的,empty才会被拉高。underflow都在读空之后还试图继续读取的时候才会拉高,所以underflow总是比empty慢一拍。valid总是和数据是同步的。

1.6、 应用

数据位宽转换:

                比如我们有32bit的数据需要转换成128bit或者32bit的数据需要转换成8bit,那么用FIFO来转换也是非常方便的。

 跨时钟域的应用:

                比如数据是2个不同步的时钟,那么我们就可以用FIFO实现跨时钟域的传输

 

2、双fifo流水操作实验

       写一个输入的数据是86X86的矩阵,数据由串口传输过来,传过来的数据先一行一行的用fifo缓存,然后每三行的同一列进行一次相加。

2.1、模块总体架构

2.2、实现思路:

       1、 由于是三行数据的相加,故可将第0行和第一行数据分别存放在fifo1和fifo2中,当第三行数据来临时,将fifo1,fifo2,以及rx_data上的数据相加即可。

       2、第0、1、2行加完后,需要把1、2、3行相加,所以在前一次相加的时候要将1、 2行数据存放到fifo里,即相加的同事要将fifo2的数据存入fifo1中,

      3、  最后三行相加的时候,最后一行不需要存到fifo2中,最后两行不要存放到fifo1中,因此fifo1中要存入的数据位0~83行的数据,fifo2中要存放的数据位1~84行的数据,需要进行的加运算次数位84x86次。

 2.3、fifo_ctrl模块端口描述

端口传输方向端口名称位宽说明
inputclk1系统时钟50
inputrst_n1复位信号
inputrx_data8rx传送过来的86x86数据
inputpi_flag1标志威高表示rx_data有效
outputpo_sum8三行数据相加的和,传给tx
outputpo_flag1标志高表示po_sum输出有效传送给tx
中间变量cnt_col7列计数器,pi_flag为1时加一
中间变量

cnt_row

7行计数器
中间变量data_in28存入fifo2中的数据
中间变量wr_en21

fifo2写请求

中间变量rd_en1fifo1,fifo2 读请求
中间变量dout1/28两个fifo输出信号,当rd_en为1时下一拍输出
中间变量wr_en1_pre11fifo1写请求提前一拍
中间变量wr_en1_pre21fifo1写请求提前两拍
中间变量wr_en11

fifo1写请求

2.4、代码实现

double_fifo_ctrl

  1. // ----------------------------------------------------------
  2. // Copyright (c) 2014-2022 All rights reserved
  3. // ----------------------------------------------------------
  4. // Author : yongchan jeon (Kris) poucotm@gmail.com
  5. // File : double_fifo_ctrl.v
  6. // Create : 2022-08-23 14:55:13
  7. // Revise : 2022-08-23 14:55:13
  8. // Editor : sublime text3, tab size (4)
  9. // --------------------------------------------------------
  10. module double_fifo_ctrl(
  11. input wire clk,
  12. input wire rst_n,
  13. input wire pi_flag,
  14. input wire [7:0] pi_data,
  15. output reg po_flag,
  16. output reg [7:0] po_sum //8bit+8bit=8bit
  17. );
  18. reg wr_en1,wr_en2;
  19. reg [6:0] cnt_col,cnt_row;
  20. reg wr_en1_pre1,wr_en1_pre2;
  21. reg rd_en;
  22. reg [7:0] data_in1,data_in2;
  23. reg add_flag;
  24. wire [7:0] dout1,dout2;
  25. wire full1,empty1,full2,empty2;
  26. //wr_en1
  27. always@(posedge clk or negedge rst_n)
  28. if(rst_n == 1'b0)
  29. wr_en1 <= 1'b0;
  30. else if (cnt_row == 'd0)begin
  31. if( pi_flag == 1'b1)
  32. wr_en1 <= 1'b1;
  33. else
  34. wr_en1 <= 1'b0;
  35. end
  36. else
  37. wr_en1 <= wr_en1_pre1;
  38. //wr_en1_pre2
  39. always@(posedge clk or negedge rst_n)
  40. if(rst_n == 1'b0)
  41. wr_en1_pre2 <= 1'b0;
  42. else if (cnt_row >= 'd2 && cnt_row <='d84 && pi_flag == 1'b1) // else if (cnt_row >= 'd2 && cnt_row <= 'd84)
  43. wr_en1_pre2 <= 1'b1; // wr_en1_pre2 <= pi_flag;
  44. else //
  45. wr_en1_pre2 <= 1'b0;
  46. //wr_en1_pre1
  47. always@(posedge clk )
  48. wr_en1_pre1 <= wr_en1_pre2;
  49. //rd_en
  50. always@(posedge clk or negedge rst_n)
  51. if(rst_n == 1'b0)
  52. rd_en <= 1'b0;
  53. else if (cnt_row >= 'd2 && cnt_row <= 'd845 && pi_flag == 1'b1)//(cnt_row >= 'd2 && cnt_row <= 'd84 && pi_flag == 1'b1)少记一个cnt_row,到最后输出结果少了
  54. rd_en <= 1'b1;
  55. else
  56. rd_en <= 1'b0;
  57. //data_in1
  58. always@(posedge clk or negedge rst_n)
  59. if(rst_n == 1'b0)
  60. data_in1 <= 'd0;
  61. else if (cnt_row == 'd0)
  62. data_in1 <= pi_data;
  63. else //else if (cnt_row >= 'd2 && cnt_row <= 'd84)
  64. data_in1 <= dout1; //data_in1 <= dout1;
  65. //wr_en2
  66. always@(posedge clk or negedge rst_n)
  67. if(rst_n == 1'b0)
  68. wr_en2 <= 1'b0;
  69. else if (cnt_row >= 'd1 && cnt_row <= 'd84 && pi_flag == 1'b1)
  70. wr_en2 <= 1'b1;
  71. else
  72. wr_en2 <= 1'b0;
  73. //data_in2
  74. always@(posedge clk or negedge rst_n)
  75. if(rst_n == 1'b0)
  76. data_in2 <= 'd0;
  77. else if (cnt_row >= 'd1 && cnt_row <= 'd84)
  78. data_in2 <= pi_data;
  79. //add_flag
  80. always@(posedge clk)
  81. add_flag <= rd_en;
  82. //po_sum
  83. always@(posedge clk)
  84. if(add_flag == 1'b1)
  85. po_sum <= dout1 + dout2 + pi_data;
  86. //po_flag
  87. always@(posedge clk)
  88. po_flag <=add_flag;
  89. //cnt_col
  90. always@(posedge clk or negedge rst_n)
  91. if(rst_n == 1'b0)
  92. cnt_col <= 7'd0;
  93. else if (pi_flag == 1'b1 && cnt_col == 85)
  94. cnt_col <= 7'd0;
  95. else if (pi_flag == 1'b1 && cnt_col != 85)
  96. cnt_col <= cnt_col + 1'b1;
  97. //cnt_row
  98. always@(posedge clk or negedge rst_n)
  99. if(rst_n == 1'b0)
  100. cnt_row <= 7'd0;
  101. else if(pi_flag == 1'b1 && cnt_col == 85 && cnt_row == 85)
  102. cnt_row <= 'd0;
  103. else if (pi_flag == 1'b1 && cnt_col == 85)
  104. cnt_row <= cnt_row + 1'b1;
  105. sfifo_wr128x8 u_fifo1 (
  106. .clk(clk), // input clk
  107. .din(data_in1), // input [7 : 0] din
  108. .wr_en(wr_en1), // input wr_en
  109. .rd_en(rd_en), // input rd_en
  110. .dout(dout1), // output [7 : 0] dout
  111. .full(full1), // output full full、empty信号没有使用
  112. .empty(empty1) // output empty full、empty信号没有使用
  113. );
  114. sfifo_wr128x8 u_fifo2 (
  115. .clk(clk), // input clk
  116. .din(data_in2), // input [7 : 0] din
  117. .wr_en(wr_en2), // input wr_en
  118. .rd_en(rd_en), // input rd_en
  119. .dout(dout2), // output [7 : 0] dout
  120. .full(full2), // output full
  121. .empty(empty2) // output empty
  122. );
  123. wire [35:0] CONTROL0;
  124. wire [50:0] TRIG0;
  125. assign TRIG0 = {
  126. po_sum,
  127. pi_flag,
  128. empty2,
  129. empty1,
  130. rd_en,
  131. cnt_col,
  132. cnt_row,
  133. add_flag,
  134. pi_data,
  135. dout1,
  136. dout2
  137. };
  138. cs_icon icon_inst (
  139. .CONTROL0(CONTROL0) // INOUT BUS [35:0]
  140. );
  141. cs_ila ila_inst (
  142. .CONTROL(CONTROL0), // INOUT BUS [35:0]
  143. .CLK(clk), // IN
  144. .TRIG0(TRIG0) // IN BUS [50:0]
  145. );
  146. endmodule

urat_rx

  1. // ----------------------------------------------------------
  2. // Copyright (c) 2014-2022 All rights reserved
  3. // ----------------------------------------------------------
  4. // Author : yongchan jeon (Kris) poucotm@gmail.com
  5. // File : urat_rx.v
  6. // Create : 2022-08-15 15:16:15
  7. // Revise : 2022-08-26 13:11:28
  8. // Editor : sublime text3, tab size (4)
  9. // ----------------------------------------------------------
  10. module uart_rx (
  11. input wire clk,
  12. input wire rst_n,
  13. input wire rx,
  14. output reg po_flag,
  15. output reg [7:0] po_data
  16. );
  17. parameter BUAD_CNT_MAX = 5207;
  18. parameter BUAD_HALFCNT_MAX = 2603;
  19. reg rx_1;
  20. reg rx_2;
  21. reg reg_rx2;
  22. reg rx_flag;
  23. reg [3:0] bit_cnt;
  24. reg bit_flag;
  25. reg [12:0] buad_cnt;
  26. //rx_1 <= rx
  27. always@(posedge clk or negedge rst_n)
  28. if(rst_n == 1'b0)
  29. rx_1<= 'd1;
  30. else
  31. rx_1 <= rx;
  32. //rx_2 <= rx_1
  33. always@(posedge clk or negedge rst_n)
  34. if(rst_n == 1'b0)
  35. rx_2<= 'd1;
  36. else
  37. rx_2 <= rx_1;
  38. //reg_rx <= rx_2
  39. always@(posedge clk or negedge rst_n)
  40. if(rst_n == 1'b0)
  41. reg_rx2<= 'd1;
  42. else
  43. reg_rx2 <= rx_2;
  44. //rx_flag
  45. always@(posedge clk or negedge rst_n)
  46. if(rst_n == 1'b0)
  47. rx_flag <= 1'b0;
  48. else if((!rx_2 && reg_rx2) == 1'b1)
  49. rx_flag <= 1'b1;
  50. else if(bit_cnt ==4'd8 && bit_flag == 1'b1)
  51. rx_flag <= 1'b0;
  52. //buad_cnt
  53. always@(posedge clk or negedge rst_n)
  54. if(rst_n == 1'b0)
  55. buad_cnt <= 13'd0;
  56. else if (buad_cnt == BUAD_CNT_MAX)
  57. buad_cnt <= 13'd0;
  58. else if (bit_cnt == 4'd8 && bit_flag == 1'b1)
  59. buad_cnt <= 13'd0;
  60. else if(rx_flag == 1'b1)
  61. buad_cnt <= buad_cnt + 1'b1;
  62. //bit_flag
  63. always@(posedge clk or negedge rst_n)
  64. if(rst_n == 1'b0)
  65. bit_flag <= 1'b0;
  66. else if(buad_cnt == BUAD_HALFCNT_MAX)
  67. bit_flag <= 1'b1;
  68. else
  69. bit_flag <= 1'b0;
  70. //bit_cnt
  71. always@(posedge clk or negedge rst_n)
  72. if(rst_n == 1'b0)
  73. bit_cnt <= 4'd0;
  74. else if (bit_cnt == 8 && bit_flag == 1'b1)
  75. bit_cnt <= 4'd0;
  76. else if(bit_flag == 1'b1)
  77. bit_cnt <= bit_cnt + 1'b1;
  78. //po_data
  79. always@(posedge clk or negedge rst_n)
  80. if(rst_n == 1'b0)
  81. po_data <= 8'd0;
  82. else if (bit_cnt >= 1 && bit_flag == 1'b1)
  83. po_data <= {rx_2,po_data[7:1]};
  84. //po_flag
  85. always@(posedge clk or negedge rst_n)
  86. if(rst_n == 1'b0)
  87. po_flag <= 1'b0;
  88. else if(bit_cnt == 8 && bit_flag == 1'b1)
  89. po_flag <= 1'b1;
  90. else
  91. po_flag <= 1'b0;
  92. endmodule

uart_tx

  1. // ----------------------------------------------------------
  2. // Copyright (c) 2014-2022 All rights reserved
  3. // ----------------------------------------------------------
  4. // Author : yongchan jeon (Kris) poucotm@gmail.com
  5. // File : urat_tx.v
  6. // Create : 2022-08-15 16:07:47
  7. // Revise : 2022-08-26 13:11:12
  8. // Editor : sublime text3, tab size (4)
  9. // ----------------------------------------------------------
  10. module uart_tx(
  11. input wire clk,
  12. input wire rst_n,
  13. input wire [7:0] pi_data,
  14. input wire pi_flag,
  15. output reg tx
  16. );
  17. parameter BUAD_CNT_MAX = 5207;
  18. reg [7:0] reg_data;
  19. reg tx_flag;
  20. reg [3:0] bit_cnt;
  21. reg bit_flag;
  22. reg [12:0] buad_cnt;
  23. //reg_data <= pi_data
  24. always@(posedge clk or negedge rst_n)
  25. if(rst_n == 1'b0)
  26. reg_data <= 8'd0;
  27. else if(pi_flag == 1'b1)
  28. reg_data <= pi_data;
  29. //tx_flag
  30. always@(posedge clk or negedge rst_n)
  31. if(rst_n == 1'b0)
  32. tx_flag <= 1'b0;
  33. else if(pi_flag == 1'b1)
  34. tx_flag <= 1'b1;
  35. else if (bit_cnt == 4'd8 && bit_flag == 1'b1)
  36. tx_flag <= 1'b0;
  37. //buad_cnt
  38. always@(posedge clk or negedge rst_n)
  39. if(rst_n == 1'b0)
  40. buad_cnt <= 13'd0;
  41. else if (buad_cnt == BUAD_CNT_MAX)
  42. buad_cnt <= 13'd0;
  43. else if(tx_flag == 1'b1)
  44. buad_cnt <= buad_cnt + 1'b1;
  45. //bit_flag
  46. always@(posedge clk or negedge rst_n)
  47. if(rst_n == 1'b0)
  48. bit_flag <= 1'b0;
  49. else if(buad_cnt == BUAD_CNT_MAX-1)
  50. bit_flag <= 1'b1;
  51. else
  52. bit_flag <= 1'b0;
  53. //bit_cnt
  54. always@(posedge clk or negedge rst_n)
  55. if(rst_n == 1'b0)
  56. bit_cnt <= 4'd0;
  57. else if (bit_cnt == 8 && bit_flag == 1'b1)
  58. bit_cnt <= 4'd0;
  59. else if(bit_flag == 1'b1)
  60. bit_cnt <= bit_cnt + 1'b1;
  61. //tx
  62. always@(posedge clk or negedge rst_n)
  63. if(rst_n == 1'b0)
  64. tx <= 1'd1;
  65. else if(pi_flag == 1'b1)
  66. tx <= 1'd0;
  67. else if(bit_cnt <= 4'd7 && bit_flag == 1'b1)
  68. tx <= reg_data[bit_cnt];
  69. else if(bit_cnt == 4'd8 && bit_flag == 1'b1)
  70. tx <= 1'b1;
  71. endmodule

top_fifo

  1. // ----------------------------------------------------------
  2. // Copyright (c) 2014-2022 All rights reserved
  3. // ----------------------------------------------------------
  4. // Author : yongchan jeon (Kris) poucotm@gmail.com
  5. // File : top_fifo.v
  6. // Create : 2022-08-24 07:52:07
  7. // Revise : 2022-08-24 07:52:07
  8. // Editor : sublime text3, tab size (4)
  9. // ---------------------------------------------------------
  10. module top_fifo(
  11. input wire clk,
  12. input wire rst_n,
  13. input wire rx,
  14. output wire tx
  15. );
  16. wire pi_flag;
  17. wire [7:0] pi_data;
  18. wire [7:0] po_data1;
  19. wire po_flag1;
  20. uart_tx inst_uart_tx (
  21. .clk (clk),
  22. .rst_n (rst_n),
  23. .pi_data (po_data1),
  24. .pi_flag (po_flag1),
  25. .tx (tx)
  26. );
  27. uart_rx inst_uart_rx (
  28. .clk (clk),
  29. .rst_n (rst_n),
  30. .rx (rx),
  31. .po_flag (pi_flag),
  32. .po_data (pi_data)
  33. );
  34. double_fifo_ctrl inst_double_fifo_ctrl(
  35. .clk (clk),
  36. .rst_n (rst_n),
  37. .pi_flag (pi_flag),
  38. .pi_data (pi_data),
  39. .po_flag (po_flag1),
  40. .po_sum (po_data1)
  41. );
  42. endmodule

testbench

  1. // ----------------------------------------------------------
  2. // Copyright (c) 2014-2022 All rights reserved
  3. // ----------------------------------------------------------
  4. // Author : yongchan jeon (Kris) poucotm@gmail.com
  5. // File : top_fifo.v
  6. // Create : 2022-08-24 07:52:07
  7. // Revise : 2022-08-24 07:52:07
  8. // Editor : sublime text3, tab size (4)
  9. // ---------------------------------------------------------------
  10. `timescale 1ns / 1ps
  11. module tb_top_fifo;
  12. // Inputs
  13. reg clk;
  14. reg rst_n;
  15. reg rx;
  16. reg [7:0] mem[85:0];
  17. // Outputs
  18. wire tx;
  19. // Instantiate the Unit Under Test (UUT)
  20. top_fifo uut (
  21. .clk(clk),
  22. .rst_n(rst_n),
  23. .rx(rx),
  24. .tx(tx)
  25. );
  26. initial begin
  27. // Initialize Inputs
  28. sclk = 0;
  29. rst_n = 0;
  30. rx = 1;
  31. // Wait 100 ns for global reset to finish
  32. #100;
  33. rst_n =1;
  34. // Add stimulus here
  35. end
  36. initial begin
  37. $readmemb("./data.txt",mem);
  38. end
  39. always #10 clk = ~clk;
  40. initial begin
  41. #200;
  42. rx_byte();
  43. end
  44. task rx_byte();
  45. integer i;
  46. integer j;
  47. begin
  48. for(j=0;j<86;j=j+1)begin
  49. for (i=0;i<86;i=i+1)begin
  50. rx_bit(mem[i]);
  51. end
  52. end
  53. end
  54. endtask
  55. task rx_bit(input [7:0] data);
  56. integer i;
  57. begin
  58. for(i=0;i<10;i=i+1) begin
  59. case (i)
  60. 0:rx =0;
  61. 1:rx =data[i-1];
  62. 2:rx =data[i-1];
  63. 3:rx =data[i-1];
  64. 4:rx =data[i-1];
  65. 5:rx =data[i-1];
  66. 6:rx =data[i-1];
  67. 7:rx =data[i-1];
  68. 8:rx =data[i-1];
  69. 9:rx =1;
  70. endcase
  71. #104160;
  72. end
  73. end
  74. endtask
  75. endmodule

data.txt

  1. 0000000
  2. 0000001
  3. 0000010
  4. 0000011
  5. 0000100
  6. 0000101
  7. 0000110
  8. 0000111
  9. 0001000
  10. 0001001
  11. 0001010
  12. 0001011
  13. 0001100
  14. 0001101
  15. 0001110
  16. 0001111
  17. 0010000
  18. 0010001
  19. 0010010
  20. 0010011
  21. 0010100
  22. 0010101
  23. 0010110
  24. 0010111
  25. 0011000
  26. 0011001
  27. 0011010
  28. 0011011
  29. 0011100
  30. 0011101
  31. 0011110
  32. 0011111
  33. 0100000
  34. 0100001
  35. 0100010
  36. 0100011
  37. 0100100
  38. 0100101
  39. 0100110
  40. 0100111
  41. 0101000
  42. 0101001
  43. 0101010
  44. 0101011
  45. 0101100
  46. 0101101
  47. 0101110
  48. 0101111
  49. 0110000
  50. 0110001
  51. 0110010
  52. 0110011
  53. 0110100
  54. 0110101
  55. 0110110
  56. 0110111
  57. 0111000
  58. 0111001
  59. 0111010
  60. 0111011
  61. 0111100
  62. 0111101
  63. 0111110
  64. 0111111
  65. 1000000
  66. 1000001
  67. 1000010
  68. 1000011
  69. 1000100
  70. 1000101
  71. 1000110
  72. 1000111
  73. 1001000
  74. 1001001
  75. 1001010
  76. 1001011
  77. 1001100
  78. 1001101
  79. 1001110
  80. 1001111
  81. 1010000
  82. 1010001
  83. 1010010
  84. 1010011
  85. 1010100
  86. 1010101

2.5、仿真结果

 2.5.1modelsim仿真结果

        

        由于仿真时间较长,对后面的数据抓取比较久,故这里用chipsope pro调试工具进行抓取,本次采用调用ip核打方式进行信号的添加(仅用modelsim仿真的要在double_fifo_ctrl中将icon和ila 的IP核的例化,以及信号的提取代码删除)

icon、ila例化以及要抓取信号代码:

  1. wire [35:0] CONTROL0;
  2. wire [50:0] TRIG0;
  3. assign TRIG0 = {
  4. po_sum,
  5. pi_flag,
  6. empty2,
  7. empty1,
  8. rd_en,
  9. cnt_col,
  10. cnt_row,
  11. add_flag,
  12. pi_data,
  13. dout1,
  14. dout2
  15. };
  16. cs_icon icon_inst (
  17. .CONTROL0(CONTROL0) // INOUT BUS [35:0]
  18. );
  19. cs_ila ila_inst (
  20. .CONTROL(CONTROL0), // INOUT BUS [35:0]
  21. .CLK(clk), // IN
  22. .TRIG0(TRIG0) // IN BUS [50:0]
  23. );

 2.5.2、ChipSocpe  Pro抓取

2.6、调试助手测试结果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/206762
推荐阅读
相关标签
  

闽ICP备14008679号