-
Vivado
下创建基于
AXI
本文是为一位网友所写,据说网上
V
ivado
下自定义
IP
核的资料很难
找
~
本文主要讲述了在
Vivado<
/p>
下创建
AXI-Lite
型
IP
核的流程。
最近问
IP
问题的人略多……Vivado
为设计
人员提供了很多
IP
核,
但不可能完全
满足我们的所有设计需
求,
在设计过程中,
很多时候需要设计个性化的
IP
核,
用于
完成自己想要的功能。因此,在
Vivado
下创建
IP
核的流程
也是
必须掌握的基础之一。废话不多说,直奔主题。如图
1
所示,<
/p>
Tools &
gt; Create and Package
IP…,打开
IP
创建
和打包向导。<
/p>
图
1
进入第一
个界面,如图
2
所示。是一些提示信息,直接
< br>点击
Next
图
2
进入操作类型选择界面,如图
3
所示。图
3
这里我们要做的是创建
IP
,所以选择“Create a new AXI4
peripheral”,如
图
3
所示,选择完毕,单击
next<
/p>
,进入下一
界面,
如图
< br>4
所示。
图
4
< br>在该界面设置
IP
核的名称、
版
本、
存储路径等,完毕后,点击
Next
,进入下一界面,如图
5
所示。图
5
此处可以设置总线类型、总线位宽、寄存器个数
等,我们要做的
就是一个
AXI-Lite
型
IP
p>
,所以不必改动,直
接
Next
,
进入最后一步,
如图
6
所示。
图
6
向
导的最后一步,
IP
概要信息,选择下一步操作。这里我们选择
“Add IP to
therepository”,
这样
在
IP Catalog
中就可以找到我们新建的
IP
了。打开
IP Catalog
,在搜索框内键入
myip(
你的
Ip
的名
字
)
,就可以检索出
IP
核,如图
7<
/p>
所示。图
7
选中该
IP
,右
键,在弹出菜单中选择
Ed
it in IP Packager
,如图
8
所示。
图
8
之后会弹出对话框
,
询问新的工程存放路径及工程名称,
如图
9
所示。
图
9
设置完毕后,
点击
OK
,
会新建一个
vivado
工程,用于编辑
IP
核。在新打开的
Vivado IDE<
/p>
中,找到
Source
子窗口,双击打开
myip_v1_0.v
顶层文件(图
10
所
示位置)
,在图
11
所示的位置添加自主端口,我这里是一个
1bit
的
pwm_out
输出端口。图
10
图
11
所添加的
pwm_out
端口是连接到底层端口的,
因此,
需要添加相应的例化语句。
在
myip_v1_0.v
中如图
12
所示位置添加例化语句,修改完
毕后保存。图
12
顶层修改完了,再修改底层的
module
,具
p>
体修改部位就不说了,直接把修改后的代码贴出来,这里不
是重点,
感兴趣的话自己看一下吧。想设计
PWM IP
核,可
以参考我之前的文章,用
HLS
做,比本文的方
法简单快捷。
`timescale 1 ns / 1 ps
//
User parameters ends
module
myip_v1_0_S00_AXI #
(
// Users to add parameters here
// Do not
modify the parameters beyond this line
)
(
// Width of
S_AXI data bus
parameter integer
C_S_AXI_DATA_WIDTH
= 32,
//
Width of S_AXI address bus
parameter
integer C_S_AXI_ADDR_WIDTH
= 4
// Users to add ports here
output wire pwm_out,
// Global Clock Signal
input
wire
S_AXI_ACLK,
// Global Reset Signal. This Signal is
Active LOW
input wire
S_AXI_ARESETN,
// Write
address (issued by master, acceped by
// User ports ends
// Do not modify the ports beyond this
line
Slave)
input wire [C_S_AXI_ADDR_WIDTH-1 : 0]
S_AXI_AWADDR,
// Write channel Protection type. This
signal indicates
the
// privilege and security
level of the transaction,
and whether
access.
input wire [2 : 0] S_AXI_AWPROT,
// Write address valid. This signal
indicates that the
// the transaction
is a data access or an instruction
master signaling
// valid write address and
control information.
input wire
S_AXI_AWVALID,
// Write address ready. This signal
indicates that the
slave is ready
signals.
output wire
S_AXI_AWREADY,
// Write data (issued by master,
acceped by Slave)
input
wire [C_S_AXI_DATA_WIDTH-1 : 0]
// to
accept an address and associated control
S_AXI_WDATA,
// Write strobes. This signal indicates
which byte
lanes hold
eight
// valid
data. There is one write strobe bit for each
// bits of the write data bus.
input wire [(C_S_AXI_DATA_WIDTH/8)-1 :
0]
S_AXI_WSTRB,
// Write valid. This signal indicates
that valid write
// data and strobes
are available.
input wire
S_AXI_WVALID,
// Write
ready. This signal indicates that the slave
// can accept the write data.
output wire
S_AXI_WREADY,
//
Write response. This signal indicates the status
// of the write transaction.
output wire [1
: 0] S_AXI_BRESP,
// Write response
valid. This signal indicates that the
channel
// is signaling a valid write response.
output wire
S_AXI_BVALID,
// Response
ready. This signal indicates that the
master
// can accept a write response.
input wire
S_AXI_BREADY,
// Read
address (issued by master, acceped by
Slave)
input wire [C_S_AXI_ADDR_WIDTH-1 : 0]
S_AXI_ARADDR,
// Protection type. This signal
indicates the privilege
// and security
level of the transaction, and
whether the
access.
input wire [2 : 0] S_AXI_ARPROT,
// Read address valid. This signal
indicates that the
// transaction is a
data access or an instruction
channel
// is signaling
valid read address and control
information.
input wire
S_AXI_ARVALID,
// Read address ready. This signal
indicates that the
slave is
// ready to accept an
address and associated
control signals.
output wire
S_AXI_ARREADY,
// Read data (issued by slave)
output wire [C_S_AXI_DATA_WIDTH-1 : 0]
S_AXI_RDATA,
// Read response. This signal indicates
the status of
the
// read transfer.
output wire [1 : 0] S_AXI_RRESP,
// Read valid. This signal indicates
that the channel is
// signaling the
required read data.
output wire
S_AXI_RVALID,
// Read ready.
This signal indicates that the master
can
// AXI4LITE signals
reg
[C_S_AXI_ADDR_WIDTH-1 : 0]
axi_awaddr;
reg
axi_awready;
reg
axi_wready;
reg
[1 : 0]
axi_bresp;
reg
axi_bvalid;
reg [C_S_AXI_ADDR_WIDTH-1 : 0]
axi_araddr;
reg
axi_arready;
reg [C_S_AXI_DATA_WIDTH-1 : 0]
axi_rdata;
reg
[1 : 0]
axi_rresp;
);
// accept the
read data and response information.
input wire
S_AXI_RREADY
reg
axi_rvalid;
//------------------ add by
cuter---------------
wire
ovpprd;
wire
pwm_out_tmp;
reg
[C_S_AXI_DATA_WIDTH-1:0]
pwm_cnt;
p>
//-----------------------end-------------
-------
//
Example-specific design signals
//
local parameter for addressing 32 bit / 64 bit
C_S_AXI_DATA_WIDTH
// ADDR_LSB is used for addressing
32/64 bit
registers/memories
//
ADDR_LSB = 2 for 32 bits (n downto 2)
// ADDR_LSB = 3 for 64 bits (n downto
3)
localparam integer ADDR_LSB =
(C_S_AXI_DATA_WIDTH/32) + 1;
localparam integer
OPT_MEM_ADDR_BITS = 1;
//--------------
--------------------------------
//--
Signals for user logic register space example
//-----------------------------------------
-------
//-- Number of Slave Registers
4
reg
[C_S_AXI_DATA_WIDTH-1:0]
slv_reg0;
// used as period register
reg [C_S_AXI_DATA_WIDTH-1:0]
slv_reg1;
// used as duty
register
assign S_AXI_AWREADY = axi_awready;
assign S_AXI_WREADY
=
axi_wready;
assign S_AXI_BRESP
= axi_bresp;
assign
S_AXI_BVALID
= axi_bvalid;
assign S_AXI_ARREADY
=
axi_arready;
assign S_AXI_RDATA
= axi_rdata;
assign
S_AXI_RRESP
= axi_rresp;
assign S_AXI_RVALID
=
axi_rvalid;
// Implement axi_awready
generation
// I/O Connections
assignments
reg
[C_S_AXI_DATA_WIDTH-1:0]
slv_reg2;
reg [C_S_AXI_DATA_WIDTH-1:0]
slv_reg3;
wire
slv_reg_rden;
wire
slv_reg_wren;
reg [C_S_AXI_DATA_WIDTH-1:0]
reg_data_out;
integer
byte_index;
//
axi_awready is asserted for one S_AXI_ACLK clock
cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are
asserted.
axi_awready is
always @(
posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0
)
begin
axi_awready <= 1'b0;
end
else
begin
if
(~axi_awready && S_AXI_AWVALID
// de-asserted when reset is low.
&& S_AXI_WVALID)
begin
// slave is ready to accept
write address
when
//
there is a valid write address and write
data
// on the write address and
data bus. This
design
always @( posedge
S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0
)
begin
axi_awaddr <= 0;
end
else
// Implement axi_awaddr
latching
// This process is used to
latch the address when both
// S_AXI_AWVALID and S_AXI_WVALID are
valid.
// expects no outstanding transactions.
axi_awready <= 1'b1;
end
else
begin
axi_awready <= 1'b0;
end
end
end
begin
if (~axi_awready &&
S_AXI_AWVALID
&& S_AXI_WVALID)
// Implement axi_wready
generation
// axi_wready is asserted
for one S_AXI_ACLK clock
begin
// Write
Address latching
axi_awaddr <=
S_AXI_AWADDR;
end
end
end
cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are
asserted.
axi_wready is
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_wready <= 1'b0;
//
de-asserted when reset is low.
end
else
begin
if (~axi_wready
&& S_AXI_WVALID
&&
S_AXI_AWVALID)
begin
// slave is ready to accept write data
when
// there is a valid write address and
write
data
// on the write address and
data bus. This
design
//
Implement memory mapped register select and write
// expects no
outstanding transactions.
axi_wready <= 1'b1;
end
else
begin
axi_wready
<= 1'b0;
end
end
end