一步步学习zynq软硬件协同开发(AX7010/20)【FPGA篇】:FPGA控制流水灯及verilog基本语法学习

一、实验环境及目的

板卡:AX7010

Vivado版本:2017.1

开发机:I7  4.2GHZ  8GB  WIN10_X64

参考文档:《ALINX黑金ZYNQ7000开发平台配套教程》

实验目的:掌握ZYNQ PL端的开发流程,熟悉verilog的基本语法。

其实黑金给出了一个例子就是1S翻转一次四个LED等,这里我想通过控制一组LED灯的不同输出效果来学习verilog及fpga,所以需要做一些修改,虽然有不少操作系统驱动开发经验,但是因为是fpga部分的小白,所以还是从最基础的部分开始。以自己的学习经验来说,跟着教程刻板的做一遍是远远不够的,因为不会太多的去自己思考,遇到问题大多去论坛或者群里找技术支持,这种流程是我不太喜欢的,还是得有自主思考的过程。所以在黑金的实验基础上,实现一个流水灯的效果。

 

二、开发步骤

这部分可以参考黑金的教程,大致步骤如下:

    step1:创建vivado工程

    step2:选择RTL工程,勾选“do not specify sources at this time”

    step3:选择对应的芯片,速度等级,选择xxc7z010clg400-1

    step4:添加.v源文件,create design sources

    step5:添加xdc约束文件,create constraints

    step6:编译下载调试

 

三、源码分析及语法学习

led.v源码如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: cetc
// Engineer: xp_config
// 
// Create Date: 2018/11/26 21:44:45
// Design Name: 
// Module Name: led
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

//每隔1S翻转fpga端的led灯
module led(
    input sys_clk,//输入时钟 50MHZ
    output reg [3:0] led //四个LED灯
    );
    
reg [31:0] timer_cnt;

//led灯控制
always@(posedge sys_clk)//输入时钟的上升沿检测
begin
    if(timer_cnt >= 32'd49_999_999)//50Mhz晶振,50 000 000 - 1
   begin
        led <= ~led;
        timer_cnt <= 32'd0;
   end
   else
   begin
   led <= led;
   timer_cnt <= timer_cnt + 32'd1;
   end
end
endmodule
    

xdc约束文件:

set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]

set_property PACKAGE_PIN U18 [get_ports sys_clk]
set_property PACKAGE_PIN M14 [get_ports {led[0]}]
set_property PACKAGE_PIN M15 [get_ports {led[1]}]
set_property PACKAGE_PIN K16 [get_ports {led[2]}]
set_property PACKAGE_PIN J16 [get_ports {led[3]}]

看下一下涉及到的verilog的语法:

1.module

    只学过汇编和C语言的渣渣表示这个有点像一个功能函数模块的意思,有名称和输入参数,具体module的解释,我查了下书和资料,整理如下:

#    module是整个.v文件中的基本组成模块,是verilog设计的基本单元,以关键词module开始,以关键词endmodule结束

#    模块代表着硬件电路的运行实体,并且可以并行运行

#    模块可以分层,高层模块可以通过调用低层模块来实现复杂功能

#    各个模块的连接需要一个顶层模块——top module

#    复杂模块可以划分成多个简单的模块

2.module的结构

module <模块名称>(<端口列表>);

<定义>

<模块条目>

endmodule

<模块名>是模块唯一的标识符;

<端口列表>是输入、输出和双向端口的列表,这些端口用来与其他模块进行连接。

<定义>是一段程序,用来指定数据对象为寄存器型、存储器型、线型以及过程块,诸如函数块和任务块;

<模块条目>也是一段程序,将上面<定义>和<端口>组合起来,是说明这个模块要做什么的语句;

endmodule之后没有分号,在端口列表之后的括号后面有分好。

这里我们定义的模块名称为led,端口列表为:input sys_clk和output reg[3:0]

3.verilog中的基本语法

3.1 reg    

这里reg我暂时理解就为c语言里面的变量,是一块内存,长度为4,每一个bit对应一个led的高低电平。关于reg的用法,整理如下:

    reg型数据保持最后一次的赋值,用于always过程赋值语句中。

    暂时我只想记住这一点,多了一时也理解不了。

3.2 input和output

    类似C函数的输入参数,input是外部输入的信号,output是内部输出到外部的信号,指定了信号的方向。

3.3 alway@

    这里应该是只要满足时钟输入,并且在上升沿的时候,一直循环执行

3.3 begin和end

    我理解的是一个bebin必须对应一个end,就像C语言中的大括号{}

3.4 数字表达式

    <位宽><进制><数字>

    32'd49_999_999//表示该数字为10进制,位宽32位,值为49999999。

    不过这种定义方法和C一样,要注意越界的问题。

    'b 二进制

    'd 十进制

    'h 十六进制

3.5 =和<=

阻塞赋值语句(“=”)和非阻塞赋值语句(“<=”)
阻塞:在本语句中“右式计算”和“左式更新”完全完成之后,才开始执行下一条语句;
非阻塞:当前语句的执行不会阻塞下一语句的执行。

 

四、改个流水灯

    其实这里想到就是一个移位操作,查了下,verilog的移位操作就是<<,那么在每次进入led赋值的时候,进行一个移位,加入全部为零了,那么在从0001开始,这样一秒就一次变化就会有一个流水灯。

    代码如下,其实改的很简单:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: reworks
// Engineer: xp_config
// 
// Create Date: 2018/11/26 21:44:45
// Design Name: 
// Module Name: led
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

//每隔1S翻转fpga端的led灯
module led(
    input sys_clk,//输入时钟 50MHZ
    output reg [3:0] led //四个LED灯
    );
    
reg [31:0] timer_cnt;

//led灯控制
always@(posedge sys_clk)//输入时钟的上升沿检测
begin
   if(timer_cnt >= 32'd49_999_999)//50Mhz晶振,50 000 000 - 1
   begin
        led <= led <<1;      //1S时间到移位操作
        if(led == 4'b0000)
        led <= 4'b0001;
        timer_cnt <= 32'd0;
   end
   else
   begin
        led <= led;
        timer_cnt <= timer_cnt + 32'd1;
   end
end
endmodule
    










 over...

 

 

 

你可能感兴趣的:(Fpga,ARM驱动开发)