FPGA实现Avalon-MM接口通信

        在Avalon总线协议(一)和Avalon总线协议(二)中大概了解Avalon总线的几种类型,目前比较常用到的就是Avalon-MM接口了,虽然在概念中有那么多的属性,但是具体使用起来还是非常简单的。

一、Avalon-MM

        前面提到过Avalon总线常用于 用户自定义的逻辑 与 NIOS Ⅱ处理器 之间进行通信,再通俗一点的理解就是硬件(Verilog代码)和软件(Nios Ⅱ处理器)进行数据交互。Nios Ⅱ作为主端口(Master),而Verilog代码模块实现了从端口(Slave),比如在Verilog代码中写了一个计数器,而Nios想要知道这个计数器的值,那么就可以在Verilog代码中定义一个寄存器,该寄存器具有与之相对应的地址,Nios Ⅱ可以根据地址对这个寄存器的值进行读取或者写入,这就是Avalon-MM协议。

如图,Verilog代码中定义了三个寄存器,分别是REG1、REG2、REG3,偏移量分别是OFFSET1、OFFSET2、OFFSET3;

当这一部分Verilog代码作为自定义组件加入到NIOS中并进行编译后,会自动产生BASE;

这时候寄存器的地址和偏移量就都有了,那么NIOS就可以对寄存器中的数据进行读写,从而实现通信!

二、NIOS常用函数

在NIOS中有一些已经定义好的函数方便去对数据进行操作

最常用的肯定是IORD()、IOWR()以及对PIO操作的IORD_ALTERA_AVALON_PIO_DATA()、IOWR_ALTERA_AVALON_PIO_DATA()

其实都一样>-<,IORD_ALTERA_AVALON_PIO_DATA()还是调用的IORD()

IORD(BASE, OFFSET)
//BASE为寄存器的基地址,OFFSET为寄存器的偏移量
//从基地址为BASE的设备中读取寄存器中偏移量为OFFSET的单元里面的值

IOWR(BASE, OFFSET, DATA)
//BASE为寄存器的基地址,OFFSET为寄存器的偏移量,DATA为要写入的数据
//向基地址为BASE的设备偏移量为OFFSET寄存器中写入数据DATA

IORD_ALTERA_AVALON_PIO_DATA(BASE)
//BASE为寄存器的基地址
//向基地址为BASE的设备中读取数

IOWR_ALTERA_AVALON_PIO_DATA(BASE, DATA)
//BASE为寄存器的基地址,DATA为要写入的数据
//向基地址为BASE的设备中写入数据DATA

其他NIOS函数可以参考:NIOS常用函数详解-CSDN博客

三、Avalon-MM实现

其实已经在前面的文章中实现过了,只不过没有较为详细的解释:

SOPC之NIOS Ⅱ实现电机转速PID控制_STATEABC的博客-CSDN博客

就用其中的电机PWM控制模块作为例子

3.1 硬件部分

module MOTOR_PWM(
	input						clk,
	input						reset_n,
	//Avalon-MM输入输出
	input						avalon_cs,			// 片选信号,进行数据操作时自动置为1
	input		[2:0]			avalon_address,		// 基地址,位宽根据要定义的寄存器个数
	input						avalon_write,		// 写入信号
	input		[31:0]			avalon_writedata,	// 写入数据
	input						avalon_read,		// 读取信号
	output  reg	[31:0]			avalon_readdata,	// 读取数据
	
	input	signed [31:0]		Speed,
	output	reg					PWM,
	output	reg					IN1,
	output	reg					IN2
);

reg            pwm_tem;
reg     [31:0] total;       // 总时间
reg     [31:0] high;        // 高位时间
reg     [31:0] count;            // 计数器

/
// 定义寄存器的偏移量,两种写法都可以
localparam REGISTER_TOTAL_DUR	= 0;

`define REGISTER_HIGH_DUR      2'd1


/
// Avalon-MM通信
always @(posedge clock or negedge reset_n)
begin
    if (~reset_n)
    begin
        high <= 0;
        total <= 0;
    end
    // 当片选信号和写入信号有效,反映在软件上就是执行了IOWR()
    else if (avalon_cs & avalon_write)
    begin
        if (avalon_address == REGISTER_TOTAL_DUR)			// 当地址等于0,即REGISTER_TOTAL_DUR
            total <= avalon_writedata;						// avalon_writedata为IOWR()写入的DATA值
        else if (avalon_address == `REGISTER_HIGH_DUR)
            high <= avalon_writedata;
    end
    // 当片选信号和读取信号有效,反映在软件上就是执行了IORD()
    else if (select_cs & select_read)
    begin
        if (avalon_address == `REGISTER_TOTAL_DUR)			// 当地址等于0,即REGISTER_TOTAL_DUR
            select_readdata <= total;						// avalon_writedata为IORD()的返回值
        else if (avalon_address == `REGISTER_HIGH_DUR)
            select_readdata <= high;
    end    
end
 
/
// 进行PWM输出
always @(*)
begin
    if (Speed>0) begin
    	{IN1, IN2, PWM} <= {1'b1, 1'b0, pwm_tem};
    end
    else begin
    	{IN1, IN2, PWM} <= {1'b1, 1'b0, pwm_tem};
    end
end
 
always @(posedge clock or negedge reset_n)
begin
    if (~reset_n)
    begin
        count <= 1;
    end
    else if (count >= total)
    begin
        count <= 1;
    end
    else
        count <= count + 1;
end
 
always @(posedge clock)
begin
    pwm_tem <= (count <= high) ? 1'b1 : 1'b0;
end
 
endmodule

将其作为自定义组件加入NIOS系统中并进行编译

3.2 软件部分

硬件部分进行全编译后,生成的systm.h文件中会包含其BASE信息

然后就可以根据BASE和OFFSET进行数据的读取

#include <stdio.h>
#include <stdlib.h>
#include "system.h"
#include "altera_avalon_pio_regs.h" //IOWR_ALTERA_AVALON_PIO_DATA

int main()
{    
    int high,total;
    //写入数据
    IOWR(MOTOR_PWM_BASE,0,2000);
    IOWR(MOTOR_PWM_BASE,1,1000);
    //读取数据
    total = IORD(MOTOR_PWM_BASE,0);
    high  = IORD(MOTOR_PWM_BASE,1);

    printf("total= %d\r\n", total);
    printf("high = %d\r\n", hight);
   
    return 0;
}

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

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

相关文章

【Mysql】关于数据库增删查改的一些在线OJ练习

&#x1f308;欢迎来到Python专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mys…

大数据-之LibrA数据库系统告警处理(ALM-12048 网络写包错误率超过阈值)

告警解释 系统每30秒周期性检测网络写包错误率&#xff0c;并把实际错误率和阈值&#xff08;系统默认阈值0.5%&#xff09;进行比较&#xff0c;当检测到网络写包错误率连续多次&#xff08;默认值为5&#xff09;超过阈值时产生该告警。 用户可通过“系统设置 > 阈值配置…

PLC和SCADA有什么区别?

让我们谈谈SCADA和HMI之间的区别。今天&#xff0c;我们将讨论它们的区别和相似之处&#xff0c;以及各自的用途。由于相似之处&#xff0c;通常会出现一些混淆。 现在让我们深入了解SCADA 。SCADA代表“监控和数据采集”。它们用于监视和控制大面积区域&#xff0c;通常是整个…

Vue3 使用教程

目录 一、创建vue3工程1. 使用vue-cli创建2.使用 vite 创建 二、setup使用三、ref函数四、reactive函数五、计算属性与监视属性5.1 computed函数5.2 watch函数5.3 watchEffect函数 六、自定义hook函数七、toRef函数八、shallowReactive 与 shallowRef九、readonly 与 shallowRe…

Vue23全局事件总线

Vue2&3全局事件总线 Vue2全局事件总线 功能&#xff1a;可以解决所有组件之间通信传数据的问题原理&#xff1a;通过一个共享对象&#xff0c;将所有组件全部绑定到对象上&#xff0c;即可通过这个对象实现组件与组件之间的传递数据&#xff0c;而这个共享对象叫做全局事件…

TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…

【JUC】八、阻塞队列

文章目录 1、阻塞队列概述2、阻塞队列分类3、 阻塞队列的四组核心方法4、Demo 队列&#xff0c;先进先出&#xff0c;类似排队栈&#xff0c;先进后出&#xff0c;用于要优先处理最近发生的事件的场景 1、阻塞队列概述 阻塞队列&#xff0c;一个生产消费模式&#xff0c;当&a…

数组相关面试题--5.合并两个有序数组

5. 合并两个有序数组 88. 合并两个有序数组 - 力扣&#xff08;LeetCode&#xff09; 解题思路:1. 从后往前遍历数组&#xff0c;将nums1和nums2中的元素逐个比较将较大的元素往nums1末尾进行搬移2. 第一步结束后&#xff0c;nums2中可能会有数据没有搬移完&#xff0c;将nums…

结合scss实现黑白主题切换

是看了袁老师的视频后&#xff0c;自己做了一下练习。原视频地址&#xff1a; b站地址https://www.bilibili.com/video/BV15z4y1N7jB/?spm_id_from333.1007.top_right_bar_window_history.content.click&vd_sourcec6cf63302f28d94ebc02cbedcecc57ea首先创建一个全局的scs…

Python的基础:模块(Modules)和包(Packages)详解

1. 模块&#xff08;Modules&#xff09; 一个模块是一个包含了 Python 定义和语句的文件。模块可以包括变量、函数、类等&#xff0c;并且提供了一种将相关代码组织成可重用单元的方式。一个模块的定义通常包括以下几个方面&#xff1a;   1&#xff09;文件扩展名&#xff…

17. Series.dt.month-提取日期数据中的月份信息

【目录】 文章目录 17. Series.dt.month-提取日期数据中的月份信息1. 知识回顾-创建一个Series对象2. 知识回顾-pd.to_datetime()将数据转换为pandas中的日期时间格式3. 实例化类相关知识4. Series.dt.month是什么&#xff1f;5. 如何使用Series.dt.month&#xff1f;6. Series…

【数据库原理及应用教程】第三章 SQL

文章目录 建立数据库创建数据库选择元组select多表查询 追加元组 insert嵌套子查询 元组删除命令 deleteUpdate命令 修正与撤销数据库SQL-DDL撤销与修改撤销基本表指定数据库关闭数据库 建立数据库 学生选课数据库SCT 学生表&#xff1a;Student(SNo char(8), Sname char(10)…

Ubuntu18.04安装Loam保姆级教程

系统环境&#xff1a;Ubuntu18.04.6 LTS 1.Loam的安装前要求&#xff1a; 1.1 ROS安装&#xff1a;参考我的另一篇博客 Ubuntu18.04安装ROS-melodic保姆级教程_灬杨三岁灬的博客-CSDN博客还是那句话&#xff0c;有时候加了这行也不好使&#xff0c;我是疯狂试了20次&#xf…

stylelint报错at-rule-no-unknown

stylelint报错at-rule-no-unknown stylelint还将各种 sass -rules 标记mixin为include显示未知错误 at-rule-no-unknown ✖ stylelint --fix:Deprecation warnings: 78:1 ✖ Unexpected unknown at-rule "mixin" at-rule-no-unknown 112:3 ✖ Unexpected un…

2023 年 数维杯(A题)国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2021年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看数维杯A题&#xff01; 问题重述 1、俯仰力矩和俯…

【Rust】快速教程——冻结表达式

前言 以前谁是魔我杀谁&#xff0c;现在我杀谁谁就是魔。——《拔魔》 \;\\\;\\\; 目录 前言Rust基本知识结构体元组结构体局部作用域冻结字面量Vec元素的类型由第一个push进的类型确定type别名from和intoTryFrom和TryInto 表达式 Rust基本知识 结构体 #[derive(Debug)] str…

华为eNSP综合实验考试

VLAN信息表 设备名称 端口 链路类型 VLAN 参数 HZ-HZCampus-Agg01-S5731 GE0/0/1 Trunk PVID:1 Allow-pass&#xff1a;10 20 Eth-trunk1&#xff08;GE0/0/2,0/0/3,0/0/23&#xff09; Trunk PVID:1 Allow-pass&#xff1a;10 20 GE0/0/24 Access PVID&#xf…

vb.net 实时监控双门双向门禁控制板源代码

本示例使用设备介绍&#xff1a;实时网络双门双向门禁控制板可二次编程控制网络继电器远程开关-淘宝网 (taobao.com) Imports System.Net.Sockets Imports System.Net Imports System.Text Imports System.ThreadingImports System.Net.NetworkInformation Imports System.Man…

Python函数进阶

函数进阶 一.函数多返回值二.函数多种传参方式三.匿名函数 一.函数多返回值 思考&#xff1a;如果一个函数有两个return&#xff0c;程序如下 只执行了一个return&#xff0c;原因是return可以退出当前函数&#xff0c;导致return下方代码不会执行 多个返回值 按照返回值的顺…

BananaPi BPI-M6(Raspberry Pi 5) Android 平板电脑镜像测试温度

我已经在本文中介绍了 全新的Banana Pi BPI-M6&#xff0c;并讨论了其与Raspberry Pi 5的硬件特性比较。 然后我将 Android 平板电脑固件上传到 eMMC&#xff0c;从而使 Banana Pi 实际可用。一开始有点坎坷&#xff0c;但文章中有更多内容。 在另一台电脑上&#xff0c;一切都…