FPGA学习专题-NIOS ii中的数据与Verilog进行交互(一)

在实际应用开发中,在verilog层面上开发完成简单的功能后,如果遇到比较复杂的逻辑,就会借助类似NIOS这样的片上CPU(其实本身就是一个IP核),在上面应用C语言进行编写操作。

那么问题就有了,在verilog中已经处理好的数据怎么传到NIOS中给C语言处理?或者从NIOS传到Verilog层面上去呢?

我将应用一个简单例子说明一下。两者在通信中借助AVALON总线,哪怕简单理解成一条线,把两者连接起来。如果NIOS想得到Verilog中的数据,就执行读总线(这个读过程是要带地址的),总线会根据给出的地址找到你想读的寄存器,并把值拿到NIOS中。相反,如果想把数据发送给Verilog,就执行写总线操作(写过程同样是要带地址的,就是目标地址),总线就会根据给出的地址把数据发送到给定的地址上,也就发到了对应的寄存器。

简单理解就是下图,两边的寄存器都挂在AVALON总线上,所有的地址都可以通过AVALON总线找到,这里的地址是由自己定的,后面告诉你怎么定。

在这里插入图片描述
本文实现现象:从NIOS II中发送变量值到Verilog中,控制灯的闪烁。
请注意:不是用的PIO!!!

1.首先在Verilog中建立闪灯的逻辑

module data_deal(

clk,
rst,
data_in,
data_out
);

input clk;
input rst;
input [7:0] data_in;//NIOS发送过来的控制值
output reg  data_out;//FPGA引脚输出,相当于是Verilog中的变量,这个值也可以被NIOS 读取

always@(posedge clk or negedge rst)
	if(!rst)
	data_out <= 1'b1;
	else if(data_in == 8'd5) //当NIOS中发送过来的值为5,就亮灯,否则,灭灯。
	data_out <= 1'b0;
	else 
	data_out <= 1'b1;

endmodule

注释写在代码中,就不分析了。重点说下实现avalon总线的内容。

/*******************说明**********************/
/*这个module就是实现的通过avalon总线进行数据交互的功能*/
/*整个的模块可以说是一个通用标准了,使用中只需要修改成自己的变量即可*/
/*这里的as_writedata 和as_readdata 这两个数据寄存器,理解成NIOS可以操作的寄存器*/
/*往as_writedata里写数据就是发送给Verilog,读as_readdata就是从Verilog取数据*/
module av_data(
	clk,
	rst,
	led_out,
	as_address,			//地址,这个地址就是用来给Verilog中的变量和NIOS中的变量确定地址的
	as_chipselect,		//设备选择
	as_write,			//写请求,NIOS向Verilog中写数据
	as_writedata,		//要写数据 
	as_read,			//读请求,NIOS从Verilog中读数据
	as_readdata			//读取的数据
	
	);
	
	input clk;
	input rst;
	output led_out;
	
	input [2:0] as_address;//地址位宽根据你需要操作多少个变量决定
	input as_chipselect;
	input as_write;
	input [15:0] as_writedata;	//操作数的位宽,一般定义成16bit
	input as_read;
	output reg [15:0] as_readdata;
	
	//写数据
	reg [7:0] data;
	always@(posedge clk or negedge rst)
		if(!rst)
		data <= 1'b0;
		else if((as_chipselect && as_write && (as_address == 0)))//注意这里的写条件,当地址为0的时候,就通过as_writedata这个写寄存器
		data <= as_writedata[7:0];											//把数据写到Verilog中的data这个变量
	
	
	//读数据
	always@(posedge clk or negedge rst)
		if(!rst)
			as_readdata <= 16'd0;
		else if(as_chipselect && as_read)begin
			case(as_address)
				0:as_readdata <= {8'd0, data};//同样还是根据地址,将Verilog中的变量值读到读寄存器中
				1:as_readdata <= {15'd0, led_out};
				default:as_readdata <= 16'd0;
			endcase	
		end
	
	//例化的控制亮灯的模块
	data_deal data_deal(

	.clk(clk),
	.rst(rst),
	.data_in(data),
	.data_out(led_out)

);
	
	
	endmodule
	
	

重点也都备注在代码中,还有不懂的可以一起讨论。两个关键的模块写好了,我们在工程中建立一个名为“ip”的文件夹,将上面的两个模块放到这个文件夹中,因为后续操作的时候,系统需要识别到ip文件夹才能操作。

在这里插入图片描述
在这里插入图片描述

上面都操作完成,再添加一个用于简单逻辑控制与引脚定义的顶层文件。

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;


endmodule


上面一段代码主要就是将工程中需要连接的引脚进行定义,并点亮了一颗LED用于显示程序运行情况。全部写完再进行一次全编译。

接下来开始在qsys中进行操作,打开qsys平台,如下:

在这里插入图片描述
打开之后在按下操作:

在这里插入图片描述

知道我么要干什么吗?建立一个IP核,没错,自己都会建IP核了,了不得了。

在这里插入图片描述
按部就班操作,在file一栏要注意一下:将刚刚建立的两个module文件添加进来,并要执行一次分析综合,你可能会遇到报错,应该不是可能是肯定会,不要怕,接着往下。

在这里插入图片描述

到这一步的时候,你或许不会像我的这么整齐,因为我是已经调好的。你是不是发现这里显示的值都很眼熟,是的,这里的引脚可都是我们自己定义的,既然都是自己定义的那不要太了解了。但是你要做的,是要修改成正确的类型,类型特别特别重要,因为自动识别(就是上面建立ip文件夹的作用)不会很准确的,你要按照图中将每个引脚的类型对应上才可以。

红框中标注了特别主要注意的地方,reset引脚要注意是reset还是reset_n。这个坑搞了我一晚上没睡着,惭愧。提示有Associated Reset的地方要选上reset,这里不会默认选上,不选不行。

关注一下led_out这个脚,这个是需要连接到设备的实际的引脚,需要定义成conduit类型,这样才可以导出并连接。

在这里插入图片描述
全部执行完成后FINISH。然后双击刚刚建立的IP核,添加到NIOS系统中

在这里插入图片描述
在这里插入图片描述
一定要注意,led_out要双击导出。然后执行重要的地方,将NIOS例化到第三个引脚定义的模块中去。不要忘了Generate!

在这里插入图片描述
在这里插入图片描述
所以上面的代码就成了下面的样子:

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;

//相比较上面的程序,就多了这一块
    mysystem u0 (
        .clk_clk       (clk),       //    clk.clk
        .reset_reset_n (rst), //  reset.reset_n
        .uart_0_rxd    (uart_rx),    // uart_0.rxd
        .uart_0_txd    (uart_tx),     //       .txd
		.av_sys_data_0_led_out(led_out)
    );

endmodule


然后整个工程全编译,ctrl+L即可。
然后打开eclipse
在这里插入图片描述
写代码


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

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

  /* Event loop never exits. */
  while (1)
  {
	  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);
  }

  return 0;
}

代码说明也在注释中,看下就可,烧录后对应灯会闪烁,串口也会打印出led_out引脚对应的数值。
在这里插入图片描述
以上就实现了Verilog与NIOS双向通信的过程,附上测试工程,供大家参考。
链接:https://pan.baidu.com/s/1MBQ8Yd6Q1Kl2rjjC-Kl3Sw
提取码:wrcy

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
NIOS输出浮点数可以通过使用浮点数库函数来实现。NIOS处理器本身并不支持硬件浮点运算,但可以使用软件实现的浮点数库函数进行浮点数的计算和输出。 首先,要在NIOS工程引入浮点数库函数。在Quartus软件的Project窗口,右键点击NIOS II processor,选择"New Component",然后选择"Floating Point Software Support"。添加后,可以在NIOS II软件开发环境使用浮点数库函数。 接下来,在C语言代码,我们需要包含相应的头文件来引入浮点数库函数。通常使用`math.h`头文件。然后,可以使用库函数来进行浮点数的计算和输出。 例如,我们想要将两个浮点数相加并输出结果。首先,定义两个浮点数变量,并通过输入等方式为其赋值。然后使用库函数`float fsum(float x, float y)`来计算两个浮点数的和。最后,使用输出函数将结果打印出来。 下面是一个简单的示例代码: ```c #include <stdio.h> #include <math.h> int main() { float x, y, result; printf("请输入两个浮点数:"); scanf("%f %f", &x, &y); result = fsum(x, y); printf("相加结果为:%f\n", result); return 0; } ``` 在上面的代码,通过`scanf`函数从用户输入获取两个浮点数的值,并将其存储在`x`和`y`变量。然后使用库函数`fsum`计算两个浮点数的和,并将结果存储在`result`变量。最后,使用`printf`函数将结果输出到终端。 需要注意的是,由于NIOS处理器不支持硬件浮点运算,因此浮点数的运算会比较耗时。所以在实际应用,应尽量减少对浮点数的操作,以提高处理效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值