首页 > 代码库 > Learn ZYNC (5)

Learn ZYNC (5)

今天为了熟悉axiLite的自定义ip核设计,

把LED和SW的往AXI总线输入输出定义在一个ip核中,

BD设计如下:

image

ip核顶层文件(增加了LED_Out和SW_In的定义)mygpio_v1.0.v:

	module mygpio_v1_0 #	(		// Users to add parameters here		// User parameters ends		// Do not modify the parameters beyond this line		// Parameters of Axi Slave Bus Interface S00_AXI		parameter integer C_S00_AXI_DATA_WIDTH	= 32,		parameter integer C_S00_AXI_ADDR_WIDTH	= 4	)	(		// Users to add ports here//*****************my code***********************************        input wire [7:0] SW_In,        output wire [7:0] LED_Out,		// User ports ends		// Do not modify the ports beyond this line		// Ports of Axi Slave Bus Interface S00_AXI		input wire  s00_axi_aclk,		input wire  s00_axi_aresetn,		input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_awaddr,		input wire [2 : 0] s00_axi_awprot,		input wire  s00_axi_awvalid,		output wire  s00_axi_awready,		input wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_wdata,		input wire [(C_S00_AXI_DATA_WIDTH/8)-1 : 0] s00_axi_wstrb,		input wire  s00_axi_wvalid,		output wire  s00_axi_wready,		output wire [1 : 0] s00_axi_bresp,		output wire  s00_axi_bvalid,		input wire  s00_axi_bready,		input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_araddr,		input wire [2 : 0] s00_axi_arprot,		input wire  s00_axi_arvalid,		output wire  s00_axi_arready,		output wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_rdata,		output wire [1 : 0] s00_axi_rresp,		output wire  s00_axi_rvalid,		input wire  s00_axi_rready	);// Instantiation of Axi Bus Interface S00_AXI	mygpio_v1_0_S00_AXI # ( 		.C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH),		.C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH)	) mygpio_v1_0_S00_AXI_inst (//*****************************my code***************************	    .SW_In(SW_In),	    .LED_Out(LED_Out),		.S_AXI_ACLK(s00_axi_aclk),		.S_AXI_ARESETN(s00_axi_aresetn),		.S_AXI_AWADDR(s00_axi_awaddr),		.S_AXI_AWPROT(s00_axi_awprot),		.S_AXI_AWVALID(s00_axi_awvalid),		.S_AXI_AWREADY(s00_axi_awready),		.S_AXI_WDATA(s00_axi_wdata),		.S_AXI_WSTRB(s00_axi_wstrb),		.S_AXI_WVALID(s00_axi_wvalid),		.S_AXI_WREADY(s00_axi_wready),		.S_AXI_BRESP(s00_axi_bresp),		.S_AXI_BVALID(s00_axi_bvalid),		.S_AXI_BREADY(s00_axi_bready),		.S_AXI_ARADDR(s00_axi_araddr),		.S_AXI_ARPROT(s00_axi_arprot),		.S_AXI_ARVALID(s00_axi_arvalid),		.S_AXI_ARREADY(s00_axi_arready),		.S_AXI_RDATA(s00_axi_rdata),		.S_AXI_RRESP(s00_axi_rresp),		.S_AXI_RVALID(s00_axi_rvalid),		.S_AXI_RREADY(s00_axi_rready)	);	// Add user logic here	// User logic ends	endmodule

ip核实现文件mygpio_v1_0_S00_AXI.v:

	module mygpio_v1_0_S00_AXI #	(		// Users to add parameters here		// User parameters ends		// 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//*********************my code ****************************************        input wire [7:0] SW_In,        output wire [7:0] LED_Out,		// User ports ends		// Do not modify the ports beyond this line		// 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 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    // the transaction is a data access or an instruction access.		input wire [2 : 0] S_AXI_AWPROT,		// Write address valid. This signal indicates that the master signaling    // valid write address and control information.		input wire  S_AXI_AWVALID,		// Write address ready. This signal indicates that the slave is ready    // to accept an address and associated control signals.		output wire  S_AXI_AWREADY,		// Write data (issued by master, acceped by Slave) 		input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_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.    		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    // transaction is a data access or an instruction access.		input wire [2 : 0] S_AXI_ARPROT,		// Read address valid. This signal indicates that the 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    // accept the read data and response information.		input wire  S_AXI_RREADY	);	// 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;	reg  	axi_rvalid;	// 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//*********************my code ****************************************    wire [31:0] reg0_wire;    reg [31:0] SW_Reg0;    reg [31:0] SW_Reg1;	//------------------------------------------------	//-- Number of Slave Registers 4	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg0;	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg1;	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;	// I/O Connections assignments	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	= http://www.mamicode.com/axi_rdata;>

在这个文件中,我注释了AXI总线在写数据时对于slv_reg0写的定义,因为在我们的用户代码中使用一条reg0_wire将slv_reg0连到了sw_ul子核中,并且在子核中对reg0定义写操作(即将sw的状态输出到slv_reg0),然后另一段代码会将其放入reg_data_out,最后在slv_reg_rden线的输出为1时,它会进一步被送往axi_rdata,并通过数据总线S_AXI_RDATA输出。

ip核内包含的子文件sw_ul.v

module sw_ul(    input S_AXI_ACLK,    input slv_reg_rden,    input [1:0] axi_araddr,    input aresetn,    input [7:0] SW_In,    output reg [31:0] rdata    );    reg [31:0] SW_Reg0;    reg [31:0] SW_Reg1;    always @(posedge S_AXI_ACLK)    begin        if ( aresetn == 1‘b0 )        begin            SW_Reg0 <= 0;            SW_Reg1 <= 0;            rdata <= 0;        end        else        begin            if(slv_reg_rden)            begin                if(axi_araddr == 2‘h0)                begin                    SW_Reg0 <= SW_In;                    SW_Reg1 <= SW_Reg0;                    rdata[7:0] <= SW_Reg1[7:0];                end            end        end    endendmodule

ip核内包含的子文件led_ul.v

module led_ul(    input S_AXI_ACLK,    input slv_reg_wren,    input [1:0] axi_awaddr,    input [31:0] S_AXI_WDATA,    input aresetn,    output reg [7:0] LED    );        always @( posedge S_AXI_ACLK )    begin            if( aresetn == 1‘b0 )                begin                    LED <= 8‘b10011001;                end            else                begin                if (slv_reg_wren && (axi_awaddr == 2‘h1))                begin                    LED <= S_AXI_WDATA[7:0];                 end//                    LED <= 8‘b11111111;//                    if (slv_reg_wren)//                    begin//                        case(axi_awaddr)//                            2‘h1://                            begin//                                LED <= S_AXI_WDATA[7:0];//                                  LED <= 8‘b00000001;//                            end//                            2‘h0://                            begin//                                LED <= 8‘b00000000;//                            end//                            default://                            begin//                                LED <= 8‘b11111111;//                            end//                         endcase//                     end                end        endendmodule

EDK中standalone程序:

#include <stdio.h>#include "xparameters.h"#include "xil_io.h"#include "mygpio.h"#include "platform.h"int main(){	u32 inData = http://www.mamicode.com/0;>刚开始一直都测试不成功,一直得不到ip核中axi_araddr等于1的状态(即写第一个slv_reg1),后来看到了MYGPIO_S00_AXI_SLV_REG1_OFFSET=4,寄存器设置时设置的是32b,就是4Byte,灯只用到了其中最后的8bit,地址从0x43C00000开始,编号为1的寄存器地址应该是0x43C00004(存储器字长=1B)。(我们的ip核中,reg0用来存放sw读出的数据,而reg1用来从axi总线给led灯传送数据)。

参考文献:懒兔子教程