文章目錄
- axi lite時序
-
- 寫操作時序
- 讀操作時序
- 建立工程
- 配置Zynq子產品
- 自定義Slave AXI_LITE接口的IP子產品
- 自定義Master AXI_LITE接口的IP子產品
-
- 接口子產品代碼
- 頂層子產品代碼
- 建立Verilog的master端測試子產品
- 實作Vivado工程
- SDK程式設計
本文使用工程源碼已上傳 https://download.csdn.net/download/botao_li/10891304
從本文檔開始将介紹PS和PL之間通過AXI總線互聯。
三種AXI總線協定為
- AXI_LITE:性能較低的位址映射傳輸,一次隻能傳輸4位元組
- AXI_STREAM:高速流資料傳輸,無位址映射,不能直接與PS連接配接
- AXI(又稱AXI_FULL):性能較高的位址映射傳輸
AXI_LITE一般用于小規模的資料互動,比如參數、指令或者狀态資訊
本文檔用AXI_LITE總線實作2項功能:
- PS讀寫PL的寄存器讀取闆上按鈕狀态控制LED燈開關
- PL讀寫PS的DDR記憶體
axi lite時序
下文中生成的AXI_LITE接口的IP子產品自帶的示例代碼可以修改後使用,AXI_LITE的接口時序來源于示例代碼的參考
寫操作時序
- master:同時設定awvalid和wvalid有效
- slave:等待awvalid和wvalid同時有效,同時将awready和wready設定1
- slave:在awvalid awready wvalid wready同時為1的情況下,bvalid設1,同時取出awaddr和wdata
- master:收到awready将awvalid設0,收到wready将wvalid設0
- master:收到bvalid将bready設1,下個時鐘周期設0
- slave:收到bready将bvalid設0
讀操作時序
- master:設定arvalidy為1
- slave:收到arvalid将arready設1,下個時鐘周期設0
- slave:在arready arvalid同時為1的情況下,rvalid設1,axi_rresp設0有效
- master:收到arready将arvalid設0
- master:收到rvalid将rready設1,下個時鐘周期設0
- slave:收到rready将rvalid設1
- master:在rready rvalid同時為1的情況下,檢查rdata數值
建立工程
與之前相同的方法建立zcu102的Vivado工程
配置Zynq子產品
建立Block Design,并添加Zynq子產品
選擇Run Block Automation
在彈出視窗中按照預設配置選擇OK
輕按兩下打開Zynq子產品配置,在PS-PL Configuration頁進行如下配置
使用pl_clk0作為PL端工作時鐘,并且連接配接2個AXI接口的aclk
自定義Slave AXI_LITE接口的IP子產品
在Tools菜單選擇Create and Package New IP
在彈出視窗中選中Create AXI4 Peripheral
選擇Edit IP後點選Finish
之後彈出目前IP的Vivado工程
在Sources視窗輕按兩下打開接口子產品
在代碼注釋中訓示的位置**(非必須)**添加自定義的子產品端口
注意:端口定義必須加上wire
根據代碼所示,前述步驟配置的4個32位寄存器分别為slv_reg0~3
若目前IP在PS端的基位址為base_addr,則slv_reg0讀寫位址為base_addr,slv_reg1讀寫位址為base_addr+4,svl_reg2和3以此類推
将slv_reg0用于寫入PL端LED,slv_reg1用于讀取PL端按鈕
根據注釋位置(位置非必須)添加以下代碼
并修改讀操作指派
打開IP的頂層子產品,進行如下修改
在目前IP的Vivado工程界面,在Tools菜單選擇Create and Package IP
選擇Package your current project
在彈出視窗選擇Overwrite
最後點選Finish
完成後關閉目前IP的Vivado工程
自定義Master AXI_LITE接口的IP子產品
參考[Slave AXI_LITE的子產品的生成](#自定義Slave AXI_LITE接口的IP子產品),進行如下配置
最後選擇Edit IP打開IP的Vivado工程
由于預設生成的示例代碼過于複雜,是以根據AXI_LITE接口時序全部重寫,并添加讀寫接口
進入Vivado工程後,使用與[自定義Slave接口IP相同的方式](#自定義Slave AXI_LITE接口的IP子產品)修改接口子產品和頂層子產品如下
接口子產品代碼
`timescale 1 ns / 1 ps
module master_axi_lite_v1_0_M00_AXI #
(
// Users to add parameters here
// User parameters ends
// Do not modify the parameters beyond this line
// The master will start generating data from the C_M_START_DATA_VALUE value
parameter C_M_START_DATA_VALUE = 32'hAA000000,
// 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'h40000000,
// 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,
// Transaction number is the number of write
// and read transactions the master will perform as a part of this example memory test.
parameter integer C_M_TRANSACTIONS_NUM = 4
)
(
// Users to add ports here
//寫接口
input wire wr_en,//寫使能
input wire [31:0] wr_addr,//相對寫位址,與寫使能對齊
input wire [31:0] wr_data,//寫資料,與寫使能對齊
output wire wr_done,//寫結束,單個時鐘周期有效
//讀接口
input wire rd_en,//讀使能,單個時鐘周期有效
input wire [31:0] rd_addr,//相對讀位址,與讀使能對齊
output wire rd_valid,//讀出資料有效,單個時鐘周期有效
output wire [31:0] rd_data,//讀出資料
output wire rd_done,//讀結束,單個時鐘周期有效
// User ports ends
// Do not modify the ports beyond this line
// // Initiate AXI transactions
// input wire INIT_AXI_TXN,
// // Asserts when ERROR is detected
// output reg ERROR,
// // Asserts when AXI transactions is complete
// output wire TXN_DONE,
// 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
);
assign M_AXI_AWPROT = 3'b000;
assign M_AXI_WSTRB = 4'b1111;
assign M_AXI_ARPROT = 3'b001;
reg [31:0] M_AXI_AWADDR_REG = 32'd0; assign M_AXI_AWADDR = M_AXI_AWADDR_REG;
reg M_AXI_AWVALID_REG = 1'b0; assign M_AXI_AWVALID = M_AXI_AWVALID_REG;
reg [31:0] M_AXI_WDATA_REG = 32'd0; assign M_AXI_WDATA = M_AXI_WDATA_REG;
reg M_AXI_WVALID_REG = 1'b0; assign M_AXI_WVALID = M_AXI_WVALID_REG;
reg M_AXI_BREADY_REG = 1'b0; assign M_AXI_BREADY = M_AXI_BREADY_REG;
reg [31:0] M_AXI_ARADDR_REG = 32'd0; assign M_AXI_ARADDR = M_AXI_ARADDR_REG;
reg M_AXI_ARVALID_REG = 1'b0; assign M_AXI_ARVALID = M_AXI_ARVALID_REG;
reg M_AXI_RREADY_REG = 1'b0; assign M_AXI_RREADY = M_AXI_RREADY_REG;
// Add user logic here
//寫操作*******************************************************************
always @(posedge M_AXI_ACLK) begin
if (wr_en == 1'b1) begin
//位址和資料同時有效
M_AXI_WDATA_REG <= wr_data;
M_AXI_WVALID_REG <= 1'b1;
end
else if ((M_AXI_WVALID_REG == 1'b1) && (M_AXI_WREADY == 1'b1)) begin
//收到slave響應
M_AXI_WDATA_REG <= M_AXI_WDATA_REG;
M_AXI_WVALID_REG <= 1'b0;
end
else begin
//保持
M_AXI_WDATA_REG <= M_AXI_WDATA_REG;
M_AXI_WVALID_REG <= M_AXI_WVALID_REG;
end
end
always @(posedge M_AXI_ACLK) begin
if (wr_en == 1'b1) begin
//位址和資料同時有效
M_AXI_AWADDR_REG <= wr_addr;
M_AXI_AWVALID_REG <= 1'b1;
end
else if ((M_AXI_AWVALID_REG == 1'b1) && (M_AXI_AWREADY == 1'b1)) begin
//收到slave響應
M_AXI_AWADDR_REG <= M_AXI_AWADDR_REG;
M_AXI_AWVALID_REG <= 1'b0;
end
else begin
//收到slave響應
M_AXI_AWADDR_REG <= M_AXI_AWADDR_REG;
M_AXI_AWVALID_REG <= M_AXI_AWVALID_REG;
end
end
always @(posedge M_AXI_ACLK) begin
case (M_AXI_BREADY_REG)
1'b0: begin
//收到bvalid即設定為1
if (M_AXI_BVALID == 1'b1) begin
M_AXI_BREADY_REG <= 1'b1;
end
else begin
M_AXI_BREADY_REG <= M_AXI_BREADY_REG;
end
end
1'b1: begin
//高電平僅1個時鐘周期
M_AXI_BREADY_REG <= 1'b0;
end
endcase
end
assign wr_done = M_AXI_BREADY_REG;
//讀操作************************************************
always @(posedge M_AXI_ACLK) begin
if (rd_en == 1'b1) begin
M_AXI_ARADDR_REG <= rd_addr;
M_AXI_ARVALID_REG <= 1'b1;
end
else if ((M_AXI_ARVALID_REG == 1'b1) && (M_AXI_ARREADY == 1'b1)) begin
M_AXI_ARADDR_REG <= M_AXI_ARADDR_REG;
M_AXI_ARVALID_REG <= 1'b0;
end
else begin
//保持
M_AXI_ARADDR_REG <= M_AXI_ARADDR_REG;
M_AXI_ARVALID_REG <= M_AXI_ARVALID_REG;
end
end
always @(posedge M_AXI_ACLK) begin
case (M_AXI_RREADY_REG)
1'b0: begin
if (M_AXI_RVALID == 1'b1) begin
M_AXI_RREADY_REG <= 1'b1;
end
else begin
M_AXI_RREADY_REG <= M_AXI_RREADY_REG;
end
end
1'b1: begin
M_AXI_RREADY_REG <= 1'b0;
end
endcase
end
assign rd_done = M_AXI_RREADY_REG;
assign rd_valid = M_AXI_RREADY_REG;
reg [31:0] rd_data_reg = 32'd0;
assign rd_data = rd_data_reg;
always @(posedge M_AXI_ACLK) begin
if ((M_AXI_RVALID == 1'b1) && (M_AXI_RREADY_REG == 1'b0)) begin
rd_data_reg <= M_AXI_RDATA;
end
else begin
rd_data_reg <= rd_data_reg;
end
end
// User logic ends
endmodule
頂層子產品代碼
`timescale 1 ns / 1 ps
module master_axi_lite_v1_0 #
(
// Users to add parameters here
// User parameters ends
// Do not modify the parameters beyond this line
// Parameters of Axi Master Bus Interface M00_AXI
parameter C_M00_AXI_START_DATA_VALUE = 32'hAA000000,
parameter C_M00_AXI_TARGET_SLAVE_BASE_ADDR = 32'h40000000,
parameter integer C_M00_AXI_ADDR_WIDTH = 32,
parameter integer C_M00_AXI_DATA_WIDTH = 32,
parameter integer C_M00_AXI_TRANSACTIONS_NUM = 4
)
(
// Users to add ports here
//寫接口
input wire wr_en,//寫使能
input wire [31:0] wr_addr,//相對寫位址,與寫使能對齊
input wire [31:0] wr_data,//寫資料,與寫使能對齊
output wire wr_done,//寫結束,單個時鐘周期有效
//讀接口
input wire rd_en,//讀使能,單個時鐘周期有效
input wire [31:0] rd_addr,//相對讀位址,與讀使能對齊
output wire rd_valid,//讀出資料有效,單個時鐘周期有效
output wire [31:0] rd_data,//讀出資料
output wire rd_done,//讀結束,單個時鐘周期有效
// User ports ends
// Do not modify the ports beyond this line
// Ports of Axi Master Bus Interface M00_AXI
// input wire m00_axi_init_axi_txn,
// output wire m00_axi_error,
// output wire m00_axi_txn_done,
input wire m00_axi_aclk,
input wire m00_axi_aresetn,
output wire [C_M00_AXI_ADDR_WIDTH-1 : 0] m00_axi_awaddr,
output wire [2 : 0] m00_axi_awprot,
output wire m00_axi_awvalid,
input wire m00_axi_awready,
output wire [C_M00_AXI_DATA_WIDTH-1 : 0] m00_axi_wdata,
output wire [C_M00_AXI_DATA_WIDTH/8-1 : 0] m00_axi_wstrb,
output wire m00_axi_wvalid,
input wire m00_axi_wready,
input wire [1 : 0] m00_axi_bresp,
input wire m00_axi_bvalid,
output wire m00_axi_bready,
output wire [C_M00_AXI_ADDR_WIDTH-1 : 0] m00_axi_araddr,
output wire [2 : 0] m00_axi_arprot,
output wire m00_axi_arvalid,
input wire m00_axi_arready,
input wire [C_M00_AXI_DATA_WIDTH-1 : 0] m00_axi_rdata,
input wire [1 : 0] m00_axi_rresp,
input wire m00_axi_rvalid,
output wire m00_axi_rready
);
// Instantiation of Axi Bus Interface M00_AXI
master_axi_lite_v1_0_M00_AXI # (
.C_M_START_DATA_VALUE(C_M00_AXI_START_DATA_VALUE),
.C_M_TARGET_SLAVE_BASE_ADDR(C_M00_AXI_TARGET_SLAVE_BASE_ADDR),
.C_M_AXI_ADDR_WIDTH(C_M00_AXI_ADDR_WIDTH),
.C_M_AXI_DATA_WIDTH(C_M00_AXI_DATA_WIDTH),
.C_M_TRANSACTIONS_NUM(C_M00_AXI_TRANSACTIONS_NUM)
) master_axi_lite_v1_0_M00_AXI_inst (
// .INIT_AXI_TXN(m00_axi_init_axi_txn),
// .ERROR(m00_axi_error),
// .TXN_DONE(m00_axi_txn_done),
.M_AXI_ACLK(m00_axi_aclk),
.M_AXI_ARESETN(m00_axi_aresetn),
.M_AXI_AWADDR(m00_axi_awaddr),
.M_AXI_AWPROT(m00_axi_awprot),
.M_AXI_AWVALID(m00_axi_awvalid),
.M_AXI_AWREADY(m00_axi_awready),
.M_AXI_WDATA(m00_axi_wdata),
.M_AXI_WSTRB(m00_axi_wstrb),
.M_AXI_WVALID(m00_axi_wvalid),
.M_AXI_WREADY(m00_axi_wready),
.M_AXI_BRESP(m00_axi_bresp),
.M_AXI_BVALID(m00_axi_bvalid),
.M_AXI_BREADY(m00_axi_bready),
.M_AXI_ARADDR(m00_axi_araddr),
.M_AXI_ARPROT(m00_axi_arprot),
.M_AXI_ARVALID(m00_axi_arvalid),
.M_AXI_ARREADY(m00_axi_arready),
.M_AXI_RDATA(m00_axi_rdata),
.M_AXI_RRESP(m00_axi_rresp),
.M_AXI_RVALID(m00_axi_rvalid),
.M_AXI_RREADY(m00_axi_rready),
.wr_en(wr_en),
.wr_addr(wr_addr),
.wr_data(wr_data),
.wr_done(wr_done),
.rd_en(rd_en),
.rd_addr(rd_addr),
.rd_valid(rd_valid),
.rd_data(rd_data),
.rd_done(rd_done)
);
// Add user logic here
// User logic ends
endmodule
最後,參考[Slave AXI_LITE的子產品的生成](#自定義Slave AXI_LITE接口的IP子產品),打包IP
建立Verilog的master端測試子產品
在Sources視窗建立新verilog子產品,命名為master_test.v,用于連接配接master_axi_lite的讀寫接口進行測試
代碼如下:
module master_test(
(*keep = "TRUE"*) input clk,
(*keep = "TRUE"*) input rstn,
(*keep = "TRUE"*) output wr_en,
(*keep = "TRUE"*) output [31:0] wr_addr,
(*keep = "TRUE"*) output [31:0] wr_data,
(*keep = "TRUE"*) input wr_done,
(*keep = "TRUE"*) output rd_en,
(*keep = "TRUE"*) output [31:0] rd_addr,
(*keep = "TRUE"*) input rd_valid,
(*keep = "TRUE"*) input [31:0] rd_data,
(*keep = "TRUE"*) input rd_done
);
parameter [31:0] BASE_ADDR = 32'h7000_0000;
parameter [31:0] MAX_ADDR = 32'h7800_0000;
reg wr_en = 1'b0;
reg [31:0] wr_addr = BASE_ADDR;
assign wr_data = wr_addr;
reg rd_en = 1'b0;
reg [31:0] rd_addr = BASE_ADDR;
reg [31:0] cnt = 32'd0;//等待時間2秒
//狀态機
parameter [4:0] IDLE = 5'b00001;
parameter [4:0] WR = 5'b00010;
parameter [4:0] WR_DONE = 5'b00100;
parameter [4:0] RD = 5'b01000;
parameter [4:0] RD_DONE = 5'b10000;
reg [4:0] state = IDLE;
always @(posedge clk) begin
if (rstn == 1'b0) begin
state = IDLE;
end
else begin
case (state)
IDLE: begin
if (cnt == 32'd200_000_000) begin
state <= WR;
end
else begin
state <= state;
end
end
WR: begin
state <= WR_DONE;
end
WR_DONE: begin
if (wr_done == 1'b1) begin
state <= RD;
end
else begin
state <= state;
end
end
RD: begin
state <= RD_DONE;
end
RD_DONE: begin
if (rd_done == 1'b1) begin
state <= WR;
end
else begin
state <= state;
end
end
default: begin
state = IDLE;
end
endcase
end
end
always @(posedge clk) begin
if (rstn == 1'b0) begin
cnt <= 32'd0;
end
else begin
if (state == IDLE) begin
cnt <= cnt+32'd1;
end
else begin
cnt <= 32'd0;
end
end
end
always @(posedge clk) begin
if (rstn == 1'b0) begin
wr_en <= 1'b0;
wr_addr <= BASE_ADDR;
end
else begin
case (state)
WR: begin
wr_en <= 1'b1;
wr_addr <= wr_addr;
end
WR_DONE: begin
wr_en <= 1'b0;
if (wr_done == 1'b1) begin
//更新寫位址
if (wr_addr == MAX_ADDR) begin
wr_addr <= BASE_ADDR;
end
else begin
wr_addr <= wr_addr+32'd4;
end
end
else begin
wr_addr <= wr_addr;
end
end
default: begin
wr_en <= 1'b0;
wr_addr <= wr_addr;
end
endcase
end
end
always @(posedge clk) begin
if (rstn == 1'b0) begin
rd_en <= 1'b0;
rd_addr <= BASE_ADDR;
end
else begin
case (state)
RD: begin
rd_en <= 1'b1;
rd_addr <= rd_addr;
end
RD_DONE: begin
rd_en <= 1'b0;
if (rd_done == 1'b1) begin
//更新讀位址
if (rd_addr == MAX_ADDR) begin
rd_addr <= BASE_ADDR;
end
else begin
rd_addr <= rd_addr+32'd4;
end
end
else begin
rd_addr <= rd_addr;
end
end
default: begin
rd_en <= 1'b0;
rd_addr <= rd_addr;
end
endcase
end
end
//統計錯誤
(*keep = "TRUE"*) reg [31:0] error_cnt = 32'd0;
always @(posedge clk) begin
if ((state == RD_DONE) && (rd_valid == 1'b1) && (rd_data != rd_addr)) begin
error_cnt <= error_cnt+32'd1;
end
else begin
error_cnt <= error_cnt;
end
end
endmodule
實作Vivado工程
回到之前建立的Zynq工程
在PROJECT MANAGER内打開Settings,在IP > Repository頁确認前述2個IP的路徑已添加
向Block Design中添加2個自定義的AXI_LITE子產品
之後從Sources視窗将master_test.v檔案用滑鼠拖動至Diagram視窗,自動生成master_test的子產品
在Block Design點選Run Connection Automation
點選OK後,Block Design完成自動連接配接
之後手動連接配接master_test與master_axi_lite子產品的接口
完成連接配接後的Diagram如下:
在Block Design上右鍵菜單執行Generate Output Products,完成後在右鍵菜單執行Create HDL Wrapper
在Flow Navigator中Run Synthesis,完成後,打開Synthesized Design,從Layout菜單打開I/O Planning視窗設定button和leds管腳
儲存并建立xdc限制檔案top.xdc
接下來在Flow Navigator中SYNTHESIS下選擇Set Up Debug,添加master_test中的測試信号
最終的top.xdc檔案内容如下:
set_property PACKAGE_PIN AG14 [get_ports {leds_0[0]}]
set_property PACKAGE_PIN AF13 [get_ports {leds_0[1]}]
set_property PACKAGE_PIN AE13 [get_ports {leds_0[2]}]
set_property PACKAGE_PIN AJ14 [get_ports {leds_0[3]}]
set_property PACKAGE_PIN AJ15 [get_ports {leds_0[4]}]
set_property PACKAGE_PIN AH13 [get_ports {leds_0[5]}]
set_property PACKAGE_PIN AH14 [get_ports {leds_0[6]}]
set_property PACKAGE_PIN AL12 [get_ports {leds_0[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_0[2]}]
set_property PACKAGE_PIN AF15 [get_ports button_0]
set_property IOSTANDARD LVCMOS33 [get_ports button_0]
create_debug_core u_ila_0 ila
set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0]
set_property ALL_PROBE_SAME_MU_CNT 1 [get_debug_cores u_ila_0]
set_property C_ADV_TRIGGER false [get_debug_cores u_ila_0]
set_property C_DATA_DEPTH 2048 [get_debug_cores u_ila_0]
set_property C_EN_STRG_QUAL false [get_debug_cores u_ila_0]
set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores u_ila_0]
set_property C_TRIGIN_EN false [get_debug_cores u_ila_0]
set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0]
set_property port_width 1 [get_debug_ports u_ila_0/clk]
connect_debug_port u_ila_0/clk [get_nets [list bd_i/zynq_ultra_ps_e_0/inst/pl_clk0]]
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe0]
set_property port_width 32 [get_debug_ports u_ila_0/probe0]
connect_debug_port u_ila_0/probe0 [get_nets [list {bd_i/master_test_0/rd_data[0]} {bd_i/master_test_0/rd_data[1]} {bd_i/master_test_0/rd_data[2]} {bd_i/master_test_0/rd_data[3]} {bd_i/master_test_0/rd_data[4]} {bd_i/master_test_0/rd_data[5]} {bd_i/master_test_0/rd_data[6]} {bd_i/master_test_0/rd_data[7]} {bd_i/master_test_0/rd_data[8]} {bd_i/master_test_0/rd_data[9]} {bd_i/master_test_0/rd_data[10]} {bd_i/master_test_0/rd_data[11]} {bd_i/master_test_0/rd_data[12]} {bd_i/master_test_0/rd_data[13]} {bd_i/master_test_0/rd_data[14]} {bd_i/master_test_0/rd_data[15]} {bd_i/master_test_0/rd_data[16]} {bd_i/master_test_0/rd_data[17]} {bd_i/master_test_0/rd_data[18]} {bd_i/master_test_0/rd_data[19]} {bd_i/master_test_0/rd_data[20]} {bd_i/master_test_0/rd_data[21]} {bd_i/master_test_0/rd_data[22]} {bd_i/master_test_0/rd_data[23]} {bd_i/master_test_0/rd_data[24]} {bd_i/master_test_0/rd_data[25]} {bd_i/master_test_0/rd_data[26]} {bd_i/master_test_0/rd_data[27]} {bd_i/master_test_0/rd_data[28]} {bd_i/master_test_0/rd_data[29]} {bd_i/master_test_0/rd_data[30]} {bd_i/master_test_0/rd_data[31]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe1]
set_property port_width 32 [get_debug_ports u_ila_0/probe1]
connect_debug_port u_ila_0/probe1 [get_nets [list {bd_i/master_test_0/rd_addr[0]} {bd_i/master_test_0/rd_addr[1]} {bd_i/master_test_0/rd_addr[2]} {bd_i/master_test_0/rd_addr[3]} {bd_i/master_test_0/rd_addr[4]} {bd_i/master_test_0/rd_addr[5]} {bd_i/master_test_0/rd_addr[6]} {bd_i/master_test_0/rd_addr[7]} {bd_i/master_test_0/rd_addr[8]} {bd_i/master_test_0/rd_addr[9]} {bd_i/master_test_0/rd_addr[10]} {bd_i/master_test_0/rd_addr[11]} {bd_i/master_test_0/rd_addr[12]} {bd_i/master_test_0/rd_addr[13]} {bd_i/master_test_0/rd_addr[14]} {bd_i/master_test_0/rd_addr[15]} {bd_i/master_test_0/rd_addr[16]} {bd_i/master_test_0/rd_addr[17]} {bd_i/master_test_0/rd_addr[18]} {bd_i/master_test_0/rd_addr[19]} {bd_i/master_test_0/rd_addr[20]} {bd_i/master_test_0/rd_addr[21]} {bd_i/master_test_0/rd_addr[22]} {bd_i/master_test_0/rd_addr[23]} {bd_i/master_test_0/rd_addr[24]} {bd_i/master_test_0/rd_addr[25]} {bd_i/master_test_0/rd_addr[26]} {bd_i/master_test_0/rd_addr[27]} {bd_i/master_test_0/rd_addr[28]} {bd_i/master_test_0/rd_addr[29]} {bd_i/master_test_0/rd_addr[30]} {bd_i/master_test_0/rd_addr[31]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe2]
set_property port_width 32 [get_debug_ports u_ila_0/probe2]
connect_debug_port u_ila_0/probe2 [get_nets [list {bd_i/master_test_0/wr_addr[0]} {bd_i/master_test_0/wr_addr[1]} {bd_i/master_test_0/wr_addr[2]} {bd_i/master_test_0/wr_addr[3]} {bd_i/master_test_0/wr_addr[4]} {bd_i/master_test_0/wr_addr[5]} {bd_i/master_test_0/wr_addr[6]} {bd_i/master_test_0/wr_addr[7]} {bd_i/master_test_0/wr_addr[8]} {bd_i/master_test_0/wr_addr[9]} {bd_i/master_test_0/wr_addr[10]} {bd_i/master_test_0/wr_addr[11]} {bd_i/master_test_0/wr_addr[12]} {bd_i/master_test_0/wr_addr[13]} {bd_i/master_test_0/wr_addr[14]} {bd_i/master_test_0/wr_addr[15]} {bd_i/master_test_0/wr_addr[16]} {bd_i/master_test_0/wr_addr[17]} {bd_i/master_test_0/wr_addr[18]} {bd_i/master_test_0/wr_addr[19]} {bd_i/master_test_0/wr_addr[20]} {bd_i/master_test_0/wr_addr[21]} {bd_i/master_test_0/wr_addr[22]} {bd_i/master_test_0/wr_addr[23]} {bd_i/master_test_0/wr_addr[24]} {bd_i/master_test_0/wr_addr[25]} {bd_i/master_test_0/wr_addr[26]} {bd_i/master_test_0/wr_addr[27]} {bd_i/master_test_0/wr_addr[28]} {bd_i/master_test_0/wr_addr[29]} {bd_i/master_test_0/wr_addr[30]} {bd_i/master_test_0/wr_addr[31]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe3]
set_property port_width 32 [get_debug_ports u_ila_0/probe3]
connect_debug_port u_ila_0/probe3 [get_nets [list {bd_i/master_test_0/wr_data[0]} {bd_i/master_test_0/wr_data[1]} {bd_i/master_test_0/wr_data[2]} {bd_i/master_test_0/wr_data[3]} {bd_i/master_test_0/wr_data[4]} {bd_i/master_test_0/wr_data[5]} {bd_i/master_test_0/wr_data[6]} {bd_i/master_test_0/wr_data[7]} {bd_i/master_test_0/wr_data[8]} {bd_i/master_test_0/wr_data[9]} {bd_i/master_test_0/wr_data[10]} {bd_i/master_test_0/wr_data[11]} {bd_i/master_test_0/wr_data[12]} {bd_i/master_test_0/wr_data[13]} {bd_i/master_test_0/wr_data[14]} {bd_i/master_test_0/wr_data[15]} {bd_i/master_test_0/wr_data[16]} {bd_i/master_test_0/wr_data[17]} {bd_i/master_test_0/wr_data[18]} {bd_i/master_test_0/wr_data[19]} {bd_i/master_test_0/wr_data[20]} {bd_i/master_test_0/wr_data[21]} {bd_i/master_test_0/wr_data[22]} {bd_i/master_test_0/wr_data[23]} {bd_i/master_test_0/wr_data[24]} {bd_i/master_test_0/wr_data[25]} {bd_i/master_test_0/wr_data[26]} {bd_i/master_test_0/wr_data[27]} {bd_i/master_test_0/wr_data[28]} {bd_i/master_test_0/wr_data[29]} {bd_i/master_test_0/wr_data[30]} {bd_i/master_test_0/wr_data[31]}]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe4]
set_property port_width 1 [get_debug_ports u_ila_0/probe4]
connect_debug_port u_ila_0/probe4 [get_nets [list bd_i/master_test_0/rd_done]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe5]
set_property port_width 1 [get_debug_ports u_ila_0/probe5]
connect_debug_port u_ila_0/probe5 [get_nets [list bd_i/master_test_0/rd_en]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe6]
set_property port_width 1 [get_debug_ports u_ila_0/probe6]
connect_debug_port u_ila_0/probe6 [get_nets [list bd_i/master_test_0/rd_valid]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe7]
set_property port_width 1 [get_debug_ports u_ila_0/probe7]
connect_debug_port u_ila_0/probe7 [get_nets [list bd_i/master_test_0/wr_done]]
create_debug_port u_ila_0 probe
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe8]
set_property port_width 1 [get_debug_ports u_ila_0/probe8]
connect_debug_port u_ila_0/probe8 [get_nets [list bd_i/master_test_0/wr_en]]
set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub]
set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub]
set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub]
connect_debug_port dbg_hub/clk [get_nets u_ila_0_pl_clk0]
在Flow Navigator中PROGRAM AND DEBUG選擇Generate Bitstream
完成後在File菜單選擇Export > Export Hardware,注意選中Include bitstream
之後在File菜單選擇Launch SDK
SDK程式設計
預設建立的bd_wrapper_hw_platform_0工程目錄中已包含前文生成的bit配置檔案
根據HelloWorld模闆建立test_axi_lite工程
SDK工程用于測試slave_axi_lite,即按鈕控制led開關
修改helloworld.c檔案代碼如下:
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xil_io.h"
#include "sleep.h"
int main()
{
init_platform();
print("Hello World\n\r");
Xil_Out32(XPAR_SLAVE_AXI_LITE_V1_0_0_BASEADDR, 1);//點亮LED
u32 led = 1;
u32 button = 0;
while (1)
{
usleep(100000);
button = Xil_In32(XPAR_SLAVE_AXI_LITE_V1_0_0_BASEADDR+4);
if (button == 0xFFFFFFFF)
{
//列印消息
print("button pressed\n\r");
//複位
button = 0;
//按鈕按下
if (led == 0)
{
led = 1;
}
else
{
led = 0;
}
Xil_Out32(XPAR_SLAVE_AXI_LITE_V1_0_0_BASEADDR, led);
}
}
cleanup_platform();
return 0;
}
在test_axi_lite工程選擇Debug Configurations
配置如下:
注意,一定不能在Vivado中加載FPGA,再啟動PS程式。PL程式會在PS載入過程中被清除!!!
在SDK中啟動調試
發現按鈕控制led開關功能正确
回到Vivado,從Hardware Manager進入Debugl界面,測試發現master_test運作正确: