【【FPGA 之 MicroBlaze 自定义IP核 之 呼吸灯实验】】

FPGA 之 MicroBlaze 自定义IP核 之 呼吸灯实验

通过创建和封装 IP 向导的方式来自定义 IP 核,支持将当前工程、工程中的模块或者指定文件目录封装成 IP 核,当然也可以创建一个带有 AXI4 接口的 IP 核,用于 MicroBlaze 软核处理器和可编程逻辑的数据通信。本次实验选择常用的方式,即创建一个带有 AXI 接口的 IP 核,该 IP 核通过 AXI协议实现 MicroBlaze 软核处理器和可编程逻辑的数据通信。AXI 协议是一种高性能、高带宽、低延迟的片内总线
下面展示 本次实验的系统框图
在这里插入图片描述

Breath LED IP 核为自定义的 IP 核,McroBlaze 处理器通过 AXI 接口为LED IP 模块发送配置数据,从而来控制 LED 灯

实验任务 :
本章的实验任务是通过自定义一个 LED IP 核,来控制 LED 呈现呼吸灯的效果,并且可以通过 AXI 接口来控制呼吸灯的开关和呼吸的频率。

我们去创建自定义IP核
创建之后 会帮助我们创建一个AXI的外壳
之前我也做过类似的设计 AXI 设计 但是并没有设计的很好 这次我们细致的分析一下 该有的做法
在这里插入图片描述

我们来看
在这里插入图片描述

一共分为了2组
首先上面那组是 我们自定义的参数
下面一组是 系统定义的AXI接口的参数 系统也提示我们无法修改

接下来我们看下一部分用户自定义的
在这里插入图片描述

我们 添加了上面两个 东西 一个参数 一个输出
因为这里是 主函数 main 所以 在下面例化的添加 对参数和端口的例化

接下来我们来看 主函数下的另一个函数
这个函数的出现是为了 补充 不让main看上去很臃肿
在这里插入图片描述

这个函数的部分内容是可以修改的
我们往其中写入部分函数 使得其能够 加载入LED 呼吸灯的功能
函数同样提醒了 可以添加参数进行修改
在这里插入图片描述

为什么要修改这里的东西 主要是 我们想通过这里 AXI 的 寄存器 的 结果 来调配呼吸灯的值
现在告诉你 slv_reg0 至 slv_reg3 是寄存器地址0 至寄存器地址 3 对应的数据,通过例化呼吸灯模块,将寄存器地址对应的数据和呼吸灯模块的控制端口相连接,即可实现对呼吸灯的控制。

在这里插入图片描述

观察 我们可以知道
在这里插入图片描述

我们通过寄存器地址 0 对应的数据来控制呼吸灯的使能(sw_ctrl)
寄存器地址 1 对应数据的最高位控制呼吸灯频率的设置有效信号(set_en)
寄存器地址 1 对应数据的低 10 位控制呼吸灯频率的步长(set_freq_step)

我们会很容易的发现这个很奇怪是不是 因为我们连最重要的 breath 文件都没添加
下面补上呼吸灯的verilog 代码

module breath_led( 
 input sys_clk , //系统时钟 50MHz 
 input sys_rst_n , //系统复位,低电平有效
 input sw_ctrl , //呼吸灯开关控制信号 1:亮 0:灭
 input set_en , //设置呼吸灯频率设置使能信号
 input [9:0] set_freq_step , //设置呼吸灯频率变化步长
 output led //LED 灯
 ); 

 //parameter define 
 parameter START_FREQ_STEP = 10'd1 ; //设置频率步长初始值
 parameter CNT_2US_MAX = 7'd100 ;
 parameter CNT_2MS_MAX = 10'd1000 ; 
 parameter CNT_2S_MAX = 10'd1000 ; 

 //reg define 
 reg [6:0] cnt_2us ; 
 reg [9:0] cnt_2ms ;
 reg [9:0] cnt_2s ;
 reg inc_dec_flag ; //亮度递增/递减 0:递增 1:递减
 reg [9:0] freq_step ; //呼吸灯频率间隔步长
 reg led_t ; 

 //***************************************************** 
 //** main code 
 //***************************************************** 
 assign led = led_t & sw_ctrl; 

 //设置频率间隔,频率步长值在 1-10 之间
 always @(posedge sys_clk) begin 
 if(!sys_rst_n) 
 freq_step <= START_FREQ_STEP; 
 else if(set_en) begin 
 if(set_freq_step == 0) 
 freq_step <= 10'd1; 
 else if(set_freq_step >= 10'd10) 
 freq_step <= 10'd10; 
 else
 freq_step <= set_freq_step; 
 end
 end 

 //cnt_2us:计数 2us 
 always@(posedge sys_clk or negedge sys_rst_n) begin 
 if(!sys_rst_n) 
 cnt_2us <= 7'b0; 
 else if(cnt_2us == (CNT_2US_MAX - 7'b1 )) 
 cnt_2us <= 7'b0; 
 else 
 cnt_2us <= cnt_2us + 7'b1; 
 end 

 //cnt_2ms:计数 2ms 
 always@(posedge sys_clk or negedge sys_rst_n) begin 
 if(!sys_rst_n) 
 cnt_2ms <= 10'b0; 
 else if(cnt_2ms == (CNT_2MS_MAX - 10'b1) && cnt_2us == (CNT_2US_MAX - 7'b1)) 
 cnt_2ms <= 10'b0; 
 else if(cnt_2us == CNT_2US_MAX - 7'b1) 
 cnt_2ms <= cnt_2ms + 10'b1; 
 else 
 cnt_2ms <= cnt_2ms; 
 end 

 //cnt_2s:计数 2s 
 always@(posedge sys_clk or negedge sys_rst_n) begin 
 if(!sys_rst_n) 
 cnt_2s <= 10'b0; 
 else if(cnt_2s >= (CNT_2S_MAX - 10'b1) && cnt_2ms == (CNT_2MS_MAX - 10'b1)
 && cnt_2us == (CNT_2US_MAX - 7'b1)) 
 cnt_2s <= 10'b0; 
 else if(cnt_2ms == (CNT_2MS_MAX - 10'b1) && cnt_2us == (CNT_2US_MAX - 7'b1)) 
 cnt_2s <= cnt_2s + freq_step; 
 else 
 cnt_2s <= cnt_2s;
 end 

 //inc_dec_flag 为低电平,led 灯由暗变亮,inc_dec_flag 为高电平,led 灯由亮变暗
 always@(posedge sys_clk or negedge sys_rst_n) begin 
 if(!sys_rst_n) 
 inc_dec_flag <= 1'b0; 
 else if(cnt_2s >= (CNT_2S_MAX - 10'b1) && cnt_2ms ==( CNT_2MS_MAX - 10'b1) 
 && cnt_2us == (CNT_2US_MAX - 7'b1)) 
 inc_dec_flag <= ~inc_dec_flag; 
 else 
 inc_dec_flag <= inc_dec_flag; 
 end 

 //led:输出信号连接到外部的 led 灯
 always@(posedge sys_clk or negedge sys_rst_n) begin 
 if(!sys_rst_n) 
 led_t <= 1'b0; 
 else if((inc_dec_flag == 1'b1 && cnt_2ms >= cnt_2s) 
 || (inc_dec_flag == 1'b0 && cnt_2ms <= cnt_2s)) 
 led_t <= 1'b1; 
 else 
 led_t<= 1'b0; 
 end 
 
 endmodule

同样的 在我们自定义完整个IP之后 会自动连接成c语言 方便在 Vitis 软件中对 IP 核进行操作
在这里插入图片描述

Makefile 让人想起了 Linux 的编译 这涉及到了另一个领域

接下来我们装载进入 vitis
在这里插入图片描述

在 BSP 中包含了 我们的自己创建的 breath_led
下面介绍整个 main.c函数

#include "stdio.h"
#include "xparameters.h"
#include "xil_printf.h"
#include "breath_led_ip.h"
#include "xil_io.h"
#include "sleep.h"
#define LED_IP_BASEADDR XPAR_BREATH_LED_IP_0_S0_AXI_BASEADDR //LED IP 基地址
#define LED_IP_REG0 BREATH_LED_IP_S0_AXI_SLV_REG0_OFFSET //LED IP 寄存器地址 0
#define LED_IP_REG1 BREATH_LED_IP_S0_AXI_SLV_REG1_OFFSET //LED IP 寄存器地址 1
//main 函数
int main()
{
int freq_flag; //定义频率状态,用于循环改变呼吸灯的呼吸频率
int led_state; //定义 LED 灯的状态
xil_printf("LED User IP Test!\n");
while(1){
//根据 freq_flag 的标志位,切换呼吸灯的频率
if(freq_flag == 0){
BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x800000ef);
freq_flag = 1;
}
else{
BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x8000002f);
freq_flag = 0;
}
//获取 LED 当前开关状态 1:打开 0:关闭
led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0);
//如果开关关闭,打开呼吸灯
if(led_state == 0){
BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 1);
xil_printf("Breath LED ON\n");
}
sleep(5);
//获取 LED 当前开关状态 1:打开 0:关闭
led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0);
//如果开关打开,关闭呼吸灯
if(led_state == 1){
BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 0);
xil_printf("Breath LED OFF\n");
}
sleep(1);
}
}

我们开始分析一下
其实掌握自己的东西很开心
我们打开platform 可以看到
在这里插入图片描述

有我们的 自定义的 IP 生成的 .c .h 内文件
我们来看主函数
我们先介绍一个非常重要的基本概念
IP的接口就是函数的输入参数
生成的.c文件 就相当于 把硬件抽象 成 一个库函数
通过库函数 来设置 输入参数
所以生成的逻辑 就是 根据你的硬件IP 的接口来的

ok 我们在做设计的时候 当合成一个IP之后 进入 C语言的层次之后 其实我们并不需要 知道 这个模块究竟是如何连接的 我们只需要知道这个模块的引脚是什么 功能是什么即可
对于这里的设计 我们需要在意的是 IP的 工作 输入输出 是什么 输入是 S_AXI 而 输出是 LED (LED 我们知道是寄存器达标的值)
那么 功能是 把 数写进 寄存器
LED的改变只是 因为寄存器变化而带来的附加效果
其实相当于把 数据存进到 寄存器
所以可想而知 .c 文件大概率也是这些功能
因为是系统来完成的 我们所能做的就是 观察 得出结论
在这里插入图片描述

这句话 就相当于 把数据放进基地址+偏移量的位置
在这里插入图片描述

这句话 就相当于 输出的意思

ok 解析完 系统生成的.c .h 我们接下来看主函数 对我们自定义的.c的调用
很简单的 使用我们的.c .h文件

#include "stdio.h"
#include "xparameters.h"
#include "xil_printf.h"
#include "breath_led_ip.h"
#include "xil_io.h"
#include "sleep.h"
#define LED_IP_BASEADDR   XPAR_BREATH_LED_IP_0_S0_AXI_BASEADDR //LED IP 基地址
#define LED_IP_REG0     BREATH_LED_IP_S0_AXI_SLV_REG0_OFFSET //LED IP 寄存器地址 0
#define LED_IP_REG1     BREATH_LED_IP_S0_AXI_SLV_REG1_OFFSET //LED IP 寄存器地址 1
//main 函数
int main()
{
int freq_flag; //定义频率状态,用于循环改变呼吸灯的呼吸频率
int led_state; //定义 LED 灯的状态
xil_printf("LED User IP Test!\n");
while(1){
//根据 freq_flag 的标志位,切换呼吸灯的频率
if(freq_flag == 0){
BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x800000ef);
freq_flag = 1;
}
else{
BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x8000002f);
freq_flag = 0;
}
//获取 LED 当前开关状态 1:打开 0:关闭
led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0);
//如果开关关闭,打开呼吸灯
if(led_state == 0){
BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 1);
xil_printf("Breath LED ON\n");
}
sleep(5);
//获取 LED 当前开关状态 1:打开 0:关闭
led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0);
//如果开关打开,关闭呼吸灯
if(led_state == 1){
BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 0);
xil_printf("Breath LED OFF\n");
}
sleep(1);
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/211568.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kubernetes中YAML介绍;API资源对象Pod;Pod原理和生命周期;Pod资源限制

YAML介绍&#xff1b;API资源对象Pod&#xff1b;Pod原理和生命周期&#xff1b;Pod资源限制 1&#xff09;认识YAML 官网&#xff08;https://yaml.org/&#xff09; YAML 语言创建于 2001 年&#xff0c;比 XML 晚了三年。YAML虽然在名字上模仿了XML&#xff0c;但实质上与…

Spring之RestTemplate详解

Spring之RestTemplate详解 1 RestTemplate1.1 引言1.2 环境配置1.2.1 非Spring环境下使用RestTemplate1.2.2 Spring环境下使用 RestTemplate1.2.3 Spring环境下增加线程号 1.3 API 实践1.3.1 GET请求1.3.1.1 不带参请求1.3.1.2 带参的get请求(使用占位符号传参)1.3.1.3 带参的g…

西南科技大学模拟电子技术实验四(集成运算放大器的线性应用)预习报告

一、计算/设计过程 说明:本实验是验证性实验,计算预测验证结果。是设计性实验一定要从系统指标计算出元件参数过程,越详细越好。用公式输入法完成相关公式内容,不得贴手写图片。(注意:从抽象公式直接得出结果,不得分,页数可根据内容调整) 反相比例运算电路(1)实验…

VMware Workstation Pro 17及 Windows 11 虚拟机的安装与激活

六点钟&#xff1a; 吃晚饭吗 不吃&#xff0c;胖胖 十点钟&#xff1a; 阿昊要吃夜宵对不对 ——CSDN&#xff0c;记录牛马生活 本文是在学习 Linux 期间&#xff0c;使用 VMware 时顺带学习 Windows 11 虚拟机的安装与激活 VMware Workstation Pro 17及 Windows 11 虚拟机…

MacDroid Pro for Mac – 安卓设备文件传输助手,实现无缝连接与传输!

想要在Mac电脑上轻松管理和传输您的安卓设备文件吗&#xff1f;MacDroid Pro for Mac 是您的最佳选择&#xff01;这款强大的文件传输助手可以让您在Mac上与安卓设备之间实现快速、方便的文件传输。 MacDroid Pro for Mac 提供了简单易用的界面&#xff0c;让您能够直接在Mac上…

基于Springboot + vue的汽车资讯网站

qq&#xff08;2829419543&#xff09;获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;springboot 前端&#xff1a;采用vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xf…

Vue学习记录

Vue学习记录 一、搭建Vue开发环境 到官网下载安装Vue&#xff1a;安装 — Vue.js (vuejs.org) ----->点击开发版下载 怎么解决&#xff1f; 到官网&#xff1a;安装 — Vue.js 点击&#xff1a; 下滑找到&#xff1a; 下载相应的版本的就行&#xff1a; 下载拓展后刷新…

Collection的其他相关知识

前置知识&#xff1a;可变参数 就是一种特殊参数&#xff0c;定义在方法 构造器的形参列表里&#xff0c;格式是&#xff1a;数据类型...参数名称&#xff1b; 可变参数的特点和好处 特点&#xff1a;可以不传数据给它&#xff1b;可以传一个或者同时传多个数据给它&#xff…

Halcon tiff 点云读取以及平面矫正

一、读取tiff 图 dev_close_window () dev_open_window (0, 0, 512, 512, black, WindowHandle)xResolution:0.0025 yResolution:0.0025 zResolution:0.001 read_image (IntputImage, C:/Users/alber/Desktop/2023-08-15_16-38-24-982_/Sta5_002.tif) zoom_image_factor (Intpu…

YOLOv8改进 | 2023 | 给YOLOv8换个RT-DETR的检测头(重塑目标检测前沿技术)

一、本文介绍 本文给大家带来是用最新的RT-DETR模型的检测头去替换YOLOv8中的检测头。RT-DETR号称是打败YOLO的检测模型&#xff0c;其作为一种基于Transformer的检测方法&#xff0c;相较于传统的基于卷积的检测方法&#xff0c;提供了更为全面和深入的特征理解&#xff0c;将…

【探索Linux】—— 强大的命令行工具 P.19(多线程 | 线程的概念 | 线程控制 | 分离线程)

阅读导航 引言一、 Linux线程概念1. 什么是线程2. 线程的概念3. 线程与进程的区别4. 线程异常 二、Linux线程控制1. POSIX线程库2. 创建线程 pthread_create() 函数&#xff08;1&#xff09;头文件&#xff08;2&#xff09;函数原型&#xff08;3&#xff09;参数解释&#x…

初识消息队列

1、消息 消息&#xff08;Message&#xff09;是指在应用间传送的数据。消息可以非常简单&#xff0c;比如只包含文本字符串&#xff0c;也可以更复杂&#xff0c;可能包含嵌入对象。 2、消息队列 消息队列&#xff08;Message Queue&#xff09;是一种应用间的通信方式&#…

力扣题:字符串的反转-11.23

力扣题-11.23 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;557. 反转字符串中的单词 III 解题思想&#xff1a;先读取单词&#xff0c;然后将单词进行翻转即可 class Solution(object):def reverseWords(self, s):""":type s…

C语言-指针_02

指针-02 1. 指针的指针 概念&#xff1a;指针变量中存储的是指针的地址&#xff0c;又名 二维指针 语法&#xff1a; 数据类型 **p;示例&#xff1a; #include <stdio.h> int main(int argc, char const *argv[]) {int num 10;int *p1 &num;int **p2 &p1…

win11 无法登录微软账户 终极解决方案

背景&#xff1a;win11突然无法登录微软账户&#xff0c;office无法激活&#xff0c;Edge里的微软账户也无法登录&#xff0c;反馈中心也无法打开等&#xff0c;有网络&#xff0c;浏览器可以访问微软并进行登录。 试过网上的网络配置&#xff08;SSL及TLS协议勾选&#xff09…

论文编写软件latex安装教程

目录 1.下载安装包2.安装texlive 本人系统为windows&#xff0c;本教程基于windows系统&#xff0c;如果是其它系统请参考对应教程&#xff0c;注意选择对应系统的安装包&#xff01; 1.下载安装包 有三种集成环境安装包 texlive 是主流的环境&#xff0c;集成了较多的包&…

k8s(三): 基本概念-ReplicaSet与Deployment

PeplicaSet ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合&#xff0c;通常用来保证给定数量的、完全相同的 Pod 的可用性。 最佳实践 Deployment 是一个可以拥有 ReplicaSet 并使用声明式方式在服务器端完成对 Pod 滚动更新的对象。 尽管 Rep…

华为杯研究生数学建模优秀参考论文(优秀论文参考2004-2022年)

一、背景介绍 中国研究生数学建模竞赛是一项面向在校研究生进行数学建模应用研究的学术竞赛活动&#xff0c;是广大在校研究生提高建立数学模型和运用互联网信息技术解决实际问题能力&#xff0c;培养科研创新精神和团队合作意识的大平台&#xff0c;大赛赞助单位为华为技术有限…

<JavaEE> synchronized关键字和锁机制 -- 锁的特点、锁的使用、锁竞争和死锁、死锁的解决方法

目录 一、synchronized 关键字简介 二、synchronized 的特点 -- 互斥 三、synchronized 的特点 -- 可重入 四、synchronized 的使用示例 4.1 修饰代码块 - 锁任意实例 4.2 修饰代码块 - 锁当前实例 4.3 修饰普通方法 - 锁方法所在实例 4.4 修饰代码块 - 锁指定类对象 …

【开源】基于JAVA语言的校园疫情防控管理系统

项目编号&#xff1a; S 037 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S037&#xff0c;文末获取源码。} 项目编号&#xff1a;S037&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生2.2 老师2.3 学校管理部门 三、…