说明: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