您的位置:首页 > 文旅 > 旅游 > 深圳宝安区疫情风险等级_东莞建站公司运转全网天下有 名_互联网营销师是做什么的_长沙专业seo优化公司

深圳宝安区疫情风险等级_东莞建站公司运转全网天下有 名_互联网营销师是做什么的_长沙专业seo优化公司

2024/12/23 4:07:00 来源:https://blog.csdn.net/zljdfaljsfd/article/details/143257332  浏览:    关键词:深圳宝安区疫情风险等级_东莞建站公司运转全网天下有 名_互联网营销师是做什么的_长沙专业seo优化公司
深圳宝安区疫情风险等级_东莞建站公司运转全网天下有 名_互联网营销师是做什么的_长沙专业seo优化公司

前置调研

原理图

AXI-FULL时序

由于项目需要实时性高,采用AXI-FULL接口ADC  IP作为master端写入DDR中

引用:

AXI_02 AXI4总线简介(协议、时序)_axi4总线时序-CSDN博客

AXI总线的访问

在ARM架构中,访问I/O地址通常通过内存映射I/O(Memory-Mapped I/O, MMIO)来实现。ARM处理器不像x86那样有专门的I/O空间和IN/OUT指令;相反,它将外设寄存器映射到系统的物理地址空间中,这样就可以像访问内存一样访问这些设备寄存器。以下是ARM架构下访问I/O地址的一些关键点:

  1. 内存映射I/O (MMIO):

    • 外设的控制寄存器被映射到系统的一个特定的物理地址范围内。
    • 这些地址范围在硬件设计时就已经确定,并且会在启动过程中由引导加载程序或操作系统进行配置。
    • 应用程序或驱动程序可以使用标准的内存读写指令(如LDRSTR等)来访问这些寄存器。
  2. 设备树:

    • 在现代的ARM Linux系统中,设备树(Device Tree)是一个重要的机制,用来描述硬件信息,包括I/O资源的位置。
    • 设备树中的节点会指定每个外设使用的基地址、大小以及其他属性,这使得Linux内核能够正确地初始化和配置这些设备。
  3. 内存屏障:

    • 由于缓存的存在,对于某些类型的I/O操作,可能需要使用内存屏障指令(如DMBDSBISB)来确保数据的一致性。
    • 例如,在对一个外设寄存器执行了写操作后,你可能需要插入一个DSB指令以确保写入完成后再继续后续的操作。
  4. 权限和安全:

    • 直接访问I/O地址通常需要特权模式,即内核模式。用户空间的应用程序不能直接访问这些地址,除非它们通过某种方式获得了相应的权限。
    • 使用mmap()系统调用可以将I/O地址区域映射到用户空间,但这通常仅限于那些被特别允许的设备,比如帧缓冲区。
  5. 编程示例:

    • 写比如DMA驱动访问IO地址时:
      /* IO accessors */
      static inline u32 dma_read(struct xilinx_dma_chan *chan, u32 reg)
      {return ioread32(chan->xdev->regs + reg);
      }static inline void dma_write(struct xilinx_dma_chan *chan, u32 reg, u32 value)
      {iowrite32(value, chan->xdev->regs + reg);
      }

    • 如果是在编写内核模块或驱动程序,可以直接使用指针来访问映射后的I/O地址。例如
      void *base = ioremap(0x12345678, 0x100); // 映射0x12345678开始的0x100字节
      u32 value = readl(base + 0x10); // 从偏移0x10处读取32位值
      writel(0x5A5A5A5A, base + 0x20); // 向偏移0x20处写入32位值
      iounmap(base); // 解除映射

PL读写PS端DDR的原理

一般步骤:

1. **设备树(Device Tree)配置**:需要在设备树中描述PL和DDR之间的连接,以及PL中生成的IP核的地址范围和属性。设备树是Linux内核启动时传递给内核的数据结构,描述了系统的硬件

2. **Linux驱动程序**:需要编写一个Linux设备驱动程序,它能够在Linux内核中识别PL中的IP核,并提供用户空间访问这些IP核的接口。这可能涉及到使用Linux的UIO(Userspace I/O)框架或自定义的驱动程序。

3. **用户空间应用程序**:在Linux用户空间编写应用程序,通过使用Linux设备驱动程序提供的接口,可以从PL写入DDR的地址空间中读取数据。

引用:

FPGA打工人如何学习ZYNQ PS与PL交互。第一节:AXI_GP、AXI_HP、AXI_ACP端口总结_哔哩哔哩_bilibili

zynq pl访问ps ddr_zynq ps pl ddr交互-CSDN博客

实现步骤

硬件设计

ADC IP WITH AXI INTERFACE

AXI接口的实现、ADC数据读取逻辑,以及将数据写入DDR的逻辑


`timescale 1 ns / 1 psmodule fast_adc_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_AXIparameter  C_M00_AXI_TARGET_SLAVE_BASE_ADDR	= 32'h40000000,parameter integer C_M00_AXI_BURST_LEN	= 16,parameter integer C_M00_AXI_ID_WIDTH	= 1,parameter integer C_M00_AXI_ADDR_WIDTH	= 32,parameter integer C_M00_AXI_DATA_WIDTH	= 32,parameter integer C_M00_AXI_AWUSER_WIDTH	= 0,parameter integer C_M00_AXI_ARUSER_WIDTH	= 0,parameter integer C_M00_AXI_WUSER_WIDTH	= 0,parameter integer C_M00_AXI_RUSER_WIDTH	= 0,parameter integer C_M00_AXI_BUSER_WIDTH	= 0)(// Users to add ports hereinput	wire 			adc_clk_i 	,input	wire 	[7:0]	adc_data 	,	output wire            adc_clk_o,// User ports ends// Do not modify the ports beyond this line// Ports of Axi Master Bus Interface M00_AXIinput wire  m00_axi_init_axi_txn,output wire  m00_axi_txn_done,output wire  m00_axi_error,input wire  m00_axi_aclk,input wire  m00_axi_aresetn,output wire [C_M00_AXI_ID_WIDTH-1 : 0] m00_axi_awid,output wire [C_M00_AXI_ADDR_WIDTH-1 : 0] m00_axi_awaddr,output wire [7 : 0] m00_axi_awlen,output wire [2 : 0] m00_axi_awsize,output wire [1 : 0] m00_axi_awburst,output wire  m00_axi_awlock,output wire [3 : 0] m00_axi_awcache,output wire [2 : 0] m00_axi_awprot,output wire [3 : 0] m00_axi_awqos,output wire [C_M00_AXI_AWUSER_WIDTH-1 : 0] m00_axi_awuser,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_wlast,output wire [C_M00_AXI_WUSER_WIDTH-1 : 0] m00_axi_wuser,output wire  m00_axi_wvalid,input wire  m00_axi_wready,input wire [C_M00_AXI_ID_WIDTH-1 : 0] m00_axi_bid,input wire [1 : 0] m00_axi_bresp,input wire [C_M00_AXI_BUSER_WIDTH-1 : 0] m00_axi_buser,input wire  m00_axi_bvalid,output wire  m00_axi_bready,output wire [C_M00_AXI_ID_WIDTH-1 : 0] m00_axi_arid,output wire [C_M00_AXI_ADDR_WIDTH-1 : 0] m00_axi_araddr,output wire [7 : 0] m00_axi_arlen,output wire [2 : 0] m00_axi_arsize,output wire [1 : 0] m00_axi_arburst,output wire  m00_axi_arlock,output wire [3 : 0] m00_axi_arcache,output wire [2 : 0] m00_axi_arprot,output wire [3 : 0] m00_axi_arqos,output wire [C_M00_AXI_ARUSER_WIDTH-1 : 0] m00_axi_aruser,output wire  m00_axi_arvalid,input wire  m00_axi_arready,input wire [C_M00_AXI_ID_WIDTH-1 : 0] m00_axi_rid,input wire [C_M00_AXI_DATA_WIDTH-1 : 0] m00_axi_rdata,input wire [1 : 0] m00_axi_rresp,input wire  m00_axi_rlast,input wire [C_M00_AXI_RUSER_WIDTH-1 : 0] m00_axi_ruser,input wire  m00_axi_rvalid,output wire  m00_axi_rready);assign adc_clk_o = adc_clk_i;
// Instantiation of Axi Bus Interface M00_AXIfast_adc_v1_0_M00_AXI # ( .C_M_TARGET_SLAVE_BASE_ADDR(C_M00_AXI_TARGET_SLAVE_BASE_ADDR),.C_M_AXI_BURST_LEN(C_M00_AXI_BURST_LEN),.C_M_AXI_ID_WIDTH(C_M00_AXI_ID_WIDTH),.C_M_AXI_ADDR_WIDTH(C_M00_AXI_ADDR_WIDTH),.C_M_AXI_DATA_WIDTH(C_M00_AXI_DATA_WIDTH),.C_M_AXI_AWUSER_WIDTH(C_M00_AXI_AWUSER_WIDTH),.C_M_AXI_ARUSER_WIDTH(C_M00_AXI_ARUSER_WIDTH),.C_M_AXI_WUSER_WIDTH(C_M00_AXI_WUSER_WIDTH),.C_M_AXI_RUSER_WIDTH(C_M00_AXI_RUSER_WIDTH),.C_M_AXI_BUSER_WIDTH(C_M00_AXI_BUSER_WIDTH)) fast_adc_v1_0_M00_AXI_inst (.adc_clk(adc_clk_i),.adc_data(adc_data),.INIT_AXI_TXN(m00_axi_init_axi_txn),.TXN_DONE(m00_axi_txn_done),.ERROR(m00_axi_error),.M_AXI_ACLK(m00_axi_aclk),.M_AXI_ARESETN(m00_axi_aresetn),.M_AXI_AWID(m00_axi_awid),.M_AXI_AWADDR(m00_axi_awaddr),.M_AXI_AWLEN(m00_axi_awlen),.M_AXI_AWSIZE(m00_axi_awsize),.M_AXI_AWBURST(m00_axi_awburst),.M_AXI_AWLOCK(m00_axi_awlock),.M_AXI_AWCACHE(m00_axi_awcache),.M_AXI_AWPROT(m00_axi_awprot),.M_AXI_AWQOS(m00_axi_awqos),.M_AXI_AWUSER(m00_axi_awuser),.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_WLAST(m00_axi_wlast),.M_AXI_WUSER(m00_axi_wuser),.M_AXI_WVALID(m00_axi_wvalid),.M_AXI_WREADY(m00_axi_wready),.M_AXI_BID(m00_axi_bid),.M_AXI_BRESP(m00_axi_bresp),.M_AXI_BUSER(m00_axi_buser),.M_AXI_BVALID(m00_axi_bvalid),.M_AXI_BREADY(m00_axi_bready),.M_AXI_ARID(m00_axi_arid),.M_AXI_ARADDR(m00_axi_araddr),.M_AXI_ARLEN(m00_axi_arlen),.M_AXI_ARSIZE(m00_axi_arsize),.M_AXI_ARBURST(m00_axi_arburst),.M_AXI_ARLOCK(m00_axi_arlock),.M_AXI_ARCACHE(m00_axi_arcache),.M_AXI_ARPROT(m00_axi_arprot),.M_AXI_ARQOS(m00_axi_arqos),.M_AXI_ARUSER(m00_axi_aruser),.M_AXI_ARVALID(m00_axi_arvalid),.M_AXI_ARREADY(m00_axi_arready),.M_AXI_RID(m00_axi_rid),.M_AXI_RDATA(m00_axi_rdata),.M_AXI_RRESP(m00_axi_rresp),.M_AXI_RLAST(m00_axi_rlast),.M_AXI_RUSER(m00_axi_ruser),.M_AXI_RVALID(m00_axi_rvalid),.M_AXI_RREADY(m00_axi_rready));// Add user logic here// User logic endsendmodule

`timescale 1 ns / 1 psmodule fast_adc_v1_0_M00_AXI #(// Users to add parameters here// User parameters ends// Do not modify the parameters beyond this line// Base address of targeted slaveparameter  C_M_TARGET_SLAVE_BASE_ADDR	= 32'h40000000,// Burst Length. Supports 1, 2, 4, 8, 16, 32, 64, 128, 256 burst lengthsparameter integer C_M_AXI_BURST_LEN	= 16,// Thread ID Widthparameter integer C_M_AXI_ID_WIDTH	= 1,// Width of Address Busparameter integer C_M_AXI_ADDR_WIDTH	= 32,// Width of Data Busparameter integer C_M_AXI_DATA_WIDTH	= 32,// Width of User Write Address Busparameter integer C_M_AXI_AWUSER_WIDTH	= 0,// Width of User Read Address Busparameter integer C_M_AXI_ARUSER_WIDTH	= 0,// Width of User Write Data Busparameter integer C_M_AXI_WUSER_WIDTH	= 0,// Width of User Read Data Busparameter integer C_M_AXI_RUSER_WIDTH	= 0,// Width of User Response Busparameter integer C_M_AXI_BUSER_WIDTH	= 0)(// Users to add ports hereinput	wire 			adc_clk,input	wire 	[7:0]	adc_data,// User ports ends// Do not modify the ports beyond this line// Initiate AXI transactionsinput wire  INIT_AXI_TXN,// Asserts when transaction is completeoutput wire  TXN_DONE,// Asserts when ERROR is detectedoutput reg  ERROR,// Global Clock Signal.input wire  M_AXI_ACLK,// Global Reset Singal. This Signal is Active Lowinput wire  M_AXI_ARESETN,// Master Interface Write Address IDoutput wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_AWID,// Master Interface Write Addressoutput wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR,// Burst length. The burst length gives the exact number of transfers in a burstoutput wire [7 : 0] M_AXI_AWLEN,// Burst size. This signal indicates the size of each transfer in the burstoutput wire [2 : 0] M_AXI_AWSIZE,// Burst type. The burst type and the size information, // determine how the address for each transfer within the burst is calculated.output wire [1 : 0] M_AXI_AWBURST,// Lock type. Provides additional information about the// atomic characteristics of the transfer.output wire  M_AXI_AWLOCK,// Memory type. This signal indicates how transactions// are required to progress through a system.output wire [3 : 0] M_AXI_AWCACHE,// 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,// Quality of Service, QoS identifier sent for each write transaction.output wire [3 : 0] M_AXI_AWQOS,// Optional User-defined signal in the write address channel.output wire [C_M_AXI_AWUSER_WIDTH-1 : 0] M_AXI_AWUSER,// Write address valid. This signal indicates that// the channel is 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 signalsinput wire  M_AXI_AWREADY,// Master Interface Write Data.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 last. This signal indicates the last transfer in a write burst.output wire  M_AXI_WLAST,// Optional User-defined signal in the write data channel.output wire [C_M_AXI_WUSER_WIDTH-1 : 0] M_AXI_WUSER,// Write valid. This signal indicates that valid write// data and strobes are availableoutput 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.input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_BID,// Write response. This signal indicates the status of the write transaction.input wire [1 : 0] M_AXI_BRESP,// Optional User-defined signal in the write response channelinput wire [C_M_AXI_BUSER_WIDTH-1 : 0] M_AXI_BUSER,// 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.output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_ARID,// Read address. This signal indicates the initial// address of a read burst transaction.output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR,// Burst length. The burst length gives the exact number of transfers in a burstoutput wire [7 : 0] M_AXI_ARLEN,// Burst size. This signal indicates the size of each transfer in the burstoutput wire [2 : 0] M_AXI_ARSIZE,// Burst type. The burst type and the size information, // determine how the address for each transfer within the burst is calculated.output wire [1 : 0] M_AXI_ARBURST,// Lock type. Provides additional information about the// atomic characteristics of the transfer.output wire  M_AXI_ARLOCK,// Memory type. This signal indicates how transactions// are required to progress through a system.output wire [3 : 0] M_AXI_ARCACHE,// 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,// Quality of Service, QoS identifier sent for each read transactionoutput wire [3 : 0] M_AXI_ARQOS,// Optional User-defined signal in the read address channel.output wire [C_M_AXI_ARUSER_WIDTH-1 : 0] M_AXI_ARUSER,// Write address valid. This signal indicates that// the channel is signaling valid read address and control informationoutput wire  M_AXI_ARVALID,// Read address ready. This signal indicates that// the slave is ready to accept an address and associated control signalsinput wire  M_AXI_ARREADY,// Read ID tag. This signal is the identification tag// for the read data group of signals generated by the slave.input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_RID,// Master Read Datainput wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA,// Read response. This signal indicates the status of the read transferinput wire [1 : 0] M_AXI_RRESP,// Read last. This signal indicates the last transfer in a read burstinput wire  M_AXI_RLAST,// Optional User-defined signal in the read address channel.input wire [C_M_AXI_RUSER_WIDTH-1 : 0] M_AXI_RUSER,// 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);// function called clogb2 that returns an integer which has the//value of the ceiling of the log base 2// function called clogb2 that returns an integer which has the // value of the ceiling of the log base 2.                      function integer clogb2 (input integer bit_depth);              begin                                                           for(clogb2=0; bit_depth>0; clogb2=clogb2+1)                   bit_depth = bit_depth >> 1;                                 end                                                           endfunction                                                     // C_TRANSACTIONS_NUM is the width of the index counter for // number of write or read transaction.localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1);// Burst length for transactions, in C_M_AXI_DATA_WIDTHs.// Non-2^n lengths will eventually cause bursts across 4K address boundaries.localparam integer C_MASTER_LENGTH	= 12;// total number of burst transfers is master length divided by burst length and burst sizelocalparam integer C_NO_BURSTS_REQ = C_MASTER_LENGTH-clogb2((C_M_AXI_BURST_LEN*C_M_AXI_DATA_WIDTH/8)-1);// Example State machine to initialize counter, initialize write transactions, // initialize read transactions and comparison of read data with the // written data words.parameter [1:0] IDLE = 2'b00, // This state initiates AXI4Lite transaction // after the state machine changes state to INIT_WRITE // when there is 0 to 1 transition on INIT_AXI_TXNINIT_WRITE   = 2'b01, // This state initializes write transaction,// once writes are done, the state machine // changes state to INIT_READ INIT_READ = 2'b10, // This state initializes read transaction// once reads are done, the state machine // changes state to INIT_COMPARE INIT_COMPARE = 2'b11; // This state issues the status of comparison // of the written data with the read data	reg [1:0] mst_exec_state;// AXI4LITE signals//AXI4 internal temp signalsreg [C_M_AXI_ADDR_WIDTH-1 : 0] 	axi_awaddr;reg  	axi_awvalid;reg [C_M_AXI_DATA_WIDTH-1 : 0] 	axi_wdata;reg  	axi_wlast;reg  	axi_wvalid;reg  	axi_bready;reg [C_M_AXI_ADDR_WIDTH-1 : 0] 	axi_araddr;reg  	axi_arvalid;reg  	axi_rready;//write beat count in a burstreg [C_TRANSACTIONS_NUM : 0] 	write_index;//read beat count in a burstreg [C_TRANSACTIONS_NUM : 0] 	read_index;//size of C_M_AXI_BURST_LEN length burst in byteswire [C_TRANSACTIONS_NUM+2 : 0] 	burst_size_bytes;//The burst counters are used to track the number of burst transfers of C_M_AXI_BURST_LEN burst length needed to transfer 2^C_MASTER_LENGTH bytes of data.reg [C_NO_BURSTS_REQ : 0] 	write_burst_counter;reg [C_NO_BURSTS_REQ : 0] 	read_burst_counter;reg  	start_single_burst_write;reg  	start_single_burst_read;reg  	writes_done;reg  	reads_done;reg  	error_reg;reg  	compare_done;reg  	read_mismatch;reg  	burst_write_active;reg  	burst_read_active;reg [C_M_AXI_DATA_WIDTH-1 : 0] 	expected_rdata;//Interface response error flagswire  	write_resp_error;wire  	read_resp_error;wire  	wnext;wire  	rnext;reg  	init_txn_ff;reg  	init_txn_ff2;reg  	init_txn_edge;wire  	init_txn_pulse;reg    init_write_start;// I/O Connections assignments//I/O Connections. Write Address (AW)assign M_AXI_AWID	= 'b0;//The AXI address is a concatenation of the target base address + active offset rangeassign M_AXI_AWADDR	= C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr;//Burst LENgth is number of transaction beats, minus 1assign M_AXI_AWLEN	= C_M_AXI_BURST_LEN - 1;//Size should be C_M_AXI_DATA_WIDTH, in 2^SIZE bytes, otherwise narrow bursts are usedassign M_AXI_AWSIZE	= clogb2((C_M_AXI_DATA_WIDTH/8)-1);//INCR burst type is usually used, except for keyhole burstsassign M_AXI_AWBURST	= 2'b01;assign M_AXI_AWLOCK	= 1'b0;//Update value to 4'b0011 if coherent accesses to be used via the Zynq ACP port. Not Allocated, Modifiable, not Bufferable. Not Bufferable since this example is meant to test memory, not intermediate cache. assign M_AXI_AWCACHE	= 4'b0010;assign M_AXI_AWPROT	= 3'h0;assign M_AXI_AWQOS	= 4'h0;assign M_AXI_AWUSER	= 'b1;assign M_AXI_AWVALID	= axi_awvalid;//Write Data(W)assign M_AXI_WDATA	= axi_wdata;//All bursts are complete and aligned in this exampleassign M_AXI_WSTRB	= {(C_M_AXI_DATA_WIDTH/8){1'b1}};assign M_AXI_WLAST	= axi_wlast;assign M_AXI_WUSER	= 'b0;assign M_AXI_WVALID	= axi_wvalid;//Write Response (B)assign M_AXI_BREADY	= axi_bready;//Read Address (AR)assign M_AXI_ARID	= 'b0;assign M_AXI_ARADDR	= C_M_TARGET_SLAVE_BASE_ADDR + axi_araddr;//Burst LENgth is number of transaction beats, minus 1assign M_AXI_ARLEN	= C_M_AXI_BURST_LEN - 1;//Size should be C_M_AXI_DATA_WIDTH, in 2^n bytes, otherwise narrow bursts are usedassign M_AXI_ARSIZE	= clogb2((C_M_AXI_DATA_WIDTH/8)-1);//INCR burst type is usually used, except for keyhole burstsassign M_AXI_ARBURST	= 2'b01;assign M_AXI_ARLOCK	= 1'b0;//Update value to 4'b0011 if coherent accesses to be used via the Zynq ACP port. Not Allocated, Modifiable, not Bufferable. Not Bufferable since this example is meant to test memory, not intermediate cache. assign M_AXI_ARCACHE	= 4'b0010;assign M_AXI_ARPROT	= 3'h0;assign M_AXI_ARQOS	= 4'h0;assign M_AXI_ARUSER	= 'b1;assign M_AXI_ARVALID	= axi_arvalid;//Read and Read Response (R)assign M_AXI_RREADY	= axi_rready;//Example design I/Oassign TXN_DONE	= compare_done;//Burst size in bytesassign burst_size_bytes	= C_M_AXI_BURST_LEN * C_M_AXI_DATA_WIDTH/8;//assign init_txn_pulse	= (!init_txn_ff2) && init_txn_ff;assign init_txn_pulse	= init_write_start;//every adc clk start once write trancation modify by xzjalways @(posedge adc_clk)										      begin                                                                        // Initiates AXI transaction delay    if (M_AXI_ARESETN == 0 )                                                   begin                                                                    init_write_start <= 1'b0;                                                                                                      end                                                                               else if (init_write_start == 1'b0)                             begin                                                            init_write_start <= 1'b1;                   end                                                              else                                                               init_write_start <= 1'b0;                                                                 end     //Generate a pulse to initiate AXI transaction.always @(posedge M_AXI_ACLK)										      begin                                                                        // Initiates AXI transaction delay    if (M_AXI_ARESETN == 0 )                                                   begin                                                                    init_txn_ff <= 1'b0;                                                   init_txn_ff2 <= 1'b0;                                                   end                                                                               else                                                                       begin  init_txn_ff <= INIT_AXI_TXN;init_txn_ff2 <= init_txn_ff;                                                                 end                                                                      end     //--------------------//Write Address Channel//--------------------// The purpose of the write address channel is to request the address and // command information for the entire transaction.  It is a single beat// of information.// The AXI4 Write address channel in this example will continue to initiate// write commands as fast as it is allowed by the slave/interconnect.// The address will be incremented on each accepted address transaction,// by burst_size_byte to point to the next address. always @(posedge M_AXI_ACLK)                                   begin                                                                if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                           begin                                                            axi_awvalid <= 1'b0;                                           end                                                              // If previously not valid , start next transaction                else if (~axi_awvalid && start_single_burst_write)                 begin                                                            axi_awvalid <= 1'b1;                                           end                                                              /* Once asserted, VALIDs cannot be deasserted, so axi_awvalid      must wait until transaction is accepted */                         else if (M_AXI_AWREADY && axi_awvalid)                             begin                                                            axi_awvalid <= 1'b0;                                           end                                                              else                                                               axi_awvalid <= axi_awvalid;                                      end                                                                // Next address after AWREADY indicates previous address acceptance    always @(posedge M_AXI_ACLK)                                         begin                                                                if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                            begin                                                            axi_awaddr <= 'b0;                                             end                                                              else if (M_AXI_AWREADY && axi_awvalid)                             begin                                                            axi_awaddr <= axi_awaddr + burst_size_bytes;                   end                                                              else                                                               axi_awaddr <= axi_awaddr;                                        end                                                                //--------------------//Write Data Channel//--------------------//The write data will continually try to push write data across the interface.//The amount of data accepted will depend on the AXI slave and the AXI//Interconnect settings, such as if there are FIFOs enabled in interconnect.//Note that there is no explicit timing relationship to the write address channel.//The write channel has its own throttling flag, separate from the AW channel.//Synchronization between the channels must be determined by the user.//The simpliest but lowest performance would be to only issue one address write//and write data burst at a time.//In this example they are kept in sync by using the same address increment//and burst sizes. Then the AW and W channels have their transactions measured//with threshold counters as part of the user logic, to make sure neither //channel gets too far ahead of each other.//Forward movement occurs when the write channel is valid and readyassign wnext = M_AXI_WREADY & axi_wvalid;                                   // WVALID logic, similar to the axi_awvalid always block above                      always @(posedge M_AXI_ACLK)                                                      begin                                                                             if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                                        begin                                                                         axi_wvalid <= 1'b0;                                                         end                                                                           // If previously not valid, start next transaction                              else if (~axi_wvalid && start_single_burst_write)                               begin                                                                         axi_wvalid <= 1'b1;                                                         end                                                                           /* If WREADY and too many writes, throttle WVALID                               Once asserted, VALIDs cannot be deasserted, so WVALID                           must wait until burst is complete with WLAST */                                 else if (wnext && axi_wlast)                                                    axi_wvalid <= 1'b0;                                                           else                                                                            axi_wvalid <= axi_wvalid;                                                     end                                                                               //WLAST generation on the MSB of a counter underflow                                // WVALID logic, similar to the axi_awvalid always block above                      always @(posedge M_AXI_ACLK)                                                      begin                                                                             if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                                        begin                                                                         axi_wlast <= 1'b0;                                                          end                                                                           // axi_wlast is asserted when the write index                                   // count reaches the penultimate count to synchronize                           // with the last write data when write_index is b1111                           // else if (&(write_index[C_TRANSACTIONS_NUM-1:1])&& ~write_index[0] && wnext)  else if (((write_index == C_M_AXI_BURST_LEN-2 && C_M_AXI_BURST_LEN >= 2) && wnext) || (C_M_AXI_BURST_LEN == 1 ))begin                                                                         axi_wlast <= 1'b1;                                                          end                                                                           // Deassrt axi_wlast when the last write data has been                          // accepted by the slave with a valid response                                  else if (wnext)                                                                 axi_wlast <= 1'b0;                                                            else if (axi_wlast && C_M_AXI_BURST_LEN == 1)                                   axi_wlast <= 1'b0;                                                            else                                                                            axi_wlast <= axi_wlast;                                                       end                                                                               /* Burst length counter. Uses extra counter register bit to indicate terminal       count to reduce decode logic */                                                    always @(posedge M_AXI_ACLK)                                                      begin                                                                             if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 || start_single_burst_write == 1'b1)    begin                                                                         write_index <= 0;                                                           end                                                                           else if (wnext && (write_index != C_M_AXI_BURST_LEN-1))                         begin                                                                         write_index <= write_index + 1;                                             end                                                                           else                                                                            write_index <= write_index;                                                   end                                                                               /* Write Data Generator                                                             Data pattern is only a simple incrementing count from 0 for each burst  */         always @(posedge M_AXI_ACLK)                                                      begin                                                                             if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                         axi_wdata <= 'b0;                                                             //else if (wnext && axi_wlast)                                                  //  axi_wdata <= 'b0;                                                           else if (wnext)                                                                 axi_wdata[7:0] <= adc_data;                                                   else                                                                            axi_wdata <= axi_wdata;                                                       end                                                                             //----------------------------//Write Response (B) Channel//----------------------------//The write response channel provides feedback that the write has committed//to memory. BREADY will occur when all of the data and the write address//has arrived and been accepted by the slave.//The write issuance (number of outstanding write addresses) is started by //the Address Write transfer, and is completed by a BREADY/BRESP.//While negating BREADY will eventually throttle the AWREADY signal, //it is best not to throttle the whole data channel this way.//The BRESP bit [1] is used indicate any errors from the interconnect or//slave for the entire write burst. This example will capture the error //into the ERROR output. always @(posedge M_AXI_ACLK)                                     begin                                                                 if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                            begin                                                             axi_bready <= 1'b0;                                             end                                                               // accept/acknowledge bresp with axi_bready by the master           // when M_AXI_BVALID is asserted by slave                           else if (M_AXI_BVALID && ~axi_bready)                               begin                                                             axi_bready <= 1'b1;                                             end                                                               // deassert after one clock cycle                                   else if (axi_bready)                                                begin                                                             axi_bready <= 1'b0;                                             end                                                               // retain the previous value                                        else                                                                axi_bready <= axi_bready;                                         end                                                                   //Flag any write response errors                                        assign write_resp_error = axi_bready & M_AXI_BVALID & M_AXI_BRESP[1]; //----------------------------//Read Address Channel//----------------------------//The Read Address Channel (AW) provides a similar function to the//Write Address channel- to provide the tranfer qualifiers for the burst.//In this example, the read address increments in the same//manner as the write address channel.always @(posedge M_AXI_ACLK)                                 begin                                                              if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                         begin                                                          axi_arvalid <= 1'b0;                                         end                                                            // If previously not valid , start next transaction              else if (~axi_arvalid && start_single_burst_read)                begin                                                          axi_arvalid <= 1'b1;                                         end                                                            else if (M_AXI_ARREADY && axi_arvalid)                           begin                                                          axi_arvalid <= 1'b0;                                         end                                                            else                                                             axi_arvalid <= axi_arvalid;                                    end                                                                // Next address after ARREADY indicates previous address acceptance  always @(posedge M_AXI_ACLK)                                       begin                                                              if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                          begin                                                          axi_araddr <= 'b0;                                           end                                                            else if (M_AXI_ARREADY && axi_arvalid)                           begin                                                          axi_araddr <= axi_araddr + burst_size_bytes;                 end                                                            else                                                             axi_araddr <= axi_araddr;                                      end                                                                //--------------------------------//Read Data (and Response) Channel//--------------------------------// Forward movement occurs when the channel is valid and ready   assign rnext = M_AXI_RVALID && axi_rready;                            // Burst length counter. Uses extra counter register bit to indicate    // terminal count to reduce decode logic                                always @(posedge M_AXI_ACLK)                                          begin                                                                 if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 || start_single_burst_read)                  begin                                                             read_index <= 0;                                                end                                                               else if (rnext && (read_index != C_M_AXI_BURST_LEN-1))              begin                                                             read_index <= read_index + 1;                                   end                                                               else                                                                read_index <= read_index;                                         end                                                                   /*                                                                      The Read Data channel returns the results of the read request          In this example the data checker is always able to accept              more data, so no need to throttle the RREADY signal                    */                                                                     always @(posedge M_AXI_ACLK)                                          begin                                                                 if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                  begin                                                             axi_rready <= 1'b0;                                             end                                                               // accept/acknowledge rdata/rresp with axi_rready by the master     // when M_AXI_RVALID is asserted by slave                           else if (M_AXI_RVALID)                       begin                                      if (M_AXI_RLAST && axi_rready)          begin                                  axi_rready <= 1'b0;                  end                                    else                                    begin                                 axi_rready <= 1'b1;                 end                                   end                                        // retain the previous value                 end                                            //Check received read data against data generator                       always @(posedge M_AXI_ACLK)                                          begin                                                                 if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                   begin                                                             read_mismatch <= 1'b0;                                          end                                                               //Only check data when RVALID is active                             else if (rnext && (M_AXI_RDATA != expected_rdata))                  begin                                                             read_mismatch <= 1'b1;                                          end                                                               else                                                                read_mismatch <= 1'b0;                                            end                                                                   //Flag any read response errors                                         assign read_resp_error = axi_rready & M_AXI_RVALID & M_AXI_RRESP[1];  //----------------------------------------//Example design read check data generator//-----------------------------------------//Generate expected read data to check against actual read dataalways @(posedge M_AXI_ACLK)                     begin                                                  if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)// || M_AXI_RLAST)             expected_rdata <= 'b1;                            else if (M_AXI_RVALID && axi_rready)                  expected_rdata <= expected_rdata + 1;             else                                                  expected_rdata <= expected_rdata;                 end                                                    //----------------------------------//Example design error register//----------------------------------//Register and hold any data mismatches, or read/write interface errors always @(posedge M_AXI_ACLK)                                 begin                                                              if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                          begin                                                          error_reg <= 1'b0;                                           end                                                            else if (read_mismatch || write_resp_error || read_resp_error)   begin                                                          error_reg <= 1'b1;                                           end                                                            else                                                             error_reg <= error_reg;                                        end                                                                //--------------------------------//Example design throttling//--------------------------------// For maximum port throughput, this user example code will try to allow// each channel to run as independently and as quickly as possible.// However, there are times when the flow of data needs to be throtted by// the user application. This example application requires that data is// not read before it is written and that the write channels do not// advance beyond an arbitrary threshold (say to prevent an // overrun of the current read address by the write address).// From AXI4 Specification, 13.13.1: "If a master requires ordering between // read and write transactions, it must ensure that a response is received // for the previous transaction before issuing the next transaction."// This example accomplishes this user application throttling through:// -Reads wait for writes to fully complete// -Address writes wait when not read + issued transaction counts pass // a parameterized threshold// -Writes wait when a not read + active data burst count pass // a parameterized threshold// write_burst_counter counter keeps track with the number of burst transaction initiated            // against the number of burst transactions the master needs to initiate                                   always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                                                                 begin                                                                                                 write_burst_counter <= 'b0;                                                                         end                                                                                                   else if (M_AXI_AWREADY && axi_awvalid)                                                                  begin                                                                                                 if (write_burst_counter[C_NO_BURSTS_REQ] == 1'b0)                                                   begin                                                                                             write_burst_counter <= write_burst_counter + 1'b1;                                              //write_burst_counter[C_NO_BURSTS_REQ] <= 1'b1;                                                 end                                                                                               end                                                                                                   else                                                                                                    write_burst_counter <= write_burst_counter;                                                           end                                                                                                       // read_burst_counter counter keeps track with the number of burst transaction initiated                   // against the number of burst transactions the master needs to initiate                                   always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 begin                                                                                                 read_burst_counter <= 'b0;                                                                          end                                                                                                   else if (M_AXI_ARREADY && axi_arvalid)                                                                  begin                                                                                                 if (read_burst_counter[C_NO_BURSTS_REQ] == 1'b0)                                                    begin                                                                                             read_burst_counter <= read_burst_counter + 1'b1;                                                //read_burst_counter[C_NO_BURSTS_REQ] <= 1'b1;                                                  end                                                                                               end                                                                                                   else                                                                                                    read_burst_counter <= read_burst_counter;                                                             end                                                                                                       //implement master command interface state machine                                                        always @ ( posedge M_AXI_ACLK)                                                                            begin                                                                                                     if (M_AXI_ARESETN == 1'b0 )                                                                             begin                                                                                                 // reset condition                                                                                  // All the signals are assigned default values under reset condition                                mst_exec_state      <= IDLE;                                                                start_single_burst_write <= 1'b0;                                                                   start_single_burst_read  <= 1'b0;                                                                   compare_done      <= 1'b0;                                                                          ERROR <= 1'b0;   end                                                                                                   else                                                                                                    begin                                                                                                 // state transition                                                                                 case (mst_exec_state)                                                                               IDLE:                                                                                     // This state is responsible to wait for user defined C_M_START_COUNT                           // number of clock cycles.                                                                      if ( init_txn_pulse == 1'b1)                                                      begin                                                                                         mst_exec_state  <= INIT_WRITE;                                                              ERROR <= 1'b0;compare_done <= 1'b0;end                                                                                           else                                                                                            begin                                                                                         mst_exec_state  <= IDLE;                                                            end                                                                                           INIT_WRITE:                                                                                       // This state is responsible to issue start_single_write pulse to                               // initiate a write transaction. Write transactions will be                                     // issued until burst_write_active signal is asserted.                                          // write controller                                                                             if (writes_done)                                                                                begin                                                                                         //mst_exec_state <= INIT_READ;//mst_exec_state <= IDLE;//写完退出                                                              end                                                                                           else                                                                                            begin                                                                                         mst_exec_state  <= INIT_WRITE;                                                              if (~axi_awvalid && ~start_single_burst_write && ~burst_write_active)                       begin                                                                                     start_single_burst_write <= 1'b1;                                                       end                                                                                       else                                                                                        begin                                                                                     start_single_burst_write <= 1'b0; //Negate to generate a pulse                          end                                                                                       end                                                                                           INIT_READ:                                                                                        // This state is responsible to issue start_single_read pulse to                                // initiate a read transaction. Read transactions will be                                       // issued until burst_read_active signal is asserted.                                           // read controller                                                                              if (reads_done)                                                                                 begin                                                                                         mst_exec_state <= INIT_COMPARE;                                                             end                                                                                           else                                                                                            begin                                                                                         mst_exec_state  <= INIT_READ;                                                               if (~axi_arvalid && ~burst_read_active && ~start_single_burst_read)                         begin                                                                                     start_single_burst_read <= 1'b1;                                                        end                                                                                       else                                                                                         begin                                                                                      start_single_burst_read <= 1'b0; //Negate to generate a pulse                            end                                                                                        end                                                                                           INIT_COMPARE:                                                                                     // This state is responsible to issue the state of comparison                                   // of written data with the read data. If no error flags are set,                               // compare_done signal will be asseted to indicate success.                                     //if (~error_reg)                                                                               begin                                                                                           ERROR <= error_reg;mst_exec_state <= IDLE;                                                               compare_done <= 1'b1;                                                                         end                                                                                             default :                                                                                         begin                                                                                           mst_exec_state  <= IDLE;                                                              end                                                                                             endcase                                                                                             end                                                                                                   end //MASTER_EXECUTION_PROC                                                                               // burst_write_active signal is asserted when there is a burst write transaction                          // is initiated by the assertion of start_single_burst_write. burst_write_active                          // signal remains asserted until the burst write is accepted by the slave                                 always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 burst_write_active <= 1'b0;                                                                           //The burst_write_active is asserted when a write burst transaction is initiated                        else if (start_single_burst_write)                                                                      burst_write_active <= 1'b1;                                                                           else if (M_AXI_BVALID && axi_bready)                                                                    burst_write_active <= 0;                                                                              end                                                                                                       // Check for last write completion.                                                                        // This logic is to qualify the last write count with the final write                                      // response. This demonstrates how to confirm that a write has been                                        // committed.                                                                                              always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 writes_done <= 1'b0;                                                                                  //The writes_done should be associated with a bready response                                           //else if (M_AXI_BVALID && axi_bready && (write_burst_counter == {(C_NO_BURSTS_REQ-1){1}}) && axi_wlast)else if (M_AXI_BVALID && (write_burst_counter[C_NO_BURSTS_REQ]) && axi_bready)                          writes_done <= 1'b1;                                                                                  else                                                                                                    writes_done <= writes_done;                                                                           end                                                                                                     // burst_read_active signal is asserted when there is a burst write transaction                           // is initiated by the assertion of start_single_burst_write. start_single_burst_read                     // signal remains asserted until the burst read is accepted by the master                                 always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 burst_read_active <= 1'b0;                                                                            //The burst_write_active is asserted when a write burst transaction is initiated                        else if (start_single_burst_read)                                                                       burst_read_active <= 1'b1;                                                                            else if (M_AXI_RVALID && axi_rready && M_AXI_RLAST)                                                     burst_read_active <= 0;                                                                               end                                                                                                     // Check for last read completion.                                                                         // This logic is to qualify the last read count with the final read                                        // response. This demonstrates how to confirm that a read has been                                         // committed.                                                                                              always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 reads_done <= 1'b0;                                                                                   //The reads_done should be associated with a rready response                                            //else if (M_AXI_BVALID && axi_bready && (write_burst_counter == {(C_NO_BURSTS_REQ-1){1}}) && axi_wlast)else if (M_AXI_RVALID && axi_rready && (read_index == C_M_AXI_BURST_LEN-1) && (read_burst_counter[C_NO_BURSTS_REQ]))reads_done <= 1'b1;                                                                                   else                                                                                                    reads_done <= reads_done;                                                                             end                                                                                                     // Add user logic here// User logic endsendmodule

一顿操作之后,看波形,可以看到当前的采集频率5M,已经可以满足我们的要求了

看到数据传上来了:

软件设计

编写测试软件+上位机进行验证,软件耗时:

单次采集耗时约45us

采集+传输耗时约55us

因此软件限制下的最高频率约在10kHz

经过优化后:

采集频率做到了2500ns以内(3us)

采集+传输耗时大概20us以内

因此如果不传输,保存在内存上的理论频率约是300kHz。

用信号发生器测试下

1.100HZ 1.5V 发现下面的采集传输耗时波动挺大,因此导致实时曲线出现相位不稳定的现象。

2. 1kHz 1.5v 时 传输延时的问题后续还要优化,不然采出来的数据没法用

引用:

Linux DMA From User Space 2.0 - Xilinx Wiki - Confluence

問題記錄

1.開啓FSBL調試打印

由于从U盘启动BOOT.bin没有任何打印,需要开启FSBL的调试来看看

recipes-bsp/fsbl/fsbl_%.bbappend创建文件并添加下述内容,重新petalinux-build即可

#Enable appropriate FSBL debug flags  
YAML_COMPILER_FLAGS_append = " -DFSBL_DEBUG_INFO"

2.UBOOT无法启动系统

U-Boot 2018.01 (Nov 02 2024 - 12:47:39 +0000) Xilinx Zynq ZC702

Board: Xilinx Zynq
Silicon: v3.1
DRAM:  ECC disabled 512 MiB
MMC:   mmc@e0100000: 0 (SD)
Using default environment

In:    serial@e0000000
Out:   serial@e0000000
Err:   serial@e0000000
Board: Xilinx Zynq
Silicon: v3.1
U-BOOT for petalinux_hdmi

Hit any key to stop autoboot:  0
No boot method defined!!!

经过定位发现:

Zynq> printenv
arch=arm
baudrate=115200
board=zynq
board_name=zynq
boot_img=BOOT.BIN
bootcmd=run default_bootcmd
bootdelay=4
console=console=ttyPS0,115200
cpu=armv7
default_bootcmd=echo No boot method defined!!!
dtb_img=system.dtb
dtbnetstart=0x23fff000
fdtcontroladdr=1ffac5e0
kernel_img=image.ub
loadaddr=0x10000000
modeboot=sdboot
netstart=0x10000000
psserial0=setenv stdout ttyPS0;setenv stdin ttyPS0
serial=setenv stdout serial;setenv stdin serial
soc=zynq
stderr=serial@e0000000
stdin=serial@e0000000
stdout=serial@e0000000
vendor=xilinx

Environment size: 578/16380 bytes

这个bootcmd哪里来的呢?原来是VIVADO自动生成的

检查platform-auto.h

奇怪了,正常启动的应该长下面那样,如此看来问题还是出在VIVADO

发现VIVADO没有勾选初始化SD卡,重新生成system.hpf文件后:

petalinux-build -c u-boot -x distclean

petalinux-build -c kernel -x distclean

petalinux-build -x distclean

petalinux-config --get-hw-description=.

petalinux-build

引用:

How to Modify U-Boot Environment Variables in PetaLinux - FPGA Developer

ZynqMP Petalinux2021.1使用外部kernel和uboot源码_petalinux 使用非默认内核版本的方法-CSDN博客

u-boot启动流程,启动内核的关键点do_bootm分析_uboot加载内核地址分析-CSDN博客

其他

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com