xilinx中ddr3仿真出现tRFC maximum violation during No Op问题

1、问题描述

在调用DDR3仿真模型时出现该问题,WREADY拉高的长度与实际需要突发的长度不匹配,还可以观察到此时打印窗口的行列,bank的值都是X。

2、问题排查

        第一步:怀疑AXI总线操作违规,阅读手册后发现使用是正确的

        第二步:使用BRAM替代DDR3仿真模型,进行AXI总线时序仿真,(这一步是请教大佬得到的经验),仿真无误后确定AXI时序操作正常

        第三步:问题此时就剩下DDR3器件模型本身,将DDR3的信号拉出来观察发现地址位宽不匹配,修改与AXI读写DMA一致后解决问题

3、分享一个将AXI的读写DDR3操作封装成FIFO接口的模块,此版本仅为第一版本,后面使用时发现有问题会不断的迭代

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/10/02 15:12:08
// Design Name: 
// Module Name: MIG_AXI_Drive
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module MIG_AXI_Drive #(
		parameter           C_M_TARGET_SLAVE_BASE_ADDR	= 32'h40000000      ,
		parameter integer   C_M_AXI_BURST_LEN	        = 16                ,
		parameter integer   C_M_AXI_ID_WIDTH	        = 1                 ,
		parameter integer   C_M_AXI_ADDR_WIDTH	        = 32                ,
		parameter integer   C_M_AXI_DATA_WIDTH	        = 32                ,
		parameter integer   C_M_AXI_AWUSER_WIDTH	    = 0                 ,
		parameter integer   C_M_AXI_ARUSER_WIDTH	    = 0                 ,
		parameter integer   C_M_AXI_WUSER_WIDTH	        = 0                 ,
		parameter integer   C_M_AXI_RUSER_WIDTH	        = 0                 ,
		parameter integer   C_M_AXI_BUSER_WIDTH	        = 0                 
)(  
		input  wire                                 M_AXI_ACLK              ,
		input  wire                                 M_AXI_ARESETN           ,
        input  wire                                 i_init_calib_complete   ,
        //--------用户写接口--------//
        input  wire [8 : 0]                         i_wr_len                ,
        input  wire [C_M_AXI_ADDR_WIDTH-1   : 0]    i_wr_addr               ,
        input  wire                                 i_wr_valid              ,
        output wire                                 o_wr_ready              ,
        
        input  wire [C_M_AXI_DATA_WIDTH-1   : 0]    i_wr_data               ,
        output wire                                 o_wr_req                ,
        //--------用户读接口--------//
        input  wire [8 : 0]                         i_rd_len                ,
        input  wire [C_M_AXI_ADDR_WIDTH-1   : 0]    i_rd_addr               ,
        input  wire                                 i_rd_valid              ,
        output wire                                 o_rd_ready              ,
        
        output wire [C_M_AXI_DATA_WIDTH-1   : 0]    o_rd_data               ,
        output wire                                 o_rd_valid              ,
        //--------AXI写地址--------//
		output wire [C_M_AXI_ID_WIDTH-1     : 0]    M_AXI_AWID              ,
		output wire [C_M_AXI_ADDR_WIDTH-1   : 0]    M_AXI_AWADDR            ,
		output wire [7 : 0]                         M_AXI_AWLEN             ,
		output wire [2 : 0]                         M_AXI_AWSIZE            ,
		output wire [1 : 0]                         M_AXI_AWBURST           ,
		output wire                                 M_AXI_AWLOCK            ,   
		output wire [3 : 0]                         M_AXI_AWCACHE           ,
		output wire [2 : 0]                         M_AXI_AWPROT            ,
		output wire [3 : 0]                         M_AXI_AWQOS             ,
		output wire [C_M_AXI_AWUSER_WIDTH-1 : 0]    M_AXI_AWUSER            ,
		output wire                                 M_AXI_AWVALID           ,
		input  wire                                 M_AXI_AWREADY           ,
        //--------AXI写数据--------//  
		output wire [C_M_AXI_DATA_WIDTH-1   : 0]    M_AXI_WDATA             ,
		output wire [C_M_AXI_DATA_WIDTH/8-1 : 0]    M_AXI_WSTRB             ,
		output wire                                 M_AXI_WLAST             ,
		output wire [C_M_AXI_WUSER_WIDTH-1  : 0]    M_AXI_WUSER             ,
		output wire                                 M_AXI_WVALID            ,
		input  wire                                 M_AXI_WREADY            ,
        //--------AXI写响应--------//  
		input  wire [C_M_AXI_ID_WIDTH-1     : 0]    M_AXI_BID               ,
		input  wire [1 : 0]                         M_AXI_BRESP             ,
		input  wire [C_M_AXI_BUSER_WIDTH-1  : 0]    M_AXI_BUSER             ,
		input  wire                                 M_AXI_BVALID            ,
		output wire                                 M_AXI_BREADY            ,
        //--------AXI读地址--------//  
		output wire [C_M_AXI_ID_WIDTH-1     : 0]    M_AXI_ARID              ,
		output wire [C_M_AXI_ADDR_WIDTH-1   : 0]    M_AXI_ARADDR            ,
		output wire [7 : 0]                         M_AXI_ARLEN             ,
		output wire [2 : 0]                         M_AXI_ARSIZE            ,
		output wire [1 : 0]                         M_AXI_ARBURST           ,
		output wire                                 M_AXI_ARLOCK            ,
		output wire [3 : 0]                         M_AXI_ARCACHE           ,
		output wire [2 : 0]                         M_AXI_ARPROT            ,
		output wire [3 : 0]                         M_AXI_ARQOS             ,
		output wire [C_M_AXI_ARUSER_WIDTH-1 : 0]    M_AXI_ARUSER            ,
		output wire                                 M_AXI_ARVALID           ,
		input  wire                                 M_AXI_ARREADY           ,
        //--------AXI读数据和读响应--------//  
		input  wire [C_M_AXI_ID_WIDTH-1     : 0]    M_AXI_RID               ,
		input  wire [C_M_AXI_DATA_WIDTH-1   : 0]    M_AXI_RDATA             ,
		input  wire [1 : 0]                         M_AXI_RRESP             ,
		input  wire                                 M_AXI_RLAST             ,
		input  wire [C_M_AXI_RUSER_WIDTH-1  : 0]    M_AXI_RUSER             ,
		input  wire                                 M_AXI_RVALID            ,
		output wire                                 M_AXI_RREADY    
);

/***************function**************/
function integer clogb2(input integer bit_depth);
begin 
    for(clogb2=0;bit_depth>0;clogb2=clogb2+1)
        bit_depth = bit_depth >> 1;
end 
endfunction
/***************parameter*************/

/***************port******************/             

/***************mechine***************/

/***************reg*******************/
reg                                 ro_wr_ready              ;
reg [8 : 0]                         ri_wr_len                ;
reg [C_M_AXI_ADDR_WIDTH-1   : 0]    ri_wr_addr               ;
reg                                 ro_aw_valid              ;
reg                                 ro_w_valid               ;
reg                                 ro_w_last                ;
reg [15: 0]                         r_wr_index               ; 
reg                                 ro_w_bready              ;
reg                                 ro_rd_ready              ;
reg                                 ro_arvalid               ;
reg [8 : 0]                         ri_rd_len                ;
reg [C_M_AXI_ADDR_WIDTH-1   : 0]    ri_rd_addr               ;
reg                                 ro_rready                ;
reg [C_M_AXI_DATA_WIDTH-1   : 0]    ro_rd_data               ;
reg                                 ro_rd_valid              ;
reg                                 r_w_ready_lock           ;
reg [C_M_AXI_ADDR_WIDTH-1   : 0]    ro_awaddr                ;
reg [7 : 0]                         ro_awlen                 ;  
reg                                 r_r_ready_lock           ;   
reg [C_M_AXI_ADDR_WIDTH-1   : 0]    ro_rwaddr                ;
reg [7 : 0]                         ro_rwlen                 ;                           

/***************wire******************/
wire                                w_wr_op_act              ;
wire                                w_aw_act                 ;
wire                                w_w_act                  ;
wire                                w_wb_act                 ;
wire                                w_ra_act                 ;
wire                                w_r_act                  ;
wire                                w_rd_op_act              ;
wire                                w_init_pose              ;
/***************component*************/

/***************assign****************/
assign o_wr_ready = ro_wr_ready ;
assign w_wr_op_act= i_wr_valid & o_wr_ready;
//写地址通道
assign M_AXI_AWID   = 'b0           ;
assign M_AXI_AWADDR = ro_awaddr     ;
assign M_AXI_AWLEN  = ro_awlen      ;
assign M_AXI_AWSIZE = clogb2(C_M_AXI_DATA_WIDTH/8 -1);
assign M_AXI_AWBURST= 2'b01;//地址递增
assign M_AXI_AWLOCK = 'b0;
assign M_AXI_AWCACHE= 4'b0010;//无缓存
assign M_AXI_AWPROT = 'b0;
assign M_AXI_AWQOS  = 'b0;
assign M_AXI_AWUSER = 'b0;
assign M_AXI_AWVALID= ro_aw_valid   ;
assign w_aw_act     = M_AXI_AWVALID & M_AXI_AWREADY;
//写数据通道
assign o_wr_req     = (w_aw_act) | (w_w_act);
assign M_AXI_WVALID = ro_w_valid;
assign w_w_act      = M_AXI_WVALID & M_AXI_WREADY;
assign M_AXI_WLAST  = ro_w_last;
assign M_AXI_WSTRB  = {C_M_AXI_DATA_WIDTH/8{1'b1}};
assign M_AXI_WUSER  = 'b0;
assign M_AXI_WDATA  = i_wr_data;
//写响应通道
assign M_AXI_BREADY = ro_w_bready;
assign w_wb_act     = M_AXI_BVALID && M_AXI_BREADY && (M_AXI_BRESP == 2'b00);
//读地址通道
assign w_rd_op_act  = i_rd_valid & o_rd_ready;
assign w_ra_act     = M_AXI_ARVALID & M_AXI_ARREADY;
assign M_AXI_ARVALID= ro_arvalid;
assign M_AXI_ARID   = 'd0;
assign M_AXI_ARADDR = ro_rwaddr;
assign M_AXI_ARLEN  = ro_rwlen;
assign M_AXI_ARSIZE = clogb2(C_M_AXI_DATA_WIDTH/8 -1);
assign M_AXI_ARBURST= 2'b01;//地址递增
assign M_AXI_ARLOCK = 'd0;
assign M_AXI_ARCACHE= 4'b0010;//无缓存
assign M_AXI_ARPROT = 'b0;
assign M_AXI_ARQOS  = 4'b0;
assign M_AXI_ARUSER = 'b0;
assign o_rd_ready   = ro_rd_ready;
//读响应通道
assign w_r_act      = M_AXI_RVALID && M_AXI_RREADY && (M_AXI_RRESP == 2'b00);
assign M_AXI_RREADY = ro_rready;
assign o_rd_data    = ro_rd_data ;
assign o_rd_valid   = ro_rd_valid;

/***************always****************/

//写地址
always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        ro_wr_ready <= 1'b0;
    else if(w_aw_act)
        ro_wr_ready <= 1'b0;
    else if((M_AXI_AWREADY & i_init_calib_complete & !r_w_ready_lock) || w_wb_act)
        ro_wr_ready <= 1'b1;
    else 
        ro_wr_ready <= ro_wr_ready;
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN) begin 
        ro_awaddr <= 'd0;
        ro_awlen  <= 'd0;
    end else if(w_wr_op_act)begin 
        ro_awaddr <= i_wr_addr; 
        ro_awlen  <= i_wr_len-1;
    end else begin 
        ro_awaddr <= ro_awaddr;
        ro_awlen  <= ro_awlen;  
    end 
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        r_w_ready_lock <= 1'b0;
    else if(w_wb_act)
        r_w_ready_lock <= 1'b0;
    else if(M_AXI_AWREADY & i_init_calib_complete)
        r_w_ready_lock <= 1'b1;
    else 
        r_w_ready_lock <= r_w_ready_lock;
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN) begin 
        ri_wr_len  <= 'd0;
        ri_wr_addr <= 'd0;
    end else if(w_wr_op_act) begin 
        ri_wr_len  <= i_wr_len ;
        ri_wr_addr <= i_wr_addr;
    end else begin 
        ri_wr_len  <= ri_wr_len ;
        ri_wr_addr <= ri_wr_addr;
    end 
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        ro_aw_valid <= 1'b0;
    else if(w_aw_act)
        ro_aw_valid <= 1'b0;
    else if(!ro_aw_valid & w_wr_op_act)
        ro_aw_valid <= 1'b1;
    else 
        ro_aw_valid <= ro_aw_valid;
end 

//写数据
always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        ro_w_valid <= 1'b0;
    else if(w_aw_act)
        ro_w_valid <= 1'b1;
    else if(w_w_act & ro_w_last)
        ro_w_valid <= 1'b0;
    else 
        ro_w_valid <= ro_w_valid;
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        r_wr_index <= 'd0;
    else if(w_w_act & ro_w_last)
        r_wr_index <= 'd0;
    else if(w_w_act)
        r_wr_index <= r_wr_index + 1'b1;
    else 
        r_wr_index <= r_wr_index;
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        ro_w_last <= 1'b0;
    else if(w_w_act && (r_wr_index == ri_wr_len - 1))
        ro_w_last <= 1'b0;
    else if(w_w_act && (r_wr_index == ri_wr_len - 2))
        ro_w_last <= 1'b1;
    else 
        ro_w_last <= ro_w_last;
end 

//写响应
always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        ro_w_bready <= 1'b0;
    else if(w_wb_act)
        ro_w_bready <= 1'b0;
    else if(ro_w_last)
        ro_w_bready <= 1'b1;
    else 
        ro_w_bready <= ro_w_bready;
end 

//读地址
always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        ro_rd_ready <= 1'b0;
    else if(w_ra_act)
        ro_rd_ready <= 1'b0;
    else if((M_AXI_ARREADY & i_init_calib_complete & !r_r_ready_lock) || (w_r_act & M_AXI_RLAST))
        ro_rd_ready <= 1'b1;
    else 
        ro_rd_ready <= ro_rd_ready;
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN) begin 
        ro_rwaddr <= 'd0; 
        ro_rwlen  <= 'd0;
    end else if(w_rd_op_act) begin 
        ro_rwaddr <= ri_rd_addr;
        ro_rwlen  <= ri_rd_len-1;
    end else begin 
        ro_rwaddr <= ro_rwaddr; 
        ro_rwlen  <= ro_rwlen ; 
    end 
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        r_r_ready_lock <= 1'b0;
    else if(w_r_act & M_AXI_RLAST)
        r_r_ready_lock <= 1'b0;
    else if(M_AXI_ARREADY & i_init_calib_complete)
        r_r_ready_lock <= 1'b1;
    else 
        r_r_ready_lock <= r_r_ready_lock;
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN) begin 
        ri_rd_len  <= 'd0;
        ri_rd_addr <= 'd0;
    end else if(w_rd_op_act) begin 
        ri_rd_len  <= i_rd_len ;
        ri_rd_addr <= i_rd_addr;
    end else begin 
        ri_rd_len  <= ri_rd_len ;
        ri_rd_addr <= ri_rd_addr;
    end 
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        ro_arvalid <= 1'b0;
    else if(w_ra_act)
        ro_arvalid <= 1'b0;
    else if(w_rd_op_act && M_AXI_ARREADY)
        ro_arvalid <= 1'b1;
    else 
        ro_arvalid <= ro_arvalid;
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
        ro_rready <= 1'b0;
    else if(w_r_act & M_AXI_RLAST)
        ro_rready <= 1'b0;
    else if(w_ra_act)
        ro_rready <= 1'b1;
    else 
        ro_rready <= ro_rready;
end 

always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN) begin 
        ro_rd_data  <= 'd0;
        ro_rd_valid <= 'd0;
    end else begin 
        ro_rd_data  <= M_AXI_RDATA;
        ro_rd_valid <= w_r_act;
    end 
end 

/* always@(posedge M_AXI_ACLK,negedge M_AXI_ARESETN)
begin 
    if(!M_AXI_ARESETN)
    
    else if()
    
    else if()
    
    else 

end 
 */

endmodule

本文章仅用于学习记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值