FPGA|CPLD|ASIC论坛
直播中

Mr丶张1122

5年用户 3经验值
私信 关注
[问答]

关于AXI Lite无法正常握手的问题

关于AXI Lite的问题

为什么我写的AXI Lite在使用AXI Lite Slave IP的时候可以正常握手,但是在使用AXI Lite接口的BRAM的时候就没有办法正常握手了,我找不到问题在哪里,希望有大佬解答一下


使用AXI Lite Slave IP正常握手的样子


1F(CTK_0}KB1F(6H1N}O{9.png


使用AXI Lite Slave IP正常握手的样子

IU_E@@MW(H~IJ@@YAL7M.png

这个是我的BRAM IP配置

Snipaste_2025-07-16_18-42-35.png

Snipaste_2025-07-16_18-42-49.png

Snipaste_2025-07-16_18-42-57.png

Snipaste_2025-07-16_18-43-05.png

Snipaste_2025-07-16_18-43-11.png

Snipaste_2025-07-16_18-43-15.png


TOP层源码

`timescale 1ns / 1ps

module top
#(
	parameter	USER_ADDR_WIDTH	= 32						,	//用户地址位宽
	parameter	USER_DATA_WIDTH	= 32						,	//用户地址位宽
	parameter	AXI_ADDR_WIDTH	= 32						,	//AXI地址位宽
	parameter	AXI_DATA_WIDTH	= 32							//AXI数据位宽
)
(	
	input	wire							sys_rst_n		,
	input	wire							user_w_clk		,	//用户写时钟
	input	wire							user_r_clk		,	//用户读时钟
	input	wire							axi_clk			,	//AXI时钟

				/*		用户接口		 */
	//用户写通道	
	input	wire							user_w_en		,	//用户写使能
	input	wire	[USER_ADDR_WIDTH-1 : 0]	user_w_addr		,	//用户写地址
	input	wire	[USER_DATA_WIDTH-1 : 0]	user_w_data		,	//用户写数据
	input	wire							user_w_ready	,	//用户写准备好信号

	//用户读通道
	input	wire							user_r_en		,	//用户读使能
	input	wire	[USER_ADDR_WIDTH-1 : 0]	user_r_addr		,	//用户读地址
	output	wire	[USER_DATA_WIDTH-1 : 0]	user_r_data		,	//用户读地址
	output	wire							user_r_data_vid 	//用户读数据有效
);


wire	[32-1:0]	m_axi_aw_addr	;
wire				m_axi_aw_vid	;
wire				m_axi_aw_ready	;
wire	[2:0]		m_axi_aw_port	;
wire	[32-1:0]	m_axi_w_data	;
wire				m_axi_w_vid		;
wire				m_axi_w_ready	;
wire	[3:0]		m_axi_w_strb	;
wire				m_axi_b_resp	;
wire				m_axi_b_vid		;
wire				m_axi_b_ready	;
wire				wr_data_fifo_err;
wire				wr_cmd_fifo_err ;


wire	[32-1:0]	m_axi_ar_addr	;
wire				m_axi_ar_vid	;
wire				m_axi_ar_ready	;
wire	[2:0]		m_axi_ar_port	;
wire	[32-1:0]	m_axi_r_data	;
wire				m_axi_r_vid		;
wire				m_axi_r_ready	;
wire				m_axi_r_resp	;

axi_lite_write  inst_axi_lite_write
(
	.axi_clk        (	axi_clk			),
	.user_clk       (	user_w_clk		),
	.sys_rst_n      (	sys_rst_n		),
	.user_w_en      (	user_w_en		),
	.user_w_addr    (	user_w_addr		),
	.user_w_data    (	user_w_data		),
	.user_w_ready   (	user_w_ready	),
	.m_axi_aw_addr  (	m_axi_aw_addr	),
	.m_axi_aw_vid   (	m_axi_aw_vid	),
	.m_axi_aw_ready (	m_axi_aw_ready	),
	.m_axi_aw_port  (	m_axi_aw_port	),
	.m_axi_w_data   (	m_axi_w_data	),
	.m_axi_w_vid    (	m_axi_w_vid		),
	.m_axi_w_ready  (	m_axi_w_ready	),
	.m_axi_w_strb   (	m_axi_w_strb	),
	.m_axi_b_resp   (	m_axi_b_resp	),
	.m_axi_b_vid    (	m_axi_b_vid		),
	.m_axi_b_ready  (	m_axi_b_ready	)
);


axi_lite_read inst_axi_lite_read 
(
	.axi_clk         (	axi_clk			),
	.user_clk        (	axi_clk		),
	.sys_rst_n       (	sys_rst_n		),
	.user_r_en       (	user_r_en		),
	.user_r_addr     (	user_r_addr		),
	.user_r_data     (	user_r_data		),
	.user_r_data_vid (	user_r_data_vid	),
	.m_axi_ar_addr   (	m_axi_ar_addr	),
	.m_axi_ar_vid    (	m_axi_ar_vid	),
	.m_axi_ar_ready  (	m_axi_ar_ready	),
	.m_axi_ar_port   (	m_axi_ar_port	),
	.m_axi_r_data    (	m_axi_r_data	),
	.m_axi_r_vid     (	m_axi_r_vid		),
	.m_axi_r_ready   (	m_axi_r_ready	),
	.m_axi_r_resp    (	m_axi_r_resp	)
);

wire	rsta_busy;
wire	rstb_busy;

BRAM_w32xd1024 inst_BRAM_w32xd1024 (
  .rsta_busy		(	rsta_busy		),  // output wire rsta_busy
  .rstb_busy		(	rstb_busy		),  // output wire rstb_busy
  .s_aclk			(	axi_clk			),	// input wire s_aclk
  .s_aresetn		(	sys_rst_n		),	// input wire s_aresetn
  .s_axi_awaddr		(	m_axi_aw_addr	),  // input wire [31 : 0] s_axi_awaddr
  .s_axi_awvalid	(	m_axi_aw_vid	),  // input wire s_axi_awvalid
  .s_axi_awready	(	m_axi_aw_ready	),  // output wire s_axi_awready
  .s_axi_wdata		(	m_axi_w_data	),  // input wire [31 : 0] s_axi_wdata
  .s_axi_wstrb		(	m_axi_w_strb	),  // input wire [3 : 0] s_axi_wstrb
  .s_axi_wvalid		(	m_axi_w_vid		),  // input wire s_axi_wvalid
  .s_axi_wready		(	m_axi_w_ready	),  // output wire s_axi_wready
  .s_axi_bresp		(	m_axi_b_resp	),  // output wire [1 : 0] s_axi_bresp
  .s_axi_bvalid		(	m_axi_b_vid		),  // output wire s_axi_bvalid
  .s_axi_bready		(	m_axi_b_ready	),  // input wire s_axi_bready
  .s_axi_araddr		(	m_axi_ar_addr	),  // input wire [31 : 0] s_axi_araddr
  .s_axi_arvalid	(	m_axi_ar_vid	),  // input wire s_axi_arvalid
  .s_axi_arready	(	m_axi_b_ready	),  // output wire s_axi_arready
  .s_axi_rdata		(	m_axi_r_data	),  // output wire [31 : 0] s_axi_rdata
  .s_axi_rresp		(	m_axi_r_resp	),  // output wire [1 : 0] s_axi_rresp
  .s_axi_rvalid		(	m_axi_r_vid		),  // output wire s_axi_rvalid
  .s_axi_rready		(	m_axi_r_ready	)   // input wire s_axi_rready
);


// AXI_Lite_Slave AXI_Lite_Slave_inst
// (
// 	.s00_axi_awaddr	(	m_axi_aw_addr	),	// input wire [3 : 0] s00_axi_awaddr
// 	.s00_axi_awprot	(	m_axi_aw_port	),	// input wire [2 : 0] s00_axi_awprot
// 	.s00_axi_awvalid(	m_axi_aw_vid	),  // input wire s00_axi_awvalid
// 	.s00_axi_awready(	m_axi_aw_ready	),  // output wire s00_axi_awready
// 	.s00_axi_wdata	(	m_axi_w_data	),  // input wire [31 : 0] s00_axi_wdata
// 	.s00_axi_wstrb	(	m_axi_w_strb	),  // input wire [3 : 0] s00_axi_wstrb
// 	.s00_axi_wvalid	(	m_axi_w_vid		),  // input wire s00_axi_wvalid
// 	.s00_axi_wready	(	m_axi_w_ready	),  // output wire s00_axi_wready
// 	.s00_axi_bresp	(	m_axi_b_resp	),  // output wire [1 : 0] s00_axi_bresp
// 	.s00_axi_bvalid	(	m_axi_b_vid		),  // output wire s00_axi_bvalid
// 	.s00_axi_bready	(	m_axi_b_ready	),  // input wire s00_axi_bready
// 	.s00_axi_araddr	(	m_axi_ar_addr	),  // input wire [3 : 0] s00_axi_araddr
// 	.s00_axi_arprot	(	m_axi_ar_port	),  // input wire [2 : 0] s00_axi_arprot
// 	.s00_axi_arvalid(	m_axi_ar_vid	),  // input wire s00_axi_arvalid
// 	.s00_axi_arready(	m_axi_ar_ready	),  // output wire s00_axi_arready
// 	.s00_axi_rdata	(	m_axi_r_data	),  // output wire [31 : 0] s00_axi_rdata
// 	.s00_axi_rresp	(	m_axi_r_resp	),  // output wire [1 : 0] s00_axi_rresp
// 	.s00_axi_rvalid	(	m_axi_r_vid		),  // output wire s00_axi_rvalid
// 	.s00_axi_rready	(	m_axi_r_ready	),  // input wire s00_axi_rready
// 	.s00_axi_aclk	(	axi_clk			),  // input wire s00_axi_aclk
// 	.s00_axi_aresetn(	sys_rst_n		)   // input wire s00_axi_aresetn
// );

endmodule

AXI Lite Write写源码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/07/14 15:50:03
// Design Name: 
// Module Name: axi_lite_write
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module axi_lite_write
#(
	parameter	USER_ADDR_WIDTH	= 32						,	//用户地址位宽
	parameter	USER_DATA_WIDTH	= 32						,	//用户地址位宽
	parameter	AXI_ADDR_WIDTH	= 32						,	//AXI地址位宽
	parameter	AXI_DATA_WIDTH	= 32							//AXI数据位宽
)
(
	input	wire 							axi_clk			,
	input	wire							user_clk		,
	input	wire							sys_rst_n		,

				/*		用户接口		 */
	//用户写通道	
	input	wire							user_w_en		,	//用户写使能
	input	wire	[USER_ADDR_WIDTH-1 : 0]	user_w_addr		,	//用户写地址
	input	wire	[USER_DATA_WIDTH-1 : 0]	user_w_data		,	//用户写数据
	input	wire							user_w_ready	,	//用户写准备好信号


				/*AXI Lite Master接口*/
	//写地址通道
	output	wire	[AXI_ADDR_WIDTH-1 : 0]	m_axi_aw_addr	,	//AXI写地址
	output	wire							m_axi_aw_vid	,	//AXI写地址主机有效信号
	input	wire							m_axi_aw_ready	,	//AXI写地址从机准备好信号
	output	wire	[2:0]					m_axi_aw_port	,	//AXI保护类型,安全等级,默认保持为3'b000

	//写数据通道
	output	wire	[AXI_DATA_WIDTH-1 : 0]	m_axi_w_data	,	//AXI写数据
	output	wire							m_axi_w_vid		,	//AXI写数据主机有效信号
	input	wire							m_axi_w_ready	,	//AXI写数据从机准备好信号
	output	wire	[AXI_DATA_WIDTH/8-1:0]	m_axi_w_strb	,	//AXI写数据掩码信号

	//写响应通道
	input	wire							m_axi_b_resp	,	//AXI从机写响应信号
	input	wire							m_axi_b_vid		,	//AXI从机写响应有效信号
	output	wire							m_axi_b_ready		//AXI主机响应准备好信号
);

// localparam	ADDR_IDLE		= 0						;
// localparam	ADDR_PRE_WRITE	= 1						;
// localparam	ADDR_WRITE 		= 2						;
// localparam	ADDR_END 		= 3						;

reg							r_axi_aw_vid		;
reg							r_axi_w_vid			;

//用户复位同步信号
reg							user_rst_n_sync_d0	;
reg							user_rst_n_sync_d1	;
reg							user_rst_n			;

//AXI复位同步信号
reg							axi_rst_n_sync_d0	;
reg							axi_rst_n_sync_d1	;
reg							axi_rst_n			;

//FIFO变量
reg							fifo_addr_wr_en		;	//地址FIFO写使能
reg	[AXI_ADDR_WIDTH-1 : 0]	fifo_addr_din		;	//地址FIFO写数据
reg							fifo_addr_rd_en		;	//地址FIFO读使能
wire[AXI_ADDR_WIDTH-1 : 0]	fifo_addr_dout		;	//地址FIFO读数据
wire						fifo_addr_empty		;	//地址FIFO空信号
wire						fifo_addr_full		;	//地址FIFO满信号
wire[5:0]					fifo_rd_count		;	//地址FIFO读统计
wire[5:0]					fifo_wr_count		;	//地址FIFO写统计

reg							fifo_data_wr_en		;	//地址FIFO写使能
reg	[AXI_ADDR_WIDTH-1 : 0]	fifo_data_din		;	//地址FIFO写数据
reg							fifo_data_rd_en		;	//地址FIFO读使能
wire[AXI_ADDR_WIDTH-1 : 0]	fifo_data_dout		;	//地址FIFO读数据
wire						fifo_data_empty		;	//地址FIFO空信号
wire						fifo_data_full		;	//地址FIFO满信号
wire[5:0]					fifo_data_rd_count	;	//地址FIFO读统计
wire[5:0]					fifo_data_wr_count	;	//地址FIFO写统计


typedef enum logic [3:0] {
    ADDR_IDLE  		= 3'b000,
    ADDR_PRE_WRITE  = 3'b001,
    ADDR_WRITE 		= 3'b010,
    ADDR_END  		= 3'b100
} state_t;

state_t state_c, state_n;

// //状态机变量
// reg	[3:0]					state_c				;	
// reg	[3:0]					state_n				;

assign	m_axi_aw_port = 3'b0					;
assign	m_axi_aw_addr = fifo_addr_dout			;
assign	m_axi_aw_vid  = r_axi_aw_vid			;

assign	m_axi_w_strb  = 4'b0					;
assign	m_axi_w_data  = fifo_data_dout			;
assign	m_axi_w_vid   = r_axi_w_vid				;

assign	m_axi_b_ready = (fifo_wr_count>=28)?1'b0:1'b1;

/************************************************************************************\
								用户复位信号打拍处理
\************************************************************************************/
always @(posedge user_clk) begin
	user_rst_n_sync_d0 <= sys_rst_n;
	user_rst_n_sync_d1 <= user_rst_n_sync_d0;
	user_rst_n 		   <= user_rst_n_sync_d1;
end

/************************************************************************************\
								AXI复位信号打拍处理
\************************************************************************************/
always @(posedge user_clk) begin
	axi_rst_n_sync_d0 <= sys_rst_n;
	axi_rst_n_sync_d1 <= axi_rst_n_sync_d0;
	axi_rst_n 		   <= axi_rst_n_sync_d1;
end

/************************************************************************************\
								地址FIFO写使能信号 && 地址FIFO写入数据
\************************************************************************************/
always @(posedge user_clk or negedge user_rst_n) begin
	if(user_w_en)begin
		fifo_addr_wr_en <= 1'b1;
		fifo_data_wr_en <= 1'b1; 
		fifo_addr_din <= user_w_addr;
		fifo_data_din <= user_w_data;
	end
	else begin
		fifo_addr_wr_en <= 1'b0;
		fifo_data_wr_en <= 1'b0;
		fifo_addr_din   <= 'd0;
		fifo_data_din 	<= 'd0;
	end
end



/************************************************************************************\
								状态机第一段
\************************************************************************************/
always @(posedge axi_clk or negedge axi_rst_n) begin
    if (!user_rst_n) begin
        state_c <= ADDR_IDLE;       
    end
    else begin
        state_c <= state_n;
    end
end

/************************************************************************************\
								状态机第二段
\************************************************************************************/
always @(*) begin
    case (state_c) 
    	ADDR_IDLE	:	begin
    		if(!fifo_addr_empty) 
    			state_n = ADDR_PRE_WRITE;
    		else 
    			state_n = state_c;
    	end
    	ADDR_PRE_WRITE : begin
    		state_n = ADDR_WRITE;
    	end
    	ADDR_WRITE	: begin
    		if(m_axi_b_vid & m_axi_b_ready)
    			state_n = ADDR_END;
    		else 
    			state_n = state_c;
    	end
    	ADDR_END 	: begin
    		state_n = ADDR_IDLE;
    	end
    	default : state_n = ADDR_IDLE;
    endcase
end

/************************************************************************************\
								状态机第三段-----fifo_addr_rd_en
\************************************************************************************/
always @(posedge axi_clk or negedge axi_rst_n) begin 
	if(state_c == ADDR_PRE_WRITE)begin
		fifo_addr_rd_en <= 1'b1;
		fifo_data_rd_en	<= 1'b1;
	end
	else begin
		fifo_addr_rd_en <= 1'b0;
		fifo_data_rd_en	<= 1'b0;
	end
end

/************************************************************************************\
								状态机第三段-----r_axi_aw_vid
\************************************************************************************/
always @(posedge axi_clk or negedge axi_rst_n) begin 
	if(!axi_rst_n) begin
		r_axi_aw_vid <= 1'b0;
	end
	else if(m_axi_aw_vid & m_axi_aw_ready) begin
		r_axi_aw_vid <= 1'b0;
	end
	else if(state_c == ADDR_PRE_WRITE)begin
		r_axi_aw_vid <= 1'b1;
	end
	else begin
		r_axi_aw_vid <= r_axi_aw_vid;
	end
end

/************************************************************************************\
								状态机第三段-----r_axi_w_vid
\************************************************************************************/
always @(posedge axi_clk or negedge axi_rst_n) begin 
	if(!axi_rst_n) begin
		r_axi_w_vid <= 1'b0;
	end
	else if(m_axi_w_vid & m_axi_w_ready) begin
		r_axi_w_vid <= 1'b0;
	end
	else if(state_c == ADDR_PRE_WRITE)begin
		r_axi_w_vid <= 1'b1;
	end
	else begin
		r_axi_w_vid <= r_axi_w_vid;
	end
end


fifo_w32xd32 fifo_w32xd32_write_addr
(
	.wr_clk			(	user_clk			),  // input wire wr_clk
	.rd_clk			(	axi_clk				),  // input wire rd_clk
	.din			(	fifo_addr_din		),  // input wire [31 : 0] din
	.wr_en			(	fifo_addr_wr_en		),  // input wire wr_en
	.rd_en			(	fifo_addr_rd_en		),  // input wire rd_en
	.dout			(	fifo_addr_dout		),  // output wire [31 : 0] dout
	.full			(	fifo_addr_full		),  // output wire full
	.empty			(	fifo_addr_empty		),  // output wire empty
	.rd_data_count	(	fifo_rd_count		),  // output wire [4 : 0] rd_data_count
	.wr_data_count	(	fifo_wr_count		)   // output wire [4 : 0] wr_data_count
);

fifo_w32xd32 fifo_w32xd32_write_data
(
	.wr_clk			(	user_clk			),  // input wire wr_clk
	.rd_clk			(	axi_clk				),  // input wire rd_clk
	.din			(	fifo_data_din		),  // input wire [31 : 0] din
	.wr_en			(	fifo_data_wr_en		),  // input wire wr_en
	.rd_en			(	fifo_data_rd_en		),  // input wire rd_en
	.dout			(	fifo_data_dout		),  // output wire [31 : 0] dout
	.full			(	fifo_data_full		),  // output wire full
	.empty			(	fifo_data_empty		),  // output wire empty
	.rd_data_count	(	fifo_data_rd_count	),  // output wire [4 : 0] rd_data_count
	.wr_data_count	(	fifo_data_wr_count	)   // output wire [4 : 0] wr_data_count
);

endmodule

已退回1积分

更多回帖

发帖
×
20
完善资料,
赚取积分