0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

全网最全总结FPGA的Veilog HDL语法、框架

GReq_mcu168 来源:果果小师弟 作者:智果芯 2021-06-30 15:31 次阅读

摘要:Verilog HDL硬件描述语言是在用途最广泛的C语言的基础上发展起来的一种硬件描述语言,具有灵活性高、易学易用等特点。Verilog HDL可以在较短的时间内学习和掌握,FPGA的Veilog HDL基础语法总结,看完这些,FPGA的基本语法应该就没啥问题了!

一、基础知识1、逻辑值逻辑0:表示低电平,也就对应我们电路GND;

逻辑1:表示高电平,也就是对应我们电路的VCC;

逻辑X:表示未知,有可能是高电平,也有可能是低电平;

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

2、进制格式Verilog数字进制格式包括二进制、八进制、十进制和十六进制。

一般常用的为二进制、十进制和十六进制。

二进制表示如下:4b0101表示4位二进制数字0101

十进制表示如下:4‘d2表示4位十进制数字2(二进制0010)

十六进制表示如下:4ha表示4位十六进制数字a(二进制1010)

16’b1001 1010 1010 1001=16‘h9AA9

3、标识符标识符(identifier)用于定义模块名、端口名、信号名等。

标识符可以是任意一组字母、数字、$符号和(下划线)符号的组合;

但标识符的第一个字符必须是字母或者下划线;

标识符是区分大小写的;

4、标识符推荐写法不建议大小写混合使用;

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

信号命名最好体现信号的含义,简洁、清晰、易懂;

以下是一些推荐的写法:

1、用有意义的有效的名字如sum、cpu_addr等。

2、用下划线区分词,如cpu addr。

3、采用一些前缀或后缀,比如时钟采用clk前缀:clk_50,clk_cpu;

二、数据类型在Verilog 语言中,主要有三大类数据类型。

寄存器数据类型、线网数据类型和参数数据类型。

从名称中,我们可以看出,真正在数字电路中起作用的数据类型应该是寄存器数据类型和线网数据类型。

1、寄存器类型寄存器表示一个抽象的数据存储单元,通过赋值语句可以改变寄存器储存的值寄存器数据类型的关键字是reg,reg类型数据的默认初始值为不定值x。

ecf4dc88-d96f-11eb-9e57-12bb97331649.png

reg类型的数据只能在always语句和initial语句中被赋值。

如果该过程语句描述的是时序逻辑,即always语句带有时钟信号,则该寄存器变量对应为触发器;

如果该过程语句描述的是组合逻辑,即always语句不带有时钟信号,则该寄存器变量对应为硬件连线;

//计数器对系统时钟计数,计时0.2秒

always @(posedge sys_clk or negedge sys_rst_n) begin

if (!sys_rst_n)

counter 《= 24’d0;

else if (counter 《 24‘d999_9999)

counter 《= counter + 1’b1;

else

counter 《= 24‘d0;

end

//通过移位寄存器控制IO口的高低电平,从而改变LED的显示状态

always @(posedge sys_clk or negedge sys_rst_n) begin

if (!sys_rst_n)

led 《= 4’b0001;

else if(counter == 24‘d999_9999)

led[3:0] 《= {led[2:0],led[3]};

else

led 《= led;

end

2、线网类型线网数据类型表示结构实体(例如门)之间的物理连线。

线网类型的变量不能储存值,它的值是由驱动它的元件所决定的。驱动线网类型变量的元件有门、连续赋值语句、assign等。

如果没有驱动元件连接到线网类型的变量上,则该变量就是高阻的,即其值为z。

线网数据类型包括wire型和tri型,其中最常用的就是wire类型。

ed07e206-d96f-11eb-9e57-12bb97331649.png

3、参数类型参数其实就是一个常量,在Verilog HDL中用parameter定义常量。

我们可以一次定义多个参数,参数与参数之间需要用逗号隔开。

每个参数定义的右边必须是一个常数表达式。

ed160f84-d96f-11eb-9e57-12bb97331649.png

参数型数据常用于定义状态机的状态、数据位宽和延迟大小等。

采用标识符来代表一个常量可以提高程序的可读性和可维护性。

在模块调用时,可通过参数传递来改变被调用模块中已定义的参数。

三、运算符1、算数运算符2、关系运算符3、逻辑运算符4、条件操作符result=(a》=b)?a:b;

5、位运算符6、移位运算符两种移位运算都用0来填补移出的空位。

左移时,位宽增加;右移时,位宽不变。

4b1001 《《2 = 6’b100100;

4b1001 》》1 = 4b0100;

7、拼接运算符c={a,b[3:0];

8、优先级运算符四、模块结构Verilog的基本设计单元是“模块“(block)。

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

edc4bfe8-d96f-11eb-9e57-12bb97331649.png

使用quartusii软件编写出上图左边的硬件描述代码,通过软件编译,就能生成最右边组合逻辑电路图来。每个Verilog程序包括4个主要的部分:端口定义、I0说明、内部信号声明、功能定义。

edfdbda2-d96f-11eb-9e57-12bb97331649.png

流水灯代码

上图时流水灯的代码,第一个always块代码的意思:

如果时钟信号的上升沿或者复位信号的下降沿到来,就执行begin与end之间的代码。

如果产生了复位信号(低电平),计数器清0,如果计数器的值小于10000000,计数器的值就+1,如果没有产生复位信号和计数值不小于10000000,计数器的值就为0。在这个always块中,逻辑是顺序执行的。

第二个always块代码的意思:

如果时钟信号的上升沿或者复位信号的下降沿到来,就执行begin与end之间的代码。如果产生了复位信号(低电平),led0点亮,如果计数器的值小于10000000,led0-3顺序点亮,如果没有产生复位信号和计数值不小于10000000,led灯状态保持不变。在这个always块中,逻辑是顺序执行的。

但是这个always块代码是并行执行的,也就是说时钟信号一直在产生。

功能定义部分有三种方法:

1、assign语句描述组合逻辑

2、always语句描述组合/时序逻辑

3、例化实例元件

上述三种逻辑功能是并行执行的。

五、结构语句1、initial和always语句initial语句它在模块中只执行一次。

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

always 语句一直在不断地重复活动。但是只有和一定的时间控制结合在一起才有作用。

一般initial语句常用于测试文件,在测试文件中初始化使用。比如上面的代码首先始终信号初始化为0,之后在always语句中让其10个时钟周期翻转一次,就达到了时钟的要求。

复位信号最开始为低电平,然后延时20个时钟周期就拉高。触摸按键信号最开始为低电平,延时10和时钟周期后拉高,再延时30个时钟周期再拉低,延时110个时钟周期再拉高,再延时30个时钟周期再拉低。

always的时间控制可以是沿触发,也可以是电平触发;可以是单个信号,也可以是多个信号,多个信号中间要用关键字or连接。always 语句后紧跟的过程块是否运行,要看它的触发条件是否满足。

ee277200-d96f-11eb-9e57-12bb97331649.png

沿触发的always块常常描述时序逻辑行为。由关键词or连接的多个事件名或信号名组成的列表称为“敏感列表”。

电平触发的always块常常描述组合逻辑行为。

ee4b6746-d96f-11eb-9e57-12bb97331649.png

2、组合逻辑和时序逻辑电路根据逻辑功能的不同特点,可以将数字电路分成两大类:

组合逻辑电路和时序逻辑电路。

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

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

3、赋值语句Verilog HDL 语言中,信号有两种赋值方式

1、阻塞赋值(blocking),如b=a

2、非阻塞赋值(Non_Blocking),如b《=a

3.1、阻塞赋值

阻塞赋值可以认为只有一个步骤的操作:即计算RHS(左侧)并更新LHS(右侧)。

所谓阻塞的概念是指,在同一个always块中,后面的赋值语句是在前一句赋值语句结束后才开始赋值的。

module block_nonblock(Clk,Rst_n,a,b,c,out)

input Clk;

input Rst_n;

input a;

input b;

input c;

output reg [1:0] out;

// out a + b + c;最大值为3,所以应该定义为2位的位宽// d = a+b;// out = d+c;

reg [1:0]d;//定义一个中间变量

always @(posedge Clk or negedge Rst_n)

if (!Rst_n)

out = 2‘b0;

else begin

d = a+b;

out = d+c;

end

endmodule

eeb79c9a-d96f-11eb-9e57-12bb97331649.png

现在我们改变一下d= a+b;out = d+c;的顺序,就会发现综合出来的电路是完全不同的。

module block_nonblock(Clk,Rst_n,a,b,c,out)

input Clk;

input Rst_n;

input a;

input b;

input c;

output reg [1:0] out;

reg [1:0]d;//定义一个中间变量

always @(posedge Clk or negedge Rst_n)

if (!Rst_n)

out = 2’b0;

else begin

out = d+c;

d = a+b;

end

endmodule

ef0fe4d6-d96f-11eb-9e57-12bb97331649.png

3.2、非阻塞赋值

非阻塞赋值的操作过程可以看作两个步骤

(1)赋值开始的时候,计算RHS(左侧);

(2)赋值结束的时候,更新LHS(右侧)。

所谓非阻塞的概念是指,在计算非阻塞赋值的RHS以及更新LHS期间,允许其他的非阻塞赋值语句同时计算RHS和更新LHS。

非阻塞赋值只能用于对寄存器类型的变量进行赋值,因此只能用在initial块和always块等过程块中。

还是用上面的例子

module block_nonblock(Clk,Rst_n,a,b,c,out)

input Clk;

input Rst_n;

input a;

input b;

input c;

output reg [1:0] out;

reg [1:0]d;//定义一个中间变量

always @(posedge Clk or negedge Rst_n)

if (!Rst_n)

out = 2‘b0;

else begin

d 《= a+b;

out 《= d+c;

end

endmodule

生成效果如下:

ef5f4062-d96f-11eb-9e57-12bb97331649.png

现在我们改变一下d= a+b;out = d+c;的顺序,就会发现综合出来的电路是完全相同的。这里由于采用的非阻塞赋值,因此交换语句的前后顺序并不会对最终生成的逻辑电路有实际影响。

module block_nonblock(Clk,Rst_n,a,b,c,out)

input Clk;

input Rst_n;

input a;

input b;

input c;

output reg [1:0] out;

reg [1:0]d;//定义一个中间变量

always @(posedge Clk or negedge Rst_n)

if (!Rst_n)

out = 2’b0;

else begin

out 《= d+c;

d 《= a+b;

end

endmodule

ef7ff80c-d96f-11eb-9e57-12bb97331649.png

1、在描述组合逻辑(电平触发)的always 块中用阻塞赋值=,综合成组合逻辑的电路结构;这种电路结构只与输入电平的变化有关系。

2、在描述时序逻辑(沿触发)的always 块中用非阻塞赋值=,综合成时序逻辑的电路结构;这种电路结构往往与触发沿有关系,只有在触发沿时才可能发生赋值的变化。

“注意:在同一个always块中不要既用非阻塞赋值又用阻塞赋值不充许在多个always块中对同一个变量进行赋值!因为在多个always块中代码时并行执行的。”一般在设计中掌握以下六个原则,可解决在综合后仿真中出现绝大多数的冒险竞争问题。

1)时序电路(沿触发的always块)建模时,用非阻塞赋值;

2)锁存器电路建模时,用非阻塞赋值;

3)用always块建立组合逻辑(电平触发的always块)模型时,用阻塞赋值;

4)在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值:

5)在同一个always块中不要既用非阻塞赋值又用阻塞赋值;

6)不要在一个以上的always块中为同一个变量赋值。

4、条件语句条件语句必须在过程块中使用。过程块语句是指由initial语句和always语句引导的块语句。

4.1 if_else语句

1、允许一定形式的简写,如:

if(a) 等同于if(a==1)

if(la)等同于if(a!=1)

2、if语句对表达式的值进行判断,若为0,x,z,则按假处理;若为1,按真处理。

3、if和else后面的操作语句可以用begin和end包含多个语句。

4、允许if语句的嵌套。

4.1 case语句

case语句(多分支选择语句)

1、分支表达式的值互不相同;

2、所有表达式的位宽必须相等;不能用’bx来代替n‘bx

3、casez比较时,不考虑表达式中的高阻值

4、casex不考虑高阻值z和不定值x

f0065802-d96f-11eb-9e57-12bb97331649.png

注意if_else需要配对,一个if语句就应该必须有一个else语句。好处是避免latch产生。latch是一个锁存器,在数字电路中latch是一个电平触发的存储器,触发器是一个边沿触发的存储器。在编写veilog语句中应避免产生无畏锁存器,锁存器只在组合逻辑电路中产成,而锁存器会导致电路生成的毛刺比较多,还会影响我们对整个电路的时序分析。

什么样的情况下会产生这个锁存器呢?

首先在组合逻辑电路中,如果我们有if语句但是没有相应的else语句,他就有可能产生锁存器。第二点,比如case语句,如果我们的case语句没有给完全,没有列举完所有应该的产生的case语句,就应该写一个default,否则也会生成一个锁存器。

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 电路
    +关注

    关注

    170

    文章

    5485

    浏览量

    169603
  • 存储器
    +关注

    关注

    38

    文章

    7152

    浏览量

    162016
  • 锁存器
    +关注

    关注

    8

    文章

    752

    浏览量

    41042
  • 非阻塞赋值
    +关注

    关注

    0

    文章

    10

    浏览量

    9899

原文标题:FPGA的Veilog HDL语法、框架总结

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    基于FPGA的常见的图像算法模块总结

    意在给大家补充一下基于FPGA的图像算法基础,于是讲解了一下常见的图像算法模块,经过个人的总结,将知识点分布如下所示。
    的头像 发表于 04-28 11:45 120次阅读
    基于<b class='flag-5'>FPGA</b>的常见的图像算法模块<b class='flag-5'>总结</b>

    有什么好用的verilog HDL编辑工具可用?

    有什么好用的verilog HDL编辑工具可用?最好能集成实时的verilog HDL语法检测、自定义模块识别触发等功能,最好能够免费;
    发表于 04-28 11:00

    如何快速入门FPGA

    时钟管理模块、嵌入式块RAM、布线资源等。 学习FPGA编程语言: 掌握Verilog HDL(硬件描述语言)。Verilog用于数字电路的系统设计,具有简洁的语法和清晰的仿真语义,非常适合初学者入门
    发表于 04-28 09:06

    如何快速入门FPGA

    时钟管理模块、嵌入式块RAM、布线资源等。 学习FPGA编程语言: 掌握Verilog HDL(硬件描述语言)。Verilog用于数字电路的系统设计,具有简洁的语法和清晰的仿真语义,非常适合初学者入门
    发表于 04-28 08:54

    fpga用什么语言编程

    FPGA(现场可编程门阵列)的编程主要使用硬件描述语言(HDL),其中最常用的是Verilog HDL和VHDL。
    的头像 发表于 03-14 18:17 769次阅读

    fpga用的是什么编程语言 fpga用什么语言开发

    fpga用的是什么编程语言 FPGA(现场可编程逻辑门阵列)主要使用的编程语言是硬件描述语言(HDL)。在众多的HDL中,Verilog HDL
    的头像 发表于 03-14 17:09 911次阅读

    验证码渗透最全总结

    简单测试方法,就是看到一个登录框,然后新建打开图片链接,在图片链接中就有机会看到两个参数值,一个是 width,一个是 length。这两个参数是计算图片验证码的长宽,如果长宽过高就会过度消耗的是服务器的 CPU 资源。
    的头像 发表于 01-05 11:33 314次阅读
    验证码渗透<b class='flag-5'>最全总结</b>

    怎么使用DMA在FPGA中的HDL和嵌入式C之间传输数据?

    鉴于机器学习和人工智能等应用的 FPGA 设计中硬件加速的兴起,现在是剥开几层“云雾”并讨论 HDL 之间来回传递数据(主要指FPGA 的可编程逻辑 (PL) 中运行的代码以及 FPGA
    的头像 发表于 11-27 09:12 745次阅读
    怎么使用DMA在<b class='flag-5'>FPGA</b>中的<b class='flag-5'>HDL</b>和嵌入式C之间传输数据?

    使用MATLAB Simulink和HDL编码器创建自定义IP--AWB

    自动白平衡模块的设计是使用 HDL Coder 在 MATLAB 和 Simulink 中创建的。HDL Coder能够生成 HDL 文件,这些文件可以作为 IP 在我们的目标 FPGA
    的头像 发表于 11-13 09:27 535次阅读
    使用MATLAB Simulink和<b class='flag-5'>HDL</b>编码器创建自定义IP--AWB

    基于Python 轻量级ORM框架

    ORM框架使用最广泛的就是SQLAlchemy和Django自带的ORM框架,但是SQLAlchemy的语法显然相对Django的ORM框架麻烦一点。 而Django本身是一个web
    的头像 发表于 11-01 11:17 346次阅读
    基于Python 轻量级ORM<b class='flag-5'>框架</b>

    采用FPGA实现医疗成像总结

    电子发烧友网站提供《采用FPGA实现医疗成像总结.pdf》资料免费下载
    发表于 10-07 16:34 2次下载
    采用<b class='flag-5'>FPGA</b>实现医疗成像<b class='flag-5'>总结</b>

    verilog可综合的语法子集

    可综合的语法是指硬件能够实现的一些语法,这些语法能够被EDA工具支持,能够通过编译最终生成用于烧录到FPGA器件中的配置数据流。
    的头像 发表于 07-23 12:25 815次阅读

    FPGA编程语言之verilog语法2

    Verilog HDL是一种用于数字系统设计的语言。用Verilog HDL描述的电路设计就是该电路的Verilog HDL模型也称为模块。Verilog HDL既是一种行为描述的语言
    的头像 发表于 05-22 15:53 569次阅读
    <b class='flag-5'>FPGA</b>编程语言之verilog<b class='flag-5'>语法</b>2

    FPGA编程语言之verilog语法1

    Verilog HDL是一种用于数字系统设计的语言。用Verilog HDL描述的电路设计就是该电路的Verilog HDL模型也称为模块。Verilog HDL既是一种行为描述的语言
    的头像 发表于 05-22 15:52 600次阅读
    <b class='flag-5'>FPGA</b>编程语言之verilog<b class='flag-5'>语法</b>1

    基于FPGA提升框架的小波变换方法

    基于提升框架的小波变换方法,利用FPGA 可编程特性可实现多种小波变换。提升框架(LS :Lifting Scheme) 是由Sweldens 等人在近几年提出的一种小波变换方法,用它的框架
    的头像 发表于 05-11 15:33 494次阅读
    基于<b class='flag-5'>FPGA</b>提升<b class='flag-5'>框架</b>的小波变换方法