超群天晴

【原创】一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计

0
阅读(3462)

本小节通过使用XPS中的定制IP向导(ipwiz),为已经存在的ARM PS 系统添加用户自定IP(Custom IP ),了解AXI Lite IP基本结构,并掌握AXI Lite IP的定制方法,为后续编写复杂AXI IP打下基础。同时本小节IP定制方法同样适用于MicroBlaze处理系统。

本小节定制的是简单LED的IP,只有一个数据寄存器,向其写值就可以控制8个LED相应亮灭。

更多更新请关注我的博客:@超群天晴http://www.cnblogs.com/surpassal/

硬件平台:DigilentZedBoard

开发环境:Windows XP 32 bit

软件:XPS 14.2 +SDK 14.2

一、创建ARM PS系统

同前面几节一样,首先使用XPS创建ARM PS系统。需要注意的是,在选择外设时,同样不要添加任何外设

二、定制AXI IP

ARM PS系统创建结束后,就可以开始定制用户自定义IP。XPS提供了Create or Import Peripheral Wizward 向导,使得用户自定义IP的创建变得非常简单。当然在熟悉了AXI IP核结构和代码编写规则后,可以直接编写自己的IP核而不使用向导。这里采用向导方式。

1、产生AXI IP外设模版

Hardware->Create or Import Peripheral Wizward ,启动向导

欢迎界面

选择从模板创建新外设

默认是将外设直接包含到当前XPS工程中

填入外设名。注意必须都是小写。这里我们建立的是my_axi_ip。下面是版本控制,可以根据需要修改。同时面板的最下方还提示了将创建名为my_axi_ip_v1_00_a的库(其实就是一个目录),所有实现这个IP的HDL文件都在这个库中。

接下来要选择外设总线的类型。AXI4_Lite为最基本的AXI 总线,用于简单处理,所有空间访问都是通过地址/寄存器方式访问,不支持突发;AXI4是标准AXI4总线标准,支持突然,支持高速;AXI4_Stream专门为数据流而设计。

在IPIF (IP 接口) 配置,这里配置接口的一些属性,如是否是AXI 主/从设备等。我们所定制的IP是一个从设备,因而不需要使用主设备接口。

选择需啊哟的寄存器数量。因为我们只需要一个数据寄存器,这里选1。

接下来就是IPIC(IP 互联),也就是IP的接口信号。以BUS2开头的信号,意味对IP来说,这些信号是输入信号;同样IP2BUS意味着输出信号。

这里一些信号做一些说明。

BUS2IP_WrCE(Write Chip Enable,写使能)

Active high chip enable bus to the user logic. These chip enables are asserted only during active write transaction requests with the target address space andinconjunction with the corresponding sub-address within the space. Typically usedforuser logic writable registers selection.


BUS2IP_Data(Write Data,写数据)

Write data bus to the user logic. Write dataisaccepted by the user logic during a write operation by assertion of the write acknowledgement signal and the rising edge of the Bus2IP_Clk.


Write data bus to the user logic. Write dataisaccepted by the user logic during a write operation by assertion of the write acknowledgement signal and the rising edge of the Bus2IP_Clk.

BUS2IP_BE(Byte Enable,字节使能)

Byte Enable qualifiers forthe requested read or write operation to the user logic. A bit inthe Bus2IP_BE setto ' 1 'indicates that the associated bytelane contains valid data. For example, ifBus2IP_BE = 0011, thisindicates that bytelanes 2and 3contain valid data.

IPBUS2_RdAck(Read Acknowledgement,读反馈)

Active high read data qualifier providing the read acknowledgement fromthe user logic. Read data on the IP2Bus_Data bus isdeemed valid at the rising edge of the Bus2IP_Clk and IP2Bus_RdAck asserted high by the user logic.

接下来需要使用需要使用BFM (Bus Functional Models, 总线功能模型)对外设进行仿真。本例IP很简单,不要使用。

最后,需要选择HDL类型、ISE工程支持和软件驱动模板。因为我比较习惯使用verilog,因而使用verilog模板。需要说明的是,IP接口仍然是VHDL编写,只是用户逻辑改用verilog。如果不需要使用软件驱动模板的话,可以不选上。这里选上了,但是后续编程的时候我并没有用。

最后给出了外设的信息summary。支持,my_axi_ip"外壳"基本完成。后续我们只需要对user_logic进行编写,并修改元件引脚即可。

2、编写IP

修改.mpd文件,在目录

Lab4\pcores\my_axi_ip_v1_00_a\data\

复制代码
1###################################################################
2##
3## Name : my_axi_ip
4## Desc : Microprocessor Peripheral Description
5## : Automatically generated by PsfUtility
6##
7###################################################################
8
9BEGIN my_axi_ip
10
11## Peripheral Options
12OPTION IPTYPE =PERIPHERAL
13OPTION IMP_NETLIST =TRUE
14OPTION HDL =MIXED
15OPTION IP_GROUP = MICROBLAZE:USER
16OPTION DESC =MY_AXI_IP
17OPTION ARCH_SUPPORT_MAP = (others=DEVELOPMENT)
18
19
20## Bus Interfaces
21BUS_INTERFACE BUS = S_AXI, BUS_STD = AXI, BUS_TYPE =SLAVE
22
23## Generics for VHDL or Parameters for Verilog
24PARAMETER C_S_AXI_DATA_WIDTH =32, DT = INTEGER, BUS = S_AXI, ASSIGNMENT =CONSTANT
25PARAMETER C_S_AXI_ADDR_WIDTH =32, DT = INTEGER, BUS = S_AXI, ASSIGNMENT =CONSTANT
26PARAMETER C_S_AXI_MIN_SIZE =0x000001ff, DT = std_logic_vector, BUS =S_AXI
27PARAMETER C_USE_WSTRB =0, DT =INTEGER
28PARAMETER C_DPHASE_TIMEOUT =8, DT =INTEGER
29PARAMETER C_BASEADDR =0xffffffff, DT = std_logic_vector, MIN_SIZE =0x100, PAIR = C_HIGHADDR, ADDRESS = BASE, BUS =S_AXI
30PARAMETER C_HIGHADDR =0x00000000, DT = std_logic_vector, PAIR = C_BASEADDR, ADDRESS = HIGH, BUS =S_AXI
31PARAMETER C_FAMILY = virtex6, DT =STRING
32PARAMETER C_NUM_REG =1, DT =INTEGER
33PARAMETER C_NUM_MEM =1, DT =INTEGER
34PARAMETER C_SLV_AWIDTH =32, DT =INTEGER
35PARAMETER C_SLV_DWIDTH =32, DT =INTEGER
36PARAMETER C_S_AXI_PROTOCOL = AXI4LITE, TYPE = NON_HDL, ASSIGNMENT = CONSTANT, DT = STRING, BUS =S_AXI
37
38## Ports
39PORT LED ="", DIR = O,VEC= [7:0]
40PORT S_AXI_ACLK ="", DIR = I, SIGIS = CLK, BUS =S_AXI
41PORT S_AXI_ARESETN = ARESETN, DIR = I, SIGIS = RST, BUS =S_AXI
42PORT S_AXI_AWADDR = AWADDR, DIR = I,VEC= [(C_S_AXI_ADDR_WIDTH-1):0], ENDIAN = LITTLE, BUS =S_AXI
43PORT S_AXI_AWVALID = AWVALID, DIR = I, BUS =S_AXI
44PORT S_AXI_WDATA = WDATA, DIR = I,VEC= [(C_S_AXI_DATA_WIDTH-1):0], ENDIAN = LITTLE, BUS =S_AXI
45PORT S_AXI_WSTRB = WSTRB, DIR = I,VEC= [((C_S_AXI_DATA_WIDTH/8)-1):0], ENDIAN = LITTLE, BUS =S_AXI
46PORT S_AXI_WVALID = WVALID, DIR = I, BUS =S_AXI
47PORT S_AXI_BREADY = BREADY, DIR = I, BUS =S_AXI
48PORT S_AXI_ARADDR = ARADDR, DIR = I,VEC= [(C_S_AXI_ADDR_WIDTH-1):0], ENDIAN = LITTLE, BUS =S_AXI
49PORT S_AXI_ARVALID = ARVALID, DIR = I, BUS =S_AXI
50PORT S_AXI_RREADY = RREADY, DIR = I, BUS =S_AXI
51PORT S_AXI_ARREADY = ARREADY, DIR = O, BUS =S_AXI
52PORT S_AXI_RDATA = RDATA, DIR = O,VEC= [(C_S_AXI_DATA_WIDTH-1):0], ENDIAN = LITTLE, BUS =S_AXI
53PORT S_AXI_RRESP = RRESP, DIR = O,VEC= [1:0], BUS =S_AXI
54PORT S_AXI_RVALID = RVALID, DIR = O, BUS =S_AXI
55PORT S_AXI_WREADY = WREADY, DIR = O, BUS =S_AXI
56PORT S_AXI_BRESP = BRESP, DIR = O,VEC= [1:0], BUS =S_AXI
57PORT S_AXI_BVALID = BVALID, DIR = O, BUS =S_AXI
58PORT S_AXI_AWREADY = AWREADY, DIR = O, BUS =S_AXI
59
60END

复制代码

其中,第39行


PORT LED ="", DIR = O,VEC= [7:0]

是我们添加上的,表明我们为其添加了一个名为LED的端口,方向是输出,长度是8位。其他行代码为默认,不需要修改。

修改用户逻辑,在

Lab4\pcores\my_axi_ip_v1_00_a\hdl\verilog\user_logic.v

复制代码
1//----------------------------------------------------------------------------
2//user_logic.v - module
3//----------------------------------------------------------------------------
4//
5//***************************************************************************
6//** Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved. **
7//** **
8//** Xilinx, Inc. **
9//** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" **
10//** AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND **
11//** SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, **
12//** OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, **
13//** APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION **
14//** THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, **
15//** AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE **
16//** FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY **
17//** WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE **
18//** IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR **
19//** REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF **
20//** INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS **
21//** FOR A PARTICULAR PURPOSE. **
22//** **
23//***************************************************************************
24//
25//----------------------------------------------------------------------------
26//Filename: user_logic.v
27//Version: 1.00.a
28//Description: User logic module.
29//Date: Tue Oct 09 18:28:06 2012 (by Create and Import Peripheral Wizard)
30//Verilog Standard: Verilog-2001
31//----------------------------------------------------------------------------
32//Naming Conventions:
33//active low signals: "*_n"
34//clock signals: "clk", "clk_div#", "clk_#x"
35//reset signals: "rst", "rst_n"
36//generics: "C_*"
37//user defined types: "*_TYPE"
38//state machine next state: "*_ns"
39//state machine current state: "*_cs"
40//combinatorial signals: "*_com"
41//pipelined or register delay signals: "*_d#"
42//counter signals: "*cnt*"
43//clock enable signals: "*_ce"
44//internal version of output port: "*_i"
45//device pins: "*_pin"
46//ports: "- Names begin with Uppercase"
47//processes: "*_PROCESS"
48//component instantiations: "I_<#|FUNC>"
49//----------------------------------------------------------------------------
50
51`uselib lib=unisims_ver
52`uselib lib=proc_common_v3_00_a
53
54moduleuser_logic
55(
56//-- ADD USER PORTS BELOW THIS LINE ---------------
57LED,
58//-- ADD USER PORTS ABOVE THIS LINE ---------------
59
60//-- DO NOT EDIT BELOW THIS LINE ------------------
61//-- Bus protocol ports, do not add to or delete
62Bus2IP_Clk,//Bus to IP clock
63Bus2IP_Resetn,//Bus to IP reset
64Bus2IP_Data,//Bus to IP data bus
65Bus2IP_BE,//Bus to IP byte enables
66Bus2IP_RdCE,//Bus to IP read chip enable
67Bus2IP_WrCE,//Bus to IP write chip enable
68IP2Bus_Data,//IP to Bus data bus
69IP2Bus_RdAck,//IP to Bus read transfer acknowledgement
70IP2Bus_WrAck,//IP to Bus write transfer acknowledgement
71IP2Bus_Error//IP to Bus error response
72//-- DO NOT EDIT ABOVE THIS LINE ------------------
73);//user_logic
74
75//-- ADD USER PARAMETERS BELOW THIS LINE ------------
76//--USER parameters added here
77//-- ADD USER PARAMETERS ABOVE THIS LINE ------------
78
79//-- DO NOT EDIT BELOW THIS LINE --------------------
80//-- Bus protocol parameters, do not add to or delete
81parameterC_NUM_REG =1;
82parameterC_SLV_DWIDTH =32;
83//-- DO NOT EDIT ABOVE THIS LINE --------------------
84
85//-- ADD USER PORTS BELOW THIS LINE -----------------
86output[7:0] LED;
87//-- ADD USER PORTS ABOVE THIS LINE -----------------
88
89//-- DO NOT EDIT BELOW THIS LINE --------------------
90//-- Bus protocol ports, do not add to or delete
91inputBus2IP_Clk;
92inputBus2IP_Resetn;
93input[C_SLV_DWIDTH-1:0] Bus2IP_Data;
94input[C_SLV_DWIDTH/8-1:0] Bus2IP_BE;
95input[C_NUM_REG-1:0] Bus2IP_RdCE;
96input[C_NUM_REG-1:0] Bus2IP_WrCE;
97output[C_SLV_DWIDTH-1:0] IP2Bus_Data;
98outputIP2Bus_RdAck;
99outputIP2Bus_WrAck;
100outputIP2Bus_Error;
101//-- DO NOT EDIT ABOVE THIS LINE --------------------
102
103//----------------------------------------------------------------------------
104//Implementation
105//----------------------------------------------------------------------------
106
107//--USER nets declarations added here, as needed for user logic
108
109//Nets for user logic slave model s/w accessible register example
110reg[C_SLV_DWIDTH-1:0] slv_reg0;
111wire[0:0] slv_reg_write_sel;
112wire[0:0] slv_reg_read_sel;
113reg[C_SLV_DWIDTH-1:0] slv_ip2bus_data;
114wireslv_read_ack;
115wireslv_write_ack;
116integerbyte_index, bit_index;
117
118//USER logic implementation added here
119assignLED =slv_reg0[7:0];
120//------------------------------------------------------
121//Example code to read/write user logic slave model s/w accessible registers
122//
123//Note:
124//The example code presented here is to show you one way of reading/writing
125//software accessible registers implemented in the user logic slave model.
126//Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to correspond
127//to one software accessible register by the top level template. For example,
128//if you have four 32 bit software accessible registers in the user logic,
129//you are basically operating on the following memory mapped registers:
130//
131//Bus2IP_WrCE/Bus2IP_RdCE Memory Mapped Register
132//"1000" C_BASEADDR + 0x0
133//"0100" C_BASEADDR + 0x4
134//"0010" C_BASEADDR + 0x8
135//"0001" C_BASEADDR + 0xC
136//
137//------------------------------------------------------
138
139assign
140slv_reg_write_sel = Bus2IP_WrCE[0:0],
141slv_reg_read_sel = Bus2IP_RdCE[0:0],
142slv_write_ack = Bus2IP_WrCE[0],
143slv_read_ack = Bus2IP_RdCE[0];
144
145
146
147//implement slave model register(s)
148always@(posedgeBus2IP_Clk )
149begin
150
151if( Bus2IP_Resetn ==1'b0 )
152begin
153slv_reg0 <=0;
154end
155else
156case( slv_reg_write_sel )
1571'b1 :
158for( byte_index =0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1)
159if( Bus2IP_BE[byte_index] ==1)
160slv_reg0[(byte_index*8) +:8] <= Bus2IP_Data[(byte_index*8) +:8];
161default:begin
162slv_reg0 <=slv_reg0;
163end
164endcase
165
166end//SLAVE_REG_WRITE_PROC
167
168//implement slave model register read mux
169always@( slv_reg_read_selorslv_reg0 )
170begin
171
172case( slv_reg_read_sel )
1731'b1 : slv_ip2bus_data <= slv_reg0;
174default: slv_ip2bus_data <=0;
175endcase
176
177end//SLAVE_REG_READ_PROC
178
179//------------------------------------------------------------
180//Example code to drive IP to Bus signals
181//------------------------------------------------------------
182
183assignIP2Bus_Data = (slv_read_ack ==1'b1) ? slv_ip2bus_data : 0 ;
184assignIP2Bus_WrAck =slv_write_ack;
185assignIP2Bus_RdAck =slv_read_ack;
186assignIP2Bus_Error =0;
187
188endmodule

复制代码

代码中57、86行


LED,output[7:0] LED;

表明在用户逻辑中,定义了名为LED的端口,方向是输出,长度为8。

代码中119行


assignLED = slv_reg0[7:0];

表明将slv_reg0的低8位传递给输出端口LED。其实就是实现了数据寄存器的值作用到输出端口的功能。

需要将用户逻辑和IPIF连接上,需要完成user_logic的例化

Lab4\pcores\my_axi_ip_v1_00_a\hdl\vhdl\my_axi_ip.vhd

复制代码
1 ------------------------------------------------------------------------------
2-- my_axi_ip.vhd -entity/architecturepair
3------------------------------------------------------------------------------
4--IMPORTANT:
5-- DONOTMODIFY THISFILEEXCEPTINTHE DESIGNATED SECTIONS.
6--
7-- SEARCHFOR--USERTODETERMINE WHERE CHANGES ARE ALLOWED.
8--
9-- TYPICALLY, THE ONLY ACCEPTABLE CHANGES INVOLVE ADDINGNEW
10-- PORTSANDGENERICS THAT GET PASSED THROUGHTOTHE INSTANTIATION
11--OFTHE USER_LOGICENTITY.
12------------------------------------------------------------------------------
13--
14-- ***************************************************************************
15-- ** Copyright (c)1995-2012Xilinx, Inc. All rights reserved. **
16-- ** **
17-- ** Xilinx, Inc. **
18-- ** XILINXISPROVIDING THIS DESIGN, CODE,ORINFORMATION"AS IS"**
19-- ** AS A COURTESYTOYOU, SOLELYFORUSEINDEVELOPING PROGRAMSAND**
20-- ** SOLUTIONSFORXILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, **
21-- **ORINFORMATION AS ONE POSSIBLE IMPLEMENTATIONOFTHIS FEATURE, **
22-- ** APPLICATIONORSTANDARD, XILINXISMAKING NO REPRESENTATION **
23-- ** THAT THIS IMPLEMENTATIONISFREE FROM ANY CLAIMSOFINFRINGEMENT, **
24-- **ANDYOU ARE RESPONSIBLEFOROBTAINING ANY RIGHTS YOU MAY REQUIRE **
25-- **FORYOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY **
26-- ** WARRANTY WHATSOEVERWITHRESPECTTOTHE ADEQUACYOFTHE **
27-- ** IMPLEMENTATION, INCLUDING BUTNOTLIMITEDTOANY WARRANTIESOR**
28-- ** REPRESENTATIONS THAT THIS IMPLEMENTATIONISFREE FROM CLAIMSOF**
29-- ** INFRINGEMENT, IMPLIED WARRANTIESOFMERCHANTABILITYANDFITNESS **
30-- **FORA PARTICULAR PURPOSE. **
31-- ** **
32-- ***************************************************************************
33--
34------------------------------------------------------------------------------
35--Filename: my_axi_ip.vhd
36-- Version:1.00.a
37-- Description: Top level design, instantiateslibrarycomponentsanduser logic.
38-- Date: Tue Oct0918:28:062012(by CreateandImport Peripheral Wizard)
39-- VHDL Standard: VHDL'93
40------------------------------------------------------------------------------
41--Naming Conventions:
42-- active low signals:"*_n"
43-- clock signals:"clk","clk_div#","clk_#x"
44-- reset signals:"rst","rst_n"
45-- generics:"C_*"
46-- user defined types:"*_TYPE"
47-- state machinenextstate:"*_ns"
48-- state machine current state:"*_cs"
49-- combinatorial signals:"*_com"
50-- pipelinedorregisterdelay signals:"*_d#"
51-- counter signals:"*cnt*"
52-- clock enable signals:"*_ce"
53-- internal versionofoutputport:"*_i"
54-- device pins:"*_pin"
55-- ports:"- Names begin with Uppercase"
56-- processes:"*_PROCESS"
57--componentinstantiations:"I_<#|FUNC>"
58------------------------------------------------------------------------------
59
60libraryieee;
61useieee.std_logic_1164.all;
62useieee.std_logic_arith.all;
63useieee.std_logic_unsigned.all;
64
65libraryproc_common_v3_00_a;
66useproc_common_v3_00_a.proc_common_pkg.all;
67useproc_common_v3_00_a.ipif_pkg.all;
68
69libraryaxi_lite_ipif_v1_01_a;
70useaxi_lite_ipif_v1_01_a.axi_lite_ipif;
71
72------------------------------------------------------------------------------
73--Entity section
74------------------------------------------------------------------------------
75-- DefinitionofGenerics:
76-- C_S_AXI_DATA_WIDTH -- AXI4LITE slave: Datawidth
77-- C_S_AXI_ADDR_WIDTH --AXI4LITE slave: Address Width
78-- C_S_AXI_MIN_SIZE --AXI4LITE slave: Min Size
79-- C_USE_WSTRB --AXI4LITE slave: Write Strobe
80-- C_DPHASE_TIMEOUT --AXI4LITE slave: Data Phase Timeout
81-- C_BASEADDR --AXI4LITE slave: base address
82-- C_HIGHADDR --AXI4LITE slave: high address
83-- C_FAMILY --FPGA Family
84-- C_NUM_REG -- Numberofsoftware accessible registers
85-- C_NUM_MEM -- Numberofaddress-ranges
86-- C_SLV_AWIDTH -- Slave interface addressbuswidth
87-- C_SLV_DWIDTH -- Slave interface databuswidth
88--
89-- DefinitionofPorts:
90-- S_AXI_ACLK --AXI4LITE slave: Clock
91-- S_AXI_ARESETN --AXI4LITE slave: Reset
92-- S_AXI_AWADDR --AXI4LITE slave: Write address
93-- S_AXI_AWVALID --AXI4LITE slave: Write address valid
94-- S_AXI_WDATA --AXI4LITE slave: Write data
95-- S_AXI_WSTRB --AXI4LITE slave: Write strobe
96-- S_AXI_WVALID --AXI4LITE slave: Write data valid
97-- S_AXI_BREADY --AXI4LITE slave: Response ready
98-- S_AXI_ARADDR --AXI4LITE slave: Read address
99-- S_AXI_ARVALID --AXI4LITE slave: Read address valid
100-- S_AXI_RREADY --AXI4LITE slave: Read data ready
101-- S_AXI_ARREADY -- AXI4LITE slave:readaddres ready
102-- S_AXI_RDATA --AXI4LITE slave: Read data
103-- S_AXI_RRESP --AXI4LITE slave: Read data response
104-- S_AXI_RVALID --AXI4LITE slave: Read data valid
105-- S_AXI_WREADY --AXI4LITE slave: Write data ready
106-- S_AXI_BRESP --AXI4LITE slave: Response
107-- S_AXI_BVALID --AXI4LITE slave: Resonse valid
108-- S_AXI_AWREADY --AXI4LITE slave: Wrte address ready
109------------------------------------------------------------------------------
110
111entitymy_axi_ipis
112generic
113(
114-- ADD USER GENERICS BELOW THISLINE---------------
115--USER generics added here
116-- ADD USER GENERICS ABOVE THISLINE---------------
117
118-- DONOTEDIT BELOW THISLINE---------------------
119-- Bus protocol parameters, donotaddtoordelete
120C_S_AXI_DATA_WIDTH :integer:=32;
121C_S_AXI_ADDR_WIDTH :integer:=32;
122C_S_AXI_MIN_SIZE :std_logic_vector:= X"000001FF";
123C_USE_WSTRB :integer:=0;
124C_DPHASE_TIMEOUT :integer:=8;
125C_BASEADDR :std_logic_vector:= X"FFFFFFFF";
126C_HIGHADDR :std_logic_vector:= X"00000000";
127C_FAMILY :string:="virtex6";
128C_NUM_REG :integer:=1;
129C_NUM_MEM :integer:=1;
130C_SLV_AWIDTH :integer:=32;
131C_SLV_DWIDTH :integer:=32
132-- DONOTEDIT ABOVE THISLINE---------------------
133);
134port
135(
136-- ADD USER PORTS BELOW THISLINE------------------
137LED :outstd_logic_vector(7downto0);
138-- ADD USER PORTS ABOVE THISLINE------------------
139
140-- DONOTEDIT BELOW THISLINE---------------------
141-- Bus protocol ports, donotaddtoordelete
142S_AXI_ACLK :instd_logic;
143S_AXI_ARESETN :instd_logic;
144S_AXI_AWADDR :instd_logic_vector(C_S_AXI_ADDR_WIDTH-1downto0);
145S_AXI_AWVALID :instd_logic;
146S_AXI_WDATA :instd_logic_vector(C_S_AXI_DATA_WIDTH-1downto0);
147S_AXI_WSTRB :instd_logic_vector((C_S_AXI_DATA_WIDTH/8)-1downto0);
148S_AXI_WVALID :instd_logic;
149S_AXI_BREADY :instd_logic;
150S_AXI_ARADDR :instd_logic_vector(C_S_AXI_ADDR_WIDTH-1downto0);
151S_AXI_ARVALID :instd_logic;
152S_AXI_RREADY :instd_logic;
153S_AXI_ARREADY :outstd_logic;
154S_AXI_RDATA :outstd_logic_vector(C_S_AXI_DATA_WIDTH-1downto0);
155S_AXI_RRESP :outstd_logic_vector(1downto0);
156S_AXI_RVALID :outstd_logic;
157S_AXI_WREADY :outstd_logic;
158S_AXI_BRESP :outstd_logic_vector(1downto0);
159S_AXI_BVALID :outstd_logic;
160S_AXI_AWREADY :outstd_logic
161-- DONOTEDIT ABOVE THISLINE---------------------
162);
163
164attributeMAX_FANOUT :string;
165attributeSIGIS :string;
166attributeMAX_FANOUTofS_AXI_ACLK :signalis"10000";
167attributeMAX_FANOUTofS_AXI_ARESETN :signalis"10000";
168attributeSIGISofS_AXI_ACLK :signalis"Clk";
169attributeSIGISofS_AXI_ARESETN :signalis"Rst";
170endentitymy_axi_ip;
171
172------------------------------------------------------------------------------
173--Architecture section
174------------------------------------------------------------------------------
175
176architectureIMPofmy_axi_ipis
177
178constantUSER_SLV_DWIDTH :integer:=C_S_AXI_DATA_WIDTH;
179
180constantIPIF_SLV_DWIDTH :integer:=C_S_AXI_DATA_WIDTH;
181
182constantZERO_ADDR_PAD :std_logic_vector(0to31) := (others=>'0');
183constantUSER_SLV_BASEADDR :std_logic_vector:=C_BASEADDR;
184constantUSER_SLV_HIGHADDR :std_logic_vector:=C_HIGHADDR;
185
186constantIPIF_ARD_ADDR_RANGE_ARRAY : SLV64_ARRAY_TYPE :=
187(
188ZERO_ADDR_PAD & USER_SLV_BASEADDR, --user logic slave space base address
189ZERO_ADDR_PAD & USER_SLV_HIGHADDR --user logic slave space high address
190);
191
192constantUSER_SLV_NUM_REG :integer:=1;
193constantUSER_NUM_REG :integer:=USER_SLV_NUM_REG;
194constantTOTAL_IPIF_CE :integer:=USER_NUM_REG;
195
196constantIPIF_ARD_NUM_CE_ARRAY : INTEGER_ARRAY_TYPE :=
197(
1980=> (USER_SLV_NUM_REG) -- numberofceforuser logic slave space
199);
200
201------------------------------------------
202-- IndexforCS/CE
203------------------------------------------
204constantUSER_SLV_CS_INDEX :integer:=0;
205constantUSER_SLV_CE_INDEX :integer:=calc_start_ce_index(IPIF_ARD_NUM_CE_ARRAY, USER_SLV_CS_INDEX);
206
207constantUSER_CE_INDEX :integer:=USER_SLV_CE_INDEX;
208
209------------------------------------------
210-- IP Interconnect (IPIC)signaldeclarations
211------------------------------------------
212signalipif_Bus2IP_Clk :std_logic;
213signalipif_Bus2IP_Resetn :std_logic;
214signalipif_Bus2IP_Addr :std_logic_vector(C_S_AXI_ADDR_WIDTH-1downto0);
215signalipif_Bus2IP_RNW :std_logic;
216signalipif_Bus2IP_BE :std_logic_vector(IPIF_SLV_DWIDTH/8-1downto0);
217signalipif_Bus2IP_CS :std_logic_vector((IPIF_ARD_ADDR_RANGE_ARRAY'LENGTH)/2-1 downto 0);
218signalipif_Bus2IP_RdCE :std_logic_vector(calc_num_ce(IPIF_ARD_NUM_CE_ARRAY)-1downto0);
219signalipif_Bus2IP_WrCE :std_logic_vector(calc_num_ce(IPIF_ARD_NUM_CE_ARRAY)-1downto0);
220signalipif_Bus2IP_Data :std_logic_vector(IPIF_SLV_DWIDTH-1downto0);
221signalipif_IP2Bus_WrAck :std_logic;
222signalipif_IP2Bus_RdAck :std_logic;
223signalipif_IP2Bus_Error :std_logic;
224signalipif_IP2Bus_Data :std_logic_vector(IPIF_SLV_DWIDTH-1downto0);
225signaluser_Bus2IP_RdCE :std_logic_vector(USER_NUM_REG-1downto0);
226signaluser_Bus2IP_WrCE :std_logic_vector(USER_NUM_REG-1downto0);
227signaluser_IP2Bus_Data :std_logic_vector(USER_SLV_DWIDTH-1downto0);
228signaluser_IP2Bus_RdAck :std_logic;
229signaluser_IP2Bus_WrAck :std_logic;
230signaluser_IP2Bus_Error :std_logic;
231
232------------------------------------------
233-- Component declarationforverilog user logic
234------------------------------------------
235componentuser_logicis
236generic
237(
238-- ADD USER GENERICS BELOW THISLINE---------------
239--USER generics added here
240-- ADD USER GENERICS ABOVE THISLINE---------------
241
242-- DONOTEDIT BELOW THISLINE---------------------
243-- Bus protocol parameters, donotaddtoordelete
244C_NUM_REG :integer:=1;
245C_SLV_DWIDTH :integer:=32
246-- DONOTEDIT ABOVE THISLINE---------------------
247);
248port
249(
250-- ADD USER PORTS BELOW THISLINE------------------
251LED :outstd_logic_vector(7downto0);
252-- ADD USER PORTS ABOVE THISLINE------------------
253
254-- DONOTEDIT BELOW THISLINE---------------------
255-- Bus protocol ports, donotaddtoordelete
256Bus2IP_Clk :instd_logic;
257Bus2IP_Resetn :instd_logic;
258Bus2IP_Data :instd_logic_vector(C_SLV_DWIDTH-1downto0);
259Bus2IP_BE :instd_logic_vector(C_SLV_DWIDTH/8-1downto0);
260Bus2IP_RdCE :instd_logic_vector(C_NUM_REG-1downto0);
261Bus2IP_WrCE :instd_logic_vector(C_NUM_REG-1downto0);
262IP2Bus_Data :outstd_logic_vector(C_SLV_DWIDTH-1downto0);
263IP2Bus_RdAck :outstd_logic;
264IP2Bus_WrAck :outstd_logic;
265IP2Bus_Error :outstd_logic
266-- DONOTEDIT ABOVE THISLINE---------------------
267);
268endcomponentuser_logic;
269
270begin
271
272------------------------------------------
273--instantiate axi_lite_ipif
274------------------------------------------
275AXI_LITE_IPIF_I :entityaxi_lite_ipif_v1_01_a.axi_lite_ipif
276genericmap
277(
278C_S_AXI_DATA_WIDTH =>IPIF_SLV_DWIDTH,
279C_S_AXI_ADDR_WIDTH =>C_S_AXI_ADDR_WIDTH,
280C_S_AXI_MIN_SIZE =>C_S_AXI_MIN_SIZE,
281C_USE_WSTRB =>C_USE_WSTRB,
282C_DPHASE_TIMEOUT =>C_DPHASE_TIMEOUT,
283C_ARD_ADDR_RANGE_ARRAY =>IPIF_ARD_ADDR_RANGE_ARRAY,
284C_ARD_NUM_CE_ARRAY =>IPIF_ARD_NUM_CE_ARRAY,
285C_FAMILY =>C_FAMILY
286)
287portmap
288(
289S_AXI_ACLK =>S_AXI_ACLK,
290S_AXI_ARESETN =>S_AXI_ARESETN,
291S_AXI_AWADDR =>S_AXI_AWADDR,
292S_AXI_AWVALID =>S_AXI_AWVALID,
293S_AXI_WDATA =>S_AXI_WDATA,
294S_AXI_WSTRB =>S_AXI_WSTRB,
295S_AXI_WVALID =>S_AXI_WVALID,
296S_AXI_BREADY =>S_AXI_BREADY,
297S_AXI_ARADDR =>S_AXI_ARADDR,
298S_AXI_ARVALID =>S_AXI_ARVALID,
299S_AXI_RREADY =>S_AXI_RREADY,
300S_AXI_ARREADY =>S_AXI_ARREADY,
301S_AXI_RDATA =>S_AXI_RDATA,
302S_AXI_RRESP =>S_AXI_RRESP,
303S_AXI_RVALID =>S_AXI_RVALID,
304S_AXI_WREADY =>S_AXI_WREADY,
305S_AXI_BRESP =>S_AXI_BRESP,
306S_AXI_BVALID =>S_AXI_BVALID,
307S_AXI_AWREADY =>S_AXI_AWREADY,
308Bus2IP_Clk =>ipif_Bus2IP_Clk,
309Bus2IP_Resetn =>ipif_Bus2IP_Resetn,
310Bus2IP_Addr =>ipif_Bus2IP_Addr,
311Bus2IP_RNW =>ipif_Bus2IP_RNW,
312Bus2IP_BE =>ipif_Bus2IP_BE,
313Bus2IP_CS =>ipif_Bus2IP_CS,
314Bus2IP_RdCE =>ipif_Bus2IP_RdCE,
315Bus2IP_WrCE =>ipif_Bus2IP_WrCE,
316Bus2IP_Data =>ipif_Bus2IP_Data,
317IP2Bus_WrAck =>ipif_IP2Bus_WrAck,
318IP2Bus_RdAck =>ipif_IP2Bus_RdAck,
319IP2Bus_Error =>ipif_IP2Bus_Error,
320IP2Bus_Data =>ipif_IP2Bus_Data
321);
322
323------------------------------------------
324--instantiate User Logic
325------------------------------------------
326USER_LOGIC_I :componentuser_logic
327genericmap
328(
329--MAPUSER GENERICS BELOW THISLINE---------------
330--USER generics mapped here
331--MAPUSER GENERICS ABOVE THISLINE---------------
332
333C_NUM_REG =>USER_NUM_REG,
334C_SLV_DWIDTH =>USER_SLV_DWIDTH
335)
336portmap
337(
338--MAPUSER PORTS BELOW THISLINE------------------
339LED =>LED,
340--MAPUSER PORTS ABOVE THISLINE------------------
341
342Bus2IP_Clk =>ipif_Bus2IP_Clk,
343Bus2IP_Resetn =>ipif_Bus2IP_Resetn,
344Bus2IP_Data =>ipif_Bus2IP_Data,
345Bus2IP_BE =>ipif_Bus2IP_BE,
346Bus2IP_RdCE =>user_Bus2IP_RdCE,
347Bus2IP_WrCE =>user_Bus2IP_WrCE,
348IP2Bus_Data =>user_IP2Bus_Data,
349IP2Bus_RdAck =>user_IP2Bus_RdAck,
350IP2Bus_WrAck =>user_IP2Bus_WrAck,
351IP2Bus_Error =>user_IP2Bus_Error
352);
353
354------------------------------------------
355--connect internal signals
356------------------------------------------
357ipif_IP2Bus_Data <=user_IP2Bus_Data;
358ipif_IP2Bus_WrAck <=user_IP2Bus_WrAck;
359ipif_IP2Bus_RdAck <=user_IP2Bus_RdAck;
360ipif_IP2Bus_Error <=user_IP2Bus_Error;
361
362user_Bus2IP_RdCE <= ipif_Bus2IP_RdCE(USER_NUM_REG-1downto0);
363user_Bus2IP_WrCE <= ipif_Bus2IP_WrCE(USER_NUM_REG-1downto0);
364
365endIMP;

复制代码

137行


LED :outstd_logic_vector(7downto0);

定义IP的端口为LED,这里需要和之前修改MPD文件一致。

232-268行为元件声明

复制代码
1------------------------------------------
2-- Component declarationforverilog user logic
3------------------------------------------
4componentuser_logicis
5generic
6(
7-- ADD USER GENERICS BELOW THISLINE---------------
8--USER generics added here
9-- ADD USER GENERICS ABOVE THISLINE---------------
10
11-- DONOTEDIT BELOW THISLINE---------------------
12-- Bus protocol parameters, donotaddtoordelete
13C_NUM_REG :integer:=1;
14C_SLV_DWIDTH :integer:=32
15-- DONOTEDIT ABOVE THISLINE---------------------
16);
17port
18(
19-- ADD USER PORTS BELOW THISLINE------------------
20LED :outstd_logic_vector(7downto0);
21-- ADD USER PORTS ABOVE THISLINE------------------
22
23-- DONOTEDIT BELOW THISLINE---------------------
24-- Bus protocol ports, donotaddtoordelete
25Bus2IP_Clk :instd_logic;
26Bus2IP_Resetn :instd_logic;
27Bus2IP_Data :instd_logic_vector(C_SLV_DWIDTH-1downto0);
28Bus2IP_BE :instd_logic_vector(C_SLV_DWIDTH/8-1downto0);
29Bus2IP_RdCE :instd_logic_vector(C_NUM_REG-1downto0);
30Bus2IP_WrCE :instd_logic_vector(C_NUM_REG-1downto0);
31IP2Bus_Data :outstd_logic_vector(C_SLV_DWIDTH-1downto0);
32IP2Bus_RdAck :outstd_logic;
33IP2Bus_WrAck :outstd_logic;
34IP2Bus_Error :outstd_logic
35-- DONOTEDIT ABOVE THISLINE---------------------
36);
37endcomponentuser_logic;

复制代码

323-352行为user_logic元件例化。VHDL是不区分大小写的。

复制代码
1 ------------------------------------------
2--instantiate User Logic
3------------------------------------------
4USER_LOGIC_I :componentuser_logic
5genericmap
6(
7--MAPUSER GENERICS BELOW THISLINE---------------
8--USER generics mapped here
9--MAPUSER GENERICS ABOVE THISLINE---------------
10
11C_NUM_REG =>USER_NUM_REG,
12C_SLV_DWIDTH =>USER_SLV_DWIDTH
13)
14portmap
15(
16--MAPUSER PORTS BELOW THISLINE------------------
17LED =>LED,
18--MAPUSER PORTS ABOVE THISLINE------------------
19
20Bus2IP_Clk =>ipif_Bus2IP_Clk,
21Bus2IP_Resetn =>ipif_Bus2IP_Resetn,
22Bus2IP_Data =>ipif_Bus2IP_Data,
23Bus2IP_BE =>ipif_Bus2IP_BE,
24Bus2IP_RdCE =>user_Bus2IP_RdCE,
25Bus2IP_WrCE =>user_Bus2IP_WrCE,
26IP2Bus_Data =>user_IP2Bus_Data,
27IP2Bus_RdAck =>user_IP2Bus_RdAck,
28IP2Bus_WrAck =>user_IP2Bus_WrAck,
29IP2Bus_Error =>user_IP2Bus_Error
30);

复制代码

这几个文件修改后保存。

Project->Rescan User Repositories(更新用户仓库?),让XPS识别到对IP所做的修改

三、将自定义IP核添加到PS系统

同第三篇一样,需要将IP添加到PS系统中。

在Ports标签中,需要将我们定义的LED端口设置为外部端口,外部引脚名按照Zedboard的习惯,定义为LD

在Address标签中,设定IP的地址。XPS支持自定义定制范围、空间大小等。可以使用默认设置,也可以手动设置。这里我设置基地址为0x40000000,其实也就是我们设定的数据寄存器的地址为0x40000000。如果有更多的寄存器,会以4字节offset 地址的方式访问即可。

最后一样修改ucf文件,完成约束。

复制代码
1NET LD[0] LOC = T22 | IOSTANDARD=LVCMOS33; #"LD0"
2NET LD[1] LOC = T21 | IOSTANDARD=LVCMOS33; #"LD1"
3NET LD[2] LOC = U22 | IOSTANDARD=LVCMOS33; #"LD2"
4NET LD[3] LOC = U21 | IOSTANDARD=LVCMOS33; #"LD3"
5NET LD[4] LOC = V22 | IOSTANDARD=LVCMOS33; #"LD4"
6NET LD[5] LOC = W22 | IOSTANDARD=LVCMOS33; #"LD5"
7NET LD[6] LOC = U19 | IOSTANDARD=LVCMOS33; #"LD6"
8NET LD[7] LOC = U14 | IOSTANDARD=LVCMOS33; #"LD7"

复制代码

最后对这个系统编译,生成bitstream文件,并将硬件配置导入到SDK,并启动SDK。

四、使用SDK编写IP核驱动程序和应用程序

打开SDK,可以从系统信息system.xml中看到我们的系统信息。可以看到我们实例化连接到系统的ip是my_axi_ip_0,基地址是0x4000000。

建立软件工程后,修改main代码,如下

复制代码
//@超群天晴http://www.cnblogs.com/surpassal/
1
#include
2#include"xparameters.h"
3#include"xil_types.h"
4#include"xstatus.h"
5#include"xil_io.h"//包含xil_io头文件,完成对绝对地址的访问
6#include"platform.h"
7
8#defineLED_DATA_REG 0x40000000
9
10voidprint(char*ptr);
11voiddelay(unsignedintdelaytime);
12voidLED_Play(unsignedcharled);
13
14
15intmain(void)
16{
17
18init_platform();
19
20print("ZedBoard LAB4: MY_AXI_LEDs\n\r");
21print("超群天晴 2012年10月8日22:12:31\n\r");
22
23LED_Play(0x03);
24while(1);
25
26cleanup_platform();
27
28return0;
29}
30
31
32voiddelay(unsignedintdelaytime)
33{
34inti;
35for(i=0;i)
36;
37}
38
39voidLED_Play(unsignedcharled)
40{
41for(;;)
42{
43led=(led<<1)|(led>>7);
44Xil_Out32(LED_DATA_REG,led);
45delay(50000000);
46}
47}

复制代码

定义了两个函数


voiddelay(unsignedintdelaytime);
voidLED_Play(unsignedcharled);

其中delay()为延时函数,参数为延时时间,100000000大约延时1s;

LED_Play()为LED流水灯函数,参数是流水初始值。在程序里面设定的是0x2,也就LD0、LD1最开始亮,然后流水。

其中第8行


#defineLED_DATA_REG 0x40000000

使用宏定义,定义LED_DATA_REG,实际上就是自定义IP的基地址。

第44行


Xil_Out32(LED_DATA_REG,led);

使用了xil_io.h提供的绝对地址访问函数Xil_Out32(u32 OutAddress, u32 Value),定义如下

复制代码
1/*****************************************************************************/
2/**
3*
4* Performs an output operation for a 32-bit memory location by writing the
5* specified Value to the the specified address.
6*
7* @param OutAddress contains the address to perform the output operation8* at.
9* @param Value contains the Value to be output at the specified address.
10*
11* @return None.
12*
13* @note None.
14*
15******************************************************************************/
16voidXil_Out32(u32 OutAddress, u32 Value)
17{
18/*write the contents of the I/O location and then synchronize the I/O
19* such that the I/O operation completes before proceeding on
20*/
21*(volatileu32 *) OutAddress =Value;
22SYNCHRONIZE_IO;
23}

复制代码

可以看出,其实现的功能就是向32位绝对地址OutAddress中写入32位无符号值Value。参考这样的写法,可以将地址访问修改


1#defineLED_DATA_ADDR 0x40000000
2#defineLED_DATA_REG(x)*(volatile unsigned int *)LED_DATA_ADDR = x

然后修改寄存器的值,只需要修改LED_DATA_REG(x)参数x的值即可。

四、运行结果

编译下载之后,可以从超级终端看到调试信息

同时Zedboard上的 LD 流水

================================

备注:

有关AXI协议,请参考

AXI Bus Functional Model v1.1 Product Brief

AXI Reference Guide (AXI)

更多资料,请参考

AXIIPDocumentation

================================

完整工程代码:Lab4.rar

Baidu
map