1.简介
在没有arm核的情况下,PL端IP核需要自己编写axi_lite协议来配置IP核,在VDMA视频流通路搭建项目中,arm核的作用是提供DDR3控制接口以及用axi_lite来配置VDMA IP核,这里我们将配置IP核的部分放到PL端来实现。实现了一个axi_master_lite IP核接口,以后其他的axi_slave_lite 都可以使用此IP核进行控制。
2.AXI_MASTER_LITE
`timescale 1 ns / 1 ps
module axi_lite_master #
(
// Users to add parameters here
// User parameters ends
// Do not modify the parameters beyond this line
// The master requires a target slave base address.
// The master will initiate read and write transactions on the slave with base address specified here as a parameter.
parameter C_M_TARGET_SLAVE_BASE_ADDR = 32'h00000000,
// Width of M_AXI address bus.
// The master generates the read and write addresses of width specified as C_M_AXI_ADDR_WIDTH.
parameter integer C_M_AXI_ADDR_WIDTH = 32,
// Width of M_AXI data bus.
// The master issues write data and accept read data where the width of the data bus is C_M_AXI_DATA_WIDTH
parameter integer C_M_AXI_DATA_WIDTH = 32
// and read transactions the master will perform as a part of this example memory test.
)
(
// Users to add ports here
input wire [C_M_AXI_ADDR_WIDTH-1: 0] wr_addr ,
input wire wr_start ,
input wire [C_M_AXI_ADDR_WIDTH-1 :0] wr_data ,
output reg wr_done ,
input wire [C_M_AXI_ADDR_WIDTH-1 :0] rd_addr ,
input wire rd_start ,
output reg [C_M_AXI_ADDR_WIDTH-1 :0] rd_data ,
output reg rd_done ,
// User ports ends
// Do not modify the ports beyond this line
// Initiate AXI transactions
// Asserts when ERROR is detected
// Asserts when AXI transactions is complete
// AXI clock signal
input wire M_AXI_ACLK,
// AXI active low reset signal
input wire M_AXI_ARESETN,
// Master Interface Write Address Channel ports. Write address (issued by master)
output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR,
// Write channel Protection type.
// This signal indicates the privilege and security level of the transaction,
// and whether the transaction is a data access or an instruction access.
output wire [2 : 0] M_AXI_AWPROT,
// Write address valid.
// This signal indicates that the master signaling valid write address and control information.
output wire M_AXI_AWVALID,
// Write address ready.
// This signal indicates that the slave is ready to accept an address and associated control signals.
input wire M_AXI_AWREADY,
// Master Interface Write Data Channel ports. Write data (issued by master)
output wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_WDATA,
// Write strobes.
// This signal indicates which byte lanes hold valid data.
// There is one write strobe bit for each eight bits of the write data bus.
output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB,
// Write valid. This signal indicates that valid write data and strobes are available.
output wire M_AXI_WVALID,
// Write ready. This signal indicates that the slave can accept the write data.
input wire M_AXI_WREADY,
// Master Interface Write Response Channel ports.
// This signal indicates the status of the write transaction.
input wire [1 : 0] M_AXI_BRESP,
// Write response valid.
// This signal indicates that the channel is signaling a valid write response
input wire M_AXI_BVALID,
// Response ready. This signal indicates that the master can accept a write response.
output wire M_AXI_BREADY,
// Master Interface Read Address Channel ports. Read address (issued by master)
output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR,
// Protection type.
// This signal indicates the privilege and security level of the transaction,
// and whether the transaction is a data access or an instruction access.
output wire [2 : 0] M_AXI_ARPROT,
// Read address valid.
// This signal indicates that the channel is signaling valid read address and control information.
output wire M_AXI_ARVALID,
// Read address ready.
// This signal indicates that the slave is ready to accept an address and associated control signals.
input wire M_AXI_ARREADY,
// Master Interface Read Data Channel ports. Read data (issued by slave)
input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA,
// Read response. This signal indicates the status of the read transfer.
input wire [1 : 0] M_AXI_RRESP,
// Read valid. This signal indicates that the channel is signaling the required read data.
input wire M_AXI_RVALID,
// Read ready. This signal indicates that the master can accept the read data and response information.
output wire M_AXI_RREADY
);
// function called clogb2 that returns an integer which has the
// value of the ceiling of the log base 2
function integer clogb2 (input integer bit_depth);
begin
for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
bit_depth = bit_depth >> 1;
end
endfunction
// TRANS_NUM_BITS is the width of the index counter for
// number of write or read transaction.
// Example State machine to initialize counter, initialize write transactions,
// initialize read transactions and comparison of read data with the
// written data words.
reg [1:0] mst_exec_state;
// AXI4LITE signals
//write address valid
reg axi_awvalid;
//write data valid
reg axi_wvalid;
//read address valid
reg axi_arvalid;
//read data acceptance
reg axi_rready;
//write response acceptance
reg axi_bready;
//write address
reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;
//write data
reg [C_M_AXI_DATA_WIDTH-1 : 0] axi_wdata;
//read addresss
reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_araddr;
//Asserts when there is a write response error
wire write_resp_error;
//Asserts when there is a read response error
wire read_resp_error;
//A pulse to initiate a write transaction
reg start_single_write;
//A pulse to initiate a read transaction
reg start_single_read;
//Asserts when a single beat write transaction is issued and remains asserted till the completion of write trasaction.
reg write_issued;
//Asserts when a single beat read transaction is issued and remains asserted till the completion of read trasaction.
reg read_issued;
//flag that marks the completion of write trasactions. The number of write transaction is user selected by the parameter C_M_TRANSACTIONS_NUM.
reg writes_done;
//flag that marks the completion of read trasactions. The number of read transaction is user selected by the parameter C_M_TRANSACTIONS_NUM
reg reads_done;
//The error register is asserted when any of the write response error, read response error or the data mismatch flags are asserted.
reg error_reg;
//Expected read data used to compare with the read data.
//Flag marks the completion of comparison of the read data with the expected read data
// I/O Connections assignments
//Adding the offset address to the base addr of the slave
assign M_AXI_AWADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr;
//AXI 4 write data
assign M_AXI_WDATA = axi_wdata;
assign M_AXI_AWPROT = 3'b000;
assign M_AXI_AWVALID = axi_awvalid;
//Write Data(W)
assign M_AXI_WVALID = axi_wvalid;
//Set all byte strobes in this example
assign M_AXI_WSTRB = 4'b1111;
//Write Response (B)
assign M_AXI_BREADY = axi_bready;
//Read Address (AR)
assign M_AXI_ARADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_araddr;
assign M_AXI_ARVALID = axi_arvalid;
assign M_AXI_ARPROT = 3'b001;
//Read and Read Response (R)
assign M_AXI_RREADY = axi_rready;
//--------------------
//Write Address Channel
//--------------------
always @(posedge M_AXI_ACLK)
begin
//Only VALID signals must be deasserted during reset per AXI spec
//Consider inverting then registering active-low reset for higher fmax
if (M_AXI_ARESETN == 0)
begin
axi_awvalid <= 1'b0;
end
//Signal a new address/data command is available by user logic
else
begin
if (wr_start)
begin
axi_awvalid <= 1'b1;
end
//Address accepted by interconnect/slave (issue of M_AXI_AWREADY by slave)
else if (M_AXI_AWREADY && axi_awvalid)
begin
axi_awvalid <= 1'b0;
end
end
end
//--------------------
//Write Data Channel
//--------------------
//The write data channel is for transfering the actual data.
//The data generation is speific to the example design, and
//so only the WVALID/WREADY handshake is shown here
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0)
begin
axi_wvalid <= 1'b0;
end
//Signal a new address/data command is available by user logic
else if (wr_start)
begin
axi_wvalid <= 1'b1;
end
//Data accepted by interconnect/slave (issue of M_AXI_WREADY by slave)
else if (M_AXI_WREADY && axi_wvalid)
begin
axi_wvalid <= 1'b0;
end
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 )
begin
wr_done <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else if (M_AXI_WREADY && axi_wvalid)
begin
wr_done <= 1;
end
else
begin
wr_done <= 0;
end
end
//----------------------------
//Write Response (B) Channel
//----------------------------
//The write response channel provides feedback that the write has committed
//to memory. BREADY will occur after both the data and the write address
//has arrived and been accepted by the slave, and can guarantee that no
//other accesses launched afterwards will be able to be reordered before it.
//The BRESP bit [1] is used indicate any errors from the interconnect or
//slave for the entire write burst. This example will capture the error.
//While not necessary per spec, it is advisable to reset READY signals in
//case of differing reset latencies between master/slave.
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0)
begin
axi_bready <= 1'b0;
end
// accept/acknowledge bresp with axi_bready by the master
// when M_AXI_BVALID is asserted by slave
else if (M_AXI_BVALID && ~axi_bready)
begin
axi_bready <= 1'b1;
end
// deassert after one clock cycle
else if (axi_bready)
begin
axi_bready <= 1'b0;
end
// retain the previous value
else
axi_bready <= axi_bready;
end
//Flag write errors
assign write_resp_error = (axi_bready & M_AXI_BVALID & M_AXI_BRESP[1]);
//----------------------------
//Read Address Channel
//----------------------------
// A new axi_arvalid is asserted when there is a valid read address
// available by the master. start_single_read triggers a new read
// transaction
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0)
begin
axi_arvalid <= 1'b0;
end
//Signal a new read address command is available by user logic
else if (rd_start)
begin
axi_arvalid <= 1'b1;
end
//RAddress accepted by interconnect/slave (issue of M_AXI_ARREADY by slave)
else if (M_AXI_ARREADY && axi_arvalid)
begin
axi_arvalid <= 1'b0;
end
// retain the previous value
end
//--------------------------------
//Read Data (and Response) Channel
//--------------------------------
//The Read Data channel returns the results of the read request
//The master will accept the read data by asserting axi_rready
//when there is a valid read data available.
//While not necessary per spec, it is advisable to reset READY signals in
//case of differing reset latencies between master/slave.
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0)
begin
axi_rready <= 1'b0;
end
// accept/acknowledge rdata/rresp with axi_rready by the master
// when M_AXI_RVALID is asserted by slave
else if (M_AXI_RVALID && ~axi_rready)
begin
axi_rready <= 1'b1;
end
// deassert after one clock cycle
else if (axi_rready)
begin
axi_rready <= 1'b0;
end
// retain the previous value
end
//Flag write errors
assign read_resp_error = (axi_rready & M_AXI_RVALID & M_AXI_RRESP[1]);
//--------------------------------
//User Logic
//--------------------------------
//Address/Data Stimulus
//Address/data pairs for this example. The read and write values should
//match.
//Modify these as desired for different address patterns.
//Write Addresses
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0)
begin
axi_awaddr <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else if (wr_start)
begin
axi_awaddr <= wr_addr;
end
end
// Write data generation
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0)
begin
axi_wdata <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else if (wr_start)
begin
axi_wdata <= wr_data;
end
end
//Read Addresses
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0)
begin
axi_araddr <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else if (rd_start)
begin
axi_araddr <= rd_addr;
end
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 )
begin
rd_data <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else if (M_AXI_RVALID && axi_rready)
begin
rd_data <= M_AXI_RDATA;
end
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 )
begin
rd_done <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else if (M_AXI_RVALID && axi_rready)
begin
rd_done <= 1;
end
else
begin
rd_done <= 0;
end
end
// Add user logic here
// User logic ends
endmodule
VMDA_CONFIG
module vdma_config(
input wire clk ,
input wire rst_n ,
output reg wr_start ,
output wire [31:0] wr_addr ,
output wire [31:0] wr_data ,
input wire wr_done ,
output wire rd_start ,
output wire [31:0] rd_addr ,
input wire [31:0] rd_data ,
input wire rd_done
);
localparam REG_NUM = 14 ;
localparam VDMA_BASEADDR = 32'h43000000;
localparam VIDEO_BASEADDR0 = 32'h01000000;
localparam VIDEO_BASEADDR1 = 32'h02000000;
localparam VIDEO_BASEADDR2 = 32'h03000000;
localparam H_ACTIVE = 32'h780 ;
localparam V_ACTIVE = 32'h438 ;
localparam H_STRIDE = 32'h780 ;
reg [$clog2(REG_NUM) - 1:0] wr_cnt;
reg [$clog2(REG_NUM) - 1:0] rd_cnt;
reg [1:0] config_valid_r ;
always @(posedge clk)begin
config_valid_r <= {config_valid_r[0],rst_n};
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 0) begin
wr_start <= 0;
end
else if ((wr_done == 1 && wr_cnt != REG_NUM) || config_valid_r == 2'b01) begin
wr_start <= 1'b1;
end
else begin
wr_start <= 1'b0;
end
end
always @(posedge clk or negedge rst_n) begin
if(rst_n ==0) begin
wr_cnt <= 0;
end
else if(wr_start)begin
wr_cnt <= wr_cnt + 1;
end
end
reg [63:0] vdma_data;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
vdma_data <= 64'h0 ;
end
else begin
case(wr_cnt)
10'd0 : vdma_data <= {VDMA_BASEADDR + 32'h030,32'h108B};
10'd1 : vdma_data <= {VDMA_BASEADDR + 32'h0AC,VIDEO_BASEADDR0};
10'd2 : vdma_data <= {VDMA_BASEADDR + 32'h0B0,VIDEO_BASEADDR1};
10'd3 : vdma_data <= {VDMA_BASEADDR + 32'h0B4,VIDEO_BASEADDR2};
10'd4 : vdma_data <= {VDMA_BASEADDR + 32'h0A8,H_STRIDE};
10'd5 : vdma_data <= {VDMA_BASEADDR + 32'h0A4,H_ACTIVE};
10'd6 : vdma_data <= {VDMA_BASEADDR + 32'h0A0,V_ACTIVE};
10'd7 : vdma_data <= {VDMA_BASEADDR + 32'h000,32'h8B};
10'd8 : vdma_data <= {VDMA_BASEADDR + 32'h05C,VIDEO_BASEADDR0};
10'd9 : vdma_data <= {VDMA_BASEADDR + 32'h060,VIDEO_BASEADDR1};
10'd10 : vdma_data <= {VDMA_BASEADDR + 32'h064,VIDEO_BASEADDR2};
10'd11 : vdma_data <= {VDMA_BASEADDR + 32'h058,H_STRIDE};
10'd12 : vdma_data <= {VDMA_BASEADDR + 32'h054,H_ACTIVE};
10'd13 : vdma_data <= {VDMA_BASEADDR + 32'h050,V_ACTIVE};
default: vdma_data <= 0;
endcase
end
end
assign wr_addr = vdma_data[63:32];
assign wr_data = vdma_data[31:0 ];
assign rd_start = 0;
assign rd_addr = 0;
endmodule