` `在使用ZYNQ7021系列的FPGA,若涉及到PL部分讀寫DDR,可使用過AXI-Lite,AXI4-FULL,AXI-Stream這三個IP來實現,使用的是這三個IP的主機模式。
## AXI 4總線協議解析
* [ ] AXI4:主要面向高性能地址映射通信的需求;
* [ ] ?AXI4-Lite:是一個簡單地吞吐量地址映射性通信總線;
* [ ] ?AXI4-Stream:面向高速流數據傳輸;
* [ ] AXI4總線分為主、從兩端,兩者間可以連續的進行通信;
` `AXI 4總線采用READY,VALID握手通信機制,主設備收到從設備發送的READY,主設備將數據和VALID信號同時發送給從設備。
` `AXI 4-Lite所有的猝發長度為1,數據總線寬度為32位或64位
` `AXI 4-Stream數據總線寬度:8、16、32、64、128、256、512和1024位;
**axi總線分為五個通道:**
* --讀地址通道,包含ARVALID,ARADDR, ARREADY信號;
* --寫地址通道,包含AWVALID,AWADDR,AWREADY信號;
* --讀數據通道,包含RVALID,RDATA, RREADY, RRESP信號;
* --寫數據通道,包含WVALID, WDATA,WSTRB,WREADY信號;
* --寫應答通道,包含BVALID,BRESP, BREADY信號;
` `AWLEN,猝發長度,是一個猝發中傳送的數據個數,傳送個數=AWLEN+1;如AWLEN=5,傳送6個數據。
` `AWSIZE,猝發大小,猝發中每個傳送的數據的大小,字節數為=2^AWSIZE;如AWSIZE=0,每個數據是1個字節,AWSIZE=3,每個數據大小是8個字節
;
**axis信號分為:**
* --TREADY信號:從告訴主做好傳輸準備;
* --TVALID信號:主告訴從數據傳輸有效;
* --TLAST信號:主告訴從該次傳輸為突發傳輸結尾
* --TDATA信號:數據,可選寬度32,64,128,256bit
* --TSTRB信號:為1的bit為對應tdata有效字節,寬度為tdata/8
* --TUSER信號? :用戶定義信號,寬度為128bit
* --ACLK信號:總線時鐘,上升沿有效;
* --ARESETn信號:總線復位,低電平有效;
` `讀操作

` `在讀交易中,主設備先發送ARADDR和ARVALID給從設備,從設備回發ARREADY,通知主設備該地址有效,當ARVALID和ARREADY都為高電平時,主設備發出RREADY,表示主設備準備好接受讀數據和相應信號了。從設備發送RVALID、RDATA以及RRESP,當RVALID和RREADY都為高電平時,數據被寫入主設備。
` `寫操作

` `在寫操作中,主設備往從設備中寫入AWADDR和AWVALID,然后主設備并沒有等待從設備的AWREADY,而是繼續發送WVALID和WDATA,當從設備回應AWREADY有效后,緊接著從設備發送WREADY表示從設備準備好接受數據,當WVALID和WREADY都為高電平是數據寫入從設備。主設備發送的AWVALID和WVALID要有重疊區。
## 關于同時對DDR寫操作的說明
` `在進行數據存儲時,有時候有幾類數據需要寫入DDR,并且這些數據相互間沒有相關性,比如將AD芯片K5394獲取的數據存入地址為0x02000000,長度為0xf,將時間信息存入0x020000f0,長度為0XF0的DDR空間,這兩者間數據基本無相關性,即獲得了數據就將其寫入DDR中,在使用這些IP來寫數據時不需要考慮數據寫入之間的競爭情況,因為AXI的IP模塊有自己的WID,不同的WID可以亂序寫入,但是同一個WID需要順序寫入,模塊將會根據WID來X向DDR寫數據。同時AK5394的數據得到為流水線形式,且得到兩個數據之間的時間較大,因此這種的數據適合使用AXI-Lite來進行數據傳輸。
` `驗證例程為pl_write_ddr_lite,其中MCU_2_FPGA的IP為修改的axi-lite的slave的IP,用于PS向PL部分發送數據。

` `axi_lite_wrddr模塊是修改的AXI-Lite的Master的IP,用于實現想DDR的某一地址寫入數據。

` `在使用時,由于對該IP進行了修改,若設置多次傳輸數據,將會對同一地址寫入相同的數據,該模塊主要是為了對一個地址寫一個數據,不進行突發數據寫入,因此需要設置寫入次數為1次,如下圖所示。同時寫入的地址和寫入的數據被引出,方便使用。

## HP和GP接口
` `在 ZYNQ 芯片內部用硬件實現了 AXI 總線協議,包括 9 個物理接口,分別為 AXI-GP0~AXI-
GP3,AXI-HP0~AXI-HP3,AXI-ACP 接口。
` `AXI_ACP 接口,是 ARM 多核架構下定義的一種接口,中文翻譯為加速器一致性端口,用
來管理 DMA 之類的不帶緩存的 AXI 外設,PS 端是 Slave 接口。
` `AXI_HP 接口,是高性能/帶寬的 AXI3.0 標準的接口,總共有四個,PL 模塊作為主設備連
接。主要用于 PL 訪問 PS 上的存儲器(DDR 和 On-Chip RAM)
` `AXI_GP 接口,是通用的 AXI 接口,總共有四個,包括兩個 32 位主設備接口和兩個 32 位
從設備接口。

` `可以看到,只有兩個 AXI-GP 是 Master Port,即主機接口,其余 7 個口都是 Slave Port(從
機接口)。主機接口具有發起讀寫的權限,ARM 可以利用兩個 AXI-GP 主機接口主動訪問 PL 邏
輯,其實就是把 PL 映射到某個地址,讀寫 PL 寄存器如同在讀寫自己的存儲器。其余從機接口
就屬于被動接口,接受來自 PL 的讀寫,逆來順受。
` `另外這 9 個 AXI 接口性能也是不同的。GP 接口是 32 位的低性能接口,理論帶寬
600MB/s,而 HP 和 ACP 接口為 64 位高性能接口,理論帶寬 1200MB/s。有人會問,為什么高
性能接口不做成主機接口呢?這樣可以由 ARM 發起高速數據傳輸。答案是高性能接口根本不
需要 ARM CPU 來負責數據搬移,真正的搬運工是位于 PL 中的 DMA 控制器。
## 幾個AXI IP介紹
` `下面為幾個常用的 AXI 接口 IP 的功能介紹:
` `AXI-DMA:實現從 PS 內存到 PL 高速傳輸高速通道 AXI-HP<---->AXI-Stream 的轉換
。
` `AXI-FIFO-MM2S:實現從 PS 內存到 PL 通用傳輸通道 AXI-GP<----->AXI-Stream 的轉換
。
` `AXI-Datamover:實現從 PS 內存到 PL 高速傳輸高速通道 AXI-HP<---->AXI-Stream 的轉換,只
不過這次是完全由 PL 控制的,PS 是完全被動的。
` `AXI-VDMA:實現從 PS 內存到 PL 高速傳輸高速通道 AXI-HP<---->AXI-Stream 的轉換,只不
過是專門針對視頻、圖像等二維數據的。
` `AXI-CDMA:這個是由 PL 完成的將數據從內存的一個位置搬移到另一個位置,無需 CPU 來
插手。
` `AXI 協議嚴格的講是一個點對點的主從接口協議,當多個外設需要互相交互數據時,我們
需要加入一個 AXI Interconnect 模塊,也就是 AXI 互聯矩陣,作用是提供將一個或多個 AXI 主設
備連接到一個或多個 AXI 從設備的一種交換機制(有點類似于交換機里面的交換矩陣)。
` `這個 AXI Interconnect IP 核最多可以支持 16 個主設備、16 個從設備,如果需要更多的接
口,可以多加入幾個 IP 核。
## 多個AXI模塊并存時的地址分配
` `當使用多個AXI的IP(主機/從機),需要對地址進行映射。

` `需要對每一個主機會映射的從機進行地址分配,如硬核PS的AXI主機接口需要連接MCU_2_FPGA的IP,那么就對這哥IP進行地址分配。axi_lite_wrddr需要映射到PS的HP接口,則對HP進行地址分配。

` `但是需要注意的是,兩個IP不要對重復地址段進行寫數據,因為這樣會造成數據混亂。
## 測試程序說明
` `main文件代碼如下:
```
/*
* helloworld.c: simple test application
*
* This application configures UART 16550 to baud rate 9600.
* PS7 UART (Zynq) is not initialized by this application, since
* bootrom/bsp configures it to baud rate 115200
*
* ------------------------------------------------
* | UART TYPE BAUD RATE |
* ------------------------------------------------
* uartns550 9600
* uartlite Configurable only in HW design
* ps7_uart 115200 (configured by bootrom/bsp)
*/
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "sleep.h"
#include "xil_io.h"
#include "xparameters.h"
#include "xparameters_ps.h"
#include "mcu_2_fpga.h"
#include "stdbool.h"
void mcu2fpga_write(int id,u32 data)
{
switch(id){
case(0):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_0_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG0_OFFSET,data);break;
case(1):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_0_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG1_OFFSET,data);break;
case(2):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_0_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG2_OFFSET,data);break;
case(3):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_0_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG3_OFFSET,data);break;
default:break;
}
}
void mcu2fpga1_write(int id,u32 data)
{
switch(id){
case(0):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_1_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG0_OFFSET,data);break;
case(1):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_1_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG1_OFFSET,data);break;
case(2):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_1_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG2_OFFSET,data);break;
case(3):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_1_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG3_OFFSET,data);break;
default:break;
}
}
void mcu2fpga2_write(int id,u32 data)
{
switch(id){
case(0):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_2_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG0_OFFSET,data);break;
case(1):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_2_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG1_OFFSET,data);break;
case(2):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_2_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG2_OFFSET,data);break;
case(3):MCU_2_FPGA_mWriteReg(XPAR_MCU_2_FPGA_2_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG3_OFFSET,data);break;
default:break;
}
}
u32 mcu2fpga_read(int id)
{
switch(id){
case(0):return MCU_2_FPGA_mReadReg(XPAR_MCU_2_FPGA_0_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG0_OFFSET);break;
case(1):return MCU_2_FPGA_mReadReg(XPAR_MCU_2_FPGA_0_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG1_OFFSET);break;
case(2):return MCU_2_FPGA_mReadReg(XPAR_MCU_2_FPGA_0_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG2_OFFSET);break;
case(3):return MCU_2_FPGA_mReadReg(XPAR_MCU_2_FPGA_0_S00_AXI_BASEADDR,MCU_2_FPGA_S00_AXI_SLV_REG3_OFFSET);break;
default:break;
}
return 12;
}
//分配DDR中對應AD數據的內存地址給數組
u32 ak5394_m1[60] __attribute__((section(".ak5394M1Section")));//hpy test PS read DDR
u32 ak5394_m2[60] __attribute__((section(".ak5394M2Section")));//hpy test PS read DDR
void pl_update_ddr(u32 addr,int offset,_Bool display)//測試PL寫DDR,用于發送數據到FPGA更新DDR中的數據
{
for(int j = 0;j<30;j++){
mcu2fpga_write(3,4*j + offset);
mcu2fpga_write(2,4*j+1 + offset);
mcu2fpga_write(1,4*j+2 + offset);
usleep(10);
mcu2fpga_write(0,addr + j*16);
if(display == true){
printf("data[%d] = %d\n",4*j,4*j + offset);
printf("data[%d] = %d\n",4*j+1,4*j+1 + offset);
printf("data[%d] = %d\n",4*j+2,4*j+2 + offset);
printf("data[%d] = %d\n",4*j+3,4*j+3 + offset);
}
usleep(100);
}
}
//利用MCU_2_FPGA向PL發送數據,然后PL將數據寫入DDR
void lite_write(u32 ad,int off)、{
for(int i=0;i<30;i++){
mcu2fpga2_write(1,i+off);
mcu2fpga1_write(1,i+off+1);
mcu2fpga2_write(0,ad+i*4);
mcu2fpga1_write(0,ad+i*4 + 120);
usleep(100);
}
pl_update_ddr(0x020000F0,off,false);
}
void write_ddr_lite_test(){
int i = 0;
int mdata = 5;
u32 ad0 = 0x02000000;
u32 ad = ad0;
int cnt=0;
while(1){
lite_write(ad,cnt);
if(cnt>=100)cnt = 0;
else cnt++;
printf("--------------------------\n");
usleep(1000000);
Xil_DCacheInvalidateRange(ad0,sizeof(ak5394_m1));//將DDR中數據更新到cache中
Xil_DCacheInvalidateRange(0x020000F0,sizeof(ak5394_m2));//將DDR中數據更新到cache中
for(u32 j=0;j<30;j++){// PS讀取DDR并顯示
printf("a[%d]=%d a[%d]=%d b[%d]=%d\n ",j,ak5394_m1[j],j+30,ak5394_m1[j+30],j,ak5394_m2[j]);
}
}
}
int main()
{
init_platform();
int max = 7;
int i = 1;
u32 addr = 0x02000000;
u32 addr2 =0x02000000;
write_ddr_lite_test();
pl_update_ddr(addr,0,false);//測試函數
cleanup_platform();
return 0;
}
```
## link腳本文件編寫
` `為了方便數據讀出,將寫入DDR的地址段分配給數組,得益于GCC的強大功能,通過``__attribute__``可以實現給數組分配指定地址空間。
` `文件編寫如下
```
/*******************************************************************/
/* */
/* This file is automatically generated by linker script generator.*/
/* */
/* Version: 2018.3 */
/* */
/* Copyright (c) 2010-2016 Xilinx, Inc. All rights reserved. */
/* */
/* Description : Cortex-A9 Linker Script */
/* */
/*******************************************************************/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;
_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;
/* Define Memories in the system */
MEMORY
{
ps7_ddr_0 : ORIGIN = 0x100000, LENGTH = 0x1f00000 /*0x3FF00000*/
ps7_ram_0 : ORIGIN = 0x0, LENGTH = 0x30000
ps7_ram_1 : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00
/*以下為自己定義,需要分配的地址段*/
AK5394_M1 : ORIGIN = 0x02000000, LENGTH = 0x000000F0
AK5394_M2 : ORIGIN = 0x020000F0, LENGTH = 0x000000F0
}
/* Specify the default entry point to the program */
ENTRY(_vector_table)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.ak5394M1Section :{
__ak5394Section_start = .;
*(.ak5394M1Section)
__ak5394Section_end = .;
} > AK5394_M1
.ak5394M2Section :{
__ak5394Section_start = .;
*(.ak5394M2Section)
__ak5394Section_end = .;
} > AK5394_M2
.text : {
KEEP (*(.vectors))
*(.boot)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.plt)
*(.gnu_warning)
*(.gcc_execpt_table)
*(.glue_7)
*(.glue_7t)
*(.vfp11_veneer)
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
} > ps7_ddr_0
.init : {
KEEP (*(.init))
} > ps7_ddr_0
.fini : {
KEEP (*(.fini))
} > ps7_ddr_0
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > ps7_ddr_0
.rodata1 : {
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > ps7_ddr_0
.sdata2 : {
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > ps7_ddr_0
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > ps7_ddr_0
.data : {
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > ps7_ddr_0
.data1 : {
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > ps7_ddr_0
.got : {
*(.got)
} > ps7_ddr_0
.ctors : {
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > ps7_ddr_0
.dtors : {
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
___DTORS_END___ = .;
} > ps7_ddr_0
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > ps7_ddr_0
.eh_frame : {
*(.eh_frame)
} > ps7_ddr_0
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > ps7_ddr_0
.gcc_except_table : {
*(.gcc_except_table)
} > ps7_ddr_0
.mmu_tbl (ALIGN(16384)) : {
__mmu_tbl_start = .;
*(.mmu_tbl)
__mmu_tbl_end = .;
} > ps7_ddr_0
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > ps7_ddr_0
.preinit_array : {
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > ps7_ddr_0
.init_array : {
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > ps7_ddr_0
.fini_array : {
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > ps7_ddr_0
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > ps7_ddr_0
.sdata : {
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > ps7_ddr_0
.sbss (NOLOAD) : {
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
__sbss_end = .;
} > ps7_ddr_0
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > ps7_ddr_0
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > ps7_ddr_0
.bss (NOLOAD) : {
__bss_start = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
__bss_end = .;
} > ps7_ddr_0
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(16);
_heap = .;
HeapBase = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
HeapLimit = .;
} > ps7_ddr_0
.stack (NOLOAD) : {
. = ALIGN(16);
_stack_end = .;
. += _STACK_SIZE;
. = ALIGN(16);
_stack = .;
__stack = _stack;
. = ALIGN(16);
_irq_stack_end = .;
. += _IRQ_STACK_SIZE;
. = ALIGN(16);
__irq_stack = .;
_supervisor_stack_end = .;
. += _SUPERVISOR_STACK_SIZE;
. = ALIGN(16);
__supervisor_stack = .;
_abort_stack_end = .;
. += _ABORT_STACK_SIZE;
. = ALIGN(16);
__abort_stack = .;
_fiq_stack_end = .;
. += _FIQ_STACK_SIZE;
. = ALIGN(16);
__fiq_stack = .;
_undef_stack_end = .;
. += _UNDEF_STACK_SIZE;
. = ALIGN(16);
__undef_stack = .;
} > ps7_ddr_0
_end = .;
}
```
` `然后利用`__attribute__`進行分配地址。`u32 ak5394_m1[60] __attribute__((section(".ak5394M1Section")));//hpy test PS read DDR`
## 串口顯示驗證

- 序
- 第1章 Linux下開發FPGA
- 1.1 Linux下安裝diamond
- 1.2 使用輕量級linux仿真工具iverilog
- 1.3 使用linux shell來讀寫串口
- 1.4 嵌入式上的linux
- 設備數教程
- linux C 標準庫文檔
- linux 網絡編程
- 開機啟動流程
- 1.5 linux上實現與樹莓派,FPGA等通信的串口腳本
- 第2章 Intel FPGA的使用
- 2.1 特別注意
- 2.2 高級應用開發流程
- 2.2.1 生成二進制bit流rbf
- 2.2.2 制作Preloader Image
- 2.2.2.1 生成BSP文件
- 2.2.2.2 編譯preloader和uboot
- 2.2.2.3 更新SD的preloader和uboot
- 2.3 HPS使用
- 2.3.1 通過JTAG下載代碼
- 2.3.2 HPS軟件部分開發
- 2.3 quartus中IP核的使用
- 2.3.1 Intel中RS232串口IP的使用
- 2.4 一些問題的解決方法
- 2.4.1 關于引腳的復用的綜合出錯
- 第3章 關于C/C++的一些語法
- 3.1 C中數組作為形參不傳長度
- 3.2 匯編中JUMP和CALL的區別
- 3.3 c++中map的使用
- 3.4 鏈表的一些應用
- 3.5 vector的使用
- 3.6 使用C實現一個簡單的FIFO
- 3.6.1 循環隊列
- 3.7 C語言不定長參數
- 3.8 AD采樣計算同頻信號的相位差
- 3.9 使用C實現棧
- 3.10 增量式PID
- 第4章 Xilinx的FPGA使用
- 4.1 Alinx使用中的一些問題及解決方法
- 4.1.1 在Genarate Bitstream時提示沒有name.tcl
- 4.1.2 利用verilog求位寬
- 4.1.3 vivado中AXI寫DDR說明
- 4.1.4 zynq中AXI GPIO中斷問題
- 4.1.5 關于時序約束
- 4.1.6 zynq的PS端利用串口接收電腦的數據
- 4.1.7 SDK啟動出錯的解決方法
- 4.1.8 讓工具綜合是不優化某一模塊的方法
- 4.1.9 固化程序(雙核)
- 4.1.10 分配引腳時的問題
- 4.1.11 vivado仿真時相對文件路徑的問題
- 4.2 GCC使用Attribute分配空間給變量
- 4.3 關于Zynq的DDR寫入byte和word的方法
- 4.4 常用模塊
- 4.4.1 I2S接收串轉并
- 4.5 時鐘約束
- 4.5.1 時鐘約束
- 4.6 VIVADO使用
- 4.6.1 使用vivado進行仿真
- 4.7 關于PicoBlaze軟核的使用
- 4.8 vivado一些IP的使用
- 4.8.1 float-point浮點單元的使用
- 4.10 zynq的雙核中斷
- 第5章 FPGA的那些好用的工具
- 5.1 iverilog
- 5.2 Arduino串口繪圖器工具
- 5.3 LabVIEW
- 5.4 FPGA開發實用小工具
- 5.5 Linux下繪制時序圖軟件
- 5.6 verilog和VHDL相互轉換工具
- 5.7 linux下搭建輕量易用的verilog仿真環境
- 5.8 VCS仿真verilog并查看波形
- 5.9 Verilog開源的綜合工具-Yosys
- 5.10 sublim text3編輯器配置verilog編輯環境
- 5.11 在線工具
- 真值表 -> 邏輯表達式
- 5.12 Modelsim使用命令仿真
- 5.13 使用TCL實現的個人仿真腳本
- 5.14 在cygwin下使用命令行下載arduino代碼到開發板
- 5.15 STM32開發
- 5.15.1 安裝Atollic TrueSTUDIO for STM32
- 5.15.2 LED閃爍吧
- 5.15.3 模擬U盤
- 第6章 底層實現
- 6.1 硬件實現加法的流程
- 6.2 硬件實現乘法器
- 6.3 UART實現
- 6.3.1 通用串口發送模塊
- 6.4 二進制數轉BCD碼
- 6.5 基本開源資源
- 6.5.1 深度資源
- 6.5.2 FreeCore資源集合
- 第7章 常用模塊
- 7.1 溫濕度傳感器DHT11的verilog驅動
- 7.2 DAC7631驅動(verilog)
- 7.3 按鍵消抖
- 7.4 小腳丫數碼管顯示
- 7.5 verilog實現任意人數表決器
- 7.6 基本模塊head.v
- 7.7 四相八拍步進電機驅動
- 7.8 單片機部分
- 7.8.1 I2C OLED驅動
- 第8章 verilog 掃盲區
- 8.1 時序電路中數據的讀寫
- 8.2 從RTL角度來看verilog中=和<=的區別
- 8.3 case和casez的區別
- 8.4 關于參數的傳遞與讀取(paramter)
- 8.5 關于符號優先級
- 第9章 verilog中的一些語法使用
- 9.1 可綜合的repeat
- 第10章 system verilog
- 10.1 簡介
- 10.2 推薦demo學習網址
- 10.3 VCS在linux上環境的搭建
- 10.4 deepin15.11(linux)下搭建system verilog的vcs仿真環境
- 10.5 linux上使用vcs寫的腳本仿真管理
- 10.6 system verilog基本語法
- 10.6.1 數據類型
- 10.6.2 枚舉與字符串
- 第11章 tcl/tk的使用
- 11.1 使用Tcl/Tk
- 11.2 tcl基本語法教程
- 11.3 Tk的基本語法
- 11.3.1 建立按鈕
- 11.3.2 復選框
- 11.3.3 單選框
- 11.3.4 標簽
- 11.3.5 建立信息
- 11.3.6 建立輸入框
- 11.3.7 旋轉框
- 11.3.8 框架
- 11.3.9 標簽框架
- 11.3.10 將窗口小部件分配到框架/標簽框架
- 11.3.11 建立新的上層窗口
- 11.3.12 建立菜單
- 11.3.13 上層窗口建立菜單
- 11.3.14 建立滾動條
- 11.4 窗口管理器
- 11.5 一些學習的腳本
- 11.6 一些常用的操作語法實現
- 11.6.1 刪除同一后綴的文件
- 11.7 在Lattice的Diamond中使用tcl
- 第12章 FPGA的重要知識
- 12.1 面積與速度的平衡與互換
- 12.2 硬件原則
- 12.3 系統原則
- 12.4 同步設計原則
- 12.5 乒乓操作
- 12.6 串并轉換設計技巧
- 12.7 流水線操作設計思想
- 12.8 數據接口的同步方法
- 第13章 小項目
- 13.1 數字濾波器
- 13.2 FIFO
- 13.3 一個精簡的CPU( mini-mcu )
- 13.3.1 基本功能實現
- 13.3.2 中斷添加
- 13.3.3 使用中斷實現流水燈(實際硬件驗證)
- 13.3.4 綜合一點的應用示例
- 13.4.5 使用flex開發匯編編譯器
- 13.4.5 linux--Flex and Bison
- 13.4 有符號數轉單精度浮點數
- 13.5 串口調試FPGA模板