利用zedboard添加自定义IP核完成简易计算器功能

认识zedboard板子也有半个多月了,期间有不少杂事,学的也不是很认真,最近几天在学习如何利用axi总线进行ps和pl部分的相互通信,利用自定义的ip核实现了简易的计算功能(只有加减),下面对实验的过程和自己的理解进行一下记录。
首先本次试验的目的是做一个建议的计算器,通过zedboard上的sw1,sw2标识操作(01表示加法操作,10表示剪发操作),另外通过led灯进行结果的显示,通过串口进行操作数的输入,而后利用fpga进行运算,串口输出结果。
实验步骤:
首先在xps中进行工程的建立,导入配置文件(.xml);
而后进行自定义ip核的生成,这部分在下面进行详细记录;
将由xps完成的工程导出,进行ps端应用程序的编写
xps工程的建立,这部分较为简单,只用简单图示进行记录
首先建立工程,在这里听师兄讲的,我理解为建立工程时用base system builder的好处是不需要对基础的一些信息进行配置,这样就能省去很多开发的麻烦,更深层次的就不能体会了。
建立工程后选择avnet,在base system builder界面将右侧不用的外设进行remove掉,而后完成对工程的建立
利用hardware下的create or import peripheral建立自定义的ip核(在此我理解为这一步仅为对ip核的一些基础信息的配置,至于ip核具体实现的功能和引出的端口还需要对用户逻辑等信息进行配置),在选择寄存器的个数时,由于本工程中涉及到sw,led和进行计算时对操作数和结果的存储,因此共需要五个寄存器
在完成此ip的基本配置信息之后,进行用户逻辑和端口号的配置
首先找到工程目录下的pcores\my_calc_v1_v1_00_a\hdl\verilog的user_logic.v文件对用户逻辑进行修改,本工程中设计到的用户逻辑很简单,根据sw前两位的值判断运算方式,而后利用运算数进行运算结果在led灯上进行显示,代码如下,对加入的代码部分进行解释,并加入我的理解
代码:
//----------------------------------------------------------------------------
// user_logic.v - module
//----------------------------------------------------------------------------
//
// ***************************************************************************
// ** copyright (c) 1995-2012 xilinx, inc. all rights reserved. **
// ** **
// ** xilinx, inc. **
// ** xilinx is providing this design, code, or information “as is” **
// ** as a courtesy to you, solely for use in developing programs and **
// ** solutions for xilinx devices. by providing this design, code, **
// ** or information as one possible implementation of this feature, **
// ** application or standard, xilinx is making no representation **
// ** that this implementation is free from any claims of infringement, **
// ** and you are responsible for obtaining any rights you may require **
// ** for your implementation. xilinx expressly disclaims any **
// ** warranty whatsoever with respect to the adequacy of the **
// ** implementation, including but not limited to any warranties or **
// ** representations that this implementation is free from claims of **
// ** infringement, implied warranties of merchantability and fitness **
// ** for a particular purpose. **
// ** **
// ***************************************************************************
//
//----------------------------------------------------------------------------
// filename: user_logic.v
// version: 1.00.a
// description: user logic module.
// date: fri jul 19 15:24:36 2013 (by create and import peripheral wizard)
// verilog standard: verilog-2001
//----------------------------------------------------------------------------
// naming conventions:
// active low signals: “*_n”
// clock signals: “clk”, “clk_div#”, “clk_#x”
// reset signals: “rst”, “rst_n”
// generics: “c_*”
// user defined types: “*_type”
// state machine next state: “*_ns”
// state machine current state: “*_cs”
// combinatorial signals: “*_com”
// pipelined or register delay signals: “*_d#”
// counter signals: “*cnt*”
// clock enable signals: “*_ce”
// internal version of output port: “*_i”
// device pins: “*_pin”
// ports: “- names begin with uppercase”
// processes: “*_process”
// component instantiations: “i_《#|func》”
//----------------------------------------------------------------------------
`uselib lib=unisims_ver
`uselib lib=proc_common_v3_00_a
module user_logic

// -- add user ports below this line ---------------
// --user ports added here
sw_in, //the operator
led_out, //show some information
// -- add user ports above this line ---------------
// -- do not edit below this line ------------------
// -- bus protocol ports, do not add to or delete
bus2ip_clk, // bus to ip clock
bus2ip_resetn, // bus to ip reset
bus2ip_data, // bus to ip data bus
bus2ip_be, // bus to ip byte enables
bus2ip_rdce, // bus to ip read chip enable
bus2ip_wrce, // bus to ip write chip enable
ip2bus_data, // ip to bus data bus
ip2bus_rdack, // ip to bus read transfer acknowledgement
ip2bus_wrack, // ip to bus write transfer acknowledgement
ip2bus_error // ip to bus error response
// -- do not edit above this line ------------------
); // user_logic
// -- add user parameters below this line ------------
// --user parameters added here
// -- add user parameters above this line ------------
// -- do not edit below this line --------------------
// -- bus protocol parameters, do not add to or delete
parameter c_num_reg = 5;
parameter c_slv_dwidth = 32;
// -- do not edit above this line --------------------
// -- add user ports below this line -----------------
// --user ports added here
input [7 : 0] sw_in;
output [7 : 0] led_out;
// -- add user ports above this line -----------------
// -- do not edit below this line --------------------
// -- bus protocol ports, do not add to or delete
input bus2ip_clk;
input bus2ip_resetn;
input [c_slv_dwidth-1 : 0] bus2ip_data;
input [c_slv_dwidth/8-1 : 0] bus2ip_be;
input [c_num_reg-1 : 0] bus2ip_rdce;
input [c_num_reg-1 : 0] bus2ip_wrce;
output [c_slv_dwidth-1 : 0] ip2bus_data;
output ip2bus_rdack;
output ip2bus_wrack;
output ip2bus_error;
// -- do not edit above this line --------------------
//----------------------------------------------------------------------------
// implementation
//----------------------------------------------------------------------------
// --user nets declarations added here, as needed for user logic \
reg [7 : 0] led_reg;
// nets for user logic slave model s/w accessible register example
reg [c_slv_dwidth-1 : 0] slv_reg0;
reg [c_slv_dwidth-1 : 0] slv_reg1;
reg [c_slv_dwidth-1 : 0] slv_reg2;
reg [c_slv_dwidth-1 : 0] slv_reg3;
reg [c_slv_dwidth-1 : 0] slv_reg4;
wire [4 : 0] slv_reg_write_sel;
wire [4 : 0] slv_reg_read_sel;
reg [c_slv_dwidth-1 : 0] slv_ip2bus_data;
wire slv_read_ack;
wire slv_write_ack;
integer byte_index, bit_index;
// user logic implementation added here
// ------------------------------------------------------
// example code to read/write user logic slave model s/w accessible registers
//
// note:
// the example code presented here is to show you one way of reading/writing
// software accessible registers implemented in the user logic slave model.
// each bit of the bus2ip_wrce/bus2ip_rdce signals is configured to correspond
// to one software accessible register by the top level template. for example,
// if you have four 32 bit software accessible registers in the user logic,
// you are basically operating on the following memory mapped registers:
//
// bus2ip_wrce/bus2ip_rdce memory mapped register
// “1000” c_baseaddr + 0x0
// “0100” c_baseaddr + 0x4
// “0010” c_baseaddr + 0x8
// “0001” c_baseaddr + 0xc
//
// ------------------------------------------------------
assign
slv_reg_write_sel = bus2ip_wrce[4:0],
slv_reg_read_sel = bus2ip_rdce[4:0],
slv_write_ack = bus2ip_wrce[0] || bus2ip_wrce[1] || bus2ip_wrce[2] || bus2ip_wrce[3] || bus2ip_wrce[4],
slv_read_ack = bus2ip_rdce[0] || bus2ip_rdce[1] || bus2ip_rdce[2] || bus2ip_rdce[3] || bus2ip_rdce[4];
// implement slave model register(s)
always @( posedge bus2ip_clk )
begin
if ( bus2ip_resetn == 1‘b0 )
begin
//slv_reg0 《= 0;
//slv_reg1 《= 0;
slv_reg2 《= 0;
slv_reg3 《= 0;
// slv_reg4 《= 0;
end
else
case ( slv_reg_write_sel )
/* 5’b10000 :
for ( byte_index = 0; byte_index 《= (c_slv_dwidth/8)-1; byte_index = byte_index+1 )
if ( bus2ip_be[byte_index] == 1 )
slv_reg0[(byte_index*8) +: 8] 《= bus2ip_data[(byte_index*8) +: 8]; */
5‘b01000 :
for ( byte_index = 0; byte_index 《= (c_slv_dwidth/8)-1; byte_index = byte_index+1 )
if ( bus2ip_be[byte_index] == 1 )
slv_reg1[(byte_index*8) +: 8] 《= bus2ip_data[(byte_index*8) +: 8];
5’b00100 :
for ( byte_index = 0; byte_index 《= (c_slv_dwidth/8)-1; byte_index = byte_index+1 )
if ( bus2ip_be[byte_index] == 1 )
slv_reg2[(byte_index*8) +: 8] 《= bus2ip_data[(byte_index*8) +: 8];
5‘b00010 :
for ( byte_index = 0; byte_index 《= (c_slv_dwidth/8)-1; byte_index = byte_index+1 )
if ( bus2ip_be[byte_index] == 1 )
slv_reg3[(byte_index*8) +: 8] 《= bus2ip_data[(byte_index*8) +: 8];
/* 5’b00001 :
for ( byte_index = 0; byte_index 《= (c_slv_dwidth/8)-1; byte_index = byte_index+1 )
if ( bus2ip_be[byte_index] == 1 )
slv_reg4[(byte_index*8) +: 8] 《= bus2ip_data[(byte_index*8) +: 8]; */
default : begin
slv_reg0 《= slv_reg0;
slv_reg1 《= slv_reg1;
slv_reg2 《= slv_reg2;
slv_reg3 《= slv_reg3;
slv_reg4 《= slv_reg4;
end
endcase
end // slave_reg_write_proc
// implement slave model register read mux
always @( slv_reg_read_sel or slv_reg0 or slv_reg1 or slv_reg2 or slv_reg3 or slv_reg4 )
begin
case ( slv_reg_read_sel )
5‘b10000 : slv_ip2bus_data 《= slv_reg0;
5’b01000 : slv_ip2bus_data 《= slv_reg1;
5‘b00100 : slv_ip2bus_data 《= slv_reg2;
5’b00010 : slv_ip2bus_data 《= slv_reg3;
5‘b00001 : slv_ip2bus_data 《= slv_reg4;
default : slv_ip2bus_data 《= 0;
endcase
end // slave_reg_read_proc
// ------------------------------------------------------------
// example code to drive ip to bus signals
// ------------------------------------------------------------
always @(posedge bus2ip_clk)
begin
slv_reg0[7 : 0] 《= sw_in[7 : 0];
led_reg 《= slv_reg1[7 : 0];
end
always @(posedge bus2ip_clk)
begin
case(slv_reg0[1 : 0])
2’b01 : slv_reg4 《= slv_reg2 + slv_reg3;
2‘b10 : slv_reg4 《= slv_reg2 - slv_reg3;
default : slv_reg4 《= 0;
endcase
end
assign ip2bus_data = (slv_read_ack == 1’b1) ? slv_ip2bus_data : 0 ;
assign ip2bus_wrack = slv_write_ack;
assign ip2bus_rdack = slv_read_ack;
assign ip2bus_error = 0;
assign led_out = led_reg;
endmodule
其中代码slv_reg0~slv_reg4为ip核中申请的5个寄存器,在这里可以根据自己的需要对这个5个寄存器的作用进行分配,在这里完全是按照自己的意愿分配,本程序中,我将slv_reg0用来存储sw的值,slv_reg1用来表示led的信息,slv_reg2和slv_reg3用来进行操作数的存储,slv_reg4用来存储运算结果。
注意,由于在模块中sw为input故他的值不是从总线上进行读取的,slv_reg4存储运算结果,其值也不需要进行存储,故需要对源程序中的一些信息进行注释,即对case下的第一和最后一个选项进行注释,这个地方需要进行自己的判断
另外用户逻辑的加入在代码:
always @(posedge bus2ip_clk)
begin
slv_reg0[7 : 0] 《= sw_in[7 : 0];
led_reg 《= slv_reg1[7 : 0];
end
always @(posedge bus2ip_clk)
begin
case(slv_reg0[1 : 0])
2‘b01 : slv_reg4 《= slv_reg2 + slv_reg3;
2’b10 : slv_reg4 《= slv_reg2 - slv_reg3;
default : slv_reg4 《= 0;
endcase
end
可以看出本工程中的逻辑比较简单,就是根据sw的值进行操作数的加减运算。
在完成用户逻辑后,还需要对ip核的端口进行配置,与ipif相连接(我是这么理解的,可能会不对)
在目录pcores\my_calc_v1_v1_00_a\hdl\vhdl下对文件my_calc_v1.vhd进行更改,代码如下:
------------------------------------------------------------------------------
-- my_calc_v1.vhd - entity/architecture pair
------------------------------------------------------------------------------
-- important:
-- do not modify this file except in the designated sections.
--
-- search for --user to determine where changes are allowed.
--
-- typically, the only acceptable changes involve adding new
-- ports and generics that get passed through to the instantiation
-- of the user_logic entity.
------------------------------------------------------------------------------
--
-- ***************************************************************************
-- ** copyright (c) 1995-2012 xilinx, inc. all rights reserved. **
-- ** **
-- ** xilinx, inc. **
-- ** xilinx is providing this design, code, or information “as is” **
-- ** as a courtesy to you, solely for use in developing programs and **
-- ** solutions for xilinx devices. by providing this design, code, **
-- ** or information as one possible implementation of this feature, **
-- ** application or standard, xilinx is making no representation **
-- ** that this implementation is free from any claims of infringement, **
-- ** and you are responsible for obtaining any rights you may require **
-- ** for your implementation. xilinx expressly disclaims any **
-- ** warranty whatsoever with respect to the adequacy of the **
-- ** implementation, including but not limited to any warranties or **
-- ** representations that this implementation is free from claims of **
-- ** infringement, implied warranties of merchantability and fitness **
-- ** for a particular purpose. **
-- ** **
-- ***************************************************************************
--
------------------------------------------------------------------------------
-- filename: my_calc_v1.vhd
-- version: 1.00.a
-- description: top level design, instantiates library components and user logic.
-- date: fri jul 19 15:24:36 2013 (by create and import peripheral wizard)
-- vhdl standard: vhdl‘93
------------------------------------------------------------------------------
-- naming conventions:
-- active low signals: “*_n”
-- clock signals: “clk”, “clk_div#”, “clk_#x”
-- reset signals: “rst”, “rst_n”
-- generics: “c_*”
-- user defined types: “*_type”
-- state machine next state: “*_ns”
-- state machine current state: “*_cs”
-- combinatorial signals: “*_com”
-- pipelined or register delay signals: “*_d#”
-- counter signals: “*cnt*”
-- clock enable signals: “*_ce”
-- internal version of output port: “*_i”
-- device pins: “*_pin”
-- ports: “- names begin with uppercase”
-- processes: “*_process”
-- component instantiations: “i_《#|func》”
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library proc_common_v3_00_a;
use proc_common_v3_00_a.proc_common_pkg.all;
use proc_common_v3_00_a.ipif_pkg.all;
library axi_lite_ipif_v1_01_a;
use axi_lite_ipif_v1_01_a.axi_lite_ipif;
------------------------------------------------------------------------------
-- entity section
------------------------------------------------------------------------------
-- definition of generics:
-- c_s_axi_data_width -- axi4lite slave: data width
-- c_s_axi_addr_width -- axi4lite slave: address width
-- c_s_axi_min_size -- axi4lite slave: min size
-- c_use_wstrb -- axi4lite slave: write strobe
-- c_dphase_timeout -- axi4lite slave: data phase timeout
-- c_baseaddr -- axi4lite slave: base address
-- c_highaddr -- axi4lite slave: high address
-- c_family -- fpga family
-- c_num_reg -- number of software accessible registers
-- c_num_mem -- number of address-ranges
-- c_slv_awidth -- slave interface address bus width
-- c_slv_dwidth -- slave interface data bus width
--
-- definition of ports:
-- s_axi_aclk -- axi4lite slave: clock
-- s_axi_aresetn -- axi4lite slave: reset
-- s_axi_awaddr -- axi4lite slave: write address
-- s_axi_awvalid -- axi4lite slave: write address valid
-- s_axi_wdata -- axi4lite slave: write data
-- s_axi_wstrb -- axi4lite slave: write strobe
-- s_axi_wvalid -- axi4lite slave: write data valid
-- s_axi_bready -- axi4lite slave: response ready
-- s_axi_araddr -- axi4lite slave: read address
-- s_axi_arvalid -- axi4lite slave: read address valid
-- s_axi_rready -- axi4lite slave: read data ready
-- s_axi_arready -- axi4lite slave: read addres ready
-- s_axi_rdata -- axi4lite slave: read data
-- s_axi_rresp -- axi4lite slave: read data response
-- s_axi_rvalid -- axi4lite slave: read data valid
-- s_axi_wready -- axi4lite slave: write data ready
-- s_axi_bresp -- axi4lite slave: response
-- s_axi_bvalid -- axi4lite slave: resonse valid
-- s_axi_awready -- axi4lite slave: wrte address ready
------------------------------------------------------------------------------
entity my_calc_v1 is
generic

-- add user generics below this line ---------------
--user generics added here
-- add user generics above this line ---------------
-- do not edit below this line ---------------------
-- bus protocol parameters, do not add to or delete
c_s_axi_data_width : integer := 32;
c_s_axi_addr_width : integer := 32;
c_s_axi_min_size : std_logic_vector := x“000001ff”;
c_use_wstrb : integer := 0;
c_dphase_timeout : integer := 8;
c_baseaddr : std_logic_vector := x“ffffffff”;
c_highaddr : std_logic_vector := x“00000000”;
c_family : string := “virtex6”;
c_num_reg : integer := 1;
c_num_mem : integer := 1;
c_slv_awidth : integer := 32;
c_slv_dwidth : integer := 32
-- do not edit above this line ---------------------
);
port

-- add user ports below this line ------------------
--user ports added here
-- add user ports above this line ------------------
gpio_led_out : out std_logic_vector(7 downto 0);
gpio_sw_in : in std_logic_vector(7 downto 0);
-- do not edit below this line ---------------------
-- bus protocol ports, do not add to or delete
s_axi_aclk : in std_logic;
s_axi_aresetn : in std_logic;
s_axi_awaddr : in std_logic_vector(c_s_axi_addr_width-1 downto 0);
s_axi_awvalid : in std_logic;
s_axi_wdata : in std_logic_vector(c_s_axi_data_width-1 downto 0);
s_axi_wstrb : in std_logic_vector((c_s_axi_data_width/8)-1 downto 0);
s_axi_wvalid : in std_logic;
s_axi_bready : in std_logic;
s_axi_araddr : in std_logic_vector(c_s_axi_addr_width-1 downto 0);
s_axi_arvalid : in std_logic;
s_axi_rready : in std_logic;
s_axi_arready : out std_logic;
s_axi_rdata : out std_logic_vector(c_s_axi_data_width-1 downto 0);
s_axi_rresp : out std_logic_vector(1 downto 0);
s_axi_rvalid : out std_logic;
s_axi_wready : out std_logic;
s_axi_bresp : out std_logic_vector(1 downto 0);
s_axi_bvalid : out std_logic;
s_axi_awready : out std_logic
-- do not edit above this line ---------------------
);
attribute max_fanout : string;
attribute sigis : string;
attribute max_fanout of s_axi_aclk : signal is “10000”;
attribute max_fanout of s_axi_aresetn : signal is “10000”;
attribute sigis of s_axi_aclk : signal is “clk”;
attribute sigis of s_axi_aresetn : signal is “rst”;
end entity my_calc_v1;
------------------------------------------------------------------------------
-- architecture section
------------------------------------------------------------------------------
architecture imp of my_calc_v1 is
constant user_slv_dwidth : integer := c_s_axi_data_width;
constant ipif_slv_dwidth : integer := c_s_axi_data_width;
constant zero_addr_pad : std_logic_vector(0 to 31) := (others =》 ’0‘);
constant user_slv_baseaddr : std_logic_vector := c_baseaddr;
constant user_slv_highaddr : std_logic_vector := c_highaddr;
constant ipif_ard_addr_range_array : slv64_array_type :=

zero_addr_pad & user_slv_baseaddr, -- user logic slave space base address
zero_addr_pad & user_slv_highaddr -- user logic slave space high address
);
constant user_slv_num_reg : integer := 5;
constant user_num_reg : integer := user_slv_num_reg;
constant total_ipif_ce : integer := user_num_reg;
constant ipif_ard_num_ce_array : integer_array_type :=

0 =》 (user_slv_num_reg) -- number of ce for user logic slave space
);
------------------------------------------
-- index for cs/ce
------------------------------------------
constant user_slv_cs_index : integer := 0;
constant user_slv_ce_index : integer := calc_start_ce_index(ipif_ard_num_ce_array, user_slv_cs_index);
constant user_ce_index : integer := user_slv_ce_index;
------------------------------------------
-- ip interconnect (ipic) signal declarations
------------------------------------------
signal ipif_bus2ip_clk : std_logic;
signal ipif_bus2ip_resetn : std_logic;
signal ipif_bus2ip_addr : std_logic_vector(c_s_axi_addr_width-1 downto 0);
signal ipif_bus2ip_rnw : std_logic;
signal ipif_bus2ip_be : std_logic_vector(ipif_slv_dwidth/8-1 downto 0);
signal ipif_bus2ip_cs : std_logic_vector((ipif_ard_addr_range_array’length)/2-1 downto 0);
signal ipif_bus2ip_rdce : std_logic_vector(calc_num_ce(ipif_ard_num_ce_array)-1 downto 0);
signal ipif_bus2ip_wrce : std_logic_vector(calc_num_ce(ipif_ard_num_ce_array)-1 downto 0);
signal ipif_bus2ip_data : std_logic_vector(ipif_slv_dwidth-1 downto 0);
signal ipif_ip2bus_wrack : std_logic;
signal ipif_ip2bus_rdack : std_logic;
signal ipif_ip2bus_error : std_logic;
signal ipif_ip2bus_data : std_logic_vector(ipif_slv_dwidth-1 downto 0);
signal user_bus2ip_rdce : std_logic_vector(user_num_reg-1 downto 0);
signal user_bus2ip_wrce : std_logic_vector(user_num_reg-1 downto 0);
signal user_ip2bus_data : std_logic_vector(user_slv_dwidth-1 downto 0);
signal user_ip2bus_rdack : std_logic;
signal user_ip2bus_wrack : std_logic;
signal user_ip2bus_error : std_logic;
------------------------------------------
-- component declaration for verilog user logic
------------------------------------------
component user_logic is
generic

-- add user generics below this line ---------------
--user generics added here
-- add user generics above this line ---------------
-- do not edit below this line ---------------------
-- bus protocol parameters, do not add to or delete
c_num_reg : integer := 5;
c_slv_dwidth : integer := 32
-- do not edit above this line ---------------------
);
port

-- add user ports below this line ------------------
--user ports added here
-- add user ports above this line ------------------
led_out :out std_logic_vector(7 downto 0);
sw_in :in std_logic_vector(7 downto 0);
-- do not edit below this line ---------------------
-- bus protocol ports, do not add to or delete
bus2ip_clk : in std_logic;
bus2ip_resetn : in std_logic;
bus2ip_data : in std_logic_vector(c_slv_dwidth-1 downto 0);
bus2ip_be : in std_logic_vector(c_slv_dwidth/8-1 downto 0);
bus2ip_rdce : in std_logic_vector(c_num_reg-1 downto 0);
bus2ip_wrce : in std_logic_vector(c_num_reg-1 downto 0);
ip2bus_data : out std_logic_vector(c_slv_dwidth-1 downto 0);
ip2bus_rdack : out std_logic;
ip2bus_wrack : out std_logic;
ip2bus_error : out std_logic
-- do not edit above this line ---------------------
);
end component user_logic;
begin
------------------------------------------
-- instantiate axi_lite_ipif
------------------------------------------
axi_lite_ipif_i : entity axi_lite_ipif_v1_01_a.axi_lite_ipif
generic map

c_s_axi_data_width =》 ipif_slv_dwidth,
c_s_axi_addr_width =》 c_s_axi_addr_width,
c_s_axi_min_size =》 c_s_axi_min_size,
c_use_wstrb =》 c_use_wstrb,
c_dphase_timeout =》 c_dphase_timeout,
c_ard_addr_range_array =》 ipif_ard_addr_range_array,
c_ard_num_ce_array =》 ipif_ard_num_ce_array,
c_family =》 c_family

port map

s_axi_aclk =》 s_axi_aclk,
s_axi_aresetn =》 s_axi_aresetn,
s_axi_awaddr =》 s_axi_awaddr,
s_axi_awvalid =》 s_axi_awvalid,
s_axi_wdata =》 s_axi_wdata,
s_axi_wstrb =》 s_axi_wstrb,
s_axi_wvalid =》 s_axi_wvalid,
s_axi_bready =》 s_axi_bready,
s_axi_araddr =》 s_axi_araddr,
s_axi_arvalid =》 s_axi_arvalid,
s_axi_rready =》 s_axi_rready,
s_axi_arready =》 s_axi_arready,
s_axi_rdata =》 s_axi_rdata,
s_axi_rresp =》 s_axi_rresp,
s_axi_rvalid =》 s_axi_rvalid,
s_axi_wready =》 s_axi_wready,
s_axi_bresp =》 s_axi_bresp,
s_axi_bvalid =》 s_axi_bvalid,
s_axi_awready =》 s_axi_awready,
bus2ip_clk =》 ipif_bus2ip_clk,
bus2ip_resetn =》 ipif_bus2ip_resetn,
bus2ip_addr =》 ipif_bus2ip_addr,
bus2ip_rnw =》 ipif_bus2ip_rnw,
bus2ip_be =》 ipif_bus2ip_be,
bus2ip_cs =》 ipif_bus2ip_cs,
bus2ip_rdce =》 ipif_bus2ip_rdce,
bus2ip_wrce =》 ipif_bus2ip_wrce,
bus2ip_data =》 ipif_bus2ip_data,
ip2bus_wrack =》 ipif_ip2bus_wrack,
ip2bus_rdack =》 ipif_ip2bus_rdack,
ip2bus_error =》 ipif_ip2bus_error,
ip2bus_data =》 ipif_ip2bus_data
);
------------------------------------------
-- instantiate user logic
------------------------------------------
user_logic_i : component user_logic
generic map

-- map user generics below this line ---------------
--user generics mapped here
-- map user generics above this line ---------------
c_num_reg =》 user_num_reg,
c_slv_dwidth =》 user_slv_dwidth

port map

-- map user ports below this line ------------------
--user ports mapped here
led_out =》 gpio_led_out,
sw_in =》 gpio_sw_in,
-- map user ports above this line ------------------
bus2ip_clk =》 ipif_bus2ip_clk,
bus2ip_resetn =》 ipif_bus2ip_resetn,
bus2ip_data =》 ipif_bus2ip_data,
bus2ip_be =》 ipif_bus2ip_be,
bus2ip_rdce =》 user_bus2ip_rdce,
bus2ip_wrce =》 user_bus2ip_wrce,
ip2bus_data =》 user_ip2bus_data,
ip2bus_rdack =》 user_ip2bus_rdack,
ip2bus_wrack =》 user_ip2bus_wrack,
ip2bus_error =》 user_ip2bus_error
);
------------------------------------------
-- connect internal signals
------------------------------------------
ipif_ip2bus_data 《= user_ip2bus_data;
ipif_ip2bus_wrack 《= user_ip2bus_wrack;
ipif_ip2bus_rdack 《= user_ip2bus_rdack;
ipif_ip2bus_error 《= user_ip2bus_error;
user_bus2ip_rdce 《= ipif_bus2ip_rdce(user_num_reg-1 downto 0);
user_bus2ip_wrce 《= ipif_bus2ip_wrce(user_num_reg-1 downto 0);
end imp;
这个里面的一些部分比较难理解,我只是按照我的想法进行解释,不一定正确
我理解的这个文件是对ip核这个实体进行的配置,其中包括的部分分别是,实体的信息,包括实体包含的寄存器,寄存器位宽,实体的对外端口等,其代码为:
entity my_calc_v1 is
generic

-- add user generics below this line ---------------
--user generics added here
-- add user generics above this line ---------------
-- do not edit below this line ---------------------
-- bus protocol parameters, do not add to or delete
c_s_axi_data_width : integer := 32;
c_s_axi_addr_width : integer := 32;
c_s_axi_min_size : std_logic_vector := x“000001ff”;
c_use_wstrb : integer := 0;
c_dphase_timeout : integer := 8;
c_baseaddr : std_logic_vector := x“ffffffff”;
c_highaddr : std_logic_vector := x“00000000”;
c_family : string := “virtex6”;
c_num_reg : integer := 1;
c_num_mem : integer := 1;
c_slv_awidth : integer := 32;
c_slv_dwidth : integer := 32
-- do not edit above this line ---------------------
);
port

-- add user ports below this line ------------------
--user ports added here
-- add user ports above this line ------------------
gpio_led_out : out std_logic_vector(7 downto 0);
gpio_sw_in : in std_logic_vector(7 downto 0);
-- do not edit below this line ---------------------
-- bus protocol ports, do not add to or delete
s_axi_aclk : in std_logic;
s_axi_aresetn : in std_logic;
s_axi_awaddr : in std_logic_vector(c_s_axi_addr_width-1 downto 0);
s_axi_awvalid : in std_logic;
s_axi_wdata : in std_logic_vector(c_s_axi_data_width-1 downto 0);
s_axi_wstrb : in std_logic_vector((c_s_axi_data_width/8)-1 downto 0);
s_axi_wvalid : in std_logic;
s_axi_bready : in std_logic;
s_axi_araddr : in std_logic_vector(c_s_axi_addr_width-1 downto 0);
s_axi_arvalid : in std_logic;
s_axi_rready : in std_logic;
s_axi_arready : out std_logic;
s_axi_rdata : out std_logic_vector(c_s_axi_data_width-1 downto 0);
s_axi_rresp : out std_logic_vector(1 downto 0);
s_axi_rvalid : out std_logic;
s_axi_wready : out std_logic;
s_axi_bresp : out std_logic_vector(1 downto 0);
s_axi_bvalid : out std_logic;
s_axi_awready : out std_logic
-- do not edit above this line ---------------------
);
在这里需要对实体添加自定义的对外接口,sw和led
下面就是对ip核的实现进行描述,包括ip核的架构(也是图形界面配置的一部分)包含的用户逻辑和用户逻辑到对外端口的映射关系
component user_logic is
generic

-- add user generics below this line ---------------
--user generics added here
-- add user generics above this line ---------------
-- do not edit below this line ---------------------
-- bus protocol parameters, do not add to or delete
c_num_reg : integer := 5;
c_slv_dwidth : integer := 32
-- do not edit above this line ---------------------
);
port

-- add user ports below this line ------------------
--user ports added here
-- add user ports above this line ------------------
led_out :out std_logic_vector(7 downto 0);
sw_in :in std_logic_vector(7 downto 0);
-- do not edit below this line ---------------------
-- bus protocol ports, do not add to or delete
bus2ip_clk : in std_logic;
bus2ip_resetn : in std_logic;
bus2ip_data : in std_logic_vector(c_slv_dwidth-1 downto 0);
bus2ip_be : in std_logic_vector(c_slv_dwidth/8-1 downto 0);
bus2ip_rdce : in std_logic_vector(c_num_reg-1 downto 0);
bus2ip_wrce : in std_logic_vector(c_num_reg-1 downto 0);
ip2bus_data : out std_logic_vector(c_slv_dwidth-1 downto 0);
ip2bus_rdack : out std_logic;
ip2bus_wrack : out std_logic;
ip2bus_error : out std_logic
-- do not edit above this line ---------------------
);
end component user_logic;
这部分用户逻辑的描述,需要再其中加入自己添加的部分,由于在用户逻辑中添加了sw和led的输入输出,因此在这部分中需要进行添加
最后是用户逻辑中的端口到ip核对外端口的映射,在map中进行了体现,代码如下
user_logic_i : component user_logic
generic map

-- map user generics below this line ---------------
--user generics mapped here
-- map user generics above this line ---------------
c_num_reg =》 user_num_reg,
c_slv_dwidth =》 user_slv_dwidth

port map

-- map user ports below this line ------------------
--user ports mapped here
led_out =》 gpio_led_out,
sw_in =》 gpio_sw_in,
-- map user ports above this line ------------------
bus2ip_clk =》 ipif_bus2ip_clk,
bus2ip_resetn =》 ipif_bus2ip_resetn,
bus2ip_data =》 ipif_bus2ip_data,
bus2ip_be =》 ipif_bus2ip_be,
bus2ip_rdce =》 user_bus2ip_rdce,
bus2ip_wrce =》 user_bus2ip_wrce,
ip2bus_data =》 user_ip2bus_data,
ip2bus_rdack =》 user_ip2bus_rdack,
ip2bus_wrack =》 user_ip2bus_wrack,
ip2bus_error =》 user_ip2bus_error
);
在完成以上代码的书写后,就基本完成了ip的控制,下面就是将ip核添加到工程中去,在此双击用户的ip核即可添加,在添加完成后,会在bus interface中发现此ip核,而后在port中进行配置,在port的配置过程中我理解为,此部分为经过ipif包装后ip核的对外端口,通过这些对外端口可以进行一些外设的连接,而后此ip核映射到ps端,当作一个外设进行同意编址,ps端可以直接对地址进行操作,就可以控制外设(如sw和led)
将gpio_led_out和gpio_sw_in配置为external ports,这样我理解是利用external ports就可以对外设进行连接,外设看到的端口名称为my_calc_v1_0_gpio_led_out_pin,和my_calc_v1_0_gpio_sw_in_pin。
进行完端口的配置后,就可以进行约束文件的建立,将端口映射到fpga的具体引脚上,约束文件如下:
#
# pin constraints
#
#
net “my_calc_v1_0_gpio_led_out_pin[0]” loc = t22;
net “my_calc_v1_0_gpio_led_out_pin[1]” loc = t21;
net “my_calc_v1_0_gpio_led_out_pin[2]” loc = u22;
net “my_calc_v1_0_gpio_led_out_pin[3]” loc = u21;
net “my_calc_v1_0_gpio_led_out_pin[4]” loc = v22;
net “my_calc_v1_0_gpio_led_out_pin[5]” loc = w22;
net “my_calc_v1_0_gpio_led_out_pin[6]” loc = u19;
net “my_calc_v1_0_gpio_led_out_pin[7]” loc = u14;
net “my_calc_v1_0_gpio_led_out_pin[0]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_led_out_pin[1]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_led_out_pin[2]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_led_out_pin[3]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_led_out_pin[4]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_led_out_pin[5]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_led_out_pin[6]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_led_out_pin[7]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_sw_in_pin[0]” loc = f22;
net “my_calc_v1_0_gpio_sw_in_pin[1]” loc = g22;
net “my_calc_v1_0_gpio_sw_in_pin[2]” loc = h22;
net “my_calc_v1_0_gpio_sw_in_pin[3]” loc = f21;
net “my_calc_v1_0_gpio_sw_in_pin[4]” loc = h19;
net “my_calc_v1_0_gpio_sw_in_pin[5]” loc = h18;
net “my_calc_v1_0_gpio_sw_in_pin[6]” loc = h17;
net “my_calc_v1_0_gpio_sw_in_pin[7]” loc = m15;
net “my_calc_v1_0_gpio_sw_in_pin[0]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_sw_in_pin[1]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_sw_in_pin[2]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_sw_in_pin[3]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_sw_in_pin[4]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_sw_in_pin[5]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_sw_in_pin[6]” iostandard = lvcmos33;
net “my_calc_v1_0_gpio_sw_in_pin[7]” iostandard = lvcmos33;
# additional constraints
#
完成后,xps端的配置就完成,点击generate bitstream生成bit文件,成功后导出的sdk
在进入sdk后,我们可以在system.xml文件中可以看到建立的ip核搭建的pl部分被当作外设映射到ps端,映射地址为0x78c00000
在此后我们只需要根据c语言的知识,对此地址端进行编程即可,下面逻辑就不再展开叙述,具体代码如下,写的比较乱
/*
* copyright (c) 2009 xilinx, inc. all rights reserved.
*
* xilinx, inc.
* xilinx is providing this design, code, or information “as is” as a
* courtesy to you. by providing this design, code, or information as
* one possible implementation of this feature, application or
* standard, xilinx is making no representation that this implementation
* is free from any claims of infringement, and you are responsible
* for obtaining any rights you may require for your implementation.
* xilinx expressly disclaims any warranty whatsoever with respect to
* the adequacy of the implementation, including but not limited to
* any warranties or representations that this implementation is free
* from claims of infringement, implied warranties of merchantability
* and fitness for a particular purpose.
*
*/
/*
* helloworld.c: simple test application
*/
#include
#include “platform.h”
#define sw (* (volatile unsigned int *) 0x78c00000) //
#define led (* (volatile unsigned int *) 0x78c00004) //
#define add1 (* (volatile unsigned int *) 0x78c00008) // 第一个寄存器地址---加数一
#define add2 (* (volatile unsigned int *) 0x78c0000c) // 第二个寄存器地址---加数二
#define sum (* (volatile unsigned int *) 0x78c00010) // 第三个寄存器地址---和
//void print(char *str);
int main()
{
init_platform();
printf(“hello world\n\r”);
printf(“please input the first operator:\n\r”);
scanf(“%d”, &add1);
printf(“please second the first operator:\n\r”);
scanf(“%d”, &add2);
if(sw == 0x01)
{
printf(“the result of add1 + add2 = %d\n\r”, sum);
}
else if(sw == 0x02)
{
printf(“the result of add1 - add2 = %d\n\r”, sum);
}
led = sum;

诚迈科技助力知名智能照明设备制造商立达信接入鸿蒙生态
高光谱成像技术的工作原理与食品安全的关系
为什么苏州无人公交开通线路的定位是“城市微循环公交”?
为了实现消费级别的自动驾驶,Mobileye做了哪些?
嵌入式编程之单片机的外围功能电路
利用zedboard添加自定义IP核完成简易计算器功能
区块链技术在电力交易方面有什么作为
线上召开照明电器行业职业技能等级评价工作会议
秒杀几道运用Dijkstra算法的题目
科学家以白细胞为模型,研发出一款微型机器人
除了嫦娥五号,还有哪些探测器从太空采样返回?
魅族表示最快将在2020年第二季度推出真5G双模手机
USB3.0一拖四集线器
电子身份证来了,CTID网证身份核验终端助力提升窗口服务效率
精密玻璃管技术规格
谷歌承认部分 Duplex AI 订座服务有人工介入
RFMD发表RF3232系列四频传输模块
不得不说ASIC成为数字电子电路集成首选方法
万用表小电阻测试精度的差异
基于区块链模块化高效率基础设施“Luther”介绍