Nios实验入门——用Verilog编程方式完成LED流水灯显示并使用串口输出“Hello Nios-II”字符到笔记本电脑

news2024/12/24 3:14:41

文章目录

  • 前言
  • 一、Verilog编程方式完成LED流水灯显示
    • 1.1 新建工程并添加FPGA芯片
    • 1.2 新建.v文件并添加至顶层实体
    • 1.3 引脚分配
    • 1.4 编译(包含分析与综合)
    • 1.5 选择烧录器
    • 1.6 添加烧录文件
    • 1.7 下载
    • 1.8 实验现象
  • 二、Verilog编程方式实现串口
    • 2.1 uart_tx.v文件
    • 2.2 test.v文件
    • 2.3 top.v顶层文件
    • 2.5 串口代码讲解
    • 2.4 引脚分配
    • 2.5 实验现象
  • 总结


前言

主要目的:
(1)学习 Quartus Prime 、Platform Designer、Nios II SBT 的基本操作;
(2)初步了解 SOPC 的开发流程,基本掌握 Nios II 软核的定制方法;
(3)掌握 Nios II 软件的开发流程,软件的基本调式方法。

主要内容

  • 在DE2-115开发板上用Nios软件编程方式完成LED流水灯显示
  • 用Verilog编程方式通过DE2-115开发板串口输出“Hello Nios-II”字符到笔记本电脑串口助手

一、Verilog编程方式完成LED流水灯显示

1.1 新建工程并添加FPGA芯片

打开quartus新建工程:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一直next,到选择型号界面。
选择芯片型号,根据实际情况选择
在这里插入图片描述
点击finish
在这里插入图片描述

在这里插入图片描述

1.2 新建.v文件并添加至顶层实体

在这里插入图片描述

在这里插入图片描述

代码如下:

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)begin
        if(!sys_rst_n) begin
            cnt <= 25'b0;
        end
        else if(add_cnt) begin
            if(end_cnt) begin
                cnt <= 25'b0;
            end
            else begin
                cnt <= cnt+1'b1;
            end
        end
        else begin
            cnt <= cnt;
        end
    end

    // 异步复位
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)begin
            cnt1 <= 3'b0;
        end
        else if(add_cnt1) begin
            if(end_cnt1)begin
                cnt1 <= 3'b0;
            end
            else begin
                cnt1 <= cnt1 + 1'b1;
            end
        end
    end

    always @(posedge sys_clk or negedge sys_rst_n)begin
        if(!sys_rst_n)begin
            led <= 8'b0;
        end
        else begin
            case (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;
            endcase
        end
    end


    assign 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

在这里插入图片描述

在这里插入图片描述

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

1.3 引脚分配

在这里插入图片描述
引脚如下:
在这里插入图片描述

1.4 编译(包含分析与综合)

在这里插入图片描述

在这里插入图片描述

1.5 选择烧录器

在这里插入图片描述

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

1.6 添加烧录文件

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

1.7 下载

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

1.8 实验现象

Verilog编程方式完成LED流水灯显示

在这里插入图片描述

二、Verilog编程方式实现串口

项目创建同第一章的LED流水灯

示例串口代码如下:

2.1 uart_tx.v文件

uart_tx.v 代码如下:

//波特率为115200bps,即每秒传送115200bit的数据,传送1bit数据需要434个时钟周期
//tx内部是并行数据,需要串行传出去,一般数据格式是1bit的起始位,8bit的数据位,1bit的停止位
//所以需要一个8bit的计数器,计算传送了多少个bit,起始位是低电平有效,停止位是持续的高电平
//需要接收8bit的数据
//需要1bit的传送出去
module uart_tx(
    input               clk     ,
    input               rst_n   ,

//in
    input    [7:0]      din ,//要发送的数据
    input               din_vld,//数据有效

//out
    output  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)begin
         cnt_baud <= 0;
    end 
    else if(add_cnt_baud)begin 
        if(end_cnt_baud)begin
            cnt_baud <= 0;
        end
        else begin
            cnt_baud<=cnt_baud+1;
        end
    end 
    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)begin
    if(!rst_n)begin
        flag <= 1'b0;
    end
    else if(din_vld)begin
        flag <= 1'b1;
    end
    else if(end_cnt_bit)begin
        flag <= 1'b0;
    end
    else begin
        flag <= 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)begin
         cnt_bit <= 0;
    end 
    else if(add_cnt_bit)begin 
        if(end_cnt_bit)begin
            cnt_bit <= 0;
        end
        else begin
            cnt_bit <= cnt_bit + 1;
        end
    end 
    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)begin
         cnt_byte <= 0;
    end 
    else if(add_cnt_byte)begin 
        if(end_cnt_byte)begin
            cnt_byte <= 0;
        end
        else begin
            cnt_byte <= cnt_byte + 1;
        end
    end 
    else begin 
        cnt_byte <= cnt_byte;
    end 
end

assign      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)begin
    if(!rst_n)begin
        data <= 9'h1ff;
    end
    else if(din_vld)begin
        data <= {din,1'b0};  //数据加上起始位
    end
    else begin
        data <= data;
    end
end

//并行转串行逻辑
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
         tx <= 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;
    end
    else begin 
        tx <= tx;
    end
end


endmodule

2.2 test.v文件

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)begin
        cnt_200uS <= 0;
    end 
    else if(add_cnt_200uS)begin 
        if(end_cnt_200uS)begin 
            cnt_200uS <= 0;
        end
        else begin 
            cnt_200uS <= cnt_200uS + 1;
        end 
    end
    else begin
        cnt_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)begin
        if(!rst_n)begin
            dout_vld <= 1'b0;
        end
        else if(end_cnt_200uS)begin
            dout_vld <= 1'b1;
            case(cnt_byte)
                 0     :   led_data = 8'b01001000;//H
                 1     :   led_data = 8'b01100101;//e
                 2     :   led_data = 8'b01101100;//l
                 3     :   led_data = 8'b01101100;//l
                 4     :   led_data = 8'b01101111;//o
                 5     :   led_data = 8'b00100000;//space
                 6     :   led_data = 8'b01001110;//N
                 7     :   led_data = 8'b01101001;//i
                 8     :   led_data = 8'b01101111;//o
                 9      :   led_data = 8'b01110011;//s
                10      :   led_data = 8'b00101101;//-
                11      :   led_data = 8'b01001001;//I
                12      :   led_data = 8'b01001001;//I
                13      :   led_data = 8'b00001101;//\r
                14      :   led_data = 8'b00001010;//\n
                default :   led_data = 8'b0;
            endcase
        end
        else begin
            dout_vld <= 1'b0;
        end
    end
endmodule

2.3 top.v顶层文件

**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

2.5 串口代码讲解

波特率(Band Rate):
串口协议中很重要的一点就是波特率,波特率的概念是每秒钟传送码元的个数,就是一秒钟传输了几个二进制的个数,他的单位是Bit/s和bps两种。常见的串口速度有115200bps 9600bps等等,串口(RS232)的最大传输速率是 115200bps,表示一秒钟传输了115200个二进制 。
波特率和字节的关系
1GB=1024MB
1MB=1024KB
1KB=1024B(字节)

我们需要串口接收的数据数每秒512字节,串口的波特率是115200位/秒

波特率115200=115200(位/秒)

如果没有校验位,就应该除以10,得到的是每秒字节数:波特率115200=115200(位/秒)=11520(字节/秒)

再除以1024,就是每秒KB数:波特率115200=115200(位/秒)=11.25(KB/秒)也就是满足每秒可以接收512字节。

在Verilog代码中,我们只需要理解计算这两个值就可以完成串口代码的梳理, 假设我们FPGA使用的是50MHZ的系统时钟 波特率使用的是9600bps 传输一个bit需要的时钟周期个数是50_000_000/9600个个数,得到个数之后再用这个个数乘以周期的时间便是传输1bit需要的时间50_000_000/9600*20便是1bit需要的时间。

Uart通信协议
1.串口通信的信号线只需要两条线就可以完成,TX和RX TX发送端 RX为接收端。
2.起始位,数据线从高变低,低有效为0,数据传输开始。
3.数据位,起始位传输之后便是数据位开始,一般为8位,传输时低位(LSB)在前,高位(MSB)在后。
4.校验位,校验位可以认为是一个特殊的数据位,通常使用的是奇偶校验,使用串口协议时通常取消奇偶校验位。
5.停止位,停止位高有效为1,他表示这一个个字节传输结束。
6.位时间,起始位、数据位、校验位的位宽度是一致的,停止位有0.5位、1位、1.5位格式,一般为1位。
7.空闲位,持续的高电平。
7.帧:从起始位开始到停止位结束的时间间隔称之为一帧。
在这里插入图片描述

将8位或者多位数据拆分为一位一位的发送出去的过程称为并转串。将一位一位接收的数据合并为8位或者多位数据的过程称为串转并。
对于串行通信设备来说,发送方都是在执行并转串,接收方都是在执行串转并。
UART设备为串行通信设备。

2.4 引脚分配

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

2.5 实验现象

程序代码的编译及运行同LED流水灯显示一样

实现效果如下:
在这里插入图片描述


总结

在比较Verilog和Nios-II两种硬件描述语言(HDL)时,我们可以从它们的编程方式、易用性、灵活性以及对细节的要求等方面进行阐述。

Verilog编程

  • 选择性实现:Verilog提供了高度的灵活性,允许开发者根据需要选择性地实现特定的硬件功能,例如只编写串口通信部分的代码。
  • 时序敏感:Verilog编程需要对时序有非常精确的控制和理解,这要求开发者在编写代码时非常细心,以避免潜在的bug。
  • 简洁性:虽然Verilog代码可以非常简洁,但这也意味着开发者需要对硬件设计有深入的理解,才能确保设计的准确性。

Nios-II编程

  • 模块化设计:Nios-II采用模块化的IP核,使得开发者可以通过组合现成的模块来构建复杂的系统,类似于构建一个微型计算机。
  • 易用性:对于初学者来说,Nios-II相对容易上手,因为它提供了一种类似于拼图的编程方式,通过软件编程来实现硬件逻辑。
  • 深入理解的挑战:尽管Nios-II在表面上看起来简单,但要深入理解其内部工作原理和优化性能,仍然需要相当的专业知识和经验。

综合比较

  • 灵活性与控制:Verilog提供了更多的控制和灵活性,但这也意味着需要更高的专业知识和对细节的关注。
  • 易用性与构建速度:Nios-II通过提供预构建的模块和软件编程接口,简化了硬件开发过程,使得构建速度更快,但可能牺牲了一定的定制性。
  • 学习曲线:Verilog的学习曲线可能更陡峭,因为它要求开发者对硬件设计有更深入的理解;而Nios-II则提供了一个较为平缓的学习曲线,使得新手也能较快地开始项目开发。

总的来说,Verilog和Nios-II各有优势,选择哪一种取决于项目的具体需求、开发者的专业知识以及对开发时间和定制性的要求。

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

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

相关文章

海外客户开发渠道有哪些

海外客户开发是一个多元化的过程&#xff0c;涉及线上与线下多个渠道。以下是一些有效的海外客户开发渠道&#xff1a; 平台电商&#xff1a; 利用国际B2B电商平台&#xff0c;如阿里巴巴国际站、 Globalsources、Made-in-China等&#xff0c;这些平台拥有庞大的国际买家流量&a…

linux phpstudy 重启命令

[rootLinuxWeb phpstudy]# ./system/phpstudyctl restart 查看命令 1) phpstudy -start 启动小皮面板 2) phpstudy -stop 停止小皮面板 3) phpstudy -restart 重启小皮面板 4) phpstudy -status 查询面板状态 5) phpstudy -in…

速锐得深入解析吉利几何CAN总线数据通信网络的拓扑层级框架技术

在现代汽车工业中&#xff0c;车辆的电子控制单元&#xff08;ECU&#xff09;之间的通信至关重要。这种通信大多通过控制器局域网络&#xff08;CAN&#xff09;总线实现&#xff0c;它是德国BOSCH公司于20世纪80年代初开发的一种串行数据通信协议。随着技术的不断进步&#x…

平面设计基础指南:从零开始的学习之旅!

平面设计师主要做什么&#xff1f; 平面设计师通过创建视觉概念来传达信息。他们创造了从海报和广告牌到包装、标志和营销材料的所有内容&#xff0c;并通过使用形状、颜色、排版、图像和其他元素向观众传达了他们的想法。平面设计师可以在内部工作&#xff0c;专门为品牌创建…

计算机Java项目|Springboot学生读书笔记共享

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、Python项目、前端项目、人工智能与大数据、简…

图数据库原理在构建实体血缘关系图中的应用与实践

在当今复杂的数据驱动型应用中&#xff0c;理解和管理实体间的复杂关系变得日益重要。通过低代码平台进行配置的应用&#xff0c;因采用了DSL语言进行统一设计&#xff0c;要让专业开发者和非专业开发者都能快速实现复杂应用的构建&#xff0c;实体之间的数据逻辑和关系梳理就尤…

Android adb shell关于CPU核的命令

Android adb shell关于CPU核的命令 先使用命令&#xff1a; adb shell 进入控制台。 然后&#xff0c;直接在$后面输入下面命令&#xff0c;针对CPU的命令。 cat /proc/cpuinfo | grep ^processor | wc -l 查看当前手机的CPU是几核的。 cat sys/devices/system/cpu/online …

【云原生】Kubeadm搭建K8S

一、部署Kubernetes 实验环境 服务器主机名IP地址主要组件k8s集群master01 etcd01master01192.168.10.100kube-apiserver kube-controller-manager kube-schedular etcdk8s集群node01 etcd02node01192.168.10.101kubelet kube-proxy docker flannelk8s集群node02 etcd03nod…

win server服务器 关闭危险端口 135,137,138,139,445的方法

通过防火墙来控制 打开控制面板 选择检查防火墙状态 选择高级设置 选择入站规则&#xff0c;再新建规则 选择端口&#xff0c;下一步 选择端口应用于啥协议&#xff0c;再指定端口&#xff0c;再下一步 选择阻止连接&#xff0c;下一步 下一步 给规则别名一下&#xff0c;方便…

【谷粒商城】04.快速开发

1.克隆代码 https://gitee.com/renrenio DELLLJL MINGW64 ~/Desktop $ git clone https://gitee.com/renrenio/renren-fast.git Cloning into renren-fast... remote: Enumerating objects: 1965, done. remote: Counting objects: 100% (1965/1965), done. remote: Compress…

齐护K210系列教程(十八)_识别条码

识别条码 联系我们 将识别到的条形码内容打印输出并显示 测试条形码可以到如下网站得到&#xff1a;http://www.jsons.cn/barcode/ 4&#xff0c;课程资源 课程程序下载&#xff1a;【18条形码】 联系我们 扫码 或者点这里加群了解更多&#xff01; Created by qdprobot

2024年3月 青少年等级考试机器人理论真题四级

202403 青少年等级考试机器人理论真题四级 第 1 题 Arduino UNO/Nano主控板&#xff0c;通过按键开关切换高低电平&#xff0c;电路搭设如下&#xff0c;该电路属于&#xff1f;&#xff08; &#xff09; A&#xff1a;外部上拉电阻电路 B&#xff1a;外部下拉电阻电路 C&a…

Docker 入门篇(八)-- Docker Compose 使用指南

一、Docker Compose 简介 Docker Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose&#xff0c;您可以使用 YML 文件来配置应用程序需要的所有服务。然后&#xff0c;使用一个命令&#xff0c;就可以从 YML 文件配置中创建并启动所有服务。 Compose 使用…

Android:资源的管理,Glide图片加载框架的使用

目录 一&#xff0c;Android资源分类 1.使用res目录下的资源 res目录下资源的使用&#xff1a; 2.使用assets目录下的资源 assets目录下的资源的使用&#xff1a; 二&#xff0c;glide图片加载框架 1.glide简介 2.下载和设置 3.基本用法 4.占位符&#xff08;Placehold…

Linux信号概念,信号的产生异常情况,信号的保存,信号的处理,捕捉信号,可重入函数,volatile,SIGCHLD信号

文章目录 信号的概念谈谈硬件 信号的产生1. 键盘组合键2. kill命令3. 系统调用异常4. 由硬件异常产生信号5. 由软件异常产生信号Core Dump 信号的保存sigset_t信号集操作函数sigprocmasksigpending 信号的处理重谈地址空间 捕捉信号1. 内核如何实现信号的捕捉2. sigaction问题一…

重磅 | 国家标准《网络安全技术 零信任参考体系架构》正式发布

根据2024年4月25日国家市场监督管理总局、国家标准化管理委员会发布的中华人民共和国国家标准公告&#xff08;2024年第6号&#xff09;&#xff0c;其中易安联参编的国家标准GB/T 43696-2024《网络安全技术 零信任参考体系架构》正式发布&#xff0c;并于2024年11月1日正式施行…

基于Python实现蔬菜水果识别

蔬菜水果识别在农业生产、食品加工和市场销售等领域具有重要意义。随着计算机视觉和机器学习技术的发展,利用图像识别技术实现蔬菜水果的自动化识别已成为可能。 目录 引言研究背景问题陈述研究目标文献综述蔬菜水果识别的相关研究概述基于计算机视觉和机器学习的图像识别方法…

SCQA表达模型:让你的表达更具吸引力(2)

一、引言 站在巨人的肩膀上&#xff0c;思维模型是前人智慧结晶&#xff0c;当我们面对相似挑战时&#xff0c;借鉴与模仿这些模型&#xff0c;往往能为我们带来意想不到的结果。 在信息爆炸的时代&#xff0c;如何高效、准确地传达信息成为了人们关注的焦点。SCQA表达模型作为…

企业网站HTTP网站业务被慢连接攻击了该怎么办

企业的网站建设中遇到网络攻击会出现哪些问题&#xff1f;一些中小型企业对于网络安全的认知不足&#xff0c;网站建设种类众多&#xff0c;电子商城类&#xff0c;小型游戏&#xff0c;支付类型&#xff0c;H5页面的网站&#xff0c;开发等等&#xff0c;如遇见网络攻击造成的…

LOTO示波器软件PC缓存(波形录制与回放)功能

当打开PC缓存功能后, 软件将采用先进先出的原则排队对示波器采集的每一帧数据, 进行帧缓存。 当发现屏幕中有感兴趣的波形掠过时, 鼠标点击软件的(暂停)按钮, 可以选择回看某一帧的波形。一帧数据的量 是 当前用户选择时基档位缓冲区总数据大小。不同时基档位缓冲区大小不同&am…