文章目录
数据接口
分为三个通道,写地址通道,写数据通道,应答通道。其中AWPROT,WSTRB用的比较少。
WSTRB为写的数据的掩码,写的数据为32bit,4个Byte,所以WSTRB为4bit位宽,WSTRB为4位对应4Byte的数据。
AWPROT保护信号,3bit全设置0即可。
写操作时序
读操作
程序设计
上面波形画的有BUG,这里以写入地址与数据对齐的方式写入。
程序思路
用户端:写数据,读数据。将用户写的数据转化位AXI协议写入到AXI从机,并且可以从丛机读出数据到用户端。写入优先级大于读出优先级。
module AXI_LITE_Master # (
parameter P_ADDR_WIDTH = 32 ,
parameter P_DATA_WIDTH = 32
)(
input M_AXI_ACLK ,
input M_AXI_ARESETN ,
output M_AXI_AWVALID ,
input M_AXI_AWREADY ,
output [P_ADDR_WIDTH-1:0] M_AXI_AWADDR ,
output [3:0] M_AXI_AWPROT ,
output M_AXI_WVALID ,
input M_AXI_WREADY ,
output [P_DATA_WIDTH-1:0] M_AXI_WDATA ,
output [P_DATA_WIDTH/8-1:0] M_AXI_WSTRB ,
input M_AXI_BVALID ,
output M_AXI_BREADY ,
input [3:0] M_AXI_BRESP ,
output M_AXI_ARVALID ,
input M_AXI_ARREADY ,
output [P_ADDR_WIDTH-1:0] M_AXI_ARADDR ,
output [3:0] M_AXI_ARPROT ,
input M_AXI_RVALID ,
output M_AXI_RREADY ,
input [P_DATA_WIDTH-1:0] M_AXI_RDATA ,
input [3:0] M_AXI_RRESP ,
input [P_DATA_WIDTH-1:0] USER_WDATA_I ,
input [P_ADDR_WIDTH-1:0] USER_WADDR_I ,
input USER_WVALID_I ,
input [P_ADDR_WIDTH-1:0] USER_RADDR_I ,
input USER_RVALID_I ,
output USER_RVALID_O ,
output [P_DATA_WIDTH-1:0] USER_RDATA_O
);
//???????????reg???????
reg ro_M_AXI_AWVALID ;
reg [P_ADDR_WIDTH-1:0] ro_M_AXI_AWADDR ;
reg [3:0] ro_M_AXI_AWPROT ;
reg ro_M_AXI_WVALID ;
reg [P_DATA_WIDTH-1:0] ro_M_AXI_WDATA ;
reg [P_DATA_WIDTH/8-1:0] ro_M_AXI_WSTRB ;
reg ro_M_AXI_BREADY ;
reg ro_M_AXI_ARVALID ;
reg [P_ADDR_WIDTH-1:0] ro_M_AXI_ARADDR ;
reg [3:0] ro_M_AXI_ARPROT ;
reg ro_M_AXI_RREADY ;
reg ro_USER_RVALID_O ;
reg [P_DATA_WIDTH-1:0] ro_USER_RDATA_O ;
reg write_run ;
reg read_run ;
reg waddr_fifo_rd_en_d1;
reg raddr_fifo_rd_en_d1;
//§Õ????fifo???
wire [P_DATA_WIDTH-1:0] wdata_fifo_din ;
wire wdata_fifo_wr_en ;
wire [P_DATA_WIDTH-1:0] wdata_fifo_out ;
wire wdata_fifo_empty ;
wire wdata_fifo_full ;
//§Õ???fifo???
wire [P_ADDR_WIDTH-1:0] waddr_fifo_din ;
wire waddr_fifo_wr_en ;
reg waddr_fifo_rd_en ;
wire [P_ADDR_WIDTH-1:0] waddr_fifo_out ;
wire waddr_fifo_empty ;
//?????fifo???
wire [P_ADDR_WIDTH-1:0] raddr_fifo_din ;
wire raddr_fifo_wr_en ;
reg raddr_fifo_rd_en ;
wire raddr_fifo_empty ;
wire [P_ADDR_WIDTH-1:0] raddr_fifo_out ;
//?????????
wire AW_active ;
wire W_active ;
wire WB_active ;
wire AR_active ;
wire R_active ;
//????????????????????
assign M_AXI_AWVALID = ro_M_AXI_AWVALID ;
assign M_AXI_AWADDR = ro_M_AXI_AWADDR ;
assign M_AXI_AWPROT = ro_M_AXI_AWPROT ;
assign M_AXI_WVALID = ro_M_AXI_WVALID ;
assign M_AXI_WDATA = ro_M_AXI_WDATA ;
assign M_AXI_WSTRB = ro_M_AXI_WSTRB ;
assign M_AXI_BREADY = ro_M_AXI_BREADY ;
assign M_AXI_ARVALID = ro_M_AXI_ARVALID ;
assign M_AXI_ARADDR = ro_M_AXI_ARADDR ;
assign M_AXI_ARPROT = ro_M_AXI_ARPROT ;
assign M_AXI_RREADY = ro_M_AXI_RREADY ;
assign USER_RVALID_O = ro_USER_RVALID_O ;
assign USER_RDATA_O = ro_USER_RDATA_O ;
//??????????
assign AW_active = M_AXI_AWREADY & M_AXI_AWVALID;
assign W_active = M_AXI_WREADY & M_AXI_WVALID ;
assign WB_active = M_AXI_BREADY & M_AXI_BVALID ;
assign AR_active = M_AXI_ARREADY & M_AXI_ARVALID;
assign R_active = M_AXI_RREADY & M_AXI_RVALID ;
//????fifo§Õ??
assign wdata_fifo_din = USER_WDATA_I ;
assign wdata_fifo_wr_en = USER_WVALID_I ;
assign waddr_fifo_din = USER_WADDR_I ;
assign waddr_fifo_wr_en = USER_WVALID_I ;
assign raddr_fifo_wr_en = USER_RVALID_I ;
assign raddr_fifo_din = USER_RADDR_I ;
fifo_32x32 user_wdata_fifo (
.clk ( M_AXI_ACLK ), // input wire clk
.srst ( ~M_AXI_ARESETN ), // input wire srst
.din ( wdata_fifo_din ), // input wire [31 : 0] din
.wr_en ( waddr_fifo_wr_en ), // input wire wr_en
.rd_en ( waddr_fifo_rd_en ), // input wire rd_en
.dout ( wdata_fifo_out ), // output wire [31 : 0] dout
.full ( wdata_fifo_full ), // output wire full
.empty ( wdata_fifo_empty ) // output wire empty
);
fifo_32x32 user_waddr_fifo (
.clk ( M_AXI_ACLK ), // input wire clk
.srst ( ~M_AXI_ARESETN ), // input wire srst
.din ( waddr_fifo_din ), // input wire [31 : 0] din
.wr_en ( waddr_fifo_wr_en ), // input wire wr_en
.rd_en ( waddr_fifo_rd_en ), // input wire rd_en
.dout ( waddr_fifo_out ), // output wire [31 : 0] dout
.empty ( waddr_fifo_empty ) // output wire empty
);
fifo_32x32 user_raddr_fifo (
.clk ( M_AXI_ACLK ), // input wire clk
.srst ( ~M_AXI_ARESETN ), // input wire srst
.din ( raddr_fifo_din ), // input wire [31 : 0] din
.wr_en ( raddr_fifo_wr_en ), // input wire wr_en
.rd_en ( raddr_fifo_rd_en ), // input wire rd_en
.dout ( raddr_fifo_out ), // output wire [31 : 0] dout
.empty ( raddr_fifo_empty ) // output wire empty
);
//??§Õ?????????????§Õ????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
write_run <= 'd0;
else if(WB_active)
write_run <= 'd0;
else if(!waddr_fifo_empty)
write_run <= 'd1;
else
write_run <= write_run;
end
//???????§Õ????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
waddr_fifo_rd_en <= 'd0;
else if(!waddr_fifo_empty && !write_run)
waddr_fifo_rd_en <= 'd1;
else
waddr_fifo_rd_en <= 'd0;
end
//??????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
waddr_fifo_rd_en_d1 <= 'd0;
else
waddr_fifo_rd_en_d1 <= waddr_fifo_rd_en;
end
//???????????????????????????§¹???
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN) begin
ro_M_AXI_AWVALID <= 'd0;
ro_M_AXI_AWADDR <= 'd0;
ro_M_AXI_AWPROT <= 'd0;
ro_M_AXI_WVALID <= 'd0;
end
else if(AW_active) begin
ro_M_AXI_AWVALID <= 'd0;
ro_M_AXI_AWADDR <= 'd0;
ro_M_AXI_AWPROT <= 'd0;
end
else if(waddr_fifo_rd_en_d1) begin
ro_M_AXI_AWVALID <= 'd1;
ro_M_AXI_AWADDR <= waddr_fifo_out;
ro_M_AXI_AWPROT <= 'd0;
end
else begin
ro_M_AXI_AWVALID <= ro_M_AXI_AWVALID;
ro_M_AXI_AWADDR <= ro_M_AXI_AWADDR ;
ro_M_AXI_AWPROT <= ro_M_AXI_AWPROT ;
end
end
//??????????????????????????????§¹???
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN) begin
ro_M_AXI_WVALID <= 'd0;
ro_M_AXI_WDATA <= 'd0;
ro_M_AXI_WSTRB <= 'd0;
end
else if(W_active || AW_active) begin
ro_M_AXI_WVALID <= 'd0;
ro_M_AXI_WDATA <= 'd0;
ro_M_AXI_WSTRB <= 'd0;
end
else if(waddr_fifo_rd_en_d1) begin
ro_M_AXI_WVALID <= 'd1;
ro_M_AXI_WDATA <= wdata_fifo_out;
ro_M_AXI_WSTRB <= 'b1111;
end
else begin
ro_M_AXI_WVALID <= ro_M_AXI_WVALID;
ro_M_AXI_WDATA <= ro_M_AXI_WDATA ;
ro_M_AXI_WSTRB <= ro_M_AXI_WSTRB ;
end
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
ro_M_AXI_BREADY <= 'd0;
else if(WB_active)
ro_M_AXI_BREADY <= 'd0;
else if(W_active)
ro_M_AXI_BREADY <= 'd1;
else
ro_M_AXI_BREADY <= ro_M_AXI_BREADY;
end
//????????????§Õ????????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
read_run <= 'd0;
else if(R_active)
read_run <= 'd0;
else if(!raddr_fifo_empty && waddr_fifo_empty)
read_run <= 'd1;
else
read_run <= read_run;
end
//?????fifo?????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
raddr_fifo_rd_en <= 'd0;
else if(!read_run && !raddr_fifo_empty && waddr_fifo_empty)
raddr_fifo_rd_en <= 'd1;
else
raddr_fifo_rd_en <= 'd0;
end
//????????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
raddr_fifo_rd_en_d1 <= 'd0;
else
raddr_fifo_rd_en_d1 <= raddr_fifo_rd_en;
end
//???????§Õ??AXI??????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN) begin
ro_M_AXI_ARVALID <= 'd0;
ro_M_AXI_ARADDR <= 'd0;
ro_M_AXI_ARPROT <= 'd0;
end
else if(AR_active) begin
ro_M_AXI_ARVALID <= 'd0;
ro_M_AXI_ARADDR <= 'd0;
ro_M_AXI_ARPROT <= 'd0;
end
else if(raddr_fifo_rd_en_d1) begin
ro_M_AXI_ARVALID <= 'd1;
ro_M_AXI_ARADDR <= raddr_fifo_out;
ro_M_AXI_ARPROT <= 'd0;
end
else begin
ro_M_AXI_ARVALID <= ro_M_AXI_ARVALID;
ro_M_AXI_ARADDR <= ro_M_AXI_ARADDR ;
ro_M_AXI_ARPROT <= ro_M_AXI_ARPROT ;
end
end
//???????§Õ?????????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
ro_M_AXI_RREADY <= 'd0;
else if(R_active)
ro_M_AXI_RREADY <= 'd0;
else if(AR_active)
ro_M_AXI_RREADY <= 'd1;
else
ro_M_AXI_RREADY <= ro_M_AXI_RREADY;
end
//??AXI?????????????????????????????
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN) begin
ro_USER_RVALID_O <= 'd0;
ro_USER_RDATA_O <= 'd0;
end
else begin
ro_USER_RVALID_O <= M_AXI_RVALID;
ro_USER_RDATA_O <= M_AXI_RDATA ;
end
end
endmodule
仿真波形分析
写入地址、数据FIFO
从地址、数据FIFO将数据读出
当FIFO读使能拉高,数据会延时一个周期