当前位置:   article > 正文

Ram Based Shift Register Xilinx IP核仿真与理解_ram_base_shift

ram_base_shift

        在学习图像处理过程中,卷积模板和FIFO的运用是肯定离不开的,以彬哥的《基于MATLAB与FPGA的图像处理教程》里的腐蚀与膨胀知识点、帧差法运动目标检测为例。

        开运算在生成3x3的卷积模板的时候,就需要调用Xilinx官方IP核:FIFO Ganerator 和 Ram-based Shift Register。同步FIFO是将从VDMA IP核中读取到的AXI_Stream流数据信号进行缓存做帧差运算,调用这个IP核的目的是防止前面的数据还没有处理完,后面的数据就已经改变导致数据混乱发生错误。

        接下来只需要例化两次Shift Ram IP核,以菊花链的方式进行连接,作用等同于寄存帧差之后的两行数据,第三行的数据为输入的实时数据,就能够实现一个3x1的模板,Shift Ram IP核的数据位宽设置为1(因为之前的帧差结果是二值化数据,所以数据只会是0和1,同时能够节约一部分资源),深度设置为800(因为本人的tft显示屏是800*480,一行的像素数据是800个,根据具体情况而定),如下图所示:

         在例化完Ram-based Shift Register IP核和时序约束之后,我以为直接进行封装就能用了,因为说是0延迟,我也就没有进行仿真,但是其实是需要将IP核的输出寄存一拍之后才能对齐输入的帧差数据,要不然生成的3x3矩阵就是错误的。测试代码如下:

  1. module top( //顶层模块
  2. input clk,
  3. input rst_n,
  4. input CE, //时钟使能信号,在配置中可以打开,也可以关闭
  5. input [7:0]data,
  6. output [7:0]data1,
  7. output [7:0]data2
  8. );
  9. reg [7:0]data1_out; //寄存一拍后的数据
  10. reg [7:0]data2_out;
  11. wire [7:0]data1_r; //IP核输出数据
  12. wire [7:0]data2_r;
  13. c_shift_ram_0 c_shift_ram_u0 (
  14. .D(data),
  15. .CLK(clk),
  16. .CE(CE),
  17. .Q(data1_r)
  18. );
  19. c_shift_ram_0 c_shift_ram_u1 (
  20. .D(data1_r),
  21. .CLK(clk),
  22. .CE(CE),
  23. .Q(data2_r)
  24. );
  25. always@(posedge clk or negedge rst_n)begin //将数据寄存一拍
  26. if(!rst_n)begin
  27. data1_out <= 8'd0;
  28. data2_out <= 8'd0;
  29. end
  30. else begin
  31. data1_out <= data1_r;
  32. data2_out <= data2_r;
  33. end
  34. end
  35. assign data1 = data1_out;
  36. assign data2 = data2_out;
  37. endmodule

 

  1. `timescale 1ns / 1ps
  2. `define clk_period 20
  3. module top_tb(); //testbench模块
  4. reg clk;
  5. reg rst_n;
  6. reg ce;
  7. reg [7:0]data ;
  8. wire [7:0]data1;
  9. wire [7:0]data2;
  10. top top_u(
  11. .clk (clk),
  12. .rst_n (rst_n),
  13. .CE (ce),
  14. .data (data),
  15. .data1 (data1),
  16. .data2 (data2)
  17. );
  18. initial clk = 1;
  19. always#(`clk_period/2) clk = ~clk;
  20. integer i;
  21. initial begin
  22. rst_n = 1'b0;
  23. data = 8'd0;
  24. ce = 1'b0;
  25. #(`clk_period*200);
  26. rst_n = 1'b1;
  27. #(`clk_period*50);
  28. ce = 1'b1; //这里会有一个小bug,后面再解释
  29. for(i=1;i<400;i=i+1)begin //连续输入400个数据
  30. data = 8'd0 + i;
  31. #(`clk_period);
  32. end
  33. #200;
  34. ce = 1'b0;
  35. $stop;
  36. end
  37. endmodule

  

错误仿真波形

        在这里发现数据是对齐的,但是data2的第一个数据是从2开始的,这就明显是错误的,其实就是我的基础不是太牢固,在testbench中 ce 信号拉高之后我就紧跟着开始输入了数据,这时候在下一个时钟的上升沿才开始把输入数据传进Shift Ram IP核,所以开始的数据就变成了2而不是1。只要在拉高ce之后再延迟一个时钟周期就能解决这个问题(不是卖关子,只是记录一下自己平常会犯的错)。

 

正确仿真波形

 

 

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

闽ICP备14008679号