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常用函数详解-优快云博客

三、Avalon-MM实现

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

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

就用其中的电机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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值