FPGA学习专题-NIOS II与Verilog数据交互方式(二)

在上一期的分享中阐述了使用自定义IP核的方式实现NIOS与Verilog中的数据交互方式。在该方法中,基于AVALON总线的读写函数需要作为顶层文件,其他包含有需要操作的数据的模块都必须作为子模块来操作,这种是很不方便的。

举例来说就是,对于一个已经实现好读温度值的verilog程序,如果想把verilog中读到的温度值通过nios中发送出去,那么就需要重新再建一个avalon的module,将已经实现的程序当成子模块给avalon module例化才行,这样的改动会很大的,那么有没有一种方法可以在不动源程序的基础上,把已经得到的值发送出去呢?答案是肯定的。

本篇的方法较上一个方法会简单很多。

在此之前,我需要引用上一篇中的一些概念:conduit。这个是针对用户操作的管脚,上一篇中,我们利用这个地方当成了连接LED的管脚,配置的时候实际这个是连接到了FPGA的管脚上的。在此篇中,我们还是会使用conduit,但是我们不必将它连接到实际的FPGA引脚,而是把它当成一个寄存器。那么就看下怎么实现这个寄存器功能。

本篇中,我们将使用PIO实现:从nios中向verilog中写数据,再从verilog中将写入的数据读出来的功能。

既然说到了使用PIO实现,那我么主要讨论下PIO这一块的内容。通常来说,我们在NIOS中使用PIO,是要操作对应的IO口,控制灯的亮灭,控制外设的通信等。当然,上面的操作就需要将配置的PIO映射到对应的FPGA引脚上,但是我们在本例中使用的PIO,是当成寄存器使用的,尤其要注意理解这个寄存器,这里是不需要将PIO映射到FPGA引脚上的。(我在这之前一直以为PIO一定要映射到真实的管脚上)

首先看下qsys中配置的PIO吧:

在这里插入图片描述

对应上图,配置的data_out是使用的PIO配置的一个8bit的寄存器,表明一次可以发送一个8bit的数据;配置中需要注意的是IO的方向,如果是从NIOS向Verilog中发送数据,就配置成output,反之就配置成input;当把PIO配置成寄存器使用时,不要动下面的中断配置。

我上面已经配置了两个,一个data_out是用来从nios中发送数据的,一个data_in是用来从verilog中读数据的。

好,可以上程序分析了

module nios_test(

	clk,
	rst,	
	work_led,
	led_out,	
	uart_tx,
	uart_rx

);

input clk;
input rst;
output reg work_led;
output led_out;

input uart_rx;
output uart_tx;

//500ms计时 25000000
reg [24:0] cnt;
always@(posedge clk or negedge rst)
	if(!rst)
	cnt <= 1'b0;
	else if(cnt == 25'd24999999)
	cnt <= 1'b0;
	else
	cnt <= cnt +1'b1;


always@(posedge clk or negedge rst)
	if(!rst)
	work_led <= 1'b1;
	else if(cnt == 25'd24999999)
	work_led <= ~work_led;

	
//建一个测试用的
reg [7:0] test_signal;
wire [7:0] test_data_out;
wire [7:0] test_data_in;
always@(posedge clk or negedge rst)
if(!rst)
test_signal <= 1'b0;
else 
test_signal <= test_data_out;//test_signal是用来存nios中发送过来的数据的


assign test_data_in = test_signal;//同时又将保存的nios中的数据发送给nios,如果两个值相等,证明测试成功。

//例化的qsys
    mysystem u0 (
        .clk_clk       (clk),       //    clk.clk
        .reset_reset_n (rst), //  reset.reset_n
        .uart_0_rxd    (uart_rx),    // uart_0.rxd 这里的uart是连接的FPGA的两个引脚,通过一个TTL转USB模块可以在串口打印工具上打印信息
        .uart_0_txd    (uart_tx),     //       .txd
		.av_sys_data_0_led_out(led_out),//上一篇中的led管脚
		.test_data_out_export  (test_data_out),  // nios中发送来的数据
        .test_data_in_export   (test_data_in) //nios读verilog中的数据
    );
	 
endmodule

该程序是基于上一版的修改,控制led的程序没动,只是增加了PIO通信部分的内容,整个的工程需要修改的不多。前面的主体还是一个亮灯的程序,每500ms闪一次,指示程序的运行;后面例化的是qsys生成的module,在module中增加了两个导出的端口,test_data_out_export和test_data_in_export这两个,也就是我们配置的PIO的端口,需要破除的误区就是,这里的导出的两个PIO端口是当成寄存器使用的,并不是实际连接的引脚,也就是说,可以进行module之间的数据交换使用。

再看下nios中需要修改哪些地方:

#include "sys/alt_stdio.h"
#include "io.h"				//这个头文件就是操作读写数据寄存器的需要
#include "system.h"
#include "unistd.h"
#include "altera_avalon_pio_regs.h"

int main()
{
  alt_putstr("Hello from Nios II!\n");

  /* Event loop never exits. */
  while (1)
  {
  	/*******************avalon自定义IP读写的测试***********************/
	  IOWR_16DIRECT(AV_SYS_DATA_0_BASE,0,0x05);//通过这个写函数,向地址0上写一个5,对应Verilog中就会写到data中,此时data_out输出为0,灯亮

	  //printf("data is %x\r\n",IORD_16DIRECT(AV_SYS_DATA_0_BASE,2));//注意这里的读函数,地址写的是2,我们在Verilog中定义的读led_out的地址是1
	  usleep(100000);											   //这个就是地址对应的关系,Verilog中是16bit,NIOS中是8bit,需要2个对应上1个
	  IOWR_16DIRECT(AV_SYS_DATA_0_BASE,0,0x01);	//写一个1,灯会灭
	 // printf("data is %x\r\n",IORD_16DIRECT(AV_SYS_DATA_0_BASE,2));//读出Verilog中灯的输出状态
	  usleep(100000);
	  /********************PIO的读写测试********************/
	  IOWR_ALTERA_AVALON_PIO_DATA(DATA_OUT_BASE,0xaa);//向verilog中写一个0xaa
	
	  printf("data in data in:%x\r\n",IORD_ALTERA_AVALON_PIO_DATA(DATA_IN_BASE));//从verilog中读出刚刚写的0xaa,并打印出来
  }

  return 0;
}

C中修改的同样不多,仅仅是调用了两个PIO读写的函数,将数据0Xaa写到Verilog的数据中,然后再读回来。

实际测试结果这里就不用展示了,当然是正确的。

看到这里,是不是发现比上一篇的方法少了很多配置,这就是利用PIO当寄存器实现NIOS与Verilog数据交互的方法。不知道大家注意到没有,在配置PIO的时候,数据位数的配置只能配置到32bit,这就意味着,一次传输最多32bit数据。这个同样又造成了困扰。那么你们有方法可以传输多字节数据吗?该方法将在后续揭晓。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值