1. axi4_lite的作用
axi4_lite:它的作用可以配置一些IP核处于不同的工作模式,xdma IP核,在ZYNQ中的axi dma,在做高速接口时的srio,功能类似STM32中外设与CPU之间的通信时使用的协议,比如当访问串口的数据寄存器时,只访问四个字节的数据,所以使用AXI4-lite
就特别合适。再比如,在PL
写一个用于PS
端操作的外设时,其外设寄存器一般通过AXI4-lite
总线和PS
交互。
- 数据总线只能是32位或者64位。
- 每次传输只能传输一个数据。
- 所有访问都是不可修改(Non-modifiable),不可缓冲(Non-bufferable)。
- Exclusive 访问不支持。
2. axi4_lited 的仿真
这里是用户读写请求仿真模块的仿真结果
2.1 IP
2.1.1 FIFO
2.1.2 BRAM
2.2 RTL
module axilite_master #(
parameter USER_WR_DATA_WIDTH = 32,
parameter USER_RD_DATA_WIDTH = 32,
parameter AXI_DATA_WIDTH = 32,
parameter AXI_ADDR_WIDTH = 32
)(
input user_wr_clk ,
input user_rd_clk ,
input axi_clk ,
input reset ,
input user_wr_en ,
input [USER_WR_DATA_WIDTH-1:0] user_wr_data ,
input [AXI_ADDR_WIDTH-1:0] user_wr_addr ,
output user_wr_ready ,
input user_rd_en ,
input [AXI_ADDR_WIDTH-1:0] user_rd_addr ,
output user_rd_ready ,
output user_rd_valid ,
output [USER_RD_DATA_WIDTH-1:0] user_rd_data ,
output m_axi_awvalid ,
input m_axi_awready ,
output [AXI_ADDR_WIDTH-1:0] m_axi_awaddr ,
output [2:0] m_axi_awport ,
output m_axi_wvalid ,
input m_axi_wready ,
output [AXI_ADDR_WIDTH-1:0] m_axi_wdata ,
output [AXI_DATA_WIDTH-1:0] m_axi_strb ,
input m_axi_bvalid ,
output m_axi_bready ,
input [1:0] m_axi_bresp ,
output m_axi_arvalid ,
input m_axi_arready ,
output [AXI_ADDR_WIDTH-1:0] m_axi_araddr ,
output [2:0] m_axi_arport ,
input m_axi_rvalid ,
input [AXI_ADDR_WIDTH-1:0] m_axi_rdata ,
input [1:0] m_axi_rresp ,
output m_axi_rready
);
wire wr_data_fifo_err;
wire wr_cmd_fifo_err;
wire rd_data_fifo_err;
wire rd_cmd_fifo_err;
axilite_wr_channel
#(
.USER_WR_DATA_WIDTH (USER_WR_DATA_WIDTH ),
.AXI_DATA_WIDTH (AXI_DATA_WIDTH ),
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH )
)axilite_wr_channel_inst(
.clk (user_wr_clk ),
.axi_clk (axi_clk ),
.reset (reset ),
.user_wr_en (user_wr_en ),
.user_wr_data (user_wr_data ),
.user_wr_addr (user_wr_addr ),
.user_wr_ready (user_wr_ready ),
.m_axi_awvalid (m_axi_awvalid ),
.m_axi_awready (m_axi_awready ),
.m_axi_awaddr (m_axi_awaddr ),
.m_axi_awport (m_axi_awport ),
.m_axi_wvalid (m_axi_wvalid ),
.m_axi_wready (m_axi_wready ),
.m_axi_wdata (m_axi_wdata ),
.m_axi_strb (m_axi_strb ),
.m_axi_bvalid (m_axi_bvalid ),
.m_axi_bready (m_axi_bready ),
.m_axi_bresp (m_axi_bresp ),
.wr_data_fifo_err(wr_data_fifo_err ),
.wr_cmd_fifo_err (wr_cmd_fifo_err )
);
axilite_rd_channel
#(
.USER_RD_DATA_WIDTH (USER_RD_DATA_WIDTH ),
.AXI_DATA_WIDTH (AXI_DATA_WIDTH ),
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH )
)axilite_rd_channel_inst(
.clk (user_rd_clk ),
.axi_clk (axi_clk ),
.reset (reset ),
.user_rd_en (user_rd_en ),
.user_rd_addr (user_rd_addr ),
.user_rd_ready (user_rd_ready ),
.user_rd_valid (user_rd_valid ),
.user_rd_data (user_rd_data ),
.m_axi_arvalid (m_axi_arvalid ),
.m_axi_arready (m_axi_arready ),
.m_axi_araddr (m_axi_araddr ),
.m_axi_arport (m_axi_arport ),
.m_axi_rvalid (m_axi_rvalid ),
.m_axi_rdata (m_axi_rdata ),
.m_axi_rresp (m_axi_rresp ),
.m_axi_rready (m_axi_rready ),
.rd_data_fifo_err (rd_data_fifo_err ),
.rd_cmd_fifo_err (rd_cmd_fifo_err )
);
endmodule
module axilite_wr_channel
#(
parameter USER_WR_DATA_WIDTH = 32,//用户写数据的位宽
parameter AXI_DATA_WIDTH = 32,//注释,AXI4_LITE的数据位宽只有32Bit或者64Bit
parameter AXI_ADDR_WIDTH = 32//
)(
input clk ,//用户写时钟
input axi_clk ,//axi工作时钟
input reset ,//复位信号
//用户写地址写通道端口
input user_wr_en ,//用户写使能
input [USER_WR_DATA_WIDTH-1:0] user_wr_data ,//用户写数据
input [AXI_ADDR_WIDTH-1:0] user_wr_addr ,//用户写地址
output user_wr_ready ,//用户写准备信号
//写地址通道端口
output reg m_axi_awvalid ,//axi主机写地址有效
input m_axi_awready ,//axi从机写准备信号,为高表示准备好了,与m_axi_awvalid信号同时为高是,用户地址可以写入从机
output reg [AXI_ADDR_WIDTH-1:0] m_axi_awaddr ,//axi主机写入从机的地址信号
output [2:0] m_axi_awport ,//保护类型,表示一个传输的安全等级,默认为3’b000
//写数据通道端口
output reg m_axi_wvalid ,//axi写数据有效信号
input m_axi_wready ,//axi从机写数据准备信号,高表示准备好了,与m_axi_wvalid信号同时为高时,用户数据可以写入从机
output reg [AXI_DATA_WIDTH-1:0] m_axi_wdata ,//axi主机写入从机的数据信号
output [AXI_DATA_WIDTH/8 -1:0] m_axi_strb ,//axi指示有效字节位置,类似于掩码,默认全为1
//写响应信号
input m_axi_bvalid ,//axi写响应信号,从机到主机
output m_axi_bready ,//axi写准备信号,主机到从机,为高时表示主机准备好了,可以接收从机的响应
input [1:0] m_axi_bresp ,//axi响应信号,值为多少
//Debug信号
output reg wr_data_fifo_err,//这里是存储data数据fifo_err
output reg wr_cmd_fifo_err//这里是存储addr数据fifo_err
);
//大拍操作,避免用户时钟和axi时钟与复位信号不同源导致信号亚稳态
(* dont_touch="true" *) reg reset_sync_d0;
(* dont_touch="true" *) reg reset_sync_d1;
(* dont_touch="true" *) reg reset_sync;
(* dont_touch="true" *) reg a_reset_sync_d0;
(* dont_touch="true" *) reg a_reset_sync_d1;
(* dont_touch="true" *) reg a_reset_sync;
//wr_cmd_fifo内部端口信号
reg [31:0] cmd_din;
reg cmd_wren;
wire [31:0] cmd_dout;
reg cmd_rden;
wire cmd_wrfull;
wire cmd_rdempty;
wire [3:0] cmd_wrcount;
wire [3:0] cmd_rdcount;
//wr_data_fifo内部端口信号
reg [31:0] data_din;
reg data_wren;
wire [31:0] data_dout;
reg data_rden;
wire data_wrfull;
wire data_rdempty;
wire [3:0] data_wrcount;
wire [3:0] data_rdcount;
//状态机信号定义
reg [2:0] cur_status;//现状态
reg [2:0] nxt_status;//次状态
localparam WR_IDLE = 3'b000;//独热码
localparam WE_PRE = 3'b001;
localparam WR_DATA_EN = 3'b010;
localparam WR_END = 3'b100;
//assign
assign m_axi_bready = 1'b1 ;
assign m_axi_strb = {AXI_DATA_WIDTH/8{1'd1}};//表示的含义是32除以8=4,后面拼接1
assign m_axi_awport = 3'b000;//保护类型,表示一个传输的安全等级,默认为3’b000
assign user_wr_ready = reset_sync?1'b0:cmd_wrcount <= 'd12;//留出一些余量
//开始对复位信号进行打拍操作,防止亚稳态
always @(posedge clk) begin
reset_sync_d0 <= reset;
reset_sync_d1 <= reset_sync_d0;
reset_sync <= reset_sync_d1;
end
always @(posedge axi_clk) begin
a_reset_sync_d0 <= reset;
a_reset_sync_d1 <= a_reset_sync_d0;
a_reset_sync <= a_reset_sync_d1;
end
//将用户传过来的数据和地址写入FIFO中,只有当user_wr_ready信号为高电平时,才被允许将用户数据和地址写入FIFO中,否则,即使用户一直请求写使能,也不会写入到FIFO当中
always @(posedge clk)begin
if(user_wr_ready==1'b1)begin
cmd_wren <= user_wr_en ;
cmd_din <= user_wr_addr ;
data_wren <= user_wr_en ;
data_din <= user_wr_data ;
end
else begin
cmd_wren <= 1'b0 ;
cmd_din <= 1'b0 ;
data_wren <= 1'b0 ;
data_din <= 1'b0 ;
end
end
//状态机代码编写
always @(posedge axi_clk)begin
if(a_reset_sync)begin//复位信号,高电平有效
cur_status <= WR_IDLE ;
end
else
cur_status <= nxt_status ;
end
always @(*)begin//状态机使用组合逻辑实现
if(a_reset_sync)
nxt_status <= WR_IDLE ;
else
case (cur_status)
WR_IDLE:begin
if(~cmd_rdempty)
nxt_status <= WE_PRE ;
else
nxt_status <= cur_status;
end
WE_PRE:begin
nxt_status <= WR_DATA_EN;
end
WR_DATA_EN:begin
if(m_axi_bvalid&&m_axi_bready)
nxt_status <= WR_END ;
else
nxt_status <= cur_status;
end
WR_END:begin
nxt_status <= WR_IDLE ;
end
default: nxt_status <= WR_IDLE;
endcase
end
//读地址和读数据
always @(*)begin
if(a_reset_sync)begin
cmd_rden <= 1'b0;
data_rden <= 1'b0;
end
else begin
cmd_rden <= cur_status == WE_PRE;
data_rden <= cur_status == WE_PRE;
end
end
always @(axi_clk)begin
if(cmd_rden)
m_axi_awaddr <= cmd_dout;
else
m_axi_awaddr <= m_axi_awaddr;
end
always @(axi_clk)begin
if(cmd_rden)
m_axi_wdata <= data_dout;
else
m_axi_wdata <= m_axi_wdata;
end
always @(posedge axi_clk)begin
if(a_reset_sync)
m_axi_wvalid <= 1'b0;
else if(m_axi_wvalid&&m_axi_wready)
m_axi_wvalid <= 1'b0;
else if(cur_status == WE_PRE)
m_axi_wvalid <= 1'b1;
else
m_axi_wvalid <= m_axi_wvalid;
end
always @(posedge axi_clk)begin
if(a_reset_sync)
m_axi_awvalid <= 1'b0;
else if(m_axi_awvalid&&m_axi_awready)
m_axi_awvalid <= 1'b0;
else if(cur_status == WE_PRE)
m_axi_awvalid <= 1'b1;
else
m_axi_awvalid <= m_axi_awvalid;
end
//调试信号
always @(posedge clk)begin
if(reset_sync)
wr_cmd_fifo_err <= 1'b0;
else if(cmd_wrfull&&user_wr_en)
wr_cmd_fifo_err <= 1'b1;
else
wr_cmd_fifo_err <= wr_cmd_fifo_err;
end
always @(posedge clk)begin
if(reset_sync)
wr_data_fifo_err <= 1'b0;
else if(data_wrfull&&user_wr_en)
wr_data_fifo_err <= 1'b1;
else
wr_data_fifo_err <= wr_data_fifo_err;
end
// 例化fifo_w32xd16
fifo_w32xd16 wr_cmd_fifo(
.rst (reset_sync ),
.wr_clk (clk ),
.rd_clk (axi_clk ),
.din (cmd_din ),
.wr_en (cmd_wren ),
.rd_en (cmd_rden ),
.dout (cmd_dout ),
.full (cmd_wrfull ),
.empty (data_rdempty),
.rd_data_count (cmd_wrcount),
.wr_data_count (cmd_rdcount)
);
fifo_w32xd16 wr_data_fifo(
.rst (reset_sync ),
.wr_clk (clk ),
.rd_clk (axi_clk ),
.din (data_din ),
.wr_en (data_wren ),
.rd_en (data_rden ),
.dout (data_dout ),
.full (data_wrfull),
.empty (data_rdempty),
.rd_data_count (data_rdcount),
.wr_data_count (data_wrcount)
);
endmodule
module axilite_rd_channel#(
parameter USER_RD_DATA_WIDTH = 32,//用户读数据的数据位宽
parameter AXI_DATA_WIDTH = 32,//注释,AXI4_LITE的数据位宽只有32Bit或者64Bit
parameter AXI_ADDR_WIDTH = 32 //
)(
input clk ,//用户写时钟
input axi_clk ,//axi工作时钟
input reset ,//复位信号
//用户读取数据端口
input user_rd_en ,//用户读数据使能
input [AXI_ADDR_WIDTH-1:0] user_rd_addr ,//用户读地址位宽
output user_rd_ready ,//用户读准备信号
output reg user_rd_valid ,//用户读有效信号
output reg [USER_RD_DATA_WIDTH-1:0] user_rd_data ,//用户读数据信号位宽
//axi读地址接口
output reg m_axi_arvalid ,//axi主机读地址有效
input m_axi_arready ,//axi主机读地址准备
output reg [AXI_ADDR_WIDTH-1:0] m_axi_araddr ,//axi主机读地址数据
output [2:0] m_axi_arport ,//保护类型,表示一个传输的安全等级,默认为3’b000
//axi读数据接口
input m_axi_rvalid ,//axi主机读数据有效
output m_axi_rready ,//axi主机读数据准备
input [AXI_ADDR_WIDTH-1:0] m_axi_rdata ,//axi主机读数据
input [1:0] m_axi_rresp ,//axi主机读响应信号
//Debug信号
output reg rd_data_fifo_err ,//
output reg rd_cmd_fifo_err
);
//打拍操作,避免用户时钟和axi时钟与复位信号不同源导致信号亚稳态
(* dont_touch="true" *) reg reset_sync_d0;
(* dont_touch="true" *) reg reset_sync_d1;
(* dont_touch="true" *) reg reset_sync;
(* dont_touch="true" *) reg a_reset_sync_d0;
(* dont_touch="true" *) reg a_reset_sync_d1;
(* dont_touch="true" *) reg a_reset_sync;
//wr_cmd_fifo内部端口信号
reg [31:0] cmd_din;
reg cmd_wren;
wire [31:0] cmd_dout;
reg cmd_rden;
wire cmd_wrfull;
wire cmd_rdempty;
wire [3:0] cmd_wrcount;
wire [3:0] cmd_rdcount;
//wr_data_fifo内部端口信号
reg [31:0] data_din;
reg data_wren;
wire [31:0] data_dout;
wire data_rden;
wire data_wrfull;
wire data_rdempty;
wire [3:0] data_wrcount;
wire [3:0] data_rdcount;
//状态机信号定义
reg [2:0] cur_status;//现状态
reg [2:0] nxt_status;//次状态
localparam RD_IDLE = 3'b000;//独热码
localparam RD_PRE = 3'b001;
localparam RD_DATA_EN = 3'b010;
localparam RD_END = 3'b100;
//assign
assign m_axi_arport = 3'b000;
assign m_axi_rready = 1'b1;
assign user_rd_ready = reset_sync?1'b0:cmd_wrcount <= 'd12;//留出一些余量;
//开始对复位信号进行打拍操作,防止亚稳态
always @(posedge clk) begin
reset_sync_d0 <= reset;
reset_sync_d1 <= reset_sync_d0;
reset_sync <= reset_sync_d1;
end
always @(posedge axi_clk) begin
a_reset_sync_d0 <= reset;
a_reset_sync_d1 <= a_reset_sync_d0;
a_reset_sync <= a_reset_sync_d1;
end
// 将用户端的读地址写入cmd_fifo
always @(posedge clk) begin
if(user_rd_ready)begin
cmd_wren <= user_rd_en ;
cmd_din <= user_rd_addr;
end
else begin
cmd_wren <= 1'b0 ;
cmd_din <= 1'b0 ;
end
end
//状态机
always @(axi_clk) begin
if(a_reset_sync)
cur_status <= RD_IDLE;
else
cur_status <= nxt_status;
end
always @(*)begin//状态机使用组合逻辑实现
if(a_reset_sync)
nxt_status <= RD_IDLE ;
else
case (cur_status)
RD_IDLE:begin
if(~cmd_rdempty)
nxt_status <= RD_PRE ;
else
nxt_status <= cur_status;
end
RD_PRE:begin
nxt_status <= RD_DATA_EN;
end
RD_DATA_EN:begin
if(m_axi_rvalid && m_axi_rready)
nxt_status <= RD_END ;
else
nxt_status <= cur_status;
end
RD_END:begin
nxt_status <= RD_IDLE ;
end
default: nxt_status <= RD_IDLE;
endcase
end
// 发起AXI4读请求
always @(*) begin
if(a_reset_sync)
cmd_rden <= 1'd0;
else
cmd_rden <= cur_status == RD_PRE;
end
always @(posedge clk) begin
if(cmd_rden)
m_axi_araddr <= cmd_dout;
else
m_axi_araddr <= m_axi_araddr;
end
always @(posedge clk) begin
if(a_reset_sync)
m_axi_arvalid <= 1'b0;
else if(m_axi_arvalid && m_axi_arready)
m_axi_arvalid <= 1'b0;
else if(cur_status == RD_PRE)
m_axi_arvalid <= 1'b1;
else
m_axi_arvalid <= m_axi_arvalid;
end
// 将AXI4的读数据写入data_fifo
always @(posedge axi_clk) begin
data_wren <= m_axi_rvalid;
data_din <= m_axi_rdata;
end
assign data_rden = reset_sync ? 1'b0 : ~data_rdempty;
always @(posedge clk) begin
user_rd_valid <= data_rden;
user_rd_data <= data_dout;
end
//调试信号
always @(posedge clk)begin
if(reset_sync)
rd_data_fifo_err <= 1'b0;
else if(rd_data_fifo_err && user_rd_en)
rd_data_fifo_err <= 1'b1;
else
rd_data_fifo_err <= rd_data_fifo_err;
end
always @(posedge clk)begin
if(reset_sync)
rd_cmd_fifo_err <= 1'b0;
else if(data_wrfull && user_rd_en)
rd_cmd_fifo_err <= 1'b1;
else
rd_cmd_fifo_err <= rd_cmd_fifo_err;
end
// 例化fifo_w32xd16
fifo_w32xd16 rd_cmd_fifo(
.rst (reset_sync ),
.wr_clk (clk ),//注意这里,写的时钟是clk的时钟
.rd_clk (axi_clk ),//读的时钟是axi的
.din (cmd_din ),
.wr_en (cmd_wren ),
.rd_en (cmd_rden ),
.dout (cmd_dout ),
.full (cmd_wrfull ),
.empty (data_rdempty),
.rd_data_count (cmd_wrcount),
.wr_data_count (cmd_rdcount)
);
fifo_w32xd16 rd_data_fifo(
.rst (reset_sync ),
.wr_clk (axi_clk ),//注意这里,写的时钟是axi的时钟
.rd_clk (clk ),//读的时钟是clk的
.din (data_din ),
.wr_en (data_wren ),
.rd_en (data_rden ),
.dout (data_dout ),
.full (data_wrfull),
.empty (data_rdempty),
.rd_data_count (data_rdcount),
.wr_data_count (data_wrcount)
);
endmodule
2.3 SIM
`timescale 1ns/1ns
module tb_top();
parameter USER_WR_DATA_WIDTH = 32;
parameter USER_RD_DATA_WIDTH = 32;
parameter AXI_DATA_WIDTH = 32;
parameter AXI_ADDR_WIDTH = 32;
reg user_wr_clk ;
reg user_rd_clk ;
reg axi_clk ;
reg reset ;
wire user_wr_en ;
wire [USER_WR_DATA_WIDTH-1:0] user_wr_data ;
wire [AXI_ADDR_WIDTH-1:0] user_wr_addr ;
wire user_wr_ready ;
wire user_rd_en ;
wire [AXI_ADDR_WIDTH-1:0] user_rd_addr ;
wire user_rd_ready ;
wire user_rd_valid ;
wire [USER_RD_DATA_WIDTH-1:0] user_rd_data ;
wire m_axi_awvalid ;
wire m_axi_awready ;
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr ;
wire [2:0] m_axi_awport ;
wire m_axi_wvalid ;
wire m_axi_wready ;
wire [AXI_ADDR_WIDTH-1:0] m_axi_wdata ;
wire [AXI_DATA_WIDTH-1:0] m_axi_strb ;
wire m_axi_bvalid ;
wire m_axi_bready ;
wire [1:0] m_axi_bresp ;
wire m_axi_arvalid ;
wire m_axi_arready ;
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr ;
wire [2:0] m_axi_arport ;
wire m_axi_rvalid ;
wire [AXI_ADDR_WIDTH-1:0] m_axi_rdata ;
wire [1:0] m_axi_rresp ;
wire m_axi_rready ;
initial begin
user_wr_clk = 1;
forever #(10)
user_wr_clk = ~user_wr_clk;
end
initial begin
axi_clk = 1;
forever #(5)
axi_clk = ~axi_clk;
end
initial begin
reset = 1;
forever #(300)
reset = 0;
end
user_req_generate #(
.USER_WR_DATA_WIDTH (USER_WR_DATA_WIDTH),
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH)
)user_req_generate_inst(
.clk (user_wr_clk ),
.reset (reset ),
.user_wr_en (user_wr_en ),
.user_wr_addr (user_wr_addr ),
.user_wr_data (user_wr_data ),
.user_rd_en (user_rd_en ),
.user_rd_addr (user_rd_addr )
);
axilite_master #(
.USER_RD_DATA_WIDTH (USER_RD_DATA_WIDTH),
.USER_WR_DATA_WIDTH (USER_WR_DATA_WIDTH),
.AXI_DATA_WIDTH (AXI_DATA_WIDTH ),
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH )
)axilite_master_inst(
.user_wr_clk (user_wr_clk ),
.user_rd_clk (user_rd_clk ),
.axi_clk (axi_clk ),
.reset (reset ),
.user_wr_en (user_wr_en ),
.user_wr_data (user_wr_data ),
.user_wr_addr (user_wr_addr ),
.user_wr_ready (user_wr_ready),
.user_rd_en (user_rd_en ),
.user_rd_addr (user_rd_addr ),
.user_rd_ready (user_rd_ready),
.user_rd_valid (user_rd_valid),
.user_rd_data (user_rd_data ),
.m_axi_awvalid (m_axi_awvalid),
.m_axi_awready (m_axi_awready),
.m_axi_awaddr (m_axi_awaddr ),
.m_axi_awport (m_axi_awport ),
.m_axi_wvalid (m_axi_wvalid ),
.m_axi_wready (m_axi_wready ),
.m_axi_wdata (m_axi_wdata ),
.m_axi_strb (m_axi_strb ),
.m_axi_bvalid (m_axi_bvalid ),
.m_axi_bready (m_axi_bready ),
.m_axi_bresp (m_axi_bresp ),
.m_axi_arvalid (m_axi_arvalid),
.m_axi_arready (m_axi_arready),
.m_axi_araddr (m_axi_araddr ),
.m_axi_arport (m_axi_arport ),
.m_axi_rvalid (m_axi_rvalid ),
.m_axi_rdata (m_axi_rdata ),
.m_axi_rresp (m_axi_rresp ),
.m_axi_rready (m_axi_rready )
);
blk_mem_gen_0 blk_mem_gen_0_inst (
.rsta_busy ( ), // output wire rsta_busy
.rstb_busy ( ), // output wire rstb_busy
.s_aclk (axi_clk ), // input wire s_aclk
.s_aresetn (~reset ), // input wire s_aresetn
.s_axi_awaddr (m_axi_awaddr ), // input wire [31 : 0] s_axi_awaddr
.s_axi_awvalid (m_axi_awvalid ), // input wire s_axi_awvalid
.s_axi_awready (m_axi_awready ), // output wire s_axi_awready
.s_axi_wdata (m_axi_wdata ), // input wire [31 : 0] s_axi_wdata
.s_axi_wstrb (m_axi_strb ), // input wire [3 : 0] s_axi_wstrb
.s_axi_wvalid (m_axi_wvalid ), // input wire s_axi_wvalid
.s_axi_wready (m_axi_wready ), // output wire s_axi_wready
.s_axi_bresp (m_axi_bresp ), // output wire [1 : 0] s_axi_bresp
.s_axi_bvalid (m_axi_bvalid ), // output wire s_axi_bvalid
.s_axi_bready (m_axi_bready ), // input wire s_axi_bready
.s_axi_araddr (m_axi_araddr ), // input wire [31 : 0] s_axi_araddr
.s_axi_arvalid (m_axi_arvalid ), // input wire s_axi_arvalid
.s_axi_arready (m_axi_arready ), // output wire s_axi_arready
.s_axi_rdata (m_axi_rdata ), // output wire [31 : 0] s_axi_rdata
.s_axi_rresp (m_axi_rresp ), // output wire [1 : 0] s_axi_rresp
.s_axi_rvalid (m_axi_rvalid ), // output wire s_axi_rvalid
.s_axi_rready (m_axi_rready ) // input wire s_axi_rready
);
endmodule
module user_req_generate #(
parameter USER_WR_DATA_WIDTH = 32,
parameter AXI_ADDR_WIDTH = 32
)(
input wire clk,
input wire reset,
output reg user_wr_en,
output reg [AXI_ADDR_WIDTH-1:0] user_wr_addr,
output reg [USER_WR_DATA_WIDTH-1:0] user_wr_data,
output reg user_rd_en,
output reg [USER_WR_DATA_WIDTH-1:0] user_rd_addr
);
reg [2:0] status;
localparam IDLE = 3'b000;
localparam WAIT = 3'b001;
localparam WR = 3'b010;
localparam RD = 3'b100;
reg [7:0] wait_cnt;
reg [3:0] wr_cnt;
reg [3:0] rd_cnt;
always @(posedge clk) begin
if(reset)
wait_cnt <= 8'b0;
else if(wait_cnt == 100)
wait_cnt <= 8'b0;
else if(status == WAIT)
wait_cnt <= wait_cnt + 1'b1;
else
wait_cnt <= wait_cnt;
end
always @(posedge clk) begin
if(reset)
wr_cnt <= 4'b0;
else if(user_wr_en && wr_cnt == 10)
wr_cnt <= 4'b0;
else if(user_wr_en)
wr_cnt <= wr_cnt + 1'b1;
else
wr_cnt <= wr_cnt;
end
always @(posedge clk) begin
if(reset)
rd_cnt <= 4'b0;
else if(user_rd_en && rd_cnt == 10)
rd_cnt <= 4'b0;
else if(user_rd_en)
rd_cnt <= rd_cnt + 1'b1;
else
rd_cnt <= rd_cnt;
end
always @(posedge clk) begin
if(reset)
user_wr_en <= 1'b0;
else if(user_wr_en && wr_cnt == 10)
user_wr_en <= 1'b0;
else if(status == WR)
user_wr_en <= 1'b1;
else
user_wr_en <= user_wr_en;
end
always @(posedge clk) begin
if(reset)
user_rd_en <= 1'b0;
else if(user_rd_en && rd_cnt == 10)
user_rd_en <= 1'b0;
else if(status == RD)
user_rd_en <= 1'b1;
else
user_rd_en <= user_rd_en;
end
always @(posedge clk) begin
if(reset)
user_wr_addr <= 0;
else if(user_wr_en)
user_wr_addr <= user_wr_addr + USER_WR_DATA_WIDTH/8;
else if(user_wr_addr == 1024 && user_wr_en)
user_wr_addr <= 0;
else
user_wr_addr <= user_wr_addr;
end
always @(posedge clk) begin
if(reset)
user_rd_addr <= 0;
else if(user_rd_en)
user_rd_addr <= user_rd_addr + USER_WR_DATA_WIDTH/8;
else if(user_rd_addr == 1024 && user_rd_en)
user_rd_addr <= 0;
else
user_rd_addr <= user_rd_addr;
end
always @(posedge clk) begin
if(reset)
user_wr_data <= 0;
else if(user_wr_en)
user_wr_data <= user_wr_data + 1'b1 ;
else
user_wr_data <= user_wr_data;
end
always @(*) begin
if(reset)
status <= IDLE;
else begin
case (status)
IDLE : status <= WAIT;
WAIT : if(wait_cnt == 100) status <= WR;
WR : if(wr_cnt == 10 && user_wr_en) status <= RD;
RD : if(rd_cnt == 10 && user_rd_en) status <= IDLE;
default: status <= IDLE;
endcase
end
end
endmodule