HOME
Shop
  • English
  • 简体中文
HOME
Shop
  • English
  • 简体中文
  • Product Series

    • FPGA+ARM

      • GM-3568JHF

        • Introduction

          • GM-3568JHF Introduction
        • Quick Start

          • Preface
          • Environment Setup
          • Compilation Notes
          • Flashing Guide
          • Debugging Tools
          • Software Update
          • Viewing System Information
          • Test Commands
          • Application Compilation
          • Source Code Access
        • Peripherals & Interfaces

          • USB
          • Display and Touch
          • Ethernet
          • WIFI
          • Bluetooth
          • TF-Card
          • Audio
          • Serial Port
          • CAN
          • RTC
        • Application Development

          • UART Read/Write Demo
          • Key Detection Demo
          • LED Blink Demo
          • MIPI Screen Detection Demo
          • Read USB Device Information Demo
          • FAN Detection Demo
          • FPGA FSPI Communication Demo
          • FPGA DMA Read/Write Demo
          • GPS Debugging Demo
          • Ethernet Test Demo
          • RS485 Read/Write Demo
          • FPGA I2C Read/Write Demo
          • PN532 NFC Card-Reading Demo
          • TF Card Read/Write Demo
        • QT Development

          • ARM64 Cross-Compiler Environment Setup
          • Adding a QT Program to Boot Auto-Start
        • RKNN_NPU Development

          • RK3568 NPU Overview
          • Development Environment Setup
          • Run the Official YOLOv5 Example
        • FPGA Development

          • ARM and FPGA Communication
          • FPGA Development Manual
        • Others

          • Modifying the Root Filesystem
          • System Auto-Start Services
        • Downloads

          • Downloads
      • MB-E30P

        • Introduction

          • MB-E30P Introduction
        • Quick Start

          • Preface
          • Environment Setup
          • Compilation Instructions
          • Flashing Guide
          • Debugging Tools
          • Software Update
          • Viewing Information
          • Test Commands
          • Application Compilation
          • Source Code Acquisition
        • Peripherals & Interfaces

          • USB
          • Display and Touch
          • Ethernet
          • WIFI
          • Bluetooth
          • TF-Card
          • Audio
          • RTC
        • Application Development

          • Key Detection Demo
          • LED Blink Demo
          • MIPI Screen Detection Demo
          • Read USB Device Information Demo
          • FAN Detection Demo
          • FPGA FSPI Communication Demo
          • FPGA DMA Read/Write Demo
          • Ethernet Test Demo
          • FPGA IIC Read/Write Demo
          • PN532 NFC Card Reading Demo
          • TF Card Read/Write Demo
        • QT Development

          • ARM64 Cross-Compiler Environment Setup
          • Adding a QT Program to the Boot Auto-Start Service
        • RKNN_NPU Development

          • RK3568 NPU Overview
          • Development Environment Setup
          • Run the Official YOLOv5 Example
          • Model Conversion In Detail
          • Run Custom Models on the Board
        • FPGA Development

          • ARM and FPGA Communication
          • FPGA Development Manual
        • Others

          • Modifying the Root Filesystem
          • System Auto-Start Service
        • Downloads

          • Downloads
    • ShimetaPi

      • M4-R1

        • Introduction

          • M4-R1 Introduction
        • Quick Start

          • OpenHarmony Overview
          • Image Burning
          • Application Development Quick Start
          • Device Development Quick Start
        • Application Development

          • ArkUI

            • ArkTS Language Overview
            • UI Components - Row Container Introduction
            • UI Components - Column Container Introduction
            • UI Components - Text Component
            • UI Components - Toggle Component
            • UI Components - Slider Component
            • UI Components - Animation Component & Transition Component
          • Documentation

            • OpenHarmony Official Materials
          • Development Notes

            • Full-SDK Replacement Tutorial
            • Introducing and Using Third-Party Libraries
            • HDC Debugging
            • Restore Factory Mode via Command Line
            • Upgrade App to System Permission
          • First App

            • Build Your First ArkTS Application - HelloWorld
          • Demos

            • Serial-Debug-Assistant Application Demo
            • Writing-Board Application Demo
            • Digital Clock Application Demo
            • Wi-Fi Information Acquisition Application Demo
        • Device Development

          • Ubuntu Development

            • Environment Setup
            • Download Source Code
            • Compile Source Code
          • DevEco Device Tool

            • Tool Introduction
            • Development Environment Construction
            • Import the SDK
            • HUAWEI DevEco Tool Function Introduction
        • Kernel Peripherals & Interfaces

          • Guide
          • Device Tree Introduction
          • NAPI Introduction
          • ArkTS Introduction
          • NAPI Development Hands-on Demo
          • GPIO Introduction
          • I2C Communication
          • SPI Communication
          • PWM Control
          • UART Communication
          • TF Card (MicroSD)
          • Screen (Display)
          • Touch
          • Ethernet
          • M.2 SSD
          • Audio
          • WIFI & BT
          • Camera
        • Downloads

          • Downloads
      • M5-R1

        • Introduction

          • M5-R1 Development Docs
        • Quick Start

          • Image Burning
          • Environment Setup
          • Download Source Code
        • Peripherals & Interfaces

          • Raspberry Pi Interfaces
          • GPIO Interface
          • I2C Interface
          • SPI Communication
          • PWM Control
          • Serial Port Communication
          • TF Card
          • Display
          • Touch
          • Audio
          • RTC
          • Ethernet
          • M.2
          • MINI-PCIE
          • Camera
          • WIFI & BT
        • Downloads

          • Downloads
      • Pico-G1

        • Product Overview

          • Product Introduction
          • SDK Version Information
        • Quick Start

          • Development Environment Setup
          • Image Build
          • Image Flashing
          • System Login
          • Network Configuration
          • File Transfer
          • SDK Directory Structure
          • Deploying Your First Application
          • Deploying Your First Driver
          • Mounting an SD Card
        • Peripherals & Interfaces

          • GPIO Control
          • UART Serial Communication
          • I2C Communication
          • SPI Communication
        • MPP Media Development

          • MPP Media Processing Software
          • Image Processing Chain
          • Video Input
          • Image Encoding
        • NPU & AI

          • NPU Driver and Runtime Library Architecture
          • .xmm Model Loading
          • SVP Video Processing
          • AI Noise Reduction (AI_NR)
        • Application Samples

          • Encryption/Decryption Application
          • ADC Acquisition Application
          • Low-Power Application
          • Audio Processing Application
          • Video Encoding Application
          • Video Input Application
          • Video Graphics Subsystem (VGS) Application
          • 08 Region Overlay Application
          • 09 Intelligent Video Engine Application
          • 10 UVC Webcam Application
          • 11 All-in-One Quickstart Application
          • 12 FPN Correction Application
          • 13 Regional Motion Detection Application
          • 14 MTCNN Face Detection Application
        • Expansion Board Peripheral Examples

          • 00 - Pico Expansion Board Peripheral Examples Overview
          • 01 - OLED Display Application
          • 02 - TFT Display Application
          • 03 - MPU6050 Gyroscope Application
          • 04 - ADC Acquisition Application
          • 05 - Passive Buzzer Application
          • 06 - MQ Gas Sensor Application
          • 07 - GPS Positioning Application
          • 08 - SHT20 Temperature & Humidity Application
          • 09 - Ultrasonic Ranging Application
          • 10 - SpO2 Sensor Application
          • 11 - DC Motor Control Application
          • 12 - Servo Control Application
    • OpenHarmony

      • SC-3568HA

        • Introduction

          • SC-3568HA Overview
        • Quick Start Guide

          • OpenHarmony Overview
          • Image Flashing
          • Setting Up the Development Environment
          • Hello World Application and Deployment
        • Application Development

          • ArkUI

            • Introduction to ArkTS Language
            • Introduction to UI Components and Practical Applications (Part 1)
            • Introduction to UI Components and Practical Applications (Part 2)
            • Introduction to UI Components and Practical Applications (Part 3)
          • Expand

            • Getting Started Guide
            • Referencing and Using Third-Party Libraries
            • Application Compilation and Deployment
            • Command-Line Factory Reset
            • System Debugging -- HDC Debugging
            • APP Stability Testing
            • Chapter 7 Application Testing
        • Device Development

          • Environment Setup
          • Download Source Code
          • Compiling Source Code
        • Peripheral And Interface

          • Raspberry Pi interface
          • GPIO Interface
          • I2C Interface
          • SPI communication
          • PWM (Pulse Width Modulation) control
          • Serial port communication
          • TF Card
          • Display Screen
          • Touch
          • Audio
          • RTC
          • Ethernet
          • M.2
          • MINI-PCIE
          • Camera
          • WIFI&BT
          • Raspberry Pi expansion board
        • Downloads

          • Downloads
      • M-K1HSE

        • Introduction

          • M-K1HSE Introduction
        • Quick Start

          • Development environment construction
          • Source code acquisition
          • Compilation Notes
          • Burning Guide
        • Application Development

          • Application Development Environment Setup
          • First Application - Hello World
        • Peripherals and interfaces

          • 01 Audio
          • 02 RS485
          • 03 Display
        • System customization development

          • System transplant
          • System customization
          • Driver Development
          • System Debugging
          • OTA Update
        • Downloads

          • Downloads
    • HVS Camera

      • Quick Start

        • SDK Overview
        • Downloads
        • Your First C++ Program
        • Python Data Analysis
        • MultiVision Studio
      • Development

        • Programming Guides

          • Open Camera
          • Read Events
          • Recording & Replay
          • Event Processing (Denoising)
          • Display & Visualization
          • Tuning
          • Capture APS Image
        • Toolkit SDK

          • Hybrid Vision Toolkit
          • Quick Start
          • C++ API
          • Python API
        • Algorithm

          • Hybrid Vision Algo
          • Hybrid Vision Algo API
          • Windows Algo SDK
        • Samples Overview
        • Applications
      • Fundamentals

        • Event Camera Fundamentals
        • HVS Hybrid Vision
        • Event Visualization
        • Data Formats Reference
        • Glossary
        • Bias & Tuning
        • Video Tutorials
      • USB Cameras

        • HVS Camera Quick Start
        • Networking Capabilities

          • HVS Camera System Architecture
          • EVS Network Server
          • EVS Time Sync
          • Web Window
        • HVS Camera Compatibility Matrix
        • FAQ & Troubleshooting Guide
        • Products

          • CF-NRS1 (Lingguang No.1 Hybrid Vision Camera)
      • MIPI Modules

        • MIPI Module Quick Start
        • Carrier Boards

          • RDK X5 Carrier Board Adaptation
          • Raspberry Pi Carrier Board Adaptation
          • Digua Pi Carrier Board Adaptation
          • ShimeTai Board Carrier Board Adaptation
        • MIPI Module Compatibility Matrix
        • Products

          • EVS_003 Sensor Module
    • AI-model

      • 1684XB-32T

        • Introduction

          • AIBOX-1684XB-32 Introduction
        • Quick Start

          • First Use
          • Network Configuration
          • Disk Usage
          • Memory Allocation
          • Fan Control Strategy
          • Firmware Upgrade
          • Cross Compilation
          • Model Quantization
        • Application Development

          • Development Overview

            • Sophgo SDK Development
            • Sophgo Demo Introduction
          • Large Language Models

            • Deploying Llama3 Example
            • Sophon LLM_api_server Development
            • Deploying MiniCPM-V-2_6
            • Qwen-2-5-VL Image and Video Recognition Demo
            • Qwen3-chat Demo
            • Qwen3-Qwen Agent-MCP Development
            • Qwen3-langchain-AI Agent
          • Deep Learning

            • ResNet (Image Classification)
            • LPRNet (License Plate Recognition)
            • SAM (General Image Segmentation Foundation Model)
            • YOLOv5 (Object Detection)
            • OpenPose (Human Keypoint Detection)
            • PP-OCR (Optical Character Recognition)
        • Downloads

          • Downloads
      • 1684X-416T

        • Introduction

          • AIBOX-1684X-416 Introduction
        • Demo Quick Guide

          • ShimeTai Intelligent Monitoring Demo Quick Usage Guide
      • RDK-X5

        • Introduction

          • RDK-X5 Hardware Introduction
        • Quick Start

          • RDK-X5 Quick Start
        • Application Development

          • AI Online Model Development

            • Experiment 01 - Access Volcengine Doubao AI
            • Experiment 02 - Image Analysis
            • Experiment 03 - Multimodal Visual Analysis & Localization
            • Experiment 04 - Multimodal Image-Text Comparison
            • Experiment 05 - Multimodal Document/Table Analysis
            • Experiment 06 - Camera-based AI Visual Analysis
          • Large Language Models

            • Experiment 01 - Speech Recognition
            • Experiment 02 - Voice Conversation
            • Experiment 03 - Multimodal Image Analysis - Voice
            • Experiment 04 - Multimodal Image Comparison - Voice
            • Experiment 05 - Multimodal Document Analysis - Voice
            • Experiment 06 - Multimodal Vision Application - Voice
          • ROS2 Basics

            • Experiment 01 - Environment Setup
            • Experiment 02 - Create & Build a Workspace Package
            • Experiment 03 - Run ROS2 Topic Communication Node
            • Experiment 04 - ROS2 Camera Application
          • 40-pin IO Development

            • Experiment 01 - GPIO Output (LED Blink)
            • Experiment 02 - GPIO Input
            • Experiment 03 - Button-controlled LED
            • Experiment 04 - PWM Output
            • Experiment 05 - Serial Output
            • Experiment 06 - I2C Experiment
            • Experiment 07 - SPI Experiment
          • USB Module Usage

            • Experiment 01 - USB Voice Module Usage
            • Experiment 02 - Sound Source Localization Module
          • Machine Vision Practice

            • Experiment 01 - Open USB Camera
            • Experiment 02 - Color Recognition
            • Experiment 03 - Gesture Recognition
            • Experiment 04 - YOLOv5 Object Detection
      • RDK-S100

        • Introduction

          • RDK-S100 Hardware Introduction
        • Quick Start

          • RDK-S100 Quick Start
        • Application Development

          • AI Online Model Development

            • Experiment 01 - Access Volcengine Doubao AI
            • Experiment 02 - Image Analysis
            • Experiment 03 - Multimodal Visual Analysis & Localization
            • Experiment 04 - Multimodal Image-Text Comparison
            • Experiment 05 - Multimodal Document/Table Analysis
            • Experiment 06 - Camera-based AI Visual Analysis
          • Large Language Models

            • Experiment 01 - Speech Recognition
            • Experiment 02 - Voice Conversation
            • Experiment 03 - Multimodal Image Analysis - Voice
            • Experiment 04 - Multimodal Image Comparison - Voice
            • Experiment 05 - Multimodal Document Analysis - Voice
            • Experiment 06 - Multimodal Vision Application - Voice
          • ROS2 Basics

            • Experiment 01 - Environment Setup
            • Experiment 02 - Create & Build a Workspace Package
            • Experiment 03 - Run ROS2 Topic Communication Node
            • Experiment 04 - ROS2 Camera Application
          • 40-pin IO Development

            • Experiment 01 - GPIO Output (LED Blink)
            • Experiment 02 - GPIO Input
            • Experiment 03 - Button-controlled LED
            • Experiment 04 - PWM Output
            • Experiment 05 - Serial Output
            • Experiment 06 - I2C Experiment
            • Experiment 07 - SPI Experiment
          • USB Module Usage

            • Experiment 01 - USB Voice Module Usage
            • Experiment 02 - Sound Source Localization Module
          • Machine Vision Practice

            • Experiment 01 - Open USB Camera
            • Experiment 02 - Image Processing Basics
            • Experiment 03 - Object Detection
            • Experiment 04 - Image Segmentation
      • RK1828

        • Introduction

          • M5-182X-A1 AI Edge Box - Product Introduction
          • M5-182X-A1 Hardware Specifications
          • M5-182X-A1 Usage & Safety
        • Quick Start

          • M5-182X-A1 Image Flashing
          • RK182X Hardware Installation & Verification
          • RK182X Development Environment Quick Setup
          • RK182X SDK Overview
          • RK182X Environment Setup in Detail
          • RK182X Quick Start
          • Vendor SDK Data Extraction Record
        • Development Guide

          • ClawChips Architecture and Principles
          • SKILL User Manual
          • RK182X Series LLM Inference (RK1828 Model)
          • RK182X Series CNN Inference (RK1828 Model)
          • Model Conversion
          • RK182X AI Agent Application Development Guide
          • RK182X Industrial Anomaly Detection Application
        • SDK Reference

          • RKNN3-SDK Overview

            • RKNN3 SDK Overview
          • RKNN3-Toolkit

            • RKNN3 Toolkit Installation and Usage
          • RKLLM

            • RKLLM On-Device LLM Inference
          • RK182X Series NPU Overview and Architecture (RK1828 Model)
          • RK182X INT8 Quantized Inference Deployment
          • RK182X MPP Multimedia Framework
          • MPP Details

            • RK182X Video Decoding
            • RK182X Video Encoding
          • NPU Details

            • RKNN Model Conversion
            • RK182X NPU INT8 Quantized Inference
            • RK182X Multi-Model Parallel Inference
          • RGA Details

            • RK182X RGA 2D Graphics Acceleration
          • VPU Details

            • RK182X VPU Codec
        • Hardware Reference

          • RK182X Series Hardware Architecture Overview (RK1828 Model)
          • RK182X Pin Definitions and Multiplexing Configuration
          • RK182X Pin Definitions
          • RK182X Power Management
          • RK182X Clock and PLL Configuration
          • RK182X Clock and Frequency Configuration
        • Tutorials

          • Hello World
          • Hello RK1828 - The First Program
          • RTSP Streaming
          • RTSP Streaming + AI Analysis
          • ShiMetaPi AI Lobster One-Click Deployment
          • PaddleOCR-VL Text Recognition
          • Qwen3-1.7B LLM Text Chat
          • AI Multi-View Inspection (Qwen3-VL Wrapper)
          • YOLOv5 Object Detection
        • Downloads

          • Downloads
        • FAQ

          • FAQ
    • Core-Board

      • C-3568BQ

        • Introduction

          • C-3568BQ Overview
      • C-3588LQ

        • Introduction

          • C-3588LQ Overview
      • GC-3568JBAF

        • Introduction

          • GC-3568JBAF Overview
      • C-K1BA

        • Introduction

          • C-K1BA Overview
    • Software Platform

      • ShiMetaPi Workbench

        • Introduction

          • Product Overview
          • Core Architecture
          • Feature Entries
          • Supported Hardware
          • Release Notes
        • Quick Start

          • Install & Login
          • Connect the Device
          • Set Up the Environment
          • Connect to AIHub
          • First Inference
        • User Guide

          • Workspace Overview
          • Device Manager
          • Model Market
          • One-Click Deploy
          • Vision — SVP
          • Vision - Custom Models
          • shimeta-py IDE
          • Terminal
          • Agent Debug Assistant
          • Settings and Resources
        • FAQ

          • Installation & Login
          • Device Connection
          • Models & Deployment
          • Vision & Runtime
          • Settings & Other
      • ShimetaPi Repository

        • Introduction

          • ShimetaPi Software Repository
        • Pico G1 (GK7206)

          • Quick Start

            • Installation & First Inference
            • shimeta_infer — Image Inference
            • shimeta_camera — Real-time Camera Inference
            • SVP Scene Detection
            • File Transfer & Built-in Model Reference
            • FAQ
          • HTTP API & Python SDK

            • HTTP API Reference
      • Model Fine-tuning Platform

        • Introduction

          • Model Training Platform
        • Quick Start

          • Register & Login
          • Create Your First Model (30-Minute Quick Experience)
        • Training Guide

          • Data Preparation & Annotation
          • Training Parameter Configuration
          • Start & Monitor Training
          • Model Evaluation & Testing
        • Model Deployment

          • Export Model
          • Deploy to Edge Device

FPGA Development Manual

1 Using and Adding Pango IP Cores

1.1 Experiment Introduction

Experiment objective: Understand how the PDS software installs IPs, uses IPs, and views IP manuals.

Experiment environment: Window11 PDS2022.2-SP6.4 Chip model: PG2L50H-484

1.2 Experiment Principle

1.2.1 IP Installation

After the PDS software is installed, PDS comes with some basic IPs; other IPs require the user to download the IP installation package and install the IP.

rootfile1

After opening PDS, click the IP icon in the red box above.

rootfile1

Then in the tab that pops up, click File->Update... in the upper-left corner.

rootfile1

Click Add Package in the upper-left corner.

rootfile1

As shown above, these are the installation files for the PCIE IP; their suffix is .iar. After selecting the corresponding file, click Open in the lower-right corner. Then tick the checkmark in front, and click Install.

rootfile1

Afterwards, you can see the just-installed IP in the panel on the left. Note that if you find a warning pops up after installation and the left panel shows no change, that means the device family does not support the IP you installed — because your project may be LOGOS, LOGOS2, or Tian2 series, and different chip families use slightly different IPs, so pay attention to this.

1.2.2 Instantiating an IP and viewing the IP manual

rootfile1

Continue clicking the icon in the red box above.

rootfile1

Select the IP you want to generate — here FIFO is used as an example, as shown in red box 1. Red box 2 is used to fill in the name of the generated IP. Click red box 3 to generate the IP and pop up the IP configuration interface, as shown below:

rootfile1

The popup asks whether we want to add this IP to the project; just click YES. If we don't know how to use the IP, we can open the official reference manual to view it, as shown below:

rootfile1

Select the IP you want to view, then click the icon in red box 1 — the official reference document will pop up automatically.

rootfile1

After we finish configuring our IP, click Generate at red box 1 in the upper-left corner.

rootfile1rootfile1

With no errors, generation has succeeded.

rootfile1

At the same time, the tool will automatically pop up an IP instantiation template for us to use. You only need to add this instantiation template into your own project to use the IP we generated.

2 Key-controlled LED Experiment

2.1 Experiment Introduction

Experiment objective: From creating a project to writing code, completing pin constraints, and finally generating a bitstream to download onto the development board — implement Key0 controlling led0 blinking and Key1 controlling led1 on/off.

Experiment environment: Window11 PDS2022.2-SP6.4 Chip model: PG2L50H-484

2.2 Experiment Principle

Everyone should be familiar with the common hour/minute/second time-keeping carry;

1 hour = 60 minutes = 3600 seconds; when the hour hand rotates 1 hour, the second hand ticks 3600 times.

The clock signal in a digital circuit also has a fixed rhythm; the start-to-end time of this rhythm is what we usually call the period (T).

rootfile1

In a digital system we usually care about the clock frequency. The relationship between frequency and period is:

f=1/T

And the crystal oscillator on this development board provides a 25 MHz single-ended clock.

So its period is about 40 ns. In our FPGA design, our always block typically assigns data on the rising edge of the clock, so we can define a variable that increments by 1 on every rising edge of the clock, turning it into a counter. Each increment by 1 means 40 ns has elapsed, so to time 1 s we only need it to count up to 24999999 — since we count from 0, counting to 24999999 is exactly one second. By analogy, 12499999 is 0.5 s.

rootfile1

The figure above is the schematic of the 2 LEDs on the development board.

rootfile1

The figure above is the schematic of the 2 push-buttons on the development board.

KEY0 controls LED0 to toggle its state every 1 s; KEY1 controls LED1 on/off state. (High level is represented by 1; low level is represented by 0.)

2.3 Interface List

top.v top-level module interface list:

PortI/OWidthDescription
sys_clkinput1System clock 25MHZ
key0input1User button 0
key1input1User button 1
led_0output1LED control signal
led_1output1LED control signal

btn_deb_fix.v button debounce module interface list:

PortI/OWidthDescription
BTN_WIDTHparameter4Number of buttons
sys_clkinput1System clock 25MHZ
rst_ninput1Global reset
btn_ininputBTN_WIDTHUser button input
btn_deb_fixoutputBTN_WIDTHOutput after button debounce (pulse signal)

2.4 Project Description

The project framework is as follows:

rootfile1

This project mainly implements button-controlled LED state. Button 0 controls led0 blinking; button 1 controls led1 on/off.

First, both key0 and key1 pass through the button debounce module, because the development board uses mechanical buttons, so every press produces bouncing; without debouncing this would cause misdetection. After debouncing, every button press produces a high level lasting one clk — i.e. key0_flag and key1_flag. key0_flag controls whether the 1 s counter is enabled to start led0 blinking; key1_flag directly controls LED1 toggling — each press of key1 toggles the LED state once.

2.5 Code Module Description

//key0->led0	闪烁
//key1->key1	翻转
module	top(
input	wire	sys_clk	","	//系统时钟25MHZ
input	wire	key0	","
input	wire	key1	","

output	reg	led_0	","
output	reg	led_1
);
//----------------------------------parameter----------------------------------------
parameter	CNT_MAX	=	32'd25_000_000	;	//1s计数

//----------------------------------reg----------------------------------------------
reg	[7:0]	rsn_cnt	0	;	//复位计数器
reg	[31:0]	cnt_1s	;	//计数器
reg	led0_en	;	//led0闪烁使能

//----------------------------------wire----------------------------------------------
wire	rst_n	;	"//复位信号,低电平有效"
wire	key0_flag	;	//按键按下后的上升沿
wire	key1_flag	;	//按键按下后的上升沿

//----------------------------------always	&	assign----------------------------------------------
//产生复位
always@(posedge	sys_clk)	begin
if(rsn_cnt	>=100)
rsn_cnt	<=	rsn_cnt;
else
rsn_cnt	<=	rsn_cnt	+	1'b1;
end
assign	rst_n	=	(rsn_cnt>=100)?1'b1:1'b0	;

//每按下一次key0进行一次翻转
always@(posedge	sys_clk)	begin
if(!rst_n)
led0_en	<=	1'd0;
else	if(key0_flag)
led0_en	<=	~led0_en;
end

//计数1s
always@(posedge	sys_clk)	begin
if(!rst_n)
cnt_1s	<=	32'd0;
else	if(led0_en)	//led0闪烁使能
begin
if(cnt_1s	==	CNT_MAX-1)	//1秒
cnt_1s	<=	32'd0;
else
cnt_1s	<=	cnt_1s	+	1'b1;
end
else
cnt_1s	<=	32'd0;
end

//led0	1s闪烁
always@(posedge	sys_clk)	begin
if(!rst_n)
led_0	<=	1'd0;
else	if(led0_en)
begin
if(cnt_1s	==	CNT_MAX-1)	//1s翻转led
led_0	<=	~led_0;
else
led_0	<=	led_0;
end
else
led_0	<=	1'd0;
end

//led1翻转
always@(posedge	sys_clk)	begin
if(!rst_n)
led_1	<=	1'd0;
else	if(key1_flag)
led_1	<=	~led_1;
end

//----------------------------------instance----------------------------------------------
//按键消抖模块
btn_deb_fix#(
BTN_WIDTH	(	4'd2	)	//2个按键
)u_btn_deb_fix(
sys_clk	(	sys_clk	"),"
rst_n	(	rst_n	"),"
btn_in	(	"{key1,key0}"	"),"
btn_deb_fix	(	"{key1_flag,key0_flag}"	)
);


endmodule

CNT_MAX defines a maximum count value. Because our system clock is 25 MHz — i.e. 25000000 — to make the LED blink every 1 s we count from 0 to 24999999 and then toggle the LED once.

In lines 26–31, a reset signal is generated after counting 100 cycles of the system clock, to provide reset for subsequent modules and sequential logic.

In lines 43–55, counting of one second begins only when led0_en is pulled high; otherwise the counter stays at 0.

In lines 82–89, a button debounce module is instantiated. After a button is pressed and released, it produces a pulse signal — i.e. key0_flag and key1_flag — where key0_flag controls led0 blinking and key1_flag controls led1 toggling.

//按键消抖
`define	UD	#1
module	btn_deb_fix#(
parameter	BTN_WIDTH	=	4'd8	//按键数量
)
(
input	sys_clk	","
input	wire	rst_n	","
input	[BTN_WIDTH-1:0]	btn_in	","

output	reg	[BTN_WIDTH-1:0]	btn_deb_fix
);

//----------------------------------parameter----------------------------------------
parameter	CNT_20MS_MAX	=	32'd500_000	;	//20MS计数

//----------------------------------reg----------------------------------------------
reg	[23:0]	cnt[BTN_WIDTH-1:0];	//计数器
reg	[BTN_WIDTH-1:0]	btn_in_reg	;	//寄存按键信号
//打一拍
always	@(posedge	sys_clk)	begin
btn_in_reg	<=	btn_in;
end
//----------------------------------消抖主要逻辑----------------------------------------------
genvar	i;
generate
begin
for(i=0;i<BTN_WIDTH;i=i+1)
begin
always	@(posedge	sys_clk)	begin
if(!rst_n)
cnt[i]	<=	24'd0;
if	(btn_in_reg[i]	==	1'b0)	//按下时	计数20ms时归零
cnt[i]	<=	24'd0;
else	if(cnt[i]==CNT_20MS_MAX)	//抖动区间有效时计数
cnt[i]	<=	cnt[i];
else
cnt[i]	<=	cnt[i]	+	1'b1;
end

always	@(posedge	sys_clk)	begin
if(!rst_n)
btn_deb_fix[i]	<=	1'd0;
else	if(cnt[i]==CNT_20MS_MAX-1)	//消抖后输出一个clk的高电平
btn_deb_fix[i]	<=	1'b1;
else
btn_deb_fix[i]	<=	1'b0;
end
end
end
endgenerate

endmodule

This part is the button debounce module. The parameter defines the number of button inputs; the module output produces a pulse signal — i.e. a high level lasting one clk.

In lines 30–50, cnt continuously counts for 20 ms; when the button is pressed, cnt resets to 0 and counts up from 0 to 20 ms. When it reaches 20 ms, it outputs a one-clk high level — setting btn_deb_fix to 1 — and holds it for only one clk.

2.6 Experiment Steps

This section describes in detail the specific steps from creating a new project to downloading the program; subsequent projects will not be explained in such detail.

2.6.1 Open the PDS software and create a project

Step 1: Open the PDS software, click NEW Project, then complete the new-project setup.

rootfile1

Step 2: Click NEXT.

rootfile1

Step 3: Create a project named led_water in the corresponding directory, then click Next.

Creating a new project mainly includes setting the project name and path, project type, project files, and device information.

Project Name is the project file name, which defaults to project. (Only letters, digits, underscore (_), dash (-), dot (.) are allowed.)

Project Location is used to select the working path for the new project. The folder name allows only letters, digits, underscore (_), dash (-), dot (.), @, ~, comma, +, =, #, and space — but a space must not appear at the start or end of the path name. That is, this is the path where the project files are placed.

Create Preject Subdirectory makes the project file name part of the working directory.

rootfile1

Step 4: Select RTL project and click Next.

RTL Project is used to create an RTL project. The new project can perform synthesize, device map, place& route, report timing, report power, generate netlist, and generate bitstream, etc.

Post-Synthesize Project is used to create a post-synthesis project. The new project can perform device map, place& route, report timing, report power, generate netlist, and generate bitstream, etc.

rootfile1

Step 5: Click Next.

This interface allows you to use Add Files and Add Directories to add RTL source files and create new RTL source files, as well as adjust the RTL file compile order. Add Files adds selected files; Add Directories adds all suitable files in the selected folder. If you tick Add source from subdirecotires below, it adds all suitable files in subdirectories as well. You can also skip adding files by clicking NEXT directly.

rootfile1

Step 6: Click Next.

rootfile1

Step 7: Click Next.

rootfile1

Step 8: Select the device family, model, package, speed, and synthesis tool, then click Next.

In synthesize tool you can choose the synthesis tool as Synplify Pro or ADS; we use the ADS synthesis tool in this experiment.

rootfile1

Step 9: Click Finish in the summary to complete project creation.

rootfile1

2.6.2 Add design files

The PDS software interface is shown below:

rootfile1

Double-click Designs to create the previously designed module in a file, or add the previously edited Verilog file to the project:

rootfile1

Add files to the project:

In the window, click Add Files to select files to add to the project;

rootfile1

Create a new file in the project:

  1. In the window, click Create File;
rootfile1
  1. Select Verilog Design File; the file name matches the module name; default path; click OK;
rootfile1
  1. Click OK;
rootfile1
  1. Click Cancel;
rootfile1
  1. The new file opens by default; copy the previously designed code into it;
rootfile1
  1. Click save to finish creating the new file.
rootfile1

Ctrl+S to save.

rootfile1

Double-click Designs.

rootfile1

Click Add Files;

rootfile1

Add the btn_deb_fix.v module — i.e. the button debounce module.

rootfile1

Click OK.

2.6.3 Compile

You can run the Compile flow in any of the following ways:

(1) Double-click Compile in the Flow to synthesize;

(2) Right-click Compile and click Run to synthesize;

rootfile1

2.6.4 Project Constraints

Click Tools and choose User Constraint Editor (Timing and Logic), or click the toolbar icon, User Constraint Editor (Timing and Logic), and select Pre Synthesize UCE, as shown below.

rootfile1

User Constraint Editor (Timing and Logic) under Tools

rootfile1

The User Constraint Editor (Timing and Logic) icon in the toolbar

2.6.4.1 Clock constraints

After opening the UCE, select Timing Constraints, then select Create Clock to add the reference clock. The reference clock is generally the on-board clock entered through an input port.

rootfile1

In the popup, name the clock, associate the clock pin, and add the clock parameters. Clicking OK creates a clock constraint; Reset resets this page. After creation it looks as shown below:

rootfile1

The clock provided to the development board is 25 MHz, i.e. a 40 ns period.

rootfile1
2.6.4.2 Physical constraints

After opening the UCE, select Device, then select I/O, and edit the IO assignments according to the schematic.

rootfile1

After editing the IO assignments according to the schematic, click save — this generates an .fdc file, completing the constraints.

2.6.5 Synthesize

The Synthesize flow can be run in the following ways:

(1) Double-click Synthesize in the Flow to synthesize;

(2) Right-click Synthesize and click Run to synthesize;

After completing Synthesize, you will see the following:

rootfile1

2.6.6 Device Map

The main purpose of Device Map is to map the design onto specific model sub-cells (LUT, FF, Carry, etc.). The Device Map flow can be run in the following ways:

(1) Double-click Device Map directly;

(2) Right-click Device Map and click Run;

After completing Device Map, you will see the following:

rootfile1

2.6.7 Place & Route

Place & Route performs the actual placement and routing of design modules according to user constraints and physical constraints. The Place & Route flow can be run in the following ways:

(1) Double-click Place & Route directly;

(2) Right-click Place & Route and click Run;

After completing Device Map, you will see the following:

rootfile1

2.6.8 Generate Bitstream

Generate Bitstream produces a binary bitstream file. The Generate Bitstream flow can be run in the following ways:

(1) Double-click Generate Bitstream directly;

(2) Right-click Generate Bitstream and click Run;

After the above operations, a bitstream file will be produced. Running Generate Bitstream, the interface is as shown below:

rootfile1

2.6.9 Download the generated bitstream file

Click Tools and select Configuration, or click the Configuration icon in the toolbar, as shown below.

rootfile1

Configuration under Tools

rootfile1

The Configuration icon in the toolbar

After opening Configuration, select Scan Device directly to perform the JTAG chain scan. Once the chain initializes successfully, all devices scanned on the chain are displayed in the work area, and the device attributes window shows the current device's information. A dialog pops up showing the configuration files that can be added for the device:

rootfile1

Chain initialization succeeded

In the dialog, select the bitstream file to add that configuration file; the absolute path of the loaded file is displayed and shown in the message bar, as shown below:

rootfile1

Download the bitstream file

rootfile1

When all 4 signals are 1, the download succeeded.

The development board is also equipped with an external flash. To flash the program onto the board, the bitstream file must first be converted into an .sfc file.

First click the Covert File option under the Operations section on the Configuration page.

rootfile1

After clicking, the following screen appears. On the Generate Flash Programing File page, select the manufacturer and model of the corresponding Flash device, then at BitStreamFile select the path to the bitstream file and click OK. (If the flash device in use is not in the selectable flash list, you must manually add the corresponding flash model; for the procedure, refer to the development-board download and flashing instructions.)

rootfile1

After successfully converting to the .sfc file, the page is as shown below; click OK.

rootfile1

The user can right-click the position below and click Scan Outer Flash.

rootfile1

The page displays the model of the Flash mounted on the board. Click the .sfc file and click OPEN.

rootfile1

After right-clicking the position below, click Program.

rootfile1

Successful Flash programming is as shown below:

rootfile1

Now power off the board and re-apply power. If pressing key0 and key1 produces the corresponding experimental behavior, flashing succeeded. (Wait about 15 s.)

The final on-board result is as follows.

3 Pango Clock Resources — Phase-Locked Loop

3.1 Experiment Introduction

Experiment objective: Understand the basic usage of the PLL IP.

Experiment environment: Window11 PDS2022.2-SP6.4 Chip model: PG2L50H-484

3.2 Experiment Principle

3.2.1 PLL Introduction

A phase-locked loop (PLL) is a feedback-control circuit whose characteristic is using an externally input reference signal to control the frequency and phase of the oscillation signal inside the loop. Because a PLL can automatically track the input signal's frequency with its output signal's frequency, PLLs are commonly used in closed-loop tracking circuits. While the PLL is operating, when the output signal's frequency equals the input signal's frequency, the output voltage and input voltage maintain a fixed phase difference — i.e. the phase of the output voltage is "locked" to that of the input voltage. This is the origin of the name "phase-locked loop".

A PLL has powerful capabilities: it can perform arbitrary frequency division, frequency multiplication, phase adjustment, and duty-cycle adjustment on the clock signal input to the FPGA, thereby outputting a desired clock. In addition, in some complex projects, even when we don't need to modify any clock parameters, we often use a PLL to optimize clock jitter in order to obtain a more stable clock signal. It is precisely because these PLL capabilities are what we need in actual design — and cannot be achieved by writing code — that the PLL IP core has become one of the most commonly used IP cores in program design.

The PLL IP is an IP designed by Pango based on PLL and clock-network resources. Through different parameter configurations, it can implement clock frequency adjustment, phase adjustment, synchronization, frequency synthesis, and more.

3.2.2 IP Configuration

First click the "IP" icon in the shortcut toolbar to enter the IP instantiation settings.

rootfile1

Then select PLL in the IP directory, give a name to this instantiated IP in Instance name, and click Customise to enter the IP configuration page. The operation is illustrated below:

rootfile1

The PLL can be used in two modes: Basic and Advanced. In Advanced mode, the PLL's internal parameters are fully exposed; you must fill in the input divider, output divider, duty cycle, phase, feedback divider, etc. yourself to configure it correctly. In Basic mode, the user does not need to worry about the PLL's internal parameters — just enter the desired frequency, phase, duty cycle, etc., and the IP will automatically compute the optimal configuration parameters. If there is no special requirement, Basic mode is recommended for configuring the PLL. In this experiment we choose Basic Configuration.

rootfile1

Next, the basic configuration:

In Public Configurations, set the input clock frequency to 25 MHz.

Under the Clockout0 Configurations tab, tick to enable clkout0 and set the output frequency to 50 MHz.

Under the Clockout1 Configurations tab, tick to enable clkout1 and set the output frequency to 100 MHz.

Under the Clockout2 Configurations tab, tick to enable clkout2, set the output frequency to 100 MHz, and set the phase offset to 180 degrees.

Other options can use default settings; if you have other needs, consult the IP manual. This experiment only covers the basic usage of the IP:

rootfile1

Click Generate in the upper-left corner to generate the IP.

rootfile1

3.3 Code Design

The module interface list is as follows:

PLL IP usage experiment module interface table

PortI/OWidthDescription
sys_clkinput1System clock
clkout0output154 MHz clock
clkout1output181 MHz clock
clkout2output181 MHz clock, phase offset 180 degrees
lockoutput1Clock-locked signal; when high, indicates the IP core output clock is stable.

PLL_TEST top-level code:

module PLL_TEST(  
    input                               sys_clk                    ,  
    output                              clkout0                    ,  
    output                              clkout1                    ,  
    output                              clkout2                    ,  
    output                              lock                          
   );  
  
PLL PLL_U0 (  
    .clkout0                            (clkout0                   ),// output  
    .clkout1                            (clkout1                   ),// output  
    .clkout2                            (clkout2                   ),// output  
    .lock                               (lock                      ),// output  
    .clkin1                             (sys_clk                   ) // input  
);  
  
 
endmodule

This module instantiates the PLL IP core; the function is simple and is not explained further here.

PLL_tb test code:

timescale 1ns / 1ps  
 
module    PLL_tb();  
    reg                                        sys_clk                    ;  
    wire                                       clkout0                    ;  
    wire                                       clkout1                    ;  
    wire                                       clkout2                    ;  
    wire                                       lock                       ;  
  
  
  
    initial  
        begin  
            #2                                               
                    sys_clk <= 0     ;                            
        end                                                  
                                                             
    parameter   CLK_FREQ = 25;//Mhz                         
    always # ( 1000/CLK_FREQ/2 ) sys_clk = ~sys_clk ;                
                                                             
                                                             
PLL_TEST u_PLL_TEST(  
    .sys_clk                            (sys_clk                   ),  
    .clkout0                            (clkout0                   ),  
    .clkout1                            (clkout1                   ),  
    .clkout2                            (clkout2                   ),  
    .lock                               (lock                      )  
);  
 
  
endmodule

The timescale defines the simulation time unit and time precision of the module. The time unit is 1 nanosecond and the precision is 1 picosecond.

The initial block initializes the system clock. Two nanoseconds after the simulation starts, the system clock sys_clk is set to 0. This defines a known initial state at the start of the simulation.

The code defines a clock-frequency parameter CLK_FREQ of 25 MHz and uses an always block to toggle the system clock signal. The logic in the always block toggles sys_clk every 40 nanoseconds, thereby generating a 25 MHz square-wave clock signal. This clock signal drives the PLL_TEST module under test.

Finally, the various signals of the testbench are connected to the PLL_TEST module. This includes connecting the generated system clock sys_clk to the clock input of PLL_TEST, and bringing out PLL_TEST's output signals clkout0, clkout1, clkout2, and lock using wires for observation.

3.4 PDS and Modelsim Co-simulation

PDS supports co-simulation with third-party simulators such as Modelsim or QuestaSim. Modelsim is the more commonly used simulator, so we use PDS together with Modelsim for co-simulation.

Next, select Project -> Project Setting to open the project settings and prepare to configure co-simulation.

rootfile1

Select the Simulation tab. Red box 1 selects the path to the simulation library just compiled; red box 2 selects the Modelsim launch path; then click OK.

Right-click the file to be simulated and select Run Behavior Simulation to start behavioral simulation.

rootfile1

After running, Modelsim opens automatically and the simulation executes. If there are no errors, it succeeded. If errors appear, check the PDS and Modelsim configuration.

rootfile1

3.5 Experimental Phenomena

Click Wave to observe the PLL output signals:

rootfile1

Using the cursor to measure clkout0, we find one clock period is 20 ns — i.e. 50 MHz.

rootfile1

You can see clkout1's clock frequency is 100 MHz, and it is 180° out of phase with clkout2 — consistent with the settings. Note that the PLL's output clocks should only be used after the clock-lock signal lock is valid; the clocks output before lock goes high are indeterminate.

4 Using ROM, RAM, and FIFO

4.1 Experiment Introduction

Experiment objective: Master the use of RAM, ROM, and FIFO IPs on the Pango platform.

Experiment environment: Window11 PDS2022.2-SP6.4 Chip model: PG2L50H-484

4.2 Experiment Principle

Whether it's the Logos series or the Logos2 series, the IP configuration as well as the modes and functions are identical — they don't have differences like the PLL's dynamic-configuration and internal-feedback options. So RAM, ROM, and FIFO are universal.

4.2.1 RAM Introduction

RAM is random-access memory. During operation it can write data to any address and read data from any address. It can be used for data caching, clock-domain crossing, and storing intermediate algorithm results, among other things.

Note that the PDS IP configuration tool provides two different RAMs: one is Distributed RAM and the other is DRM Based RAM. Distributed RAM is a RAM built from LUT (lookup-table) resources — this kind of RAM consumes a lot of LUT resources, so it is typically used only for relatively small storage to save DRM resources. DRM Based RAM is a RAM built from on-chip DRM resources; it does not occupy logic resources and is fast, so DRM Based RAM is used in most designs.

RAM is divided into three types, as shown in the following table:

RAM typeCharacteristics
Single-port RAMOnly one port can read/write. There is only one read/write port and one address port
Pseudo dual-port RAMHas wr and rd ports; as the name implies, wr can only write and rd can only read
True dual-port RAMProvides A and B ports; both ports can independently read and write

Note that when using true dual-port, avoid reading and writing the same address at the same time — this will cause the write to fail, and should be avoided in logic design.

Below we present the commonly used RAM configuration as an introduction. We typically use the pseudo dual-port RAM for design, as shown below:

rootfile1

The following figure shows the IP configuration:

rootfile1

Note that if you tick Enable Output Register (output register), the output data is delayed by one clock cycle.

For the meaning of each port, refer to the official manual; you can also view the IP manual yourself, as shown below:

rootfile1

DRM Resource Type: Configures which resource the RAM IP core is built from. Different chip models have different selectable resources — some are 9K, some 18K, some 36K. If there is no special case, just use AUTO.

4.2.1.1 RAM Read/Write Timing

When configured in different modes, the RAM's read/write timing differs. True dual-port and single-port RAM each have three modes, while pseudo dual-port has only one. Since the true dual-port and single-port configurations are the same, we use true dual-port as the example.

There are three modes: NORMAL_WRITE (normal mode), TRANSPARENT_WRITE (transparent write), and READ_BEFORE_WRITE (read-priority mode).

rootfile1

Pseudo dual-port does not belong to the above three modes; it has its own unique mode. The difference between these modes lies in the read/write timing. Next, we analyze the read/write timing.

The following timing diagrams are all from the official IP manual, and none of them enable the output register. Note that wr_en = 1 means write data, and 0 means read data.

(1) NORMAL_WRITE

rootfile1

In NORMAL_WRITE mode, you can see that when the clock rising edge arrives and both clk_en and wr_en are high, the data is written to the corresponding address — as at time 1 in the figure. Then looking at the read-data port: when wr_en is not 0, a_rd_data is always in the Don't Care state; when the clock rising edge arrives, clk_en is high, and wr_en is low, a_rd_data outputs the data at the current a_addr — i.e. Mem(ADDR1) and D0 in ADDR0.

(2) READ_BEFORE_WRITE

rootfile1

In READ_BEFORE_WRITE mode, at time 1, when the clock rising edge arrives and both clk_en and wr_en are high, D0 is written into ADDR0. But notice a_rd_data and a_addr at this time — a_wr_en is not 0, yet a_rd_data still outputs the previous data of ADDR0 (because it's not outputting D0). Afterwards, a_wr_en goes low — now it reads data. At time 3, the data of ADDR0 is read out and a_rd_data outputs D0.

So to summarize, this mode outputs the original data of the address currently being written while a write operation is in progress. That's why it's fittingly called read-priority mode — it prioritizes reading out the original data.

(3) Transparent_Write

rootfile1

In Transparent_Write mode, at time 1, when the clock rising edge arrives and both clk_en and wr_en are high, D0 is written into ADDR0. But notice a_rd_data and a_addr at this time — a_wr_en is not 0, yet a_rd_data directly outputs D0. Afterwards a_wr_en goes low, entering the read state; at time 2, the data of ADDR0 is read out again and D0 is output.

Analyzing and summarizing the situation at time 1, we can conclude that in this mode, when we perform a write operation, the read port immediately outputs the data we are writing. Hence it is called transparent-write mode.

(4) Pseudo dual-port read/write timing

Note: wr_en = 1 is a write operation; 0 is a read operation.

The pseudo dual-port read/write timing differs from all three above. Let's analyze the timing in the figure below:

rootfile1

Note time 1: both wr_en and wr_clk_en are high, so it's a write operation. At time 1, D0 is written to address ADDR0. Notice rd_addr and rd_data at this time — rd_addr is ADDR2, and during the write operation rd_data likewise outputs the data in ADDR2, while wr_en is still high. Next look at times 2 and 3: wr_en is 0 and rd_clk_en is high, so these are read operations — ADDR1 and ADDR0 data are read out respectively. Then rd_clk_en goes low, the read clock is inactive, and rd_data keeps outputting D0.

To summarize, focusing on time 1: at time 1 D0 is written to ADDR0, yet the read port outputs the data at ADDR2. Observing carefully, we can conclude: when the pseudo dual-port RAM performs a write operation, it outputs the data at the address the read port currently points to. Isn't that a bit like transparent write? Except transparent write outputs the data being written, whereas pseudo dual-port outputs the data at the address the read port points to.

2.1.1.2 ROM Introduction

ROM is read-only memory. During program execution it can only be read, not written, so we should configure its initial value at initialization — generally by importing a .dat file when generating the IP to configure the initial value.

Note that the PDS IP configuration tool provides two different ROMs: one is Distributed ROM and the other is DRM Based ROM. Distributed ROM is a ROM built from LUT (lookup-table) resources — this kind of ROM consumes a lot of LUT resources, so it is typically used only for relatively small storage to save DRM resources. DRM Based ROM is a ROM built from on-chip DRM resources; it does not occupy logic resources and is fast, so DRM Based ROM is used in most designs.

Below we present the commonly used ROM configuration as an introduction. Since it can only be read, these are all single-port ROMs, as shown below:

rootfile1

The following figure shows the IP configuration:

rootfile1

Note that if you tick Enable Output Register (output register), the output data is delayed by one clock cycle.

At the same time, you can see the Enable Init option is ticked by default and cannot be unchecked.

The format of the imported data can only be binary or hexadecimal; the demo selects hexadecimal.

For the meaning of each port, refer to the official manual; you can also view the IP manual yourself, as shown below:

rootfile1

Generally we only need four signals: addr, rd_data, clk, and rst.

The following timing diagrams are all from the official IP manual, and none of them enable the output register.

4.2.1.2 ROM Read Timing
rootfile1

You can see the timing is very simple. For example at time T1, when the clk rising edge arrives and clk_en is high, providing the address to be read makes rd_data output the data. Without ticking the output-enable register, rd_data's output has a delay — the specific time can be seen in simulation — so we obtain the ROM's read value at the rising edge of the next clock cycle, i.e. the rising edge of T2.

So the overall timing is very simple: if clk_en is ticked, clk_en must be high to read data; if clk_en is not ticked, ROM data is read continuously according to the address.

4.2.2 FIFO Introduction

FIFO is first-in-first-out. In an FPGA, the role of a FIFO is a buffer with first-in-first-out characteristics for the stored data, often used for data caching or for cross-clock-domain data transfer. The biggest difference between FIFO and RAM is that FIFO does not need addresses — it uses sequential write-in and sequential read-out.

In the Pango IP tool there are Distribute FIFO and DRM FIFO — these are simply built from different resources. The former, Distribute FIFO (distributed FIFO), is built from on-chip LUT resources, while DRM FIFO is built from on-chip DRM resources. A DRM FIFO has better performance than one built from LUT resources — not only larger capacity but also more configurable features.

This chapter focuses on DRM Based FIFO.

Note: Once a FIFO is full, you must not continue writing data — otherwise a write overflow will occur.

Note: Once a FIFO is empty, you must not continue reading data — otherwise a read overflow will occur.

Below we present the commonly used FIFO configuration as an introduction.

rootfile1rootfile1

Note that if you tick Enable Output Register (output register), the output data is delayed by one clock cycle.

FIFO Type has two options, SYNC and ASYNC. The first is a synchronous FIFO, where the read and write ports share a single clock and reset; the other is an asynchronous FIFO, where the read/write clocks and resets are all independent. In everyday design, the asynchronous FIFO is more commonly used, because the synchronous FIFO and asynchronous FIFO have identical read/write timing — only the read/write port clocks and resets differ. When the asynchronous FIFO's read and write ports use the same clock and reset, the asynchronous FIFO and synchronous FIFO are essentially the same.

Reset Type can also be SYNC or ASYNC. In SYNC mode, the reset takes effect only when sampled by the clock's rising edge; in ASYNC mode, the FIFO resets immediately once the reset is asserted.

For the remaining port descriptions, refer to the official IP manual, as shown below:

rootfile1

Here rd_water_level and wr_water_level represent the "amount of readable data" and "amount of data already written" respectively — their meaning is the same as Xilinx's wr_data_count and rd_data_count for FIFOs.

rootfile1

Only when we tick Enable Almost Full Water Level and Enable Almost Empty Water Level can we see rd_water_level and wr_water_level. The Almost Full Numbers setting means that when 1020 data items have been written, the Almost Full signal goes high; the Almost Empty Numbers setting means that when 4 readable data items remain, the Almost Empty signal goes high.

FIFO also supports mixed bit-widths — for example a 16-bit write port and an 8-bit read port. If you write 16'h0102, you will read out 8'h02 then 8'h01 — the low bits are read out first.

If the write port is 8-bit and the read port is 16-bit: when you write 8'h01 and then 8'h02, you read out 16'h0201 — the data written first is placed in the low bits.

4.2.2.1 FIFO Read/Write Timing

Because the synchronous FIFO and the asynchronous FIFO have identical read/write timing, we use the asynchronous FIFO's read/write timing diagrams for the introduction.

Note: Reset is active high. None of the read data enables Enable Output Register (output register).

(1) FIFO write timing when not full

rootfile1

You can see that at time 1, the reset signal is low (in working state); at the rising edge of wr_clk with wr_en high, data D0 is written into the FIFO, and wr_water_level changes from 0 to 1, indicating one data item has been written. At this point, look at the empty signal on the read port: at time 3 the empty signal goes from high to low, meaning the read port now has data to read and the FIFO is no longer empty. Note that rd_clk and wr_clk are different; from the write at time 1 to the empty going low at time 3, three rd_clk have elapsed.

So we can conclude: rd_water_level lags wr_water_level by three rd_clk.

(2) FIFO write timing when almost full

rootfile1

When almost full, we mainly analyze the full and almost_full signals. Suppose Almost Full Numbers is set to N-2; at time 1, N-6 data items have already been written, meaning 6 more writes will fill the FIFO. From time 1 to time 2 a total of 4 data items are written, so when wr_water_level becomes N-2 the condition is met — Almost Full goes high, and after two more data writes the FIFO is full, so two clock cycles later the Full signal goes high.

(3) FIFO read timing in the full state

rootfile1

In the full state, the FIFO already has N data items. At state 1, on the rising edge of rd_clk with rd_en high, data is read out from the FIFO (data output has a delay — 0.2 ns in simulation). Now rd_water_level becomes N-1 and rd_data outputs D0. Then look at time 2: the full signal goes low. We can check: from time 1 to time 2, three wr_clk elapse before the write port can determine that the data amount is no longer full. So we can conclude: wr_water_level lags rd_water_level by three wr_clk.

(4) FIFO read timing when almost empty

rootfile1

At time 1, 4 readable data items remain. Suppose Almost Empty Number is set to 2; at time 1 and time 2, two data items are read out respectively, so at time 2 the readable data amount drops to 2 — meeting the Almost Empty Number trigger condition — so the almost_empty signal goes high. Two clock cycles later — i.e. after reading two more data items — the FIFO becomes empty, which is state 3, and the empty signal goes high.

2.1.2 Interface list

This section describes the interfaces of each top-level module.

ram_test_top.v

PortI/OWidthDescription
wr_clkinput1Write clock
rd_clkinput1Read clock
rst_ninput1Global reset
rw_eninput11: write op, 0: read op
wr_addrinput5Write address
rd_addrinput5Read address
Wr_datainput8Data written to RAM
Rd_dataoutput8Data read out from RAM

rom_test_top.v

PortI/OWidthDescription
rd_clkinput1Read clock
rst_ninput1Global reset
rd_addrinput10Read address
rd_datainput64Data read out from ROM

fifo_test_top.v

PortI/OWidthDescription
sys_clkinput1Write/read clock
rst_ninput1Global reset
wr_addrinput8Data written to FIFO
wr_eninput1Write enable
rd_eninput1Read enable
wr_water_leveloutput8Amount of data written to FIFO
rd_water_leveloutput8Amount of data readable from FIFO
Rd_dataoutput8Data read out from FIFO

4.3 Project Description

None

4.4 Code Simulation Description

This time the top-level module is really just instantiating the IP and bringing out the ports, so most of the code is in the testbench. We therefore go straight to the simulation code.

4.4.1 RAM Simulation Test

`timescale	1ns/1ns
module	ram	test	tb()
reg	sys	clk
reg	rd	clk
reg	rst	n
reg	rw	en	//读写使能信号

reg	[7:0]	wr	data
reg	[4:0]	wr	addr
reg	[4:0]	rd	addr

wire	[7:0]	rd	data

reg	[1:0]	state

initial
begin
rst	n	<=	1'd0
sys	clk	<=	1'd0
rd	clk	<=	1'd0
#20
rst	n	<=	1'd1

end

//读写控制
always@(posedge	sys	clk	or	negedge	rst	n)	begin
if(!rst	n)
begin
state	<=	2'd0
wr	data	<=	8'd0
rw	en	<=	1'd0
wr	addr	<=	8'd0
rd	addr	<=	8'd0
end
else
begin
case(state)
2'd0:begin
rw	en	<=	1'd1
state	<=	2'd1
end

2'd1:begin
if(wr	addr	==	5'd31)
begin
rw	en	<=	1'd0
state	<=	2'd2
wr	data	<=	8'd0
wr	addr	<=	5'd0
rd	addr	<=	5'd0
end
else
begin
state	<=	2'd1
wr	data	<=	wr	data+1'b1
rd	addr	<=	rd	addr+1'b1
wr	addr	<=	wr	addr+1'b1
end
end
2'd2:begin
if(rd	addr	==	5'd31)
begin
state	<=	2'd3
rd	addr	<=	5'd0
end
else
begin
state	<=	2'd2
rd	addr	<=	rd	addr+1'b1
end
end
2'd3:begin
state	<=	2'd0
end

default:	state	<=	2'd0
endcase
end
end

//50MHZ
always#10	sys	clk	=	~sys	clk

//
GTP	GRS	GRS	INST(
GRS	N(1'b1)
)

ram	test	top	u	ram	test	top(
wr	clk	(	sys	clk	"),"
rd	clk	(	sys	clk	"),"
rst	n	(	rst	n	"),"
rw	en	(	rw	en	"),"
wr	addr	(	wr	addr	"),"
rd	addr	(	rd	addr	"),"
wr	data	(	wr	data	"),"
rd	data	(	rd	data	)
)
endmodule

Basic testbench operations will not be explained in detail here; we focus only on the key logic. Lines 27–80 of the code are the RAM read/write control state machine, mainly used to control the generation of read/write addresses and enables and the data to be written. Here we explain only the main implemented functions. First, lines 38–42 of the code — i.e. when state=0 — pull rw_en high and jump to state 1, entering the write operation (clk_en is not enabled, so we can ignore it). The next clock cycle begins writing data (note this is sequential logic, edge-sampled, so writing begins on the next clock cycle) — i.e. state=1 keeps writing data into the RAM. Lines 44–60 of the code are the write operation: you can see that when wr_addr is not equal to 31, wr_data and wr_addr increment by 1 (rd_addr is incremented here too; see the video explanation — mainly to verify the pseudo dual-port timing). When wr_addr equals 31, on the next clock cycle the data is cleared and the state jumps; in the current clock cycle it still writes data into address 31, so in this clock cycle a total of 32 data items are written (from address 0 to address 31). That is, state 1 completes writing 32 data items and then jumps to the state=2 logic. Lines 61–72 of the code — i.e. state=2 — increment rd_addr on the rising edge of each cycle until rd_addr=31, then on the next clock cycle clear the address and jump state, while in the current clock cycle it continues to read the data of address 31 — completing reading of addresses 0–31, a total of 32 data items. So this state mainly completes reading 32 data items, and on the next clock cycle jumps to state=3. state=3 — its main role is to wait one clock cycle and then jump back to state=0, acting as a delay.

rootfile1

The figure above is the waveform of the written data; the data increments from 0 to 31, and the addresses also go from 0 to 31.

rootfile1

The figure above is the read-data waveform; data 0–31 is read out from addresses 0–31.

For the specific waveform you can watch the simulation video or try simulating yourself, and read the code according to the waveform. Because this is sequential logic, beginners reading only text may be confused about why one more data item is read at rd_addr=31. It is recommended to simulate directly, or watch the simulation part of the video explanation, which helps with quick understanding.

A one-line summary: assignments in sequential logic always take effect on the next clock cycle. So the operation performed at rd_addr=31 is sampled and takes effect on the next clock cycle. Therefore the current clock still reads one more data item from the RAM.

4.4.2 ROM Simulation Test

`timescale 1ns/1ns
module rom_test_tb();
reg    sys_clk;
reg    rst_n;
reg    [9:0]    rd_addr;
wire   [63:0]    rd_data;

initial
begin
    rst_n    <=    1'd0;
    sys_clk  <=    1'd0;
    #20
    rst_n    <=    1'd1;

end

//50MHZ
always#10 sys_clk = ~sys_clk;
//
GTP_GRS GRS_INST(
    .GRS_N(1'b1)
    ) ;

always@(posedge sys_clk or negedge rst_n)    begin
    if(!rst_n)
        rd_addr    <=    10'd0;
    else
        rd_addr    <=    #2 rd_addr + 1'b1;
end

rom_test_top u_rom_test_top(
    .rd_clk   ( sys_clk  ),
    .rst_n    ( rst_n    ),
    .rd_addr  ( rd_addr  ),
    .rd_data  ( rd_data  )
);

endmodule

Lines 31–36 instantiate the ROM top-level module, which really just calls the ROM IP and brings out the signals to ports — no logic operations.

Lines 24–29 use an always block to continuously generate addresses and feed them to the ROM IP to read out data. Because clk_en is not ticked, data is read out continuously after the ROM reset completes. So there is no complex logic — just increment the address from 0 continuously and read out the data.

rootfile1

The figure above is the waveform of the read-out data; you can see the read-out data is consistent with the data in the dat file.

rootfile1

4.4.3 FIFO Simulation Test

`timescale	1ns/1ns
module	fifo_test_tb();

reg	sys_clk;
reg	rst_n;

reg	[7:0]	wr_data;
reg	wr_en;
reg	rd_en;

reg	rd_state;	//读状态
reg	wr_state;

wire	[7:0]	rd_data;
reg	[7:0]	rd_cnt;

wire	[7:0]	rd_water_level;
wire	[7:0]	wr_water_level;

initial
begin
rst_n	<=	1'd0;
sys_clk	<=	1'd0;
#20
rst_n	<=	1'd1;


end

always#10	sys_clk	=	~sys_clk;	//50MHZ

always@(posedge	sys_clk	or	negedge	rst_n)	begin
if(!rst_n)
begin
wr_state	<=	1'd0;
wr_en	<=	1'd0;
wr_data	<=	8'd0;
end
else
begin
case(wr_state)
1'd0:	if(wr_water_level	==	127)	//128个数据
begin
wr_en	<=	#2	1'd0;
wr_data	<=	#2	8'd0;
wr_state	<=	#2	1'd1;
end
else
begin
wr_en	<=	#2	1'd1;
wr_data	<=	#2	wr_data+1'b1;
wr_state	<=	#2	1'd0;
end

1'd1:	if(rd_cnt	==	127)
wr_state	<=	#2	1'd0;


default:	wr_state	<=1'd0;
endcase
end
end

always@(posedge	sys_clk	or	negedge	rst_n)	begin
if(!rst_n)
begin
rd_state<=	1'd0;
rd_en	<=	1'd0;
rd_cnt	<=	8'd0;
end
else
begin
case(rd_state)
1'd0:	if(rd_water_level	>=	8'd128)	//等待128个数据
begin
rd_state	<=	#2	1'd1;
rd_en	<=	#2	1'd1;
end
else
begin
rd_cnt	<=	#2	8'd0;
rd_state	<=	#2	1'd0;
end

1'd1:	begin

rd_cnt	<=	#2	rd_cnt	+	1'b1;
if(rd_cnt	==	127)
begin
rd_en	<=	#2	1'd0;
rd_state	<=	#2	1'd0;
end
end
default:	rd_state	<=	1'd0;
endcase
end
end

GTP_GRS	GRS_INST(
GRS_N(1'b1)
)	;

fifo_test_top	u_fifo_test_top(
sys_clk	(	sys_clk	"),"
rst_n	(	rst_n	"),"
wr_data	(	wr_data	"),"
wr_en	(	wr_en	"),"
rd_en	(	rd_en	"),"
wr_water_level	(	wr_water_level	"),"
rd_water_level	(	rd_water_level	"),"
rd_data	(	rd_data	)
);
endmodule

Basic testbench operations will not be explained in detail here; we focus only on the key logic. The whole design is split into the control of two states — read and write — and completes writing 128 data items and reading 128 data items respectively. Because FIFO does not need addresses, only enable signals need to be generated.

First, the write state: in wr_state=0, the write enable is pulled high and wr_data is continuously incremented to write data into the FIFO. When wr_water_level=127, the write enable is pulled low, the write data is reset to 0, and the write state jumps to 1. Note that one more data item is written at this point, so a total of 128 data items have been written. The operations of pulling the write enable low, resetting write data to 0, and jumping the write state to 1 will be sampled and take effect on the next clock cycle. Afterwards, in wr_state=1, it keeps waiting on rd_cnt — this condition judges that when 128 data items have been read out, wr_state jumps back to state 0.

Next, the read state: in rd_state=0, once the amount of readable data exceeds 128 (inclusive), the state jumps to rd_state=1 and starts reading data. At the same time, in rd_state=1, a variable rd_cnt is used to count the read-out data. rd_cnt counts from 0; when rd_cnt=127, one more data item will be read from the FIFO, so a total of 128 data items have been read. On the next clock cycle both rd_en and rd_state will be set to 0.

rootfile1

The waveform of the written data is as above — 128 data items are written, from 1 to 128.

rootfile1

The waveform of the read data is as above — 128 data items are read out, from 1 to 128.

For the specific waveform you can watch the simulation video or try simulating yourself, and read the code according to the waveform. Because this is sequential logic, beginners reading only text may be confused about why one more data item is read at rd_cnt=127. It is recommended to simulate directly, or watch the simulation part of the video explanation, which helps with quick understanding.

A one-line summary: assignments in sequential logic always take effect on the next clock cycle. So the operation performed at rd_cnt=127 is sampled and takes effect on the next clock cycle. Therefore rd_en is still 1 on the current clock, and one more data item is read from the FIFO.

5 DDR3 Read/Write Experiment Routine

5.1 Experiment Introduction

Experiment objective: Complete the DDR3 read/write test.

Experiment environment: Window11 PDS2022.2-SP6.4 Chip model: PG2L50H-484

5.2 Experiment Principle

The development board integrates one 4 Gbit (512 MB) DDR3 chip, model MT41K256M16. The DDR3 bus width is 16 bit. The maximum data rate of the DDR3 SDRAM is 1066 Mbps.

5.2.1 DDR3 Controller Introduction

PG2L50H provides users with a complete DDR memory controller solution. The configuration is flexible, and the DDR memory control is implemented in soft IP, with the following features:

  • Supports DDR3
  • Supports x8, x16 Memory Device
  • Maximum bit width of 32 bit
  • Supports a streamlined AXI4 bus protocol
  • One AXI4 256-bit Host Port
  • Supports Self_refresh, Power down
  • Supports Bypass DDRC
  • Supports DDR3 Write Leveling and DQS Gate Training
  • DDR3 maximum rate up to 1066 Mbps

5.3 Project Description

After installing PDS, you must manually add the DDR3 IP. Follow these steps:

DDR3 IP file: PG2L_IP\PG2L_IP\DDR3\ips2l_hmic_s_v1_10.iar

rootfile1

5.3.1 DDR3 Read/Write Example Project

Open the PDS software, create a new project ddr3_test, click the icon below to open the IP Compiler;

rootfile1

Select the DDR3 IP, name it ddr3_test, then click Customize;

rootfile1

In the DDR3 settings interface, set Step 1 as follows:

rootfile1

Set Step 2 as follows. You need to create a new DDR3 model yourself; choose MT41K256M16XX as the template, and keep the Timing parameters, addresses, and Drive Options consistent with the figure below.

rootfile1

Set Step 3 as follows: tick Custom Control/Address Group; pin constraints refer to the schematic:

rootfile1rootfile1

Reminder:

When configuring the IP core, in step 3: pin/bank options, the correspondence between the Group Number in the pin settings and the schematic is as shown below:

rootfile1

R5 means BANK5; G1 means Group Number is 1.

rootfile1

Step 4 is a summary; click Generate to generate the DDR3 IP;

rootfile1

Close this project and open the Example project at this path:

Xxxxx\ddr3_test\ip_core\ddr3\pnr

rootfile1

Open the top-level file; you need to modify the top-level file. See the detailed code for specifics. The figure below is the modified top-level file.

rootfile1

For pins other than those already constrained in "Step 3", modify them against the schematic using the UCE tool. For porting, you can directly refer to the project's fdc file for porting.

rootfile1

The following pins can be assigned to LEDs to facilitate observing the experimental phenomena:

rootfile1

You can view the IP core's user guide in the following way to understand the Example module composition:

rootfile1

5.4 Experimental Phenomena

Download the program; you can see LED1 is steady-on, LED3 blinks, LED4 blinks, and LED5 is steady-on;

Signal nameReference descriptionLED number
err_flag_ledData-check error signal3
heart_beat_ledHeartbeat signal4

Reminder:

The heart_beat_led signal blinking indicates the ddrphy system clock is normal.

rootfile1

The err_flag_led signal blinking indicates no data-detection errors. This can be found in the IP core data manual.

rootfile1

If normal, err_flag_led blinks faster than heart_beat_led.

6 Optical-Fiber Communication Test Experiment Routine

6.1 Experiment Introduction

Experiment objective: Implement data transmit/receive between optical modules via an optical-fiber connection.

Experiment environment: Window11 PDS2022.2-SP6.4 Chip model: PG2L50H-484

6.2 Experiment Principle

PG2L100H has a built-in high-speed serial interface module with line rates up to 6.6 Gbps — i.e. HSSTLP — containing 1 HSSTLP, a total of 4 full-duplex transceiver LANEs. Besides the PMA, HSSTLP also integrates rich PCS features and can be flexibly applied to various serial-protocol standards. Inside the product, each HSST supports 1–4 full-duplex transceiver LANEs. The main features of HSST include:

  • Supports DataRate: 0.6 Gbps–6.6 Gbps
  • Flexible reference-clock selection
  • Independent configuration of TX and RX data rates
  • Programmable output swing and de-emphasis
  • Receiver adaptive linear equalizer Logos2 series FPGA device data manual
  • PMA Rx supports SSC
  • Data path supports data widths: 8bit only, 10bit only, 8b10b, 16bit only, 20bit only, 32bit only, 40bit only, 64b66b/64b67b, etc.
  • Flexibly configurable PCS, supporting PCI Express GEN1, PCI Express GEN2, XAUI, Gigabit Ethernet, CPRI, SRIO, and other protocols
  • Flexible Word Alignment
  • Supports RxClock Slip to ensure fixed Receive Latency
  • Supports protocol-standard 8b10b encode/decode
  • Supports protocol-standard 64b66b/64b67b data adaptation
  • Flexible CTC scheme
  • Supports x2 and x4 Channel Bonding
  • HSSTLP configuration supports dynamic modification
  • Near-end loopback and far-end loopback modes
  • Built-in PRBS function
  • Adaptation

6.3 Project Description

6.3.1 Install the HSST IP core

After installing PDS, you must manually add the HSST IP. Follow these steps:

(1) HSST IP file: select 1_9.iar

rootfile1

(2) IP installation steps: see "Tool Usage \ 03_IP Core Installation and Viewing the User Guide"

rootfile1

6.3.2 Optical-fiber communication test routine

Open the PDS software, create a new project hsst_test, click the icon below to open the IP Compiler;

rootfile1

Select the HSST IP, name it, then click Customize;

rootfile1

In the HSST settings interface, set Protocol and Rate as follows: Channel0, Channel1, and Channel3 are DISABLE; Channel2 is set to Fullduplex (full duplex). For Protocol choose CUSTOMERIZEDX1 (custom mode); for both TX Line Rate and RX Line Rate choose 6.25 Gbps; for Encoder choose 8B10B; Data Width choose 32 bit; for the clock choose Diff_REFck0, and select 125 MHz.

rootfile1

Set Alignment and CTC as follows: for Word Align Mode choose CUSTOMERIZED_MODE. For the control word (COMMA code-group select) choose K28.5; for CTC_MODE choose Bypassed.

rootfile1

Set Misc as follows: choose 25 MHz for the clock, keep the rest at defaults, then click Generate to generate the HSST IP;

rootfile1

Close this project and open the Example project at this path: hsst_test\hsst_test\ipcore\hsst_test\pnr\example_design

rootfile1

To run on the development board, you must modify the reset of the top-level file hsst_test_dut_top. See the routine's top-level file for details:

rootfile1

The figure above is the top-level file before modification.

The figure below is the top-level file after modification. tx_disable must be pulled low to enable the SFP transmit function.

rootfile1rootfile1

The figure above shows part of the pin constraints; for specifics, see the project's fdc file. Note that the red boxes in the figure — the position constraints for hsst_lane and hsst_pll — must be added. The differential data pins do not need to be constrained, but the reference clock provided to hsst must be constrained — i.e. (i_p_refckn_0 and i_p_refckp_0).

rootfile1

To observe whether the transmit/receive data has errors, perform a Debugger insert-core operation.

rootfile1

Select o_p_clk2core_tx_2 as the clock.

You can view the IP core's user guide in the following way to understand the Example module composition:

rootfile1

6.4 Experimental Phenomena

Note: routine location: hsst_test\hsst_test\ipcore\hsst_test\pnr\example_design

rootfile1

Plug both ends of the optical fiber into the SFP ports (the user needs to purchase optical modules), then perform Debugger online debugging. You can see in the window that the sent and received data are identical.

rootfile1

Observe tx_data and rx0_data_align — they are identical, indicating there is no problem with transmit/receive.

7 Ethernet Transmission Experiment Routine

7.1 Experiment Introduction

Experiment objective: Complete the Ethernet communication test.

Experiment environment: Window11 PDS2022.2-SP6.4 Hardware environment: PG2L50H-484

7.2 Experiment Principle

7.2.1 Development Board Ethernet Interface Introduction

The development board uses a YT8521SH-CA Ethernet PHY to implement a 10/100/1000 Ethernet port. To use it, you need an optical-to-electrical conversion module; connect the computer's network port to the electrical port of the optical-to-electrical conversion module with a network cable to complete communication.

7.2.2 Ethernet Protocol Introduction

7.2.2.1 Ethernet Frame Format
rootfile1

Preamble: 8 bytes, 7 consecutive 8'h55 plus 1 8'hd5, indicating the start of a frame, used for synchronization between the two parties' devices.

Destination MAC address: 6 bytes, stores the physical address (MAC address) of the destination device; Source MAC address: 6 bytes, stores the physical address of the sending device.

Type: 2 bytes, used to specify the protocol type; commonly 0800 indicates the IP protocol, 0806 indicates the ARP protocol, and 8035 indicates the RARP protocol.

Data: 46 to 1500 bytes, minimum 46 bytes — if insufficient, it must be padded to 46 bytes. For example, the IP protocol layer is contained within the data portion, including its IP header and data.

FCS: frame trailer, 4 bytes, called the frame check sequence, using 32-bit CRC, which checks from the destination MAC address field to the data field.

Going further, taking the UDP protocol as an example, its structure is as follows. Besides the 14 bytes of the Ethernet header, the data portion contains the IP header, UDP header, and application data — totaling 46–1500 bytes.

rootfile1
7.2.2.2 ARP Datagram Format

ARP — the Address Resolution Protocol — obtains the physical address from the IP address. A host sends an ARP request broadcast (MAC address 48'hff_ff_ff_ff_ff_ff) containing the destination IP address to hosts on the network, and receives a reply message to determine the target's physical address. After receiving the reply, it saves the IP address and physical address into a cache for a period of time; next time, it directly queries the ARP cache to save resources. The following is the ARP datagram format.

rootfile1

Frame type: the ARP frame type is the two-byte 0806;

Hardware type: indicates the link-layer network type; 1 is Ethernet;

Protocol type: indicates the address type to be converted; using 0x0800 IP type, the subsequent hardware-address length and protocol-address length correspond to 6 and 4 respectively;

In the OP field, 1 indicates an ARP request and 2 indicates an ARP reply.

For example: |ff ff ff ff ff ff|00 0a 35 01 fe c0|08 06|00 01|08 00|06|04|00 01|00 0a 35 01 fe c0|c0 a8 00 02| ff ff ff ff ff ff|c0 a8 00 03|

Indicates an ARP request sent to the address 192.168.0.3.

|00 0a 35 01 fe c0 | 60 ab c1 a2 d5 15 |08 06|00 01|08 00|06|04|00 02| 60 ab c1 a2 d5 15|c0 a8 00 03|00 0a 35 01 fe c0|c0 a8 00 02|

Indicates an ARP reply sent to the address 192.168.0.2.

7.2.2.3 IP Packet Format

Because the UDP protocol packet is just one kind of IP packet, let's introduce the IP packet data format. The following figure shows the IP packet header format. The first 20 bytes of the header are fixed; the rest is variable.

rootfile1

Version: 4 bits, indicates the IP protocol version; the current IP protocol version number is 4 (i.e. IPv4);

Header length: 4 bits; the maximum representable value is 15 units (one unit is 4 bytes), so the maximum IP header length is 60 bytes;

Differentiated services: 8 bits, used to obtain better service. In the old standard this was called the type of service, but in practice it was never used. In 1998 this field was renamed Differentiated Services. It only takes effect when Differentiated Services (DiffServ) is in use; in general this field is not used;

Total length: 16 bits, indicates the length of the header plus data in bytes, so the maximum datagram length is 65535 bytes. The total length must not exceed the maximum transmission unit (MTU);

Identification: 16 bits; it is a counter used to generate datagram identification;

Flag: 3 bits; currently only the first two bits are meaningful.

The lowest bit of the flag field is MF (More Fragment): MF=1 means there are "more fragments" afterward; MF=0 means the last fragment.

The middle bit of the flag field is DF (Don't Fragment): fragmentation is allowed only when DF=0.

Fragment offset: 12 bits, indicates the relative position of a fragment in the original group after a longer group has been fragmented. The fragment offset is in units of 8 bytes;

Time to live: 8 bits, denoted TTL (Time To Live), the maximum number of routers a datagram can pass through in the network. The TTL field is an 8-bit field initially set by the sender. The recommended initial value is specified by the Assigned Numbers RFC; the current value is 64. The TTL is often set to the maximum value 255 when sending ICMP echo replies;

Protocol: 8 bits, indicates which protocol the data carried by this datagram uses, so that the destination host's IP layer knows which process to deliver the data portion to. 1 indicates the ICMP protocol, 2 indicates the IGMP protocol, 6 indicates the TCP protocol, and 17 indicates the UDP protocol;

Header checksum: 16 bits, only checks the datagram header, not the data portion. It uses binary one's-complement addition — i.e. the 16-bit data are added, then the carry is added to the low 16 bits, repeating until the carry is 0, and finally the 16 bits are inverted;

Source address and destination address: each 4 bytes, recording the source and destination addresses respectively.

7.2.2.4 UDP Protocol

UDP is the abbreviation of User Datagram Protocol. UDP provides only a basic, low-latency communication called a datagram. A datagram is a self-addressing packet that travels from the sender to the receiver. The UDP protocol is often used in scenarios with high data-transmission-speed requirements, such as image transmission and network-monitoring data exchange.

UDP header format:

The UDP header consists of 4 fields, each occupying 2 bytes, as follows:

rootfile1

① UDP source port number

② Destination port number

③ Datagram length

④ Checksum

The UDP protocol uses port numbers to reserve separate data-transmission channels for different applications. The sending side sends the UDP datagram out through the source port, while the receiving side receives data through the destination port.

The datagram length is the total number of bytes including the header and data portion. Because the header length is fixed, this field is mainly used to compute the variable-length data portion (also called the data payload). The maximum datagram length varies depending on the operating environment. Theoretically, the maximum datagram length including the header is 65535 bytes. However, some practical applications often limit the datagram size, sometimes down to 8192 bytes.

The UDP protocol uses the checksum in the header to ensure data safety. The checksum is first computed at the sender by a special algorithm, and is recomputed at the receiver after delivery. If a datagram is tampered with by a third party during transmission or damaged due to line noise, etc., the sender's and receiver's checksum computations will not match, so the UDP protocol can detect errors. Although UDP provides error detection, when an error is detected there is no error correction — it simply discards the damaged message segment or provides warning information to the application.

7.2.2.5 Ping Function

The UDP protocol uses the checksum in the header to ensure data safety. The checksum is first computed at the sender by a special algorithm, and is recomputed at the receiver after delivery. If a datagram is tampered with by a third party during transmission or damaged due to line noise, etc., the sender's and receiver's checksum computations will not match, so the UDP protocol can detect errors. Although UDP provides error detection, when an error is detected there is no error correction — it simply discards the damaged message segment or provides warning information to the application.

rootfile1rootfile1

7.3 SMI (MDC/MDIO) Bus Interface

The Serial Management Interface, also called the MII Management Interface, consists of two signal lines: MDC and MDIO. MDIO is a management interface for the PHY, used to read/write the PHY's registers to control the PHY's behavior or obtain the PHY's status. MDC provides the clock for MDIO and is provided by the MAC end — in this experiment, the FPGA end. In the RTL8211EG documentation, you can see the MDC period is at least 400 ns, i.e. a maximum clock of 2.5 MHz.

rootfile1

7.3.1 SMI Frame Format

The following shows the SMI read/write frame format:

rootfile1
NameDescription
PreambleSent by the MAC as 32 consecutive logical "1"s, synchronized to the MDC signal; used for synchronization between MAC and PHY;
STFrame start bit, fixed at 01
OPOpcode: 10 means read, 01 means write
PHYADPHY address, 5 bits
REGADRegister address, 5 bits
TATurn Around, MDIO direction turnaround. In the write state, no direction turnaround is needed and the value is 10. In the read state, the MAC output is high-impedance and in the second cycle the PHY pulls MDIO low
DATA16-bit data
IDLEIdle state; MDIO is high-impedance in this state, pulled high by an external pull-up resistor

7.3.2 Read Timing

rootfile1

You can see that in the Turn Around state, MDIO is high-impedance in the first cycle and pulled low by the PHY in the second cycle.

7.3.3 Write Timing

rootfile1

To ensure data is correctly sampled, data is prepared before the MDC rising edge; in this experiment, data is sent on the falling edge and received on the rising edge.

7.4 Experiment Design

This experiment designs a Verilog program using Gigabit Ethernet RGMII communication as an example. It first sends preset UDP data to the network, sending once per second. The program is split into two parts — transmit and receive — and implements ARP and UDP functions.

7.4.1 Transmit Part

7.4.1.1 MAC Layer Transmit

In the transmit part, mac_tx.v is the MAC-layer transmit module. First, in the SEND_START state, it waits for the mac_tx_ready signal; if valid, it means the IP or ARP data is ready and transmission can begin. Then it enters the send-preamble state; when finished it sends mac_data_req to request IP or ARP data, then enters the send-data state, and finally enters the send-CRC state. During data transmission, CRC computation is performed simultaneously. After the preamble is completed, the upper-layer protocol data is sent out; at this time these upper-layer data are also fed into the CRC32 module for sequence generation. The upper-layer protocol gives a data-output-complete flag signal — at this point mac_tx knows data transmission is complete and needs to end the CRC32 sequence generation. Now it extracts the FCS and sends it out after the data, connecting: preamble --- data (MAC frame) ---- FCS. Then it jumps to the end state, and returns to the IDLE state to wait for the next send request.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
mac_frame_datainput8Data from IP or ARP
mac_tx_reqinput1MAC transmit request
mac_tx_readyinput1IP or ARP data ready
mac_tx_endinput1IP or ARP data transfer complete
mac_tx_dataoutput8Send data to PHY
mac_send_endoutput1MAC data send end
mac_data_validoutput1MAC data-valid signal, i.e. gmii_tx_en
mac_data_reqoutput1MAC layer requests data from IP or ARP
mac_tx_ackoutput1MAC layer transmit ack for UPPER request
7.4.1.2 MAC Transmit Mode

In the project, mac_tx_mode.v selects the transmit mode — selecting the corresponding signals and data according to whether the mode is IP or ARP.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
mac_send_endinput1MAC transmit end
arp_tx_reqinput1ARP transmit request
arp_tx_readyinput1ARP data ready
arp_tx_datainput8ARP data
arp_tx_endinput1ARP data sending to MAC layer ended
arp_tx_ackinput1ARP transmit response signal
ip_tx_reqinput1IP transmit request
ip_tx_readyinput1IP data ready
ip_tx_datainput8IP data
ip_tx_endinput1IP data sending to MAC layer ended
mac_tx_readyoutput1MAC data-ready signal
ip_tx_ackoutput1IP transmit response signal
mac_tx_ackoutput1MAC transmit response signal
mac_tx_reqoutput1MAC transmit request
mac_tx_dataoutput8MAC transmit data
mac_tx_endoutput1MAC data send end
7.4.1.3 ARP Transmit

In the transmit part, arp_tx.v is the ARP transmit module. In the IDLE state it waits for an ARP send request or ARP reply-request signal; then it enters the request or reply wait state, notifies the MAC layer that data is ready, waits for the mac_data_req signal, and then enters the request or reply data-send state. Because data is less than 46 bytes, it must be padded to 46 bytes before sending.

rootfile1
Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
dest_mac_addrinput48Destination MAC address to send
sour_mac_addrinput48Source MAC address to send
sour_ip_addrinput32Source IP address to send
dest_ip_addrinput32Destination IP address to send
mac_data_reqinput1MAC layer data-request signal
arp_request_reqinput1ARP request signal
arp_reply_ackoutput1ARP reply acknowledgment signal
arp_reply_reqinput1ARP reply request signal
arp_rec_sour_ip_addrinput32ARP received source IP address; placed into destination IP address on reply
arp_rec_sour_mac_addrinput48ARP received source MAC address; placed into destination MAC address on reply
mac_send_endinput1MAC transmit end
mac_tx_ackinput1MAC transmit ack
arp_tx_readyoutput1ARP data ready
arp_tx_dataoutput8ARP transmit data
arp_tx_endoutput1ARP data send end
arp_tx_reqoutput1ARP transmit request signal
7.4.1.4 IP Layer Transmit

In the transmit part, ip_tx.v is the IP-layer transmit module. In the IDLE state, if ip_tx_req is valid — i.e. a UDP or ICMP send-request signal — it enters the wait-for-send-data-length state, then enters the generate-checksum state. The checksum adds all IP-header data as 16-bit values; the carry is then added to the low 16 bits, repeated until the carry is 0, and then the low 16 bits are inverted to obtain the checksum result.

After generating the checksum, it waits for the MAC layer's data request, starts sending data, and requests UDP or ICMP data just before finishing sending the IP header. When sending is complete, it returns to the IDLE state.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
dest_mac_addrinput48Destination MAC address to send
sour_mac_addrinput48Source MAC address to send
sour_ip_addrinput32Source IP address to send
dest_ip_addrinput32Destination IP address to send
ttlinput8Time to live
ip_send_typeinput8Upper-layer protocol number, e.g. UDP, ICMPP
upper_layer_dataoutput8Data from UDP or ICMP
upper_data_reqinput1Request data from upper layer
mac_tx_ackinput1MAC transmit ack
mac_send_endinput1MAC transmit-end signal
mac_data_reqinput1MAC layer data-request signal
upper_tx_readyinput1Upper-layer UDP or ICMP data ready
ip_tx_reqinput1Transmit request, from the upper layer
ip_send_data_lengthinput16Total length of transmitted data
ip_tx_ackoutputGenerate IP transmit ack
ip_tx_readyoutput1IP data ready
ip_tx_dataoutput8IP data
ip_tx_endoutput1IP data sending to MAC layer ended
7.4.1.5 IP Transmit Mode

In the project, ip_tx_mode.v selects the transmit mode — selecting the corresponding signals and data according to whether the mode is UDP or ICMP.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
mac_send_endinputMAC data send end
udp_tx_reqinput1UDP transmit request
udp_tx_readyinput1UDP data ready
udp_tx_datainput8UDP transmit data
udp_send_data_lengthinput16UDP transmit data length
udp_tx_ackoutput1Output UDP transmit ack
icmp_tx_reqinput1ICMP transmit request
icmp_tx_readyinput1ICMP data ready
icmp_tx_datainput8ICMP transmit data
icmp_send_data_lengthinput16ICMP transmit data length
icmp_tx_ackoutput1ICMP transmit ack
ip_tx_ackinput1IP transmit ack
ip_tx_reqinput1IP transmit request
ip_tx_readyoutput1IP data ready
ip_tx_dataoutput8IP data
ip_send_typeoutput8Upper-layer protocol number, e.g. UDP, ICMP
ip_send_data_lengthoutput16Total length of transmitted data
7.4.1.6 UDP Transmit

In the transmit part, udp_tx.v is the UDP transmit module.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
app_data_in_validinput1Data-output valid signal received from external
app_data_ininput8Data received from external
app_data_lengthinput16Length of the current packet received from external (excluding udp, ip, mac headers)
udp_dest_portinput16Source port number of the packet received from external
app_data_requestinput1User-interface data-send request
udp_send_readyoutput1UDP data send ready
udp_send_ackoutput1UDP data send ack
ip_send_readyinput1IP data send ready
ip_send_ackinput1IP data send ack
udp_send_requestoutput1User-interface data-send request
udp_data_out_validoutput1Transmitted data-output valid signal
udp_data_outoutput8Transmitted data output
udp_packet_lengthoutput16Length of the current packet (excluding udp, ip, mac headers)

7.4.2 Receive Part

7.4.2.1 MAC Layer Receive

In the receive part, mac_rx.v is the MAC-layer receive file. First, in the IDLE state, when rx_en goes high it enters the REC_PREAMBLE preamble state to receive the preamble. Then it enters the receive-MAC-header state — i.e. destination MAC address, source MAC address, and type — caches them, and in this state judges whether the preamble is correct; if wrong it enters the REC_ERROR error state. In the REC_IDENTIFY state it judges whether the type is IP (8'h0800) or ARP (8'h0806). It then enters the receive-data state, passes the data to the IP or ARP module, waits for IP or ARP data reception to complete, and then receives the CRC data. During data reception it also performs CRC processing on the received data and compares the result with the received CRC data to judge whether the data was received correctly — if correct it ends, otherwise it enters the ERROR state.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
rx_eninput1Start-receive enable
mac_rx_dataininput8Received data
checksum_errinput1IP-layer checksum error signal
ip_rx_endinput1IP receive end
arp_rx_endinput1ARP receive end
ip_rx_reqoutput1IP receive request
arp_rx_reqinput1Request ARP receive
mac_rx_dataoutoutput8MAC layer receive data output to IP or ARP
mac_rec_erroroutput1MAC layer receive error
mac_rx_dest_mac_addroutput48MAC received destination IP address
mac_rx_sour_mac_addroutput48MAC received source IP address
7.4.2.2 ARP Receive

In the project, arp_rx.v is the ARP receive module, implementing ARP data reception. In the IDLE state, upon receiving the arp_rx_req signal from the MAC layer, it enters the ARP receive state. In this state it extracts the destination MAC address, source MAC address, destination IP address, and source IP address, and judges whether the OP code is a request or a reply. If it is a request, it judges whether the received destination IP address is the local address; if so, it sends the reply-request signal arp_reply_req; if not, it ignores it. If OP is a reply, it judges whether the received destination IP address and destination MAC address match the local ones; if so, it pulls the arp_found signal high to indicate that the other party's address has been received. It then stores the other party's MAC address and IP address into the ARP cache.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
local_ip_addrinput32Local IP address
local_mac_addrinput48Local MAC address
arp_rx_datainput8ARP receive data
arp_rx_reqinput1ARP receive request
arp_rx_endoutput1ARP receive complete
arp_reply_ackinput1ARP reply acknowledgment
arp_reply_reqoutput1ARP reply request
arp_rec_sour_ip_addrinput32ARP received source IP address
arp_rec_sour_mac_addrinput48ARP received source MAC address
arp_foundoutput1ARP request/reply received correctly
7.4.2.3 IP Layer Receive Module

In the project, ip_rx is the IP-layer receive module, implementing IP-layer data reception, information extraction, and checksum verification. First, in the IDLE state, it checks the ip_rx_req signal from the MAC layer and enters the receive-IP-header state. In REC_HEADER0 it first extracts the header length and total IP length; in REC_HEADER1 it extracts the destination IP address, source IP address, and protocol type, and based on the protocol type sends udp_rx_req or icmp_rx_req. While receiving the header it also performs checksum verification: it adds all the received header data into a 32-bit register, then adds the high 16 bits to the low 16 bits repeatedly until the high 16 bits are 0, then inverts the low 16 bits and judges whether it is 0; if 0, the check is correct, otherwise wrong — it enters the IDLE state, discards this frame, and waits for the next reception.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
local_ip_addrinput32Local IP address
local_mac_addrinput48Local MAC address
ip_rx_datainput8Data received from the MAC layer
ip_rx_reqinput1IP receive request signal sent by MAC layer
mac_rx_dest_mac_addrinput48MAC layer received destination MAC address
udp_rx_reqoutput1UDP receive request signal
icmp_rx_reqoutput1ICMP receive request signal
ip_addr_check_erroroutput1Address-check error signal
upper_layer_data_lengthoutput16Upper-layer protocol data length
ip_total_data_lengthoutput16Total data length
net_protocoloutput8Network protocol number
ip_rec_source_addroutput32IP-layer received source IP address
ip_rec_dest_addroutput32IP-layer received destination IP address
ip_rx_endoutput1IP-layer receive end
ip_checksum_erroroutput1IP-layer checksum-check error signal
7.4.2.4 UDP Receive

In the project, udp_rx.v is the UDP receive module. This module first receives the UDP header, then the data portion, and performs UDP checksum verification during reception. If the UDP data is an odd number of bytes, when computing the checksum it appends 8'h00 after the last byte and computes the checksum. The verification method is the same as the IP checksum. If verification passes, the udp_rec_data_valid signal is pulled high to indicate that the received UDP data is valid; otherwise it is invalid, and it waits for the next reception.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
udp_rx_datainput8UDP receive data
udp_rx_reqinput1UDP receive request
ip_checksum_errorinput1IP-layer checksum-check error signal
ip_addr_check_errorinput1Address-check error signal
udp_rec_rdataoutput8UDP receive read data
udp_rec_data_lengthoutput16UDP receive data length
udp_rec_data_validoutput1UDP receive data valid

7.4.3 Other Parts

7.4.3.1 ICMP Reply

In the project, icmp_reply.v implements the ping function. It first receives the ICMP data sent from another device, judges whether the type is an Echo Request; if so, stores the data into RAM, computes the checksum, and judges whether the checksum is correct; if correct, it enters the send state and sends the data out.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
mac_send_endinput1MAC transmit-end signal
ip_tx_ackinput1IP transmit ack
icmp_rx_datainput8ICMP receive data
icmp_rx_reqinput1ICMP receive request
icmp_rev_errorinput1Receive error signal
upper_layer_data_lengthinput16Upper-layer protocol length
icmp_data_reqinput1Request ICMP data
icmp_tx_readyoutput1ICMP transmit ready
icmp_tx_dataoutput8ICMP transmit data
icmp_tx_endoutput1ICMP transmit end
icmp_tx_reqoutput1ICMP transmit request
7.4.3.2 ARP Cache

In the project, arp_cache.v is the ARP cache module. It caches the IP and MAC addresses of other devices that have been received. Before sending data, it queries whether the destination address exists; if not, it sends an ARP request to the destination address and waits for a reply. In the design file, only one cache slot is implemented; it can be extended if needed.

Signal nameDirectionWidthDescription
clkinput1System clock
rstninput1Active-low reset
arp_foundinput1ARP reply received correctly
arp_rec_source_ip_addrinput32ARP received source IP address
arp_rec_source_mac_addrinput48ARP received source MAC address
dest_ip_addrinput32Destination IP address
dest_mac_addroutput48Destination MAC address
mac_not_existoutput1No MAC address exists for the destination address
7.4.3.3 CRC Verification Module (crc.v)

CRC32 verification is computed starting from the destination MAC address up to the last data of a packet. Some websites can auto-generate Verilog files for the CRC algorithm: https://bues.ch/cms/hacking/crcgen.html

rootfile1

7.5 Experimental Phenomena

Plug an optical-to-electrical conversion module into the SFP port, then connect it to the PC's network port with a network cable;

Set the receiver (PC) IP address to 192.168.0.3 and the development board's IP address to 192.168.0.2, as shown below:

rootfile1

Through the command prompt, enter arp -a; you can find IP: 192.168.0.2, MAC: a0_b1_c2_d3_e1_e1;

rootfile1

Verify via Wireshark packet capture that the data link is properly connected and data transmission is normal. Open Wireshark on the PC from the materials package; after re-flashing and capturing packets, you can see the interaction process shown below.

After the connection is successfully established, the data packet "www.meyesemi.com" is sent continuously, as shown below:

rootfile1rootfile1

Ping function test — as shown above, ping basically does not drop packets.

8 PCIe-based DMA/PIO Control Experiment

8.1 Function and Performance

The PCIe DMA implements the business function of memory read/write requests and converts the AXI4-Stream interface into a RAM read/write interface for user convenience. On the CPU side, users can read/write the RAM inside the FPGA via both PIO and DMA;

The DMA application scenario is shown in Figure 1;

FPGA_PCIE
Figure 1 PCIe DMA Application Scenario

The PCIe DMA routine supports the following main functions;

  • Supports Gen1x1, Gen1x2, Gen1x4, Gen2x1, Gen2x2, Gen2x4;
  • Supports memory read operations (Mrd);
  • Supports memory write operations (Mwr);
  • Supports Max Payload Size of 128 Byte, 256 Byte, 512 Byte, 1024 Byte data transfer;
  • Converts the AXI4-Stream interface into a RAM read/write interface.

8.2 Principle and Implementation

8.2.1 RTL Implementation of the DMA

FPGA_PCIE
Figure 2 PCIe DMA Functional Block Diagram

The PCIe DMA mainly consists of uart2apb and pcie_dma. The main function of uart2apb is: to bring in external control to configure the working mode of PCIe; by default it is in EP mode controlled by the RC for DMA and PIO. The main function of the pcie_dma module is: to receive the TLP packet data output by the PCIe hard IP, and to assemble the data to be sent to the RC into TLP packets and send them to the PCIe hard IP; internally, the data written to the FPGA via PIO and DMA is stored in different BRAMs.

8.2.2 PCIe DMA Module

FPGA_PCIE
Figure 3 PCIe_DMA Module Internal Block Diagram

The DMA operation flow is shown below:

FPGA_PCIEFPGA_PCIE
Figure 4 DMA Operation Flow

The AXI4-Stream Master interface timing for PCIe data interaction is shown below; the first cycle of axis_master_tdata is the TLP Header, and axis_master_tkeep is all 1s in the TLP Header field;

FPGA_PCIE
Figure 5 4DW Posted Operation Timing
FPGA_PCIE
Figure 6 3DW Posted Operation Timing
FPGA_PCIEFPGA_PCIE
Figure 7 4DW/3DW Non-Posted Operation Timing

The AXI4-Stream slave interface timing for PCIe data interaction is shown above; once the axis_slave bus starts sending data, axis_slave0/1/2_tvalid must stay high until the last data transfer is complete (axis_slave0/1/2_tlast high pulse) before it can be pulled low.

FPGA_PCIE
Figure 8 4DW Posted Operation Timing
FPGA_PCIE
Figure 9 3DW Posted Operation Timing
FPGA_PCIEFPGA_PCIE
Figure 10 4DW/3DW Non-Posted Operation Timing
8.2.2.1 dma_rx_top module

This module's main function is to parse the TLP packets from PCIe and save the data (PIO/DMA) written by the RC to the EP into BRAM for later use;

FPGA_PCIE
Figure 11 DMA_RX_TOP Module Internal Block Diagram
  • dma_tlp_rcv module

This module's main function is to receive and parse the TLP protocol packets from the AXIS_Master interface, outputting the parsed payload data and the channel-identification information to the subsequent mwr_wr_ctrl, cpld_wr_ctrl, and dma_ctrl modules; it completes the first functional stage of PCIe interaction;

  • mwr_wr_ctrl module

This module's main function is to pre-process the parsed mwr-type (mwr, IOwr) packet data, output the signals corresponding to the BRAM write interface, and then write them into Bar0_BRAM; for that RC system, this module is the PIO write-conversion module;

  • cpld_wr_ctrl module

After the RC receives the Mrd packet sent by the EP, the DMA bus on the RC reads data from storage, assembles it into a Cpld packet, and sends it down to the EP. This module's main function is to pre-process the parsed Cpld packet data, output the signals corresponding to the BRAM write interface, and write them into Bar1_BRAM; for that RC system, this module is the DMA_RD write-conversion module;

  • BRAM module

Both BRAM modules call the FPGA's Block RAM. During testing, the RC must first perform a write operation to the RAM; only after that can the read-up data correspond one-to-one;

8.2.2.2 dma_tx_top module

This module's function is to send data from the FPGA to the PCIe interface; there are 3 AXIS interfaces in total. In this test program, the 3 axes each send different types of packets; AXIS_slave0 connects the Cpld packets fed back by the FPGA, acknowledging the Mrd/IOrd packets issued by the RC; AXIS_slave1 connects the Mrd packets actively initiated by the FPGA, where the FPGA fetches RC DDR data; AXIS_slave2 connects the Mwr packets actively initiated by the FPGA, where the FPGA writes data to the RC DDR;

FPGA_PCIE
Figure 12 DMA_TX_TOP Module Internal Block Diagram
  • cpld_tx_ctrl module

Triggered by the Cpld-related control signals parsed by the RX_TOP module, this module starts assembling Cpld packets, sends a fetch request to cpld_tx_rd_ctrl, and after receiving the data assembles a Cpld TLP packet and outputs it to the PCIe hard core;

  • cpld_tx_rd_ctrl module

After receiving the fetch request initiated by cpld_tx_ctrl, this module converts it into BRAM read-interface signals, sends a read request to the dma_rx_top module, and after receiving the data transfers it to cpld_tx_ctrl;

  • mwr_tx_ctrl module

After receiving the DMA_CTRL module's mwr request, data length, and the RC's corresponding address, this module starts preparing to send an Mwr packet, sends a fetch request to mwr_tx_rd_ctrl, and after receiving the data assembles an mwr TLP packet and outputs it to the PCIe hard core;

  • mwr_tx_rd_ctrl module

After receiving the fetch request initiated by mwr_tx_ctrl, this module converts it into BRAM read-interface signals, sends a read request to the dma_rx_top module, and after receiving the data transfers it to mwr_tx_ctrl;

  • mrd_tx_ctrl module

After receiving the DMA_CTRL module's mrd request, data length, and the RC's corresponding address, this module starts preparing to send an Mrd packet, assembles an mwr TLP packet, and outputs it to the PCIe hard core;

8.2.2.3 dma_ctrl module

The RC issues the relevant control signals through the Bar1 register space to control the FPGA for the corresponding DMA channel control; the corresponding control registers and parsing are as follows;

Register addressFunction nameDescriptionParsing
Bar1_base_addr + 0x100Dma_cmd_regDMA command register[9:0] : DMA transfer length
[16] : DMA address length (0: 32bit, 1: 64bit)
[24] : DMA packet type (0: Mrd, 1: Mwr)
Bar1_base_addr + 0x110Dma_cmd_l_addrDMA transfer address (low)[1:0] : reserved
[31:0] : dma_addr[31:2]
Bar1_base_addr + 0x120Dma_cmd_h_addrDMA transfer address (high)High 32 bits of the MEM access address

8.3 Project Introduction

  • Simulation reference design The reference-design simulation block diagram is shown in the figure.
FPGA_PCIE
Figure 13 Simulation Reference Design Functional Block Diagram

Simulation environment: third-party simulation software. Run script: sim.bat Simulation filelist: pango_pcie_top_filelist.f. The simulation waveform is shown below.

FPGA_PCIE
Figure 14 Simulation Waveform Diagram
  • On-board testing

Before the docking test, confirm the following operations are correct:

  1. Ensure the driver is installed successfully.
  2. Confirm the FPGA firmware has been flashed to Flash;
  3. Ensure the design-project fdc constraints are correct. The reference-design fdc constraint file already provides Gen1x1 mode and Gen2x2 mode.
Edit this page on GitHub
Prev
ARM and FPGA Communication