Xilinx FPGA:vivado实现乒乓缓存

一、项目要求

1、用两个伪双端口的RAM实现缓存

2、先写buffer1,再写buffer2 ,在读buffer1的同时写buffer2,在读buffer2的同时写buffer1。

3、写端口50M时钟,写入16个8bit 的数据,读出时钟25M,读出8个16bit 的数据。

二、信号转换图:

三、状态转换图:

四、程序设计:

先配置IP:

Matlab 复制代码
`timescale 1ns / 1ps
module ping_pang_1(
    input           sys_clk              ,
    input           rst_n               ,
    output  wire [15 : 0] doutb1 ,
    output  wire [15 : 0] doutb2 
    );
wire        clk_50M     ;
wire        clk_25M     ;
wire        locked      ;
wire        en          ;
assign      en = locked & rst_n;
  clk_wiz_0 instance_name
   (
    // Clock out ports
    .clk_50M(clk_50M),     // output clk_out1
    .clk_25M(clk_25M),     // output clk_out2
    // Status and control signals
    .resetn(rst_n), // input resetn
    .locked(locked),       // output locked
   // Clock in ports
    .sys_clk(sys_clk));      // input clk_in1
ram1
reg             wea1    ;
reg   [3 : 0] addra1  ;
reg   [7 : 0]  dina1   ;
reg             enb1    ;
reg   [2 : 0] addrb1  ;


ping_pang ram1 (
  .clka(clk_50M),    // input wire clka
  .ena(1),      // input wire ena
  .wea(wea1),      // input wire [0 : 0] wea
  .addra(addra1),  // input wire [3 : 0] addra
  .dina(dina1),    // input wire [7 : 0] dina
  .clkb(clk_25M),    // input wire clkb
  .enb(enb1),      // input wire enb
  .addrb(addrb1),  // input wire [2 : 0] addrb
  .doutb(doutb1)  // output wire [15 : 0] doutb
);
ram2
reg             wea2    ;
reg   [3 : 0] addra2  ;
reg   [7 : 0]  dina2   ;
reg             enb2    ;
reg   [2 : 0] addrb2  ;

ping_pang ram2 (
  .clka(clk_50M),    // input wire clka
  .ena(1),      // input wire ena
  .wea(wea2),      // input wire [0 : 0] wea
  .addra(addra2),  // input wire [3 : 0] addra
  .dina(dina2),    // input wire [7 : 0] dina
  .clkb(clk_25M),    // input wire clkb
  .enb(enb2),      // input wire enb
  .addrb(addrb2),  // input wire [2 : 0] addrb
  .doutb(doutb2)  // output wire [15 : 0] doutb
);
/状态机
localparam      IDLE  = 3'd0;
localparam      W1    = 3'd1;
localparam      W2_R1 = 3'd2;
localparam      W1_R2 = 3'd3;
reg     [2:0]   cur_state,next_state;
always@(posedge clk_50M)
    if(!rst_n)
        cur_state <= IDLE;
    else if(en)
        cur_state <= next_state;
    else
        cur_state <= IDLE;
always@(*)
    case(cur_state)
        IDLE  :begin
            next_state = W1;      
        end   
        W1    :begin
            if(addra1 == 14 && wea1)
                next_state = W2_R1;
            else
                next_state = cur_state;
        end
        W2_R1 :begin
            if(addra2 == 14 && wea2)
                next_state = W1_R2;
            else
                next_state = cur_state;
        end
        W1_R2 :begin
            if(addra1 == 14 && wea1)
                next_state = W2_R1;
            else
                next_state = cur_state;
        end
        default:;
    endcase
/写状态机
always@(posedge clk_50M)
    if(!rst_n)begin
          wea1 <= 0;   
        addra1 <= 0;
         dina1 <= 0;
          wea2 <= 0;   
        addra2 <= 0;
         dina2 <= 0;  
    end
    else
        case(cur_state)
            IDLE :begin
                
            end    
            W1   :begin
                if(addra1 == 15)
                    wea1 <= 0;
                else
                    wea1 <= 1;   
                if(wea1 == 1)
                    dina1 <= dina1 + 8'h27 ;
                else
                    dina1 <= 0;
                if(wea1 == 1 && addra1 == 15)
                    addra1 <= 0;
                else if(wea1 == 1) 
                    addra1 <= addra1 + 1;
                else
                    addra1 <= addra1;         
            end
            W2_R1:begin
                addra1 <= 0;
                wea1 <= 0;  /ram1的写使能关闭
                if(addra2 == 15)
                    wea2 <= 0;
                else
                    wea2 <= 1;   
                if(wea2 == 1)
                    dina2 <= dina2 + 8'h19 ;
                else
                    dina2 <= 0;
                if(wea2 == 1 && addra2 == 15)
                    addra2 <= 0;
                else if(wea2 == 1) 
                    addra2 <= addra2 + 1;
                else
                    addra2 <= 0;         
            end
            W1_R2:begin
                wea2 <= 0;
                addra2 <= 0;  
                if(addra1 == 15)
                    wea1 <= 0;
                else
                    wea1 <= 1;   
                if(wea1 == 1)
                    dina1 <= dina1 + 8'h27 ;
                else
                    dina1 <= 0;
                if(wea1 == 1 && addra1 == 15)
                    addra1 <= 0;
                else if(wea1 == 1) 
                    addra1 <= addra1 + 1;
                else
                    addra1 <= 0;    
            end
            default:;
        endcase
读状态机
always@(negedge clk_25M)
    if(!rst_n)begin
            enb1 <= 0;    
          addrb1 <= 0;
          enb2 <= 0;    
        addrb2 <= 0; 
    end
    else
        case(cur_state)
            IDLE  :begin
            
            end   
            W1    :begin
            
            end
            W2_R1 :begin
                enb2 <= 0; 
                addrb2 <= 0;
                if(addrb1 == 7 && enb1)
                    enb1 <= 0;
                else
                    enb1 <= 1;
                if(enb1 == 1 && addrb1 == 7)
                    addrb1 <= 0;
                else if(enb1)
                    addrb1 <= addrb1 + 1;
                else
                    addrb1 <= 0;    
            end
            W1_R2 :begin
                addrb1 <= 0; 
                enb1 <= 0;
                if(addrb2 == 7)
                    enb2 <= 0;
                else
                    enb2 <= 1;
                if(enb2 == 1 && addrb2 == 7)
                    addrb2 <= 0;
                else if(enb2)
                    addrb2 <= addrb2 + 1;
                else
                    addrb2 <= 0;    
            end
            default:;
        endcase
        
endmodule    

五、仿真设计

Matlab 复制代码
`timescale 1ns / 1ps
module test_ping_pang( );

        reg             sys_clk    ;
        reg             rst_n      ;
       wire[15:0]      doutb1     ;
       wire[15:0]      doutb2     ;
        
    initial
           begin
                sys_clk = 0 ;
                rst_n   = 0 ;
                #10
                rst_n   = 1 ;
           end    
        
     always #1 sys_clk = ~sys_clk ;   
        
    
ping_pang_1 ping_pang_1_1(
                      .   sys_clk ( sys_clk )   ,
                      .   rst_n   ( rst_n   )   , 
                      .  doutb1   (doutb1   )   ,
                      .  doutb2   (doutb2   )    
    );

endmodule

五、仿真结果

六、记录一些小问题:

(2)

(3)

所以修改思路就是尽量让enb1和enb2之间没有空隙,在时序上是衔接着的

相关推荐
小灰灰的FPGA1 小时前
低速接口项目之串口Uart开发(七)——如何在FPGA项目中实现自适应波特率串口功能
fpga开发
fei_sun20 小时前
【Verilog】第一章作业
fpga开发·verilog
深圳市雷龙发展有限公司longsto21 小时前
基于FPGA(现场可编程门阵列)的SD NAND图片显示系统是一个复杂的项目,它涉及硬件设计、FPGA编程、SD卡接口、NAND闪存控制以及图像显示等多个方面
fpga开发
9527华安1 天前
FPGA实现PCIE3.0视频采集转10G万兆UDP网络输出,基于XDMA+GTH架构,提供工程源码和技术支持
网络·fpga开发·udp·音视频·xdma·pcie3.0·万兆网
able陈1 天前
为什么verilog中递归函数需要定义为automatic?
fpga开发
fei_sun1 天前
【Verilog】第二章作业
fpga开发·verilog
碎碎思1 天前
如何使用 Vivado 从源码构建 Infinite-ISP FPGA 项目
fpga开发·接口隔离原则
江山如画,佳人北望1 天前
fpga-状态机的设计及应用
fpga开发
晓晓暮雨潇潇1 天前
Xilinx IP核(3)XADC IP核
fpga开发·vivado·xadc·ip核
CWNULT1 天前
AMD(Xilinx) FPGA配置Flash大小选择
fpga开发