Verilog(未完待续)

这篇具有很好参考价值的文章主要介绍了Verilog(未完待续)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Verilog教程

这个教程写的很好,可以多看看。本篇还没整理完。

一、Verilog简介

什么是FPGA?一种可通过编程来修改其逻辑功能的数字集成电路(芯片)

与单片机的区别?对单片机编程并不改变其地电路的内部结构,只是根据要求实现的功能来编写运行的程序(指令)。举例:单片机就两个uart,但是我想用4个uart,单片机就没办法了。

什么是HDL?(hardware description language)硬件描述语言,用于描述数字电路结构和功能的语言。

Verilog和C的区别?Verilog硬件描述语言,在编译下载到FPGA之后,会生成电路,所以Verilog是并行运行的。C语言软件编程语言,编译下载到单片机之后,是存储器中的一组指令。而单片机处理软件指令需要取指、译码、执行,这个过程是串行执行的。


二、Verilog基础语法

2.1基础知识

2.1.1 逻辑值

0:逻辑0,逻辑假。

1:逻辑1,逻辑真。

X:未知,高或低。

Z:高阻态,外部没有激励信号,是一个悬空状态。

2.1.2 数值表示

二进制(b)、八进制(o)、十进制(d)、十六进制(h)。

举例:
8'b10101010
16'h10c8_fc9a
//_可以增加可读性

//直接写数字,默认十进制。
//不指定位宽,编译器自动分配

//负数,按位取反加一,符号位在最高位。
-15 = -5'b10001

//科学计数法
1.2e4 //12000

//字符串
reg[15*8-1:0] string;
initial begin
    string = "Hello World!";
end

2.1.3 标识符

用于定义模块名、端口名、信号名。

字母、数字、$符号、_下划线。第一个字符必须是字母或者下划线。

严格区分大小写。

不建议大小写混合使用。

普通内部信号建议全部小写。

2.2 数据类型

2.2.1 线网类型wire

  • 线网类型便是结构实体之间的物理连线。不能存储值,它的值由驱动的元件所决定。
  • 驱动线网类型变量的元件有门、连续赋值语句、assign等。
  • 如果没有驱动元件连接到线网类型的变量上,则该变量就是高阻态。

2.2.2 寄存器类型reg

  • 数据存储单元,默认初始值是不定值x。未写位宽的时候默认32位。无符号数。
  • reg类型数据只能在always和initial中赋值。
  • 如果该过程语句描述的是时序逻辑,即always语句带有时钟信号,则该寄存器变量对应为触发器。
  • 如果该过程语句描述的是组合逻辑,即always语句不带有时钟信号,则该寄存器变量对应为硬件连线。

2.2.3 向量

  • 位宽大于1,wire和reg可以声明为向量的形式:
wire[3:0]     add;
reg[7:0]      data;
  • [bit+: width] : 从起始 bit 位开始递增,位宽为 width。
  • [bit-: width] : 从起始 bit 位开始递减,位宽为 width。
  • 向量组合需要{}括起来。

2.2.4 数组

  • <数组名>[<下标>]
reg[7:0]     counter[3:0];//3个8bit数组
wire         data[7:0][3:0];二维数组
reg[31:0]    data_bits[7:0][2:0][3:0];三维数组

//赋值
counter[3] = 4'hF ;  //将数组counter中第4个元素的值赋值为4bit 十六进制数F,等效于counter[3][3:0] = 4'hF,即可省略宽度;
assign data[0][1]     = 1'b1;  //将数组data的第1行第2列的元素赋值为1,这里不能省略第二个访问标号,即 assign data[0] = 1'b1; 是非法的。

2.2.5 整数,实数,时间

  • 整数(integer):32bit,有符号数。可以用来定义for循环的i。
  • 实数(real):默认值为0。
  • 时间(time):64bit,通过调用系统函数 $time 获取当前仿真时间。

2.2.6 参数类型localparam、parameter

常量,类似#define。可以一次定义多个参数,参数与参数之间需要用逗号隔开。每个参数定义的右边必须是一个常数表达式。

#

1.参数的传递

模块定义的时候传入参数,模块实例化的时候传入参数。

2.时序仿真中的延时

//延时2.5个时间单位后执行sys_clk_i信号的翻转
always #2.5 sys_clk_i = ~sys_clk_i;

2.3操作符

操作符 操作符合 优先级 说明
单目运算 + - ! ~ 最高
乘、除、取模 * / %
加减 + -
移位 <<  >> <<< >>> 注意:逻辑右移时,左边高位会补 0;而算术右移时,左边高位会补充符号位。左移(<<),右移(>>),算术左移(<<<),算术右移(>>>)
关系 <  <=  >  >=
等价 ==  !=  ===  !===
归约 & ~& 对这个操作数逐位进行操作
^ ~^
| ~|
逻辑 &&
||
条件 ?: 最低

拼接运算符:{}。{a,b[3:0]}

2.3.1优先级

Verilog(未完待续),嵌入式开发,fpga

2.4编译指令

1.`define,`undef,`ifdef,`elsif,`else,`endif同C语言

2.`include同C语言

3.`timescale

用于定义时延、仿真的单位和精度

`timescale      time_unit / time_precision
  • time_unit 表示时间单位,time_precision 表示时间精度,
  • 单位 s(秒),ms(毫秒),us(微妙),ns(纳秒),ps(皮秒)和 fs(飞秒)。
  • 时间单位≥时间精度
  • 编译过程中,`timescale会影响后面的模块中的时延值。直到遇到另一个`timescale或者`resetall。
  • 没有默认的`timescale,没有指定的情况下,会继承前面编译模块的`timescale参数,可能导致设计出错。
  • 一个设计多个模块都有`timescale时,时延单位不受影响,但是时延精度会换算成最小时延精度
  • 如果有并行子模块,子模块间的 `timescale 并不会相互影响。
  • 时间精度设置是会影响仿真时间的。时间精度越小,仿真时占用内存越多,实际使用的仿真时间就越长。所以如果没有必要,应尽量将时间精度设置的大一些。
  • 如果延时时间的最小位数小于时间精度,将会四舍五入。例如时间单位为10ns,精度为1ns,#1.04表示延时1.04个时间单位=1.04x10ns=10.4ns,但精度无法表示0.1ns,#1.04≈10ns

4.`default_nettype

//将没有被声明的连线定义为线网类型
`default_nettype wand 

//将没有被声明的连线定义为线与类型
`default_nettype none

5.`resetall

该编译器指令将所有的编译指令重新设置为缺省值。使用该指令可以防止`timescale传递。

6.`celldefine, `endcelldefine

将模块标记为单元模块。


三、程序框架

3.1Verilog注释

//、/**/、

3.2Verilog关键字

Verilog(未完待续),嵌入式开发,fpga

Verilog(未完待续),嵌入式开发,fpga

3.3Verilog程序框架

模块的结构

一个模块由两部分组成:一部分描述接口,一部分描述逻辑功能。

端口定义、IO说明、内部信号声明、功能定义。

Verilog(未完待续),嵌入式开发,fpga

模块的调用

Verilog(未完待续),嵌入式开发,fpga


四、高级知识点

4.1结构语句

1. initial

  • 只执行一次。
  • 常用于测试文件的编写,用来产生仿真测试信号(激励信号),或者用于对存储器变量赋初值。

2. always

  • 一直不断地重复活动。
  • 但是只有和一定的时间控制结合在一起才有作用。
  • always时间控制可以是沿触发或者电平触发。敏感列表
  • 沿触发:多个信号中间要用or连接。(posedge,negedge)
  • 电平触发:(*)

4.2赋值语句

always 时序逻辑块中多用非阻塞赋值,always 组合逻辑块中多用阻塞赋值。

1.阻塞赋值(与C语言一样)

b = a;

描述组合逻辑时,用阻塞赋值。

2.非阻塞赋值(并行同时赋值)

b <= a;

只能用于对寄存器类型的变量进行赋值,只能用于initial和always中。

描述时序逻辑时,用非阻塞赋值。

注意:在同一个always块中不要既用非阻塞赋值又要阻塞赋值,不允许在多个always块中对同一个变量进行赋值。

组合逻辑

任意时刻输出仅仅取决于该时刻的输入,与电路原来的状态无关。

时序逻辑

任意时刻的输出不仅取决于当时的输入信号,而且还取决于电路原来的状态。或者说还与之前的输入有关,因此时序逻辑必须具备记忆功能。

4.3 时序控制

  • 时延
常规时延:该语句需要等待一定时间,然后将计算结果赋值给目标信号。
#delay a = b;
或者
#delay;
a = b;


内嵌时延:该语句先将计算结果保存,然后等待一定的时间后赋值给目标信号。
a = #delay b;
  • 边沿触发事件控制
一般事件控制:用@表示

//在信号clk上升沿时刻,执行q<=d,正边沿D触发器模型
always @(posedge clk) q <= d ;  
//在信号clk下降沿时刻,执行q<=d,负边沿D触发器模型
always @(negedge clk) q <= d ;


命名事件控制:用户可以声明 event(事件)类型的变量,并触发该变量来识别该事件是否发生。
命名事件用关键字 event 来声明,触发信号用 -> 表示。

event     start_receiving ;
always @( posedge clk_samp) begin
        -> start_receiving ;       //采样时钟上升沿作为时间触发时刻
end
 
always @(start_receiving) begin
    data_buf = {data_if[0], data_if[1]} ; //触发时刻,对多维数据整合
end


敏感列表:
当多个信号或事件中任意一个发生变化都能够触发语句的执行时,
用关键字 or 连接多个事件或信号。这些事件或信号组成的列表称为"敏感列表"。
or 也可以用逗号 , 来代替。
当敏感列表中变量较多时,@*或@(*)。
  • 电平敏感事件控制
initial begin
    wait (start_enable) ;      //等待 start 信号
    forever begin
        //start信号使能后,在clk_samp上升沿,对数据进行整合
        @(posedge clk_samp)  ;
        data_buf = {data_if[0], data_if[1]} ;      
    end
end

语句块

顺序块:顺序执行,非阻塞赋值除外。
begin 
end

并行块:并行执行,阻塞赋值也并行执行。
fork
join

命名块
命名块的禁用:disable

4.4 条件语句

条件语句必须在过程块(initial、always)中使用。

if-else

0,x,z按假处理。

if和else后面可以用begin end包含多个语句。

case

位宽必须相等。

casez,不用考虑表达式中的高阻值。

casex,不用考虑高阻值z和不定值x。

4.5 函数

  • 只能在模块中定义,位置任意,并在模块的任何地方引用,作用范围也局限于此模块
  • 不含有任何延迟、时序或时序控制逻辑
  • 至少有一个输入变量
  • 只有一个返回值,且没有输出
  • 不含有非阻塞赋值语句
  • 函数可以调用其他函数,但是不能调用任务
//声明
function [range-1:0]     function_id ;
input_declaration ;
 other_declaration ;
procedural_statement ;
endfunction

//调用
function_id(input1, input2, …);

4.6 任务

  • 任务的输入输出可以没有或者多个,且端口声明可以为 inout 型
  • 不能出现initial和always过程块。但可以包含其他时序控制,如延时语句。
  • 任务可以调用函数和任务。
  • 任务可以作为一条单独的语句出现语句块中。

4.5.1 任务声明

任务在模块中任意位置定义,并在模块内任意位置引用,作用范围也局限于此模块。

模块内子程序出现下面任意一个条件时,则必须使用任务而不能使用函数

  • 1)子程序中包含时序控制逻辑,例如延迟,事件控制等
  • 2)没有输入变量
  • 3)没有输出或输出端的数量大于 1

对 output 信号赋值时也不要用关键字 assign。为避免时序错乱,建议 output 信号采用阻塞赋值。

task       task_id ;
    port_declaration ;
    procedural_statement ;
endtask
task xor_oper_iner(
    input [N-1:0]   numa,
    input [N-1:0]   numb,
    output [N-1:0]  numco  ) ; 
    #3  numco       = numa ^ numb ;
endtask

4.5.2 任务调用

task_id(input1, input2, …,outpu1, output2, …);

输入端连接的模块内信号可以是 wire 型,也可以是 reg 型。输出端连接的模块内信号要求一定是 reg 型

4.7 状态机

4.7.1状态机概念FSM

在有限个状态之间按一定规律转换的时序电路

4.7.2状态机模型

Verilog(未完待续),嵌入式开发,fpga

状态寄存器由一组触发器组成,用来记忆状态机当前所处的状态,状态的改变只发生在时钟的跳变沿。

4.7.3状态机设计

状态空间定义

状态跳转(时序逻辑)

下个状态判断(组合逻辑)

各个状态下的动作

Verilog(未完待续),嵌入式开发,fpga

竞争和冒险

竞争:在组合逻辑电路中,不同路径的输入信号传输到同一个门电路时,到达时间可能会不同,这种情况称为竞争。

冒险:竞争的存在导致输出信号需要一段时间才能达到期望值,这一段时间可能产生错误的输出。

判断方法

代数法:例如:Y=A+A`或Y=AA`,A的状态改变,会导致电路存在竞争冒险。

卡诺图法:卡诺图是首尾相邻的。

Verilog(未完待续),嵌入式开发,fpga

Verilog(未完待续),嵌入式开发,fpga

 消除方法:

6.4 Verilog 竞争与冒险 | 菜鸟教程 (runoob.com)

  • 增加滤波电容,滤除窄脉冲
  • 修改逻辑,增加冗余量:增加卡诺圈
  • 使用时钟同步电路,利用触发器进行打拍延迟
  • 采用格雷码计数器

Verilog书写规范

  • 时序电路建模时,用非阻塞赋值。
  • 组合逻辑建模时,用阻塞赋值。
  • 在同一个 always 块中建立时序和组合逻辑模型时,用非阻塞赋值。
  • 在同一个 always 块中不要既使用阻塞赋值又使用非阻塞赋值。
  • 不要在多个 always 块中为同一个变量赋值。
  • 避免 latch (锁存器)产生。

Verilog(未完待续),嵌入式开发,fpga

Latch 的主要危害有:

  • 输入状态可能多次变化,容易产生毛刺,增加了下一级电路的不确定性;
  • 在大部分 FPGA 的资源中,可能需要比触发器更多的资源去实现 Latch 结构;
  • 锁存器的出现使得静态时序分析变得更加复杂。

组合逻辑中,if结构不完整(时序逻辑不会产生latch)

  • 补全if-else结构
  • 对信号赋初值

组合逻辑中,case结构不完整(case选项列表不全且没有加default,或多个赋值语句不完整)

  • 补全case选项列表
  • 对信号赋初值

原信号赋值或判读

  • 避免这种写法,使用临时变量,延时一个时钟周期进行赋值。

敏感信号列表不完整(always@()块中敏感列表没有列全)

  • 多用always@(*)

teachbench(仿真激励文件)

Verilog(未完待续),嵌入式开发,fpga

1.信号声明

2.时钟生成:时延、将时钟分频。

initial clk = 0 ;
always #(CYCLE_200MHz/2) clk = ~clk;

initial begin
    clk = 0 ;
    forever begin
        #(CYCLE_200MHz/2) clk = ~clk;
    end
end

3.复位生成:一般赋初值为 0,再经过一段小延迟后,复位为 1 即可。

4.激励部分

5.模块例化

6.自校验

7.结束仿真:系统任务 $finish 来停止仿真。停止仿真之前,可以将自校验的结果,通过系统任务 $display 在终端进行显示。文章来源地址https://www.toymoban.com/news/detail-841538.html

到了这里,关于Verilog(未完待续)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 嵌入式系统中的FPGA

            假设你有一台智能家居系统,其中的FPGA可以被类比为智能家居中的中央控制器。 智能家居系统: 定制家居逻辑: 你希望智能家居系统能够根据你的生活习惯、时间表和喜好自动控制灯光、温度、窗帘等设备。就像FPGA中可以根据需求重新配置硬件逻辑一样,智能

    2024年02月03日
    浏览(55)
  • 目前研一,是选 FPGA 还是 Linux 嵌入式?

    在开始前我有一些资料,是我根据网友给的问题精心整理了一份「Linux 的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!! 从就业角度而言,FPGA偏深度发展,常见于“专精特新”的领域;嵌入式Linux偏向广度,常

    2024年03月11日
    浏览(38)
  • 嵌入式中的MCU、ARM、DSP、FPGA

    目录 “角色扮演” MCU ARM 特点 DSP 特点 FPGA 特点 应用           MCU(Microcontroller Unit)、ARM(Advanced RISC Machine)、DSP(Digital Signal Processor)和FPGA(Field-Programmable Gate Array)都是在嵌入式系统中常见的硬件组件,它们在嵌入式系统中扮演不同的角色。         1. 

    2024年02月08日
    浏览(54)
  • 【正点原子FPGA连载】第十五章eMMC读写测试实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html eMMC是一种嵌入式多媒体存储卡,它具有存储容量大、传输速度快、易于使用等优点,主要应用于对存储容量有

    2024年02月06日
    浏览(63)
  • 【正点原子FPGA连载】第十六章DP彩条显示实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html DP接口即DisplayPort接口,DisplayPort是由视频电子标准协会(VESA)发布的显示接口。作为DVI的继任者,DisplayPort将在

    2024年02月11日
    浏览(43)
  • 【正点原子FPGA连载】第二章 安装Ubuntu操作系统 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南

    1)实验平台:正点原子RV1126 Linux开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692176265749 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html 前面虚拟机已经创建成功了,相当于硬件已经准备好了,接下来就是要在虚拟机中安装Ubuntu系统了,首先

    2023年04月26日
    浏览(51)
  • 【正点原子FPGA连载】第十章Petalinux构建Qt和OpenCV交叉编译开发环境 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html 如果读者用过2019.1之前的Petalinux,会知道在设置Petalinux工作环境变量后可以直接使用arm或aarch64的linux交叉编译

    2024年02月07日
    浏览(66)
  • 关于嵌入式开发的一些信息汇总:嵌入式C开发人员、嵌入式系统Linux

    这篇文章是关于嵌入式开发的一些基本信息,供想入行的人参考。有一些作者本人的想法,以及来自外网的大拿的文章翻译而来,原文链接在此Learning Linux for embedded systems,再次感谢,支持原创。 普通C开发人员和嵌入式C开发人员之间的 基本区别在于 ,因为嵌入式C程序被设

    2024年02月03日
    浏览(65)
  • 【正点原子FPGA连载】第二十一章AXI DMA环路测试 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html DMA(Direct Memory Access,直接存储器访问)是计算机科学中的一种内存访问技术。它允许某些计算机内部的硬件子系

    2024年02月16日
    浏览(60)
  • 读书·基于RISC-V和FPGA的嵌入式系统设计

    引言:第八届集成电路创新创业大赛龙芯杯是有关嵌入式SoC设计的         由于我本身是做纯硬件设计,此前没怎么接触软硬协同         玩过Zynq,但是到SDK部分就去吃灰了         现在后悔了,所以,做人一定要有始有终啊~TAT ------------------------------------------------------

    2024年03月17日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包