上一篇《通过状态机来对axi_lite总线读写操作》中,分享网友的代码。
本工程为VIVADO 2017.04版本,先自定义AXI_LITE slave IP,源码部分未作修改,顶层文件调用该IP,通过状态机对该从器件进行读写操作,并编写testbench,观察仿真波形。工程下载链接在文末给出。
以下摘出状态机中时序输出部分代码及其注释:
always @(posedge clk_100M or posedge rst)
begin
if (rst)
begin
s_axi_awvalid <= 1'b0;
s_axi_wvalid <= 1'b0;
s_axi_arvalid <= 1'b0;
s_axi_rready <= 1'b0;
s_axi_bready <= 1'b0;
s_axi_awaddr <= 0;
s_axi_araddr <= 0;
s_axi_wdata <= 0;
m_axi_rdata <= 0;
ipc_ack_r <= 1'b0;
end
else
begin
s_axi_awvalid <= 1'b0;
s_axi_wvalid <= 1'b0;
s_axi_arvalid <= 1'b0;
s_axi_rready <= 1'b0;
s_axi_bready <= 1'b0;
ipc_ack_r <= 1'b0;
case(next_state)
//IDLE:
WRITE_START: //不需要跳转条件,即写状态只需要消耗一个时钟周期,然后自动跳转到下一个状态
begin //首先准备好访问地址,和需要写入的数据;同时给出地址有效,数据有效,bready信号
s_axi_awaddr <= ipc_waddr[6:0];
s_axi_wdata <= ipc_wdata;
s_axi_awvalid <= 1'b1;
s_axi_wvalid <= 1'b1;
s_axi_bready <= 1'b1;
end
WRITE_VALID: //检测是否接收到slave端的地址ready和数据ready信号
begin
s_axi_awvalid <= 1'b1;
s_axi_wvalid <= 1'b1;
s_axi_bready <= 1'b1;
end
WRITE_READY: //等待slave端的bvalid信号到来,表示一次写完成了,即slave端的一个写反馈过程
begin
s_axi_bready <= 1'b1;
end
//WRITE_BREADY: //WRITE_BREADY 状态不需要状态跳转条件,只需要消耗一个时钟周期,同时在这个状态中,m_axi_bready <= 1'b1,此状态输出与前一状态相同,此处可省略
WRITE_END:
begin
ipc_ack_r <= 1'b1;
end
READ_START: //首先准备好访问地址,和地址有效信号先拉高
begin
s_axi_araddr <= ipc_raddr[6:0];
s_axi_arvalid <= 1'b1;
end
READ_VALID: //接收到slave端的地址ready信号后,表示可以进行下一次读操作了
begin
s_axi_arvalid <= 1'b1;
end
//READ_READY: //当slave端传回来读数据有效信号后,状态机跳转进read_finish状态。没有相关信号需要输出。此状态输出与前一状态相同,此处可省略
READ_FINISH:
begin
m_axi_rdata <= s_axi_rdata;
s_axi_rready <= 1'b1;
end
READ_END:
begin
ipc_ack_r <= 1'b1;
end
default:
begin
s_axi_awvalid <= 1'b0;
s_axi_wvalid <= 1'b0;
s_axi_arvalid <= 1'b0;
s_axi_rready <= 1'b0;
s_axi_bready <= 1'b0;
ipc_ack_r <= 1'b0;
end
endcase
end
end
testbench文件很简单,复位完成后,先写入四个数据,然后读取四个数据,重复两次:
整体波形:
写时序局部波形
读时序局部波形:
工程下载链接: