当前位置: 首页 > news >正文

基于FPGA实现LED的闪烁——HLS

基于FPGA实现LED的闪烁——HLS

引言:

​ 随着电子技术的飞速发展,硬件设计和开发的速度与效率成为了衡量一个项目成功与否的关键因素。在传统的硬件开发流程中,工程师通常需要使用VHDL或Verilog等硬件描述语言来编写底层的硬件逻辑,这不仅耗时而且对于复杂算法的实现存在一定的局限性。为了解决这一问题,高层次综合(High-Level Synthesis, HLS)技术应运而生,它允许开发者使用更高级的编程语言,如C/C++,来设计硬件,从而大幅提高开发效率和灵活性。

·

本实验旨在通过一个具体的实例——LED灯的闪烁控制,来展示HLS技术的应用。我们将利用Xilinx的Vivado HLS工具,将C/C++代码转换为硬件电路,实现LED灯的闪烁效果。通过本实验,参与者不仅能够了解HLS的基本概念和关键技术,还能够掌握从环境配置到实际硬件实现的完整流程。

·

希望你在本次学习过后,能够有一定的收获!!!

推荐歌曲—雨爱-杨丞琳

​ 冲啊!!!! ٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶

文章目录

  • 基于FPGA实现LED的闪烁——HLS
    • 一、任务介绍
    • 二、HLS的相关介绍
      • HLS的概念拓展
      • HLS的优势
      • HLS与VHDL/Verilog的比较
    • 三、HLS相关环境配置
      • 1.vivado 安装
      • 2.创建HLS工程
      • 3.添加相关文件
      • 4.C仿真与C综合
      • 5.创建Vivado工程
      • 6.导入HLS生成的IP核
      • 7.添加实验代码
      • 8.约束文件编写
      • 9.编译生成获取结果
    • 四、效果展示
    • 五、总结

一、任务介绍

  1. 了解HLS的相关内容
  2. 实现HLS的实验环境配置
  3. 使用HLS点亮一个小灯

二、HLS的相关介绍

HLS的概念拓展

高层次综合(High-Level Synthesis, HLS) 是一种先进的硬件设计方法,它允许开发者使用高级编程语言(如C、C++或SystemC)来描述硬件功能,而不是传统的硬件描述语言(HDL)如VHDL或Verilog。HLS工具能够自动将这些高级语言代码转换为寄存器传输级(Register Transfer Level, RTL)电路设计,这大大简化了硬件设计过程,并缩短了开发周期。

HLS的优势

  1. 提高生产力:开发者可以使用熟悉的高级语言进行编程,而不需要精通硬件描述语言。
  2. 算法优化:高级语言提供了更直观的方式来表达复杂的算法,HLS工具可以优化这些算法实现,以满足硬件性能要求。
  3. 快速原型开发:HLS允许快速迭代和原型设计,加速了从概念到实现的过程。
  4. 代码重用:现有的软件代码可以被重用,减少了从头开始编写代码的需求。

HLS与VHDL/Verilog的比较

  • VHDL/Verilog:这些是传统的硬件描述语言,适用于精确控制硬件行为和结构的场景。它们通常用于复杂的硬件设计,需要开发者有较强的硬件设计背景。
  • HLS:提供了一种更高层次的设计抽象,允许开发者专注于算法和功能,而不是硬件的具体实现细节。这使得HLS特别适合于算法密集型和数据处理密集型的应用。

HLS的关键技术

  1. 代码分析与优化:HLS工具需要能够理解和分析高级语言代码,并进行优化以满足性能、面积和功耗等硬件设计要求。
  2. 资源分配:自动决定使用哪些硬件资源(如查找表、寄存器、乘法器等)来实现代码。
  3. 时序分析:确保生成的硬件设计满足时序要求,能够在给定的时钟频率下稳定工作。
  4. 并行处理:利用并行处理技术来提高设计的性能。

技术局限性

  1. 复杂性:对于极其复杂的人工智能算法,HLS可能需要高级的优化技术来实现高效的硬件加速。
  2. 编程能力要求:虽然HLS简化了硬件设计过程,但仍然需要开发者具备强大的C/C++编程能力,以及对并行计算和硬件架构的理解。
  3. 工具限制:不同的HLS工具可能有不同的优化能力和支持的语言特性,这可能限制了设计的灵活性。

三、HLS相关环境配置

1.vivado 安装

1.下载Vivado(如Vivado2019.1)
这个可以去官网下载,或者找实验室同学要一个安装文件,大概四五十GB,准备好安装文件后,直接点解xsetup程序进入安装

在这里插入图片描述

(整个安装文件夹44G)

2.安装过程
会弹出:

在这里插入图片描述点击Next,

在这里插入图片描述

点击Continue

在这里插入图片描述

三个I Agree全部勾选,点击Next,

在这里插入图片描述

选中第二个,Next,会出现选择需要的工具,设备等(本次重装的原因就是因为原版本安装的时候没有选择需要的ZYNQ的设备型号,所以建议大家磁盘有空间的把Devices全部勾选)

在这里插入图片描述

这里我将默认安装在C盘,但完全可以定义自己的路径,没有影响

在这里插入图片描述

接着Next,这次将进入长期的安装过程(约2h),如下:

在这里插入图片描述

漫长的等待后,出现这个界面,此时离安装成功只剩一步———破解了:

在这里插入图片描述

点击Get Licenses,选择Load License,在右方选择 Copy Licenses

在这里插入图片描述

这时候找到我们准备好的License文件就好了,没有的可以在这下载:https://download.csdn.net/download/weixin_49457347/85014356
下载解压后是一个这个文件(名称不重要,源文件名是vivado_lic2037):

在这里插入图片描述

选中该文件后,弹出安装成功!

在这里插入图片描述

2.创建HLS工程

创建一个HLS工程
①打开Vivado HLS,点击Create New Project
在这里插入图片描述
②输入相关工程信息
在这里插入图片描述
③选择顶层函数,此处暂不管
在这里插入图片描述

④选择添加C仿真文件,此处可以暂时不管
在这里插入图片描述
⑤选择器件
在这里插入图片描述

3.添加相关文件

①源文件添加
点击Source,右键后,选择New File,创建文件

led.h

#ifndef _SHIFT_LED_H_
#define _SHIFT_LED_H_#include "ap_int.h"
#define CNT_MAX 100000000
//#define CNT_MAX 100,100M时钟频率下计数一秒钟所需要的计数次数
#define FLASH_FLAG CNT_MAX-2
// typedef int led_t;
// typedef int cnt_t;
typedef ap_int<1> led_t;
typedef ap_int<32> cnt_t;
void flash_led(led_t *led_o , led_t led_i);#endif

led.cpp

#include "led.h"void flash_led(led_t *led_o , led_t led_i){
#pragma HLS INTERFACE ap_vld port=led_i
#pragma HLS INTERFACE ap_ovld port=led_ocnt_t i;for(i=0;i<CNT_MAX;i++){if(i==FLASH_FLAG){*led_o = ~led_i;}}
}

②仿真测试文件添加
右键Test Bench,选择New File

test_led.cpp

#include "led.h"
#include <stdio.h>
int main(){led_t led_i=0x01;led_t led_o;const int SHIFT_TIME = 4;int i;for(i=0;i<SHIFT_TIME;i++){flash_led(&led_o , led_i);led_i = led_o;printf("shift_out is %d \n",(int)(led_o&0x01));}
}

4.C仿真与C综合

①点击project->project settings->synthesis->browser->选择顶层函数

在这里插入图片描述

②点击project->Run C Simulation(输出01交替,表示C仿真结果正确)

在这里插入图片描述

③点击Solution->Run C Synthesis->Active Solution

在这里插入图片描述

5.创建Vivado工程

①打开Vivado,选择Greate Project
在这里插入图片描述
②点击Next,进行项目信息填写
在这里插入图片描述
③勾选RTL Project
在这里插入图片描述
④Source和约束文件添加,暂时不管,直接Next
⑤选择器件
img
⑥点击Finish
在这里插入图片描述

6.导入HLS生成的IP核

①生成IP核
选择Solution->Export RTL
在这里插入图片描述
②导入
点击setting
在这里插入图片描述
选择IP->Repository,并且点击加号,选择solution,将会自动识别到IP,识别到后,点击Apply->OK
在这里插入图片描述
检验是否导入成功
在这里插入图片描述
生成IP
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.添加实验代码

①选择Add Sources
在这里插入图片描述
②文件名称填写
在这里插入图片描述
③代码内容

`timescale 1ns / 1ps
module flash_led(
input wire clk ,
input wire rst_n ,
output wire led_o
);wire rst ;//同步复位
wire ap_ready ;//当前可以接收下一次数据
reg ap_start ;//IP 开始工作
reg led_i_vld ;//输入数据有效
wire led_o_vld ;
reg led_i ;//输入的 led 信号
wire led_o_r ;
wire ap_done ;
wire ap_idle ;
reg [1:0] delay_cnt ;
assign rst = ~rst_n ;
assign led_o = led_o_r ;//----------------delay_cnt------------------
always @(posedge clk) begin
if (rst==1'b1) begin
delay_cnt <= 'd0;
end
else if(delay_cnt[1]==1'b0) begin
delay_cnt <= delay_cnt + 1'b1;
end
end//----------------ap_start------------------
always @(posedge clk) begin
if (rst==1'b1) begin
ap_start <= 1'b0;
end
else if(delay_cnt[1]==1'b1)begin
ap_start <= 1'b1;
end
end//----------------led_i_vld------------------
always @(posedge clk) begin
if (rst==1'b1) begin
led_i_vld <= 1'b0;
end
else if(delay_cnt[1]==1'b1)begin
led_i_vld <= 1'b1;
end
end//----------------ap_i------------------
always @(posedge clk) begin
if (rst==1'b1) begin
led_i <= 1'b0;
end
else if(led_o_vld==1'b1)begin
led_i <= led_o_r ;
end
endflash_led_0 inst_flash_led (
.led_o_V_ap_vld(led_o_vld), // output wire led_o_V_ap_vld
.led_i_V_ap_vld(led_i_vld), // input wire led_i_V_ap_vld
.ap_clk(clk), // input wire ap_clk
.ap_rst(rst), // input wire ap_rst
.ap_start(ap_start), // input wire ap_start
.ap_done(ap_done), // output wire ap_done
.ap_idle(ap_idle), // output wire ap_idle
.ap_ready(ap_ready), // output wire ap_ready
.led_o_V(led_o_r), // output wire [0 : 0] led_o_V
.led_i_V(led_i) // input wire [0 : 0] led_i_V
); 
endmodule

8.约束文件编写

①创建约束文件
在这里插入图片描述
②填写相关文件信息
在这里插入图片描述
③代码内容

##############LED define################## 
set_property PACKAGE_PIN P15 [get_ports {led_o}] 
set_property IOSTANDARD LVCMOS33 [get_ports {led_o}]##############Reset define################## 
set_property PACKAGE_PIN P16 [get_ports {rst_n}] 
set_property IOSTANDARD LVCMOS33 [get_ports {rst_n}]##############50M CLK define################## 
create_clock -period 20.000 -name clk -waveform {0.000 10.000} [get_ports clk]
set_property PACKAGE_PIN N18 [get_ports {clk}] 
set_property IOSTANDARD LVCMOS33 [get_ports {clk}]

9.编译生成获取结果

①生成
在这里插入图片描述
②进行下载
点击Open Hardware Manager->Open target->Auto target后,显示如下
在这里插入图片描述
点击Program device,下载程序,直接点击Program
在这里插入图片描述

四、效果展示

在这里插入图片描述

五、总结

HLS的关键技术包括代码分析与优化、资源分配、时序分析和并行处理,这些技术共同确保了生成的硬件设计既高效又可靠。然而,HLS也存在一些局限性,尤其是在处理极其复杂的人工智能算法时,可能需要更高级的优化技术和对硬件架构的深入理解。此外,HLS的成功实施依赖于开发者强大的C/C++编程能力。

·

尽管有其挑战,HLS的优势不容忽视。它使得硬件设计更加快速、灵活,并且能够重用现有的软件代码,加速了从概念到实现的转换过程。随着技术的不断进步,HLS工具的优化能力和支持的语言特性也在不断增强,预示着HLS在未来硬件设计领域的广泛应用和发展潜力。

·

总结来说,高层次综合作为一种创新的设计方法,正在逐渐改变传统的硬件开发流程,为硬件设计领域带来新的机遇和挑战。随着对HLS工具的不断改进和优化,我们有理由相信,HLS将在未来的硬件设计和开发中扮演越来越重要的角色。

最后感谢大佬友情链接:

  • https://blog.csdn.net/qq_43279579/article/details/117084706
  • https://blog.csdn.net/weixin_49457347/article/details/123643998

相关文章:

基于FPGA实现LED的闪烁——HLS

基于FPGA实现LED的闪烁——HLS 引言&#xff1a; ​ 随着电子技术的飞速发展&#xff0c;硬件设计和开发的速度与效率成为了衡量一个项目成功与否的关键因素。在传统的硬件开发流程中&#xff0c;工程师通常需要使用VHDL或Verilog等硬件描述语言来编写底层的硬件逻辑&#xff0…...

平常心看待已发生的事

本篇主要记录自己在阅读此篇文章&#xff08;文章链接&#xff1a; 这才是扼杀员工积极性的真正原因&#xff08;管理者必读&#xff09; &#xff09;和这两天京东的东哥“凡是长期业绩不好&#xff0c;从来不拼搏的人&#xff0c;不是我的兄弟”观点后的一些想法。 自己在微…...

docker image分析利器之dive

dive是一个用于研究 Docker 镜像、层内容以及发现缩小 Docker/OCI 镜像大小方法的开源工具. 开源地址: dive github 为了有个直观的印象, 可以先看一下repo文档中的gif图: 安装 在Ubuntu/Debian系统下&#xff0c;可以使用deb包安装: DIVE_VERSION$(curl -sL "https:/…...

java组合设计模式Composite Pattern

组合设计模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端对单个对象和组合对象的使用具有一致性。 // Component - 图形接口 interface Graphic {void draw()…...

每天五分钟深度学习:如何使用计算图来反向计算参数的导数?

本文重点 在上一个课程中&#xff0c;我们使用一个例子来计算函数J&#xff0c;也就相当于前向传播的过程&#xff0c;本节课程我们将学习如何使用计算图计算函数J的导数。相当于反向传播的过程。 计算J对v的导数&#xff0c;dJ/dv3 计算J对a的导数&#xff0c;dJ/da&#xf…...

常见排序算法之选择排序

目录 一、选择排序 1.1 什么是选择排序&#xff1f; 1.2 思路 1.2.1 思路一 1.2.2 优化思路 1.3 C语言源码 1.3.1 思路一 1.3.2 优化思路 二、堆排序 2.1 调整算法 2.1.2 向上调整算法 2.1.3 向下调整算法 2.2 建堆排序 一、选择排序 1.1 什么是选择排序&#xf…...

Redis 事件机制 - AE 抽象层

Redis 服务器是一个事件驱动程序&#xff0c;它主要处理如下两种事件&#xff1a; 文件事件&#xff1a;利用 I/O 复用机制&#xff0c;监听 Socket 等文件描述符上发生的事件。这类事件主要由客户端&#xff08;或其他Redis 服务器&#xff09;发送网络请求触发。时间事件&am…...

Java | Leetcode Java题解之第118题杨辉三角

题目&#xff1a; 题解&#xff1a; class Solution {public List<List<Integer>> generate(int numRows) {List<List<Integer>> ret new ArrayList<List<Integer>>();for (int i 0; i < numRows; i) {List<Integer> row new…...

DNS 解析过程

文章目录 简介特点查询方式⚡️1. 浏览器缓存2. 系统缓存&#xff08;hosts文件&#xff09;3. 路由器缓存4. 本地域名服务器5. 根域名服务器6. 顶级域名服务器7. 权限域名服务器8. 本地域名服务器缓存并返回9. 操作系统缓存并返回10. 浏览器缓存并访问流程图 总结 简介 DNS&a…...

Golang | Leetcode Golang题解之第118题杨辉三角

题目&#xff1a; 题解&#xff1a; func generate(numRows int) [][]int {ans : make([][]int, numRows)for i : range ans {ans[i] make([]int, i1)ans[i][0] 1ans[i][i] 1for j : 1; j < i; j {ans[i][j] ans[i-1][j] ans[i-1][j-1]}}return ans }...

操作系统实验——线程与进程

如果代码或文章中&#xff0c;有什么错误或疑惑&#xff0c;欢迎交流沟通哦~ ## 进程与线程的区别 1. **各自定义**&#xff1a; 进程是操作系统进行资源分配和调度的一个独立单位&#xff0c;具有一定独立功能的程序关于某个数据集合的依次运行活动。 线程被称为轻量级的进程…...

最强端侧多模态模型MiniCPM-V 2.5,8B 参数,性能超越 GPT-4V 和 Gemini Pro

前言 近年来&#xff0c;人工智能领域掀起了一股大模型热潮&#xff0c;然而大模型的巨大参数量级和高昂的算力需求&#xff0c;限制了其在端侧设备上的应用。为了打破这一局限&#xff0c;面壁智能推出了 MiniCPM 模型家族&#xff0c;致力于打造高性能、低参数量的端侧模型。…...

Spring Boot中如何查询PGSQL分表后的数据

数据库用的pgsql&#xff0c;在表数据超过100w条的时候执行定时任务进行了分表&#xff0c;分表后表名命名为原的表名后面拼接时间&#xff0c;如原表名是card_device_trajectory_info&#xff0c;分表后拼接时间后得到card_device_trajectory_info_20240503&#xff0c;然后分…...

如何学习一个新技能

1. 提出想法 2.找到学习方法&#xff0c;学习路径 3.开始学 参考视频&#xff1a;如何成为超速学习者&#xff1f;快速学会任何新技能&#xff01;_哔哩哔哩_bilibili...

sklearn之logistic回归

文章目录 logistic回归logit logistic回归 logistic regression被称之为logistic回归&#xff0c;对于logistic这个单词来说&#xff0c;他本身的翻译其实不太容易&#xff0c;比较有名的译法是对数几率回归&#xff0c;我也认为这种译法是比较合适的&#xff0c;虽然并非logi…...

Warning: Each child in a list should have a unique “key“ prop.

问题描述&#xff1a; 使用ProTable的时候&#xff0c;报错如下 原因分析&#xff1a; 根据报错内容可以分析出&#xff0c;表格数据缺少唯一key&#xff0c; <PaginationTablecolumns{columns}pagination{{pageSize: 10,current: 1,showSizeChanger: true,showQuickJum…...

JavaSE:StringBuilder和StringBuffer类

1、引言 在上一篇文章中&#xff0c;我们理解了字符串的常用方法&#xff0c;细心的同学大概已经发现&#xff0c;不管是将字符串中的字符转变为大写或小写&#xff0c;或是完成字符串的替换&#xff0c;又或是去除空白字符等等&#xff0c;只要涉及到字符串的修改&#xff0c…...

C语言在线编程网站:探索编程的奥秘与深度

C语言在线编程网站&#xff1a;探索编程的奥秘与深度 在数字世界的浩瀚海洋中&#xff0c;编程已成为连接现实与虚拟的桥梁。而C语言&#xff0c;作为编程领域的经典之作&#xff0c;其深度与广度令无数探索者着迷。为了满足广大编程爱好者的需求&#xff0c;C语言在线编程网站…...

Android 之广播监听网络变化

网络状态变化监听帮助类 NetBroadcastReceiverHelper public class NetBroadcastReceiverHelper {private static final String TAG "NetBroadcastReceiverHelper";private static final String NET_CHANGE_ACTION "android.net.conn.CONNECTIVITY_CHANGE&qu…...

Hono 框架使用经验谈

Hono&#x1f525;是一个小型、快速并开源的 Serverless Web 框架&#xff0c;用 TypeScript 写就。它适用于任何JavaScript运行时&#xff1a;Cloudflare Workers&#xff0c;Fastly ComputeEdge&#xff0c;Deno&#xff0c;Bun&#xff0c;Vercel&#xff0c;Netlify&#x…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...