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
本文章仅用于学习记录