Nios-II编程入门实验

文章目录

  • 一 Verilog实现流水灯
  • 二 Nios实现流水灯
    • 2.1 创建项目
    • 2.2 SOPC添加模块
    • 2.3 SOPC输入输出连接
    • 2.4 Generate
    • 2.5 软件部分
    • 2.6 运行结果
  • 三 Verilog实现串口
    • 3.1 代码
    • 3.2 引脚
    • 3.3 效果
  • 四 Nios2实现串口
    • 4.1 sopc硬件设计
    • 4.2 top文件
    • 4.3 软件代码
    • 4.4 实现效果
  • 五 参考资料
  • 六 总结

一. 实验目标:学习 Quartus 、Platform Designer、Nios-II SBT 的基本操作;初步了解 SOPC 的开发流程,基本掌握 Nios-II 软核的定制方法;掌握 Nios-II 软件的开发流程,软件的基本调试方法。
二. 实验过程:
1、完成以下实验:

  1. 在DE2-115开发板上分别用 Verilog和 Nios软件编程两种方式完成LED流水灯显示,理解两种方式的差异;
  2. 分别用Verilog和Nios软件编程, 实现DE2-115开发板串口输出“Hello Nios-II”字符到笔记本电脑串口助手。
    3)分别在DE2-115开发板和树莓派上编写串口通信程序, 实现树莓派串口指令对FPGA板子上的流水灯程序的控制,控制方式自定。

一 Verilog实现流水灯

使用quartus创建好工程项目,将verilog文件加入项目中,分析综合一次后,添加引脚,引脚如下:
在这里插入图片描述
添加完后直接全编译,最后连接DE2-115下载即可。
代码如下:

module led_flow #(parameter TIME_0_5S = 25_000_000)(input               sys_clk     ,input               sys_rst_n   ,output  reg [7:0]   led     
);reg     [24:0]      cnt     ;wire                add_cnt ;wire                end_cnt ;reg     [2:0]       cnt1;wire                add_cnt1;wire                end_cnt1;always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n) begincnt <= 25'b0;endelse if(add_cnt) beginif(end_cnt) begincnt <= 25'b0;endelse begincnt <= cnt+1'b1;endendelse begincnt <= cnt;endend// 异步复位always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)begincnt1 <= 3'b0;endelse if(add_cnt1) beginif(end_cnt1)begincnt1 <= 3'b0;endelse begincnt1 <= cnt1 + 1'b1;endendendalways @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)beginled <= 8'b0;endelse begincase (cnt1)3'b000 : led <= 8'b0000_0001;3'b001 : led <= 8'b0000_0010;3'b010 : led <= 8'b0000_0100;3'b011 : led <= 8'b0000_1000;3'b100 : led <= 8'b0001_0000;3'b101 : led <= 8'b0010_0000;3'b110 : led <= 8'b0100_0000;3'b111 : led <= 8'b1000_0000;default: led <= led;endcaseendendassign add_cnt = 1'b1;assign end_cnt = add_cnt && cnt == TIME_0_5S - 1;assign add_cnt1 = (cnt == TIME_0_5S-1);assign end_cnt1 = add_cnt1 && cnt1 == 3'b111;endmodule

运行效果如下:
在这里插入图片描述

二 Nios实现流水灯

2.1 创建项目

在文件夹下(你放项目的文件夹)创建一个新的项目,名称任意,最好和项目有关,我的是NiosII,并在里面创建prj目录:

在这里插入图片描述
在这里插入图片描述
创建好之后打开quartus新建工程:
在这里插入图片描述
在这里插入图片描述
一直next,到选择型号界面。
选择芯片型号,根据实际情况选择
在这里插入图片描述
点击finish

2.2 SOPC添加模块

在这里插入图片描述
这里以前是叫qsys,现在变成了platform designer,他俩都是为了设置sopc(system on programmble chip),在这里面可以使用一些已经写好了的模块(IP核)来构建你自己想完成的功能。

首先,最基本的需要一个cpu(NIosII处理器)、ram存储器、jtag、systemid,这几个是最基本的配置。其次我们需要点灯,所以就需要pio。

  • 添加基本配置cpu
    在platform designer的左侧,有一个IP Catalog,是IP 目录的意思,可以在搜索栏输入关键字查找你想添加的ip核。如下:
    在这里插入图片描述
    添加之后,有弹框,让你配置这个模块,一般保持默认。
    在这里插入图片描述
    然后点击finish。
    右键Rename,将名字改为cpu
    在这里插入图片描述

  • 添加基本配置jtag
    在这里插入图片描述
    保持默认配置,finish之后改名字为uart
    在这里插入图片描述

  • 添加基本配置ram
    在这里插入图片描述
    这个需要修改一下,Size变为40960bytes,因为后续的软件代码都是存储到ram中的,还包括一些指令什么的需要较大的空间,你可以在这设定充足,或者在后续eclipse软件中修改,有点类似于cube里面的一些操作。
    在这里插入图片描述
    修改之后finish,改名字为onchip_ram
    在这里插入图片描述

  • 添加基本配置systemid
    在这里插入图片描述
    保持默认选项,finish。

  • 添加流水灯的pio
    在这里插入图片描述
    在这里插入图片描述
    点击finish后将名字改为pio_led,并且要在led下的externel_connection该名称为out_led。这里是为了说明顶层文件中有一个输出是out_led。可以在后面看到生成的模块实例格式中输出就有这个,输入包括时钟和复位信号。
    在这里插入图片描述
    以上就是你需要的所有模块,接下来就是连线。过程类似你要编写顶层top文件,需要把输出输出等地方连接起来。

2.3 SOPC输入输出连接

在打开这个platform designer的时候有一个clk_0模块,是它本身就有的,需要双击一下,看其中时钟频率是多少:
在这里插入图片描述
可以看到这里是50MHz,和手里的fpga晶振是同样的频率。所以不用修改,如果不同,就需要做一些额外的操作比如添加一个锁相环,进行倍频操作。
cpu,uart,onchip_ram,pio_led、sys_id都有clk和reset的需求,所以要把他们的时钟和复位连接起来。
接着是cpu作为处理器,uart以及pio、ram等都有数据相关的操作,需要通过数据总线,所以要将这些连接到数据总线上去。连线结果如下:
在这里插入图片描述
连接完后,再配置一下处理器,双击cpu:
在这里插入图片描述

这些模块都是基于Avalon总线,需要确保他们地址不同。
点击system->assign base address后可以看到每个模块base那一列都分配了不同的地址。
在这里插入图片描述
分配完成之后,可以看到最下方Messages中没有报错了,如果还有报错就是前面有地方没有配对。
在这里插入图片描述

2.4 Generate

点击generate中的generate HDL
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
完成之后,再点击show…template,可以看到现在这个模块的实例顶层格式:
在这里插入图片描述
复制下来。可以关闭platform designer回到quartus中。
点击File,new创建一个verilog HDL file
在这里插入图片描述

开始编写顶层文件:
创建一个顶层模块后,填写庶出庶出,并将刚才复制的粘贴进去,作为实例化的对象。

之后再添加qip文件:Assignments–>Settings–>
在这里插入图片描述
在这里插入图片描述
Applay之后,就开始分析综合、绑定引脚(可参考数据手册led绑定):
在这里插入图片描述
然后全编译。硬件部分就编好了。

2.5 软件部分

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
先有点led_flow_bsp
在这里插入图片描述
保持硬件的最新性。
然后右键led_flow,build project。如果编译没问题就开始下一步。
在这里插入图片描述
先把硬件烧录到fpga板子上。
连接板子,
在这里插入图片描述
start。

再烧软件:
在这里插入图片描述

会出现一个报错,点击右侧的refresh…就可以了。

2.6 运行结果

在这里插入图片描述

三 Verilog实现串口

项目创建和以前的一样。

3.1 代码

uart.tx:

//波特率为115200bps,即每秒传送115200bit的数据,传送1bit数据需要434个时钟周期
//tx内部是并行数据,需要串行传出去,一般数据格式是1bit的起始位,8bit的数据位,1bit的停止位
//所以需要一个8bit的计数器,计算传送了多少个bit,起始位是低电平有效,停止位是持续的高电平
//需要接收8bit的数据
//需要1bit的传送出去
module uart_tx(input               clk     ,input               rst_n   ,//ininput    [7:0]      din ,//要发送的数据input               din_vld,//数据有效//outoutput  reg [3:0]   cnt_byte,//现在输出第几个byte了output  reg         tx    //串口数据
);parameter    Baud = 434;//波特率计时器
reg         [8:0]       cnt_baud     ;
wire            add_cnt_baud ;
wire            end_cnt_baud ;
reg                     flag;always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_baud <= 0;end else if(add_cnt_baud)begin if(end_cnt_baud)begincnt_baud <= 0;endelse begincnt_baud<=cnt_baud+1;endend else begin cnt_baud <= cnt_baud;end 
end
assign add_cnt_baud = flag;
assign end_cnt_baud = add_cnt_baud && cnt_baud == Baud - 1;always @(posedge clk or negedge rst_n)beginif(!rst_n)beginflag <= 1'b0;endelse if(din_vld)beginflag <= 1'b1;endelse if(end_cnt_bit)beginflag <= 1'b0;endelse beginflag <= flag;end
end//波特率计数完成,就可以发送下一个bit
//表示需要把第几位发送出去
reg               [3:0]      cnt_bit;//最多是8
wire            add_cnt_bit;
wire            end_cnt_bit;
always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_bit <= 0;end else if(add_cnt_bit)begin if(end_cnt_bit)begincnt_bit <= 0;endelse begincnt_bit <= cnt_bit + 1;endend else begin cnt_bit <= cnt_bit;end 
end
assign  add_cnt_bit = end_cnt_baud;
assign  end_cnt_bit = add_cnt_bit && cnt_bit == 8;//发送到第几个字符,总共要发15个字符
wire                     add_cnt_byte ;
wire                     end_cnt_byte ;always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_byte <= 0;end else if(add_cnt_byte)begin if(end_cnt_byte)begincnt_byte <= 0;endelse begincnt_byte <= cnt_byte + 1;endend else begin cnt_byte <= cnt_byte;end 
endassign      add_cnt_byte = end_cnt_bit;//发送完8bit后
assign      end_cnt_byte = add_cnt_byte && cnt_byte == 14;//发送数据的逻辑,先加上起始位reg         [8:0]      data     ;
always @(posedge clk or negedge rst_n)beginif(!rst_n)begindata <= 9'h1ff;endelse if(din_vld)begindata <= {din,1'b0};  //数据加上起始位endelse begindata <= data;end
end//并行转串行逻辑
always @(posedge clk or negedge rst_n)begin if(!rst_n)begintx <= 0;end else if(cnt_baud == 1)begin //每发送完1bit,就发送一个tx;tx <= data[cnt_bit];//LSP,低位先发end else if(end_cnt_bit)begin//处理停止位tx <= 1'b1;endelse begin tx <= tx;end
endendmodule

test.v

module test(input               clk     ,input               rst_n   ,input  wire [3:0]   cnt_byte,//现在输出第几个byte了output   reg           dout_vld,//表示200us间隔实现output   reg [7:0]  led_data//表示输出的数据
);
//总共需要发送15个字符,所以需要15的计数器//200us计数器
parameter   TIME_200uS = 1_000_0;
reg         [13:0]      cnt_200uS;
wire                    add_cnt_200uS;
wire                    end_cnt_200uS;
always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_200uS <= 0;end else if(add_cnt_200uS)begin if(end_cnt_200uS)begin cnt_200uS <= 0;endelse begin cnt_200uS <= cnt_200uS + 1;end endelse begincnt_200uS <= 0;end
end 
assign add_cnt_200uS = 1'b1;
assign end_cnt_200uS = add_cnt_200uS && cnt_200uS ==  TIME_200uS - 1;//定义输出数据//Hello Nios-II到串口always @(posedge clk or negedge rst_n)beginif(!rst_n)begindout_vld <= 1'b0;endelse if(end_cnt_200uS)begindout_vld <= 1'b1;case(cnt_byte)0     :   led_data = 8'b01001000;//H1     :   led_data = 8'b01100101;//e2     :   led_data = 8'b01101100;//l3     :   led_data = 8'b01101100;//l4     :   led_data = 8'b01101111;//o5     :   led_data = 8'b00100000;//space6     :   led_data = 8'b01001110;//N7     :   led_data = 8'b01101001;//i8     :   led_data = 8'b01101111;//o9      :   led_data = 8'b01110011;//s10      :   led_data = 8'b00101101;//-11      :   led_data = 8'b01001001;//I12      :   led_data = 8'b01001001;//I13      :   led_data = 8'b00001101;//\r14      :   led_data = 8'b00001010;//\ndefault :   led_data = 8'b0;endcaseendelse begindout_vld <= 1'b0;endendendmodule

top.v

module top(input           clk     ,input           rst_n   ,output          tx      
);wire    [7:0]           led_data    ;wire    [3:0]           cnt_byte   ;wire                   din_vld   ;uart_tx             inst_uart_tx(.clk            (clk      ),.rst_n          (rst_n    ),//in.din            (led_data),//如果串口占用时,uart_data.din_vld        (din_vld),
//out.cnt_byte       (cnt_byte),.tx           (tx     ) );test                inst_test(.clk            (clk        ),.rst_n          (rst_n      ),//in.cnt_byte       (cnt_byte),//out.led_data       (led_data   ),.dout_vld       (din_vld));endmodule

3.2 引脚

指定gpio口为tx和rx,编程实现硬件逻辑
在这里插入图片描述

3.3 效果

在这里插入图片描述

四 Nios2实现串口

4.1 sopc硬件设计

在这里插入图片描述

4.2 top文件

module nios2_uart_top(input			clk,input			rst_n,input			rxd,output		txd
);nios2_uart u0 (.clk_clk       (clk),       //   clk.clk.reset_reset_n (rst_n), // reset.reset_n.uart_rxd      (rxd),      //  uart.rxd.uart_txd      (txd)       //      .txd);
endmodule

4.3 软件代码

#include <stdio.h>
#include "unistd.h"
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_uart_regs.h"
#include "sys\alt_irq.h"/** 串口发送字符串函数* */
/*
void Uart_sendString(char *data, unsigned int len)
{alt_u8 i;for(i=0;i<len;i++){IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE, data[i]);	//数据发送完,将TRDY置为1while((IORD_ALTERA_AVALON_UART_STATUS(UART_BASE) & 0x40)!=0x40); //判断数据(TRDY==1)是否发送完毕}
}
*/int main()
{char *str = "hello Niosii!\r\n";while(1){alt_u8 j;for(j = 0; j < 17; j++){IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE, str[j]);	//数据发送完,将TRDY置为1while((IORD_ALTERA_AVALON_UART_STATUS(UART_BASE) & 0x40)!=0x40); //判断数据(TRDY==1)是否发送完毕}int i = 0;while(i<500000){i++;}}return 0;
}

4.4 实现效果

在这里插入图片描述

五 参考资料

1、正点原子视频
2、NiosII流水灯
3、NiosII串口

六 总结

verilog和nios-II比较下来,verilog编程的时候可以选择性的编程,比如我现在要串口传送,我可以只写一个串口传送就可以传出去,但是在细节方面比如时序很容易搞混,简洁但是要很细心,否则就是bug。Nios-II是添加ip核,使用已有的模块去建立程序逻辑,相当于模拟一个电脑,大致了解一下是能上手的。但是要深究还是有点难度的。相比较下来,nios-ii确实方便了一点点,并且它有点像拼图,把模块拼起来,然后软件编程实现。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3 查看真实请求地址

上回说到Vue2查看真实请求地址&#xff0c;那么Vue3该如何查看呢&#xff1f; 传送门&#xff1a; Vue2 查看真实请求地址 1. bypass函数 使用bypass函数获取代理结果&#xff0c;设置响应头&#xff08;请求头设置未生效&#xff0c;也可以在响应头上看&#xff09;。 2. …

软件全套资料梳理(需求、开发、实施、运维、安全、测试、交付、认证、评审、投标等)

软件全套精华资料包清单部分文件列表&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查单&#xff0c;用户需求说明书&#xff0c;概要设计说明书&#xff0c…

BGP学习一:关于对等体建立和状态组改变

目录 一.BGP基本概念 &#xff08;1&#xff09;.BGP即是协议也是分类 1.早期EGP 2.BGP满足不同需求 3.BGP区域间传输的优势 &#xff08;1&#xff09;安全性——只传递路由信息 &#xff08;2&#xff09;跨网段建立邻居 4.BGP总结 5.BGP的应用 &#xff08;1&#…

Coursera吴恩达深度学习专项课程01: Neural Networks and Deep Learning 学习笔记 Week 02

Week 02 of Neural Networks and Deep Learning Course Certificate 本文是学习 https://www.coursera.org/learn/neural-networks-deep-learning 这门课的笔记 Course Intro 文章目录 Week 02 of Neural Networks and Deep LearningLearning Objectives [1] Logistic Regres…

YOLOv8_seg预测流程-原理解析[实例分割理论篇]

YOLOv8_seg的网络结构图在博客YOLOv8网络结构介绍已经更新了,由网络结构图可以看到相对于目标检测网络,实例分割网络只是在Head层不相同,如下图所示,在每个特征层中增加了Mask层(浅紫色),这和同一层的Box,cls的shape大小一样;另外还利用8080尺度的特征图,经过卷积+上…

如何快速的追加文章的内容(在不知道内容的情况下)

首先&#xff0c;需要用到的这个工具&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 1、打开工具&#xff0c;切换到文章模块下&#xff0c;快捷键&#xff1a;Ctrl1 2、新建一个文章做演示&#xff0c;001 3、添加一个内容&#xff0c;就随便…

冯喜运:5.12黄金回撤继续上涨,下周原油走势分析

【黄金消息面分析】&#xff1a;本周&#xff0c;黄金市场迎来了自4月中旬以来的最佳单周表现。周五&#xff08;3月9日&#xff09;&#xff0c;金价攀升至2360.54美元/盎司&#xff0c;涨幅0.62%&#xff0c;而纽约商品交易所6月交割的黄金期货价格上涨1.5%&#xff0c;收报2…

bevformer详解(1):论文介绍

3D 视觉感知任务,包括基于多摄像头的3D检测和地图分割对于自动驾驶系统至关重要。本文提出了一种名为BEVFormer的新框架,它通过使用空间和时间的Transformer 学习统一的BEV表示来支持多个自动驾驶感知任务。简而言之,BEVFormer通过预定义的网格形式的Bev Query与空间和时间空…

No module named ‘sklearn.metrics.ranking‘ 解决方法

错误代码 from sklearn.metrics.classification import * from sklearn.metrics.ranking import * 错误原因 sklearn这个文件夹下的_classification和_ranking前面有下划线&#xff01; 解决方法 第一步&#xff1a;找到sklearn位置&#xff0c;可以打开命令行输入 pip sh…

使用 Spring Boot 配合策略模式增强系统接口扩展能力

使用 Spring Boot 配合策略模式增强系统接口扩展能力 在软件开发中&#xff0c;系统的可扩展性是一个至关重要的方面。而策略模式是一种常见的设计模式&#xff0c;它可以帮助我们实现灵活的算法选择和系统功能扩展。结合 Spring Boot 框架&#xff0c;我们可以更加方便地利用策…

systrace使用

systrace使用 chrome://tracing/ 抓trace方法 1.脚本 在sdk/platformtools/systrace文件目录下执行&#xff1a; python2 systrace.py -b 32000 -o setting_qian.html gfx input view webview wm am audio video camera app ss sched irq freq idle disk load sync workq reg…

Java入门基础学习笔记18——赋值运算符

赋值运算符&#xff1a; 就是“”&#xff0c;就是给变量赋值的&#xff0c;从右边往左边看。 int a 10; // 把数据赋值给左边的变量a存储。 扩展赋值运算符&#xff1a; 注意&#xff1a;扩展的赋值运算符隐含了强制类型转换。 package cn.ensource.operator;public class…

1062: 有向图的边存在判断

解法&#xff1a; #include<iostream> #include<vector> using namespace std; int arr[100][100]; int main() {int n;int x, y;cin >> n >> x >> y;for (int i 0; i < n; i) {for (int j 0; j < n; j) {cin >> arr[i][j];}}if …

后端常用技能:基于easy-poi实现excel一对多、多对多导入导出【附带源码】

0. 引言 在业务系统开发中&#xff0c;我们经常遇到excel导入导出的业务场景&#xff0c;普通的excel导入导出我们可以利用 apache poi、jxl以及阿里开源的easyexcel来实现&#xff0c;特别easyexcel更是将excel的导入导出极大简化&#xff0c;但是对于一些负载的表格形式&…

Linux配置两个局域网间的网络转发

网络拓扑如上图所示&#xff0c;有192.168.1.0(255.255.255.0)&#xff0c;192.168.2.0(255.255.255.0)两个局域网。若要使host1可直接通过ip地址访问host3&#xff0c;则需在host2中配置路由转发。 host2 配置静态路由&#xff08;系统一般会自动配置&#xff09; # 添加静…

WEB后端复习——JSP、EL、JSTL

JSP:Java Serve Pages(Java服务器页面) 运行在服务器的脚本、在静态网页HTML代码中嵌入java 优势特点 1.被编译后可以多次直接运行&#xff0c;代码执行效率高&#xff08;一次加载、多次可用&#xff09; 2.动态代码封装&#xff0c;组件可重用性高&#xff08;JavaBean EJ…

《Fundamentals of Power Electronics》——转换器的传递函数

转换器的工程设计过程主要由以下几个主要步骤组成&#xff1a; 1. 定义了规范和其他设计目标。 2. 提出了一种电路。这是一个创造性的过程&#xff0c;利用了工程师的物理洞察力和经验。 3. 对电路进行了建模。组件和系统的其他部分适当建模&#xff0c;通常使用供应商提供的…

前端AJAX与后台交互技术知识点及案例(续2)

以下笔记均为学习哔站黑马程序员AJAX视频所得&#xff01;&#xff01;&#xff01; AJAX作用&#xff1a;浏览器和服务器之间通信&#xff0c;动态数据交互 axios函数 先引入axios库&#xff0c;可在bootcdn中寻找相关js文件或者对应的script标签 axios({url:http://hmajax…

SpringBoot基于微信小程序的星座配对(源码)

博主介绍&#xff1a;✌程序员徐师兄、10年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447…

【Shell】shell编程之循环语句

目录 1.for循环 例题 2.while循环 例题 3.until循环 1.for循环 读取不同的变量值&#xff0c;用来逐个执行同一组命令 for 变量 in 取值列表 do 命令序列 done [rootlocalhost ~]# for i in 1 2 3 > do > echo "第 $i 次跳舞" > done 第 1 次跳舞 第 …