1、第四章第四章 Verilog HDL语法进阶描述语法进阶描述LOREM IPSUM DOLOR目 录CONCENT4.1 语句块4.2 过程赋值语句4.3 过程性连续赋值语句4.4 高级程序设计语句4.5 参数化设计4.6 实例:基于SFF8485规格的SGPIO协议的Verilog HDL实现4.1 语句块GRADUATION THESIS4.1 语句块语句块语句块Verilog HDL提供了两种类型的语句块:l 顺序语句块(beginend),语句块内的语句是逐条顺序执行l 并行语句块(forkjoin),语句块内的语句是并行同时执行采用标识符时,其基本格式是:begin:标识符end 或
2、者fork:标识符Join其中:标识符为可选项4.1 语句块4.1.1 顺序语句块顺序语句块顺序语句块以关键词begin开始,以关键词end结束。在该语句块内,除了非阻塞语句,所有的语句都是按照在语句块内出现的先后顺序执行。每条语句之间的运行时间与和它上一条语句之间的时延相关。其基本格式是:begin:标识符标识符#delay procedural statementsend顺序语句块的时延可以采用“#delay”的方式,也可以采用边沿事件触发的形式,同时在语句块内可以声明局部变量。如:begin:local_var reg 7:0 data;end4.1 语句块4.1.2 并行语句块并行语句
3、块与顺序语句块不同,并行语句块以关键词fork开始,以关键词join结束。语句块内的所有语句都是并行执行,没有先后顺序。每条语句之前所定义的时延都是基于开始时间的绝对时延,与它的前一句语句执行的结束时间无关。并行语句块的基本格式如下:fork:标识符标识符join和顺序语句块一样,并行语句块的时延可以采用“#delay”的方式,也可以采用边沿跳变事件触发的方式,也可以再语句块内声明局部变量该变量只在语句块内有效。4.2 过程赋值语句GRADUATION THESIS4.2 过程赋值语句过程赋值过程赋值就是对变量类型包括reg、integer、real、realtime以及time类型的变量进行
4、赋值的操作。过程赋值语句左边的目标变量同样可以进行特定位提取、部分位提取或者两者的组合。过程赋值是在initial语句和always语句内进行的赋值。过程赋值语句和连续赋值语句的区别如下:过程赋值过程赋值连续赋值连续赋值用于用于initial语句和语句和always语句中语句中不用于initial语句和always语句中在在initial块和块和always块中与其他操作块中与其他操作相关执行相关执行与其他语句并行执行驱动变量驱动变量驱动线网有阻塞(有阻塞(=)和非阻塞()和非阻塞(=)之分)之分使用赋值符号(=)4.2 过程赋值语句4.2.1 阻塞赋值语句阻塞赋值语句阻塞赋值语句就是在下一条
5、语句执行之前,该赋值语句必须已经全部执行完毕。在赋值语句中采用“=”赋值,一般表现形式是:变数变数=表达式;表达式;阻塞赋值语句是顺序执行语句,完成阻塞赋值的过程如下:(1)首先计算阻塞赋值语句右边表达式的结果;(2)这个结果存入仿真系统的赋值事件队列(也称之为调度的临时寄存器);(3)如果没有时延,则该事件立即被调度执行。阻塞过程赋值也可以用来实现组合逻辑的功能。阻塞过程赋值严格遵循顺序语句块的规则:每条语句的时延是相对于上一条语句结束而言的。4.2 过程赋值语句【例4-4】采用阻塞赋值实现输入与输出信号的三个时钟时延module reg_buf(input clk,input rst_,i
6、nput sigA,output reg sigB,output reg sigC,output reg sigD);always(posedge clk,negedge rst_)begin if(!rst_)begin sigB=0;sigC=0;sigD=0;end else begin sigB=sigA;sigC=sigB;sigD=sigC;end endendmodule4.2 过程赋值语句4.2.2 非阻塞赋值语句非阻塞赋值语句 非阻塞赋值语句的赋值符号是“=”。非阻塞赋值语句与阻塞赋值语句不同,一条非阻塞赋值语句不会阻塞另外一条非阻塞赋值语句的执行。换句话说,非阻塞赋值语句之
7、间是同步赋值操作。其基本格式是:变数变数=表达式表达式;完成非阻塞赋值的基本过程基本过程如下:(1)首先仿真器会把非阻塞赋值放到调度队列中;(2)接着仿真器开始执行下一条语句而不是等待当前这条语句执行完毕;(3)先计算出赋值符号右边表达式的结果,再把这个结果的赋值操作保存在事件队列中,等轮到事件被调度的时候,再把这个结果赋给赋值符号的左边目标变量。(4)如果没有时延,赋值的操作会发生在当前时间单位的最后时刻。非阻塞赋值语句主要用于并发的赋值操作。4.2 过程赋值语句【例4-6】采用非阻塞赋值语句对例4-4进行修改实例module DFF3(input clk,input rst_,input
8、sigA,output reg sigB,output reg sigC,output reg sigD);always(posedge clk,negedge rst_)begin if(!rst_)begin sigB=0;sigC=0;sigD=0;end else begin sigB=sigA;sigC=sigB;sigD=sigC;end endendmodule4.2 过程赋值语句4.2.3 过程赋值语句的使用原则过程赋值语句的使用原则阻塞过程赋值语句和非阻塞过程赋值语句是Verilog HDL经常使用到的语句,也经常容易被混淆。一般使用的基本原则是一般使用的基本原则是:1.当要
9、对组合逻辑建模时,采用阻塞赋值;当要对时序逻辑建模时,采用非阻塞赋值。2.对always语句块外用到的变量进行赋值时,使用非阻塞赋值;在计算中间结果的时候,采用阻塞性赋值。4.3 过程性连续赋值语句GRADUATION THESIS4.3 过程性连续赋值语句过程性连续赋值语句概念过程性连续赋值语句概念过程性连续赋值语句是一种过程性赋值,与连续赋值语句不同,它是在always语句或initial语句中出现的语句,而连续赋值语句只能出现在always语句或initial语句之外。同时与过程性赋值语句不同,过程赋值语句把数值传递给寄存器,这个数值一直保存在这个寄存器中,只有另外一条过程赋值语句才能改
10、变这个寄存器的值,而过程连续赋值语句在一段特定时间内连续地对线网或变量进行赋值,而不受其他信号的影响。注意事项注意事项过程性连续赋值语句的目标不能是变量的位选择或部分选择。过程性连续赋值语句一般用来做模拟和测试,通过对线网或变量进行强制赋值来消除错误。不能用于综合。过程性连续赋值语句有两类:过程性连续赋值语句有两类:1.赋值与重新赋值语句,采用关键词assign和deassign,用来对变量进行赋值2.强制与释放语句,采用关键词force和release,用来对线网赋值,也可以对变量赋值4.3 过程性连续赋值语句【例4-7】采用赋值与重新赋值语句描述一个异步清零D触发器module Dff(i
11、nput clk,input rst_,input d,output reg q,output reg q_n);always(posedge clk)begin q=d;q_n=d;end always(rst_)begin if(!rst_)begin assign q=1b0;assign q_n 1;endclk每出现一个上升沿,data右移一位,并重复八次。4.4高级程序设计语句4.4.3.3 while循环语句循环语句Verilog HDL只有一种while循环语句,没有“dowhile”的语句结构。While循环的作用是只要条件布尔表达式为真,则循环体会一直循环下去,直到条件布尔
12、表达式变成假。一旦条件布尔表达式为假,则跳出循环,并开始执行下一个语句。条件布尔表达式可以有多种表示形式,如算术表达式、逻辑算术表达式、逻辑表达式、比较表达式表达式、比较表达式等。循环体可以是一条语句,也可以是一循环体可以是一条语句,也可以是一个语句块个语句块。其基本结构是:while(condition)procedural_statement;4.4高级程序设计语句4.4.3.4 for循环语句循环语句for循环语句由三部分组成:l 初始化:给寄存器控制变量赋初值。它可以在for语句之前初始化,也可以在for语句里面初始化,它只会执行一次。l 条件检测:条件检测决定什么时候退出循环。只要条
13、件检测表达式为真,循环体就会执行。l 赋值:修改控制变量的值,可以是递增,也可以是递减。其基本格式如下:for(initialization;condition;action)Procedural_statement;for语句既可以用于模拟,又可以用于综合。采用for语句生成逻辑电路相当于把一个相同的基本电路赋值把一个相同的基本电路赋值n次次,这样不仅增大了线路的面积,同时也不会改善线路延迟时间,通常可以采用移位元的方式来替代for循环语句。4.4高级程序设计语句4.4.4 generate语句语句4.4.4.1 generate循环语句循环语句generate循环语句主要用于语句的复制,基
14、本上允许对结构元素进行for循环。其基本结构如下:genvar I;generate for(initial_expression;final_expression;assignment)begin:label procedural_statement;endendgenrate在此循环语句中,需要定义一个循环变量,该变量属于genval类型,必须在循环体外显式声明,并且只能在generate语句中使用。在for语句中,循环变量需要初始化并且在每一个循环中修改变量值。同时,generate语句块需要有标签,用来表示genreate循环的实例名称。4.4高级程序设计语句4.4.4.2 gener
15、ate条件语句条件语句和行为级建模采用的条件语句一样,generate条件语句同样也是采用ifelse结构,其基本语法如下:if(Condition)Statements;else Statements;其中,Condition条件表达式只能由常数和参数组成。Statements可以是任意能够在模块中出现的语句。在执行过程中,根据条件的值,选择相应的语句。如,在进行全加器设计时,通常是两个操作数相加,同时加上低一位的进位标志,但最低位相加时,没有进位标志,那么就可以采用该条件语句来实现。4.4高级程序设计语句4.4.4.3 generate分支语句分支语句generate分支语句和genera
16、te条件语句类似,只是generate分支语句是针对多分支的情况。其基本格式如下:case(case_expression)CASE_ITEM1,CASE_ITEM2:statements;CASE_ITEMN:statements;default:statementsendcase比如,采用generate分支语句设计一个运算器,根据参数OP_METHOD实现对操作数的加减乘除运算。4.5 参数化设计GRADUATION THESIS4.5 参数化设计参数优化的必要性参数优化的必要性Verilog HDL语言以模块描述为单元。在大型设计中,往往会通过大量的模块例化来实现相应的功能。有些模块可
17、能要实现的功能相同,但是位宽不同,有些模块可能要实现的功能绝大部分相同,但可能有个别地方需要区别。因此,底层模块通用化设计就非常关键。参数化设计就应运而生。参数化设计不仅增加了整体程序的代码使用率,同时也提高了代码的可读性,减少了代码错误率。参数化设计有多种方法来实现参数化设计有多种方法来实现主要会使用的到关键词是parameter和defparam。4.5 参数化设计【例4-21】采用参数定义设计一个MAC乘积累加器。module mac(A,B,MAC,CLK,RST,Q);parameter SIZE=4;/参数定义 input SIZE-1:0 A;input SIZE-1:0 B;i
18、nput MAC;input CLK;input RST;output reg 2*SIZE-1:0 Q;wire 2*SIZE-1:0 mlt_o=A*B;/乘积项 wire 2*SIZE-1:0 adr_o=MAC?mlt_o+Q:mlt_o;/加法器 采用Synplify Pro生成的RTL线路图如下。可以看出,完全满足期望值。/D-FF to shift the data out always(posedge CLK,negedge RST)if(!RST)Q=b0;else Q=adr_o;endmodule4.5 参数化设计图 4-15 对例4-21采用Synplify Pro综合
19、生成的RTL电路图4.5 参数化设计现在要实例此模块,并把输入操作数位宽修改为32位,一种方法是,改写该模块,把SIZE修改为32,但此修改导致重复利用率差;另外一种方式就是在上层模块中直接修改其参数值。可以通过defparam关键词来实现此功能。defparam的基本格式的基本格式如下:defparam instance_name.parameter_name=new parameter;因此,该上层模块代码如下:module top_param(A,B,CLK,MAC,RST,Q);parameter SCALE_SIZE=32;input CLK,RST,MAC;input SCALE_
20、SIZE-1:0 A,B;output 2*SCALE_SIZE-1:0 Q;defparam U1.SIZE=SCALE_SIZE;/采用defparam定义新的数据位宽 mac U1(.A(A),.B(B),.RST(RST),.CLK(CLK),.MAC(MAC),.Q(Q);endmodule综合后生成的逻辑RTL电路如下图所示,可见其端口已经扩充了八倍位宽。4.5 参数化设计4.5 参数化设计参数化设计的第二种方式是参数实例化。这个方案不使用defparam来强迫改变底层模块的参数,而是通过改变上层模块来实例化参数。对上述程序修改,采用实例化参数的代码如下:module top_pa
21、ram(A,B,CLK,MAC,RST,Q);parameter SCALE_SIZE=32;input CLK,RST,MAC;input SCALE_SIZE-1:0 A,B;output 2*SCALE_SIZE-1:0 Q;/defparam U1.SIZE=SCALE_SIZE;mac#(SCALE_SIZE)U1(.A(A),.B(B),.RST(RST),.CLK(CLK),.MAC(MAC),.Q(Q);/参数实例化 endmodule该程序和采用defparam关键词实现的参数化设计得出的逻辑RTL电路一样。4.5 参数化设计显式参数实例化首先要规范被实例的子模块的形式。不同
22、于普通的模块定义,显式参数实例化的子模块必须把参数声明像端口一样定义在模块名称之后,端口列表之前,多个参数用“,”隔开。其基本格式如下:module module_name#(parameter_definition)(port list);port declaration;variable declaration;endmodule以上几种参数化设计各有各的好处。从结构化描述来说,许以上几种参数化设计各有各的好处。从结构化描述来说,许多工程师推荐采用显式参数实例化的方式来描述,这样在某种多工程师推荐采用显式参数实例化的方式来描述,这样在某种程度上来说是更加彻底地实例化,这也是不推荐采用程度上
23、来说是更加彻底地实例化,这也是不推荐采用define来来定义参数的原因。定义参数的原因。4.6实例:基于SFF8485规格的SGPIO协议的Verilog HDL实现GRADUATION THESIS4.6 实例4.6.1 SGPIO协议简介协议简介SGPIO协议是一种将通用IO信号串行化的接口协议。SGPIO协议定义了协议发起者与接收者之间的通信。接收者接收发送者传来的串行信号并把它们转换为多个并行信号,同时透过数据信号线把相关信息反馈给发送者。其基本示意图如下所示。4.6 实例信号名称信号名称发起者发起者功能描述功能描述SClockSClock发送者时钟信号SLoadSLoad发送者比特流
24、的最后一个时钟信号。有效时,接下来一个时钟开启新的比特流SDataOutSDataOut发送者串行数据输出比特流SDataInSDataIn接收者串行数据输入比特流 SGPIO总线传输示意图4.6 实例 SGPIO和SAS/SATA协议一同使用示意图4.6 实例4.6.2 SGPIO协议接收者的协议接收者的Verilog HDL代码设计代码设计系统根据SLoad在各个时段的高低电平状态分为六个状态:IDLE、VENDER_DEFINE0、VENDER_DEFINE1、VENDER_DEFINE2、RCV_DATA0以及ERROR_LATCH状态。相应的时序状态图如下:本章小结本章主要是针对本章主要是针对Verilog HDL各类高级语法设计与应各类高级语法设计与应用的总结与介绍,同时针对结构化建模采用参数化设用的总结与介绍,同时针对结构化建模采用参数化设计的一种探讨。并通过计的一种探讨。并通过SGPIO协议的协议的Verilog HDL代代码的实现与仿真具体深化对本章的认识。在示例中,码的实现与仿真具体深化对本章的认识。在示例中,同时也涉及到有限状态机以及仿真代码,这些关键知同时也涉及到有限状态机以及仿真代码,这些关键知识点将在后续章节陆续重点阐述。识点将在后续章节陆续重点阐述。谢谢THANK YOU
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。