AXI Uartlite IP AXI驱动代码

说明:AXI Uartlite IP AXI驱动代码

根据博客:Xilinx AXI Uartlite IP核的使用
有问题联系微信:Crazzy_M

效果简单展示:
在这里插入图片描述
在这里插入图片描述

module uart
#
(
	parameter	UART_REG_NUM     = 2		
)
(

    input       s_axi_aclk,
    input       s_axi_aresetn,
    input       rx,
    
	output		tx,
	output		interrupt,
    output[7:0] uart_rdata
);
/*******************************************************************************
    AXI读-数据提取
*******************************************************************************/  

//CMD
`define					AXI_IDLE 	2'b00
`define					AXI_R		2'b10
`define					AXI_W		2'b01

//写地址
wire  [3:0]           	s_axi_awaddr  ;  //input 	主机写地址
wire                  	s_axi_awvalid ;  //input	主机写地址有效
wire                  	s_axi_awready ;  //output	从机准备接收写地址
//写数据                                
wire  [31:0]           	s_axi_wdata   ;  //input 	主机写数据
wire  [3:0]           	s_axi_wstrb   ;  //input 	
wire                  	s_axi_wvalid  ;  //input 	主机写数据有效
wire                 	s_axi_wready  ;  //output	从机准备接收写数据
//写响应                               ; 
wire [1:0]           	s_axi_bresp   ;  //output	从机写响应
wire                  	s_axi_bvalid  ;  //output	从机写入响应有效
wire                 	s_axi_bready  ;  //input 	主机响应准备就绪
//读地址                                
reg  [3:0]          	s_axi_araddr  ;  //input 	主机读地址
reg                  	s_axi_arvalid ;  //input 	主机读地址有效
wire                 	s_axi_arready ;  //output	从机准备接收读地址
//读数据                               
wire [31:0]          	s_axi_rdata   ;  //output	从机返回的数据
wire [1:0]           	s_axi_rresp   ;  //output	
wire                  	s_axi_rvalid  ;  //output	从机返回数据有效
reg                 	s_axi_rready  ;  //input 	主机准备接收数据



assign					s_axi_wstrb = 4'b1111;

/*******************************************************************************
    AXI读写测试
*******************************************************************************/ 	
//测试地址

reg	[3:0]			user_raddr;	//用户读地址
reg	[3:0]			user_waddr;	//用户写地址
reg	[31:0]			user_wdata;	//用户数据
reg	[1:0]			AXI_CMD;	//1读0写
	
reg	[2:0]			AXI_STATE;
localparam			AXI_IDLE	= 3'd0	,
					AXI_RD0		= 3'd1	,	//初始化读取
					AXI_WD		= 3'd2	,	//写数据
					AXI_WDWAIT	= 3'd3	,	//写等待
					AXI_WDONE	= 3'd4	,	//检测AXI是否配置完成
					AXI_RDWAIT	= 3'd5	,	//读等待
					AXI_RD1		= 3'd6	;	//读数据
					
					
					
reg	[7:0]			mem_cnt		= 8'd0	;//用来寄存器配置

wire    [35:0]      cfg_mem[UART_REG_NUM-1:0];

assign cfg_mem[  0] = { 4'h0C,32'h0000_001F                            };
assign cfg_mem[  1] = { 4'h04,32'h0000_00AA                            };

reg		[7:0]		del_cnt;

/*******************************************************************************
   m_axi_aclk
*******************************************************************************/  
always@(posedge	s_axi_aclk or negedge s_axi_aresetn)
begin
	if(!s_axi_aresetn)
	begin
		AXI_STATE		<= AXI_IDLE;
		AXI_CMD			<= `AXI_IDLE ;
		mem_cnt			<= 8'd0;
		del_cnt			<= 8'd0;
	end
	else					
	begin							//代码配置模式
		case(AXI_STATE)
			AXI_IDLE:begin							
						AXI_STATE		<= AXI_RD0;
				end
			AXI_RD0	:begin
						AXI_CMD			<= `AXI_R;										
						user_raddr		<= 4'h8;										
						AXI_STATE		<= (s_axi_rvalid ==1'b1)?AXI_WD:AXI_RD0;		
				end
			AXI_WD	:begin
						AXI_CMD			<= `AXI_W;										
						mem_cnt			<= (s_axi_bvalid==1'b1)?((mem_cnt < UART_REG_NUM-1 )?mem_cnt +1'b1 : 8'd0):mem_cnt;
						{user_waddr,user_wdata} <= cfg_mem[mem_cnt];				    
						AXI_STATE		<= (s_axi_bvalid==1'b1)?AXI_WDWAIT : AXI_WD;	
				end
			AXI_WDWAIT:begin
						del_cnt			<= (del_cnt==8'd2)?8'd0:del_cnt+8'd1;
						{user_waddr,user_wdata} <= cfg_mem[mem_cnt];									
						AXI_CMD         <= (mem_cnt==8'd0)?`AXI_IDLE : `AXI_W;
						AXI_STATE		<= (del_cnt==8'd2)?((mem_cnt==8'd0)?AXI_WDONE : AXI_WD):AXI_WDWAIT;						
				end
			AXI_WDONE:begin
						AXI_CMD			<= `AXI_R;										
						user_raddr		<= 4'h0;
						AXI_STATE		<= (s_axi_rvalid ==1'b1)?AXI_RDWAIT:AXI_WDONE;
				end			
			AXI_RDWAIT:begin																
						AXI_CMD			<= `AXI_IDLE;	
						AXI_STATE		<= AXI_RD1;								
				end
			AXI_RD1	:begin
						AXI_CMD			<= `AXI_R;						
						user_raddr		<= 4'h0;
						AXI_STATE		<= (s_axi_rvalid ==1'b1)?AXI_RD1:AXI_RD1;						
				end
		endcase
	end	

end
/*******************************************************************************
    AXI读
*******************************************************************************/  
//状态机
reg		[1:0]	AXI_R_STATE		= 2'd0 	;
localparam		AXI_R_ADD		= 2'd0	,			//读地址
				AXI_R_DATA		= 2'd1	,			//读数据
				AXI_R_DONE		= 2'd2	;			//读完成

//读取的数据
reg		[31:0]	rdata			= 32'd0 ;
assign	uart_rdata				= rdata[7:0];


//读地址
always@(posedge	s_axi_aclk or negedge s_axi_aresetn)
begin
	if(!s_axi_aresetn)
	begin
		AXI_R_STATE		<= AXI_R_ADD;
		s_axi_arvalid   <= 1'b0;	
		s_axi_araddr	<= 4'h000;
		s_axi_rready	<= 1'b0;
	end
	else if(AXI_CMD == `AXI_R)
	begin
		case(AXI_R_STATE)	
			AXI_R_ADD :begin	
						s_axi_araddr 	<= user_raddr ;					
						s_axi_arvalid 	<= 1'b1;						
						AXI_R_STATE 	<= (s_axi_arready==1'b1)? AXI_R_DATA : AXI_R_ADD;
				end	
			AXI_R_DATA:begin
						s_axi_araddr	<= 4'h000;
						s_axi_arvalid	<= 1'b0;
						s_axi_rready	<= 1'b1;
						AXI_R_STATE 	<= (s_axi_rvalid ==1'b1)? AXI_R_DONE : AXI_R_DATA;
				end
			AXI_R_DONE :begin
						s_axi_rready	<= 1'b0;
						AXI_R_STATE		<=	AXI_R_ADD;
				end
		endcase
	end
	else
		AXI_R_STATE		<= AXI_R_ADD;
end

always@(negedge	s_axi_aclk or negedge s_axi_aresetn)
begin
	if(!s_axi_aresetn)
		rdata <= 32'd0;
	else
		rdata <= (s_axi_rvalid == 1)?s_axi_rdata : rdata;
end



/*******************************************************************************
    AXI写
*******************************************************************************/  
//状态机
reg		[2:0]	AXI_W_STATE		= 3'd0 	;
localparam		AXI_W_IDLE		= 3'd0	,		//写
				AXI_W_ADD		= 3'd1	,		//写地址
				AXI_W_DATA		= 3'd2	,		//写数据
				AXI_W_ACK		= 3'd3	,		//写响应
				AXI_W_DONE		= 3'd4	;		//写操作完成

				
reg	[11:0]		s_axi_awaddr_r	= 4'h000;		
reg	[31:0]		s_axi_wdata_r	= 32'h0000_0000;
reg				s_axi_awvalid_r	= 1'b0;
reg				s_axi_wvalid_r	= 1'b0;
reg				s_axi_bready_r	= 1'b0;
always@(posedge	s_axi_aclk or negedge s_axi_aresetn)
begin
	if(!s_axi_aresetn)
	begin
		AXI_W_STATE		<= AXI_W_IDLE;
		s_axi_awvalid_r	<=1'b0;
		s_axi_awaddr_r	<=4'h000;
		s_axi_wvalid_r	<=1'b0;
		s_axi_wdata_r	<=32'h0000_0000;
		s_axi_bready_r	<=1'b0;
	end
	else if(AXI_CMD == `AXI_W)
	begin
		case(AXI_W_STATE)
			AXI_W_IDLE :begin
						AXI_W_STATE		<= AXI_W_ADD;
						s_axi_awvalid_r	<=1'b0;
						s_axi_awaddr_r	<=4'h000;
						s_axi_wvalid_r	<=1'b0;
						s_axi_wdata_r	<=32'h0000_0000;
						s_axi_bready_r	<=1'b0;
				end
			AXI_W_ADD  :begin
						s_axi_awvalid_r	<= (s_axi_awready==1)?1'b0:1'b1;
						s_axi_awaddr_r	<= (s_axi_awready==1)?4'h000:user_waddr;	//****	
						
						s_axi_wvalid_r	<= 1'b1;
						s_axi_wdata_r	<= user_wdata;						
						AXI_W_STATE		<= (s_axi_awready==1)?AXI_W_DATA:AXI_W_ADD;
				end	
			AXI_W_DATA	:begin
						s_axi_wvalid_r	<= 1'b0;
						s_axi_wdata_r	<= 32'h0000_0000;//***
						AXI_W_STATE		<= AXI_W_ACK;
				end
			AXI_W_ACK	:begin
						s_axi_bready_r	<= (s_axi_bvalid==1)?1'b1:1'b0;
						AXI_W_STATE		<= (s_axi_bvalid==1)?AXI_W_DONE:AXI_W_ACK;
				end
			
			AXI_W_DONE	:begin
						s_axi_bready_r	<= 1'b0;
						AXI_W_STATE		<= AXI_W_IDLE;						
				end
		endcase
	end
	else
	begin
		AXI_W_STATE		<= AXI_W_IDLE;
		s_axi_bready_r	<= 1'b0;
	end
end

assign		s_axi_awvalid	= s_axi_awvalid_r;
assign		s_axi_awaddr	= s_axi_awaddr_r;
assign		s_axi_wvalid	= s_axi_wvalid_r;
assign		s_axi_wdata		= s_axi_wdata_r;
assign		s_axi_bready	= s_axi_bready_r;




/********************************************************
	UART
**********************************************************/

    

 
    
axi_uartlite_0 uart 
(
  .s_axi_aclk(s_axi_aclk),        // input wire s_axi_aclk
  .s_axi_aresetn(s_axi_aresetn),  // input wire s_axi_aresetn
  .interrupt(interrupt),          // output wire interrupt
  .s_axi_awaddr(s_axi_awaddr),    // input wire [3 : 0] s_axi_awaddr
  .s_axi_awvalid(s_axi_awvalid),  // input wire s_axi_awvalid
  .s_axi_awready(s_axi_awready),  // output wire s_axi_awready
  .s_axi_wdata(s_axi_wdata),      // input wire [31 : 0] s_axi_wdata
  .s_axi_wstrb(4'b1111),      // input wire [3 : 0] s_axi_wstrb
  .s_axi_wvalid(s_axi_wvalid),    // input wire s_axi_wvalid
  .s_axi_wready(s_axi_wready),    // output wire s_axi_wready
  .s_axi_bresp(s_axi_bresp),      // output wire [1 : 0] s_axi_bresp
  .s_axi_bvalid(s_axi_bvalid),    // output wire s_axi_bvalid
  .s_axi_bready(s_axi_bready),    // input wire s_axi_bready
  .s_axi_araddr(s_axi_araddr),    // input wire [3 : 0] s_axi_araddr
  .s_axi_arvalid(s_axi_arvalid),  // input wire s_axi_arvalid
  .s_axi_arready(s_axi_arready),  // output wire s_axi_arready
  .s_axi_rdata(s_axi_rdata),      // output wire [31 : 0] s_axi_rdata
  .s_axi_rresp(s_axi_rresp),      // output wire [1 : 0] s_axi_rresp
  .s_axi_rvalid(s_axi_rvalid),    // output wire s_axi_rvalid
  .s_axi_rready(s_axi_rready),    // input wire s_axi_rready
  .rx(rx),                        // input wire rx
  .tx(tx)                        // output wire tx
);    
    
    
    
    
    
endmodule
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数字硬鉴

你的鼓励就是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值