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之间没有空隙,在时序上是衔接着的

相关推荐
nanxl140 分钟前
FPGA-DDS信号发生器
fpga开发·verilog·vivado
黄埔数据分析3 小时前
RecoNIC 入门:SmartNIC 上支持 RDMA 的计算卸载-FPGA-智能网卡-AMD-Xilinx
fpga开发
nanxl15 小时前
FPGA-数字时钟
fpga开发·verilog·vivado
尤老师FPGA18 小时前
LVDS系列9:Xilinx 7系可编程输入延迟(二)
单片机·嵌入式硬件·fpga开发
内有小猪卖1 天前
时序约束 记录
fpga开发
Cao1234567893211 天前
FPGA时钟设计
fpga开发
JNTeresa1 天前
锁存器知识点详解
fpga开发
Cao1234567893211 天前
FPGA基础之基础语法
fpga开发
一大Cpp1 天前
通过Quartus II实现Nios II编程
fpga开发
7yewh1 天前
Verilog 语法 (二)
fpga开发