首页计算机计算机工程硬件描述语言和数字系统设计 04 第4章 各种语句语法.pptx

04 第4章 各种语句语法.pptx

页数:79页文件大小:287.8 KB来源: 硬件描述语言和数字系统设计ppt课件

本课件系统讲解Verilog的各类语句:持续赋值与过程块的适用范围,always块敏感量列表的写法,阻塞与非阻塞赋值的区别及典型时序风险,过程块内的if、case条件语句与循环语句,以及function与task的用法。

第4章Verilog各种语句语法章节封面,标示本章涵盖连续/持续赋值、过程块与always块@、阻塞赋值和非阻塞赋值等内容
第4章主要内容,依次讲述连续/持续赋值、过程块与always块@、阻塞赋值和非阻塞赋值等小节
连续/持续赋值知识点页,列出基本语法 、电路刷新动作的理解 、连续赋值语句使用举例 等知识点
查看本课件的文字版(共 79 页,供检索与复制)

第1页:第4章Verilog各种语句语法

硬件描述语言和数字系统设计

第2页:第4章主要内容

连续/持续赋值4.2过程块与always块@(敏感量)解释4.3阻塞赋值和非阻塞赋值4.4过程块内部使用的条件语句4.5过程块内部使用的循环语句4.6function和task的了解主要内容:

第3页:连续/持续赋值

连续/持续赋值知识点:

  • 4.1.1基本语法
  • 4.1.2电路刷新动作的理解
  • 4.1.3连续赋值语句使用举例
  • 4.1.4连续赋值的目标类型
  • 4.1.5连续赋值语句的并行执行情况
  • 4.1.6连续赋值语句的线与问题
  • 4.1.7连续/持续赋值语法总结

第4页:基本语法

基本语法

  • 持续赋值只能对线网net型信号进行赋值。语法格式:<assign><net_name>=<expressions>
  • 例如:wire out
  • assignout = a & b
  • //显式,推荐使用wire inv = ~in
  • //隐含,不推荐使用

第5页:电路刷新动作的

理解module mux2to1 (out, a, b, sel);input a, b, sel;output out;wire out;assignout=(sel)?b:a;endmodule为什么不可以去掉assign,直接使用out=(sel)?b:a;赋值?//去掉assign好像也可以描述相同的电路功能。

第6页:module mux2to1 代码示例

module mux2to1 (out, a, b, sel); input a, b, sel; output out; wire out; assignout=(sel)?b:a; endmodule答案:去掉assign是可以描述电路功能。但是无法模拟出电路的不断刷新的动作。所以采用保留字assign,来模拟表达式左边信号out,随右边表达式信号sel、a或者b的变化,而不断刷新的动作!;

第7页:连续赋值语句如何刷新呢?

assignout=(sel)?b:a;在上面的例子中,只要右边信号sel或a或b的值发生了改变,EDA工具提取assign保留字,映射成左边信号out能及时反应最新的逻辑结果。用assign赋值反应出这种不断刷新的过程,让建模语句的描述与实际电路工作情况吻合!

第8页:buserr 连续赋值示例

wire buserr, z; 例1:assign buserr = Parity| (One & OP); 例2:assign z= (A|B) & (C|D) & (E|F); 例2中,只要右边的信号A、B、C、D、E或F的值变化,右边整个表达式的逻辑将被刷新,结果Z将刷新为最新值。4.1.3连续赋值语句使用举例;

第9页:在下一个例子中

目标是一个向量线网和一个标量线网的拼接结果。例3:wire Cout, Cin; wire [3:0] Sum, A, B; . . .assign {Cout, Sum} = A + B + Cin; 因为A和B是4位宽,加操作的结果最大能够产生5位结果。左端表达式的长度指定为5位(Cout 1位,Sum 4位)。赋值语句因此促使右端表达式最右边的4位的结果赋给Sum,第5位(进位)赋给Cout。;

第10页:连续赋值的目标类型

连续赋值的目标类型

  • 1.标量线网
  • 2.向量线网
  • 3.线网向量的常数型一位选择
  • 4.线网向量的常数型部分位选择
  • 5.上述类型的任意的拼接运算结果

第11页:Cout 连续赋值示例

例:用连续赋值方式描述1位全加器module FA_Df (A, B, Cin, Sum, Cout ); input A, B, Cin; output Sum, Cout; assign Cout=(A&Cin)|(B&Cin)|(A&B); assign Sum =A^B^Cin; endmodule4.1.5连续赋值语句的并行执行情况;

第12页:Sum 连续赋值示例

用连续赋值方式描述1位全加器(cont.)在本例中,有两个连续赋值语句:assign Sum =A^B^Cin; assign Cout=(A&Cin)|(B&Cin)|(A&B); 这两个赋值语句是并行执行的,与其书写的顺序无关。只要信号A或者B或者Cin任何一个信号发生改变,和信号Sum与高位进位信号Cout的值就会立即相应的进行刷新,跟代码的前后顺序无关。;

第13页:正确表达

modulemux4to1_right(MUX1,a,b,c,d,sel);outputMUX1;inputa,b,c,d;input[1:0]sel;assignMUX1=(sel==2'b00)?a:((sel==2'b01)?b:((sel==2'b10)?c:d));endmodule错误表达:modulemux4to1_wrong(MUX2,a,b,c,d,sel1,sel2);input a, b, c, d;input sel1,sel2;output MUX2;wire MUX2;assignMUX2=(sel1)?b:a;//画出电路逻辑图assignMUX2=(sel2)?c:d;//为什么不能生成电路???endmodule134.1.6连续赋值语句的线与问题为什么这种做法不对????

第14页:错误原因-犯了线与错误答案

线与逻辑是两个输出信号直接相连,实现与的功能。在CMOS工艺下,线与会使灌电流过大,而烧坏逻辑门。要用oc门或者od门来实现。(还可以继续深入下去:为什么oc门和od门可以实现线与逻辑?如何实现?)

第15页:练习-常见公司数字IC设计招聘题目1.什

么是"线与"逻辑,要实现它,在硬件特性上有什么具体要求?(汉王)

第16页:可以用持续赋值语句描述组合逻辑

  • 可以用持续赋值语句描述组合逻辑。
  • 持续赋值在过程块外部使用。
  • 持续赋值只能对线网net型信号进行赋值。即连续赋值语句左边的信号只能是线网型(wire),不能是寄存器类型(reg)。4.1.7连续/持续赋值语法总结

第17页:过程块与always块@

(敏感量)解释知识点:

  • 4.2.1过程(procedural)块
  • 4.2.2过程块的赋值对象要求
  • 4.2.3过程赋值的信号类型
  • 4.2.4过程块always的结构
  • 4.2.5过程块的电平触发
  • 4.2.6过程块的边沿触发

第18页:过程

(procedural)块

  • 过程块有两种:
  • initial块,只能执行一次,用在测试模块中。
  • always块,循环执行,常用来描述组合或者时序逻辑电路。
  • always过程(procedural)块的结构包括两部分:
  • 1.过程块内部语句(描述具体的电路功能、结构)
  • 2. always@(敏感量)(设定电路刷新条件)

第19页:在过程块中的赋值称为过程赋值

  • 在过程块中的赋值称为过程赋值。
  • 在过程赋值语句中表达式左边的信号必须是寄存器类型(如reg类型)
  • 在过程赋值语句等式右边可以是任何有效的表达式,数据类型也没有限制。
  • 如果一个信号没有声明则缺省为wire类型。使用过程赋值语句给wire赋值会产生错误。4.2.2过程块的赋值对象要求

第20页:过程赋值的信号类型

过程赋值(procedural assignment)的信号类型练习信号类型改错:module adder (out, a, b, cin); input a, b, cin; output [1:0] out; wire a, b, cin; reghalf_carry;wire half_sum; assignout = {half_carry, half_ sum}; always @( a or b or cin)beginhalf_sum = a ^ b ^ cin; half_carry= (a & b) | (a & cin) |(b & cin ); endendmodule;

第21页:过程块always的结构

例如:module adder (out, a, b); input [2: 0] a, b; output [3: 0] out; reg [3: 0] out; always@( a or b)//过程块内语句描述电路功能://包括过程块赋值语句(=、<=)和条件判断语句等endendmodule1.过程块内语句描述具体电路结构、功能;2.过程块内语句多行用begin、end引导;3.用@(敏感量)来控制块里语句描述的电路刷新条件,如例题中,将敏感量改为always @( a)与always @( a or b)时电路刷新有什么不同?;

第22页:过程块的电平触发

module reg_ adder (out, a, b, clk); input clk; input [2: 0] a, b; output [3: 0] out; reg [3: 0] out; reg [3: 0] sum;//与wire [3:0] sum;assign sum = a + b; 相似endmodule;

第23页:过程块的边沿触发

用关键字posedge(上升沿)和negedge(下降沿)限定信号敏感边沿。敏感表中可以有多个信号,用关键字or连接。module reg_ adder (out, a, b, clk); input clk; input [2: 0] a, b; output [3: 0] out; reg [3: 0] out; reg [3: 0] sum;endmodule;

第24页:边沿敏感的时序控制:@

  • (posedge /negedge )
  • 可以说明信号(通常是时钟信号)有效沿是上升沿(posedge)还是下降沿(negedge)。
  • 只有在信号到达指定上升/下降边沿时,块内描述的电路才刷新。
  • 可以用关键字or指定多个参数,但是多个参数都必须是边沿触发的。
  • 边沿触发一般用来表达时序逻辑电路:
  • 如常用时序逻辑电路表达方式:always @( posedge clk or posedge rst)

第25页:阻塞赋值和非阻塞赋值

过程块内的赋值方式分为两类
1)阻塞性过程赋值(使用=符号)2)非阻塞性过程赋值(使用<=符号)

第26页:练习-常见公司数字IC设计招聘题目1.B

LOCKING、NONBLOCKING赋值的区别。(南山之桥)

第27页:知识点:4.3.1阻塞赋

知识点:

  • 4.3.1阻塞赋值
  • 4.3.2非阻塞赋值
  • 4.3.3过程赋值的比较示例
  • 4.3.4过程块的并行执行情况
  • 4.3.5两种不同过程赋值语句的区别
  • 4.3.6数据类型对应的电路模型
  • 4.3.7过程赋值语句的限制
  • 4.3.8常见过程块的线与问题

第28页:阻塞赋值

赋值操作符是“=”的过程赋值是阻塞性过程赋值。例如,RegA = 52;是阻塞性过程赋值。阻塞性过程赋值是顺序执行的,即写在前面的语句先执行,写在后面的语句后执行。

第29页:A 时序逻辑示例

例1:…input A,B,Cin;output Cout;reg T1 , T2 , T3;always@(A or B or Cin)beginT1 = A&B; T2 = B & Cin; T3 = A & Cin; Cout = T1 | T2 | T3; end…T1赋值首先发生,计算T1;接着执行第二条语句,T2被赋值;然后执行第三条语句,T3被赋值;最后才执行Cout赋值语句。(如果某时刻,A信号变为1,B变为1,Cin变为0,然后过了t时刻,A从1变为0,此时假如B、Cin保持不变);

第30页:A 时序逻辑示例(续1)

上例中,如果将语句顺序换换,会有什么样的结果?如改为,例2:…input A,B,Cin;output Cout;reg T1 , T2 , T3;always@(A or B or Cin)beginCout = T1 | T2 | T3; T1 = A&B; T2 = B & Cin; T3 = A & Cin; End…(如果某时刻,A信号变为1,B变为1,Cin变为0,然后过了t时刻,A从1变为0,此时假如B、Cin保持不变,会有什么情况发生,Cout值为什么与例1不同?如何解决这个问题?);

第31页:A 时序逻辑示例(续2)

改正为例3:reg T1 , T2 , T3; reg Cout; always@(A or B or Cin orT1 or T2 or T3 )beginCout = T1 | T2 | T3; T1 = A&B; T2 = B & Cin; T3 = A & Cin; end问题得以解决!(如果某时刻,A信号变为1,B变为1,Cin变为0,然后过了t时刻,A从1变为0,此时假如B、Cin保持不变);

第32页:A 时序逻辑示例(续3)

或者改正为,例4:reg T1 , T2 , T3; reg Cout; always@(A or B or Cin orT1 or T2 or T3 )beginT1 = A&B; T2 = B & Cin; T3 = A & Cin; Cout = T1 | T2 | T3; end问题得以解决!实际工程中,例1、例2表达方式均不使用,而使用例3、例4方式!(如果某时刻,A信号变为1,B变为1,Cin变为0,然后过了t时刻,A从1变为0,此时假如B、Cin保持不变);

第33页:非阻塞赋值

1.在非阻塞性过程赋值中,使用赋值符号“< =”。2.非阻塞性过程赋值是并行执行的,即写在前面的语句与写在后面的语句同时执行,跟书写顺序没有关系。

第34页:clk 时序逻辑示例

例如:reg T1 , T2 , T3; reg Cout; always@(posedge clk)beginT1 <= A&B;T2 <= B & Cin;T3 <= A & Cin;Cout <= T1 | T2 | T3;end左边蓝色部分描述的逻辑跟右边绿色部分描述的逻辑完全一样,跟书写顺序没有关系!;

第35页:赋值语句的阻塞和非阻塞性质不会造成赋值语

句本身生成的逻辑电路有任何不同,但是会影响以后对赋值结果的使用。强烈建议!!!描述组合逻辑使用阻塞式赋值;而描述时序逻辑使用非阻塞式赋值。

第36页:过程赋值的比较示例

下面这些表达的区别??:表达一(建议不使用该方式):module ……..reg B , out; always@ (A)beginout = B; B = A; endendmodule表达二(建议不使用该方式):reg B , out; always@ (A)beginB = A; out = B; end;

第37页:A 时序逻辑示例(续4)

表达三(可使用方式):module …..; reg B , out; always@ (A or B)beginB = A; out = B; endendmodule表达四(可使用方式):reg B , out; always@ (A or B)beginout = B; B = A; end;

第38页:A 时序逻辑示例(续5)

表达五(可使用方式):module …….reg B , out; always@ (A)B = A; always@ (B)out = B; endmodule;

第39页:B 连续赋值示例

表达六(可使用方式):module …….wire B , out; assign B = A; assign out = B; endmodule;

第40页:过程块的并行执行情况

例1:module adder (out, a, b, cin); input a, b, cin; output [1:0] out; wire a, b, cin; reghalf_carry;wirehalf_sum; assign out = {half_carry, half_ sum}; assign half_sum = a ^ b ^ cin; always @( a or b or cin)beginhalf_carry = (a & b) | (a & cin) |(b & cin ); endendmodule;

第41页:module reg_ 代码示例

例2:modulereg_ adder (out, a, b, clk); input clk; input [2: 0] a, b; output [3: 0] out,sum; reg [3: 0] out; reg [3: 0] sum; always @( posedge clk)out <= a-b; always @( a or b)sum = a + b; endmodule;

第42页:两种不同过程赋值语句的

两种不同过程赋值语句的区别

  • 非阻塞(non-blocking)赋值语句:reg b,c
  • always @(posedge clkorposedgerst)if(rst)b<=0
  • elseb<=a
  • always @(posedge clkor negedge rst)if(!rst)c<=1
  • elsec<=b
  • clkDFFcDQDQabDFF

第43页:clk 时序逻辑示例(续1)

  • 阻塞(blocking)赋值语句:reg b,c
  • always @(posedge clk)beginb = a
  • //不建议使用c = b
  • //不建议使用endclkDFFcDQab

第44页:非阻塞赋值语句

  • 非阻塞(non-blocking)赋值语句( b<= a):-块内的赋值语句同时被赋值;-建议在时序逻辑中使用非阻塞赋值。
  • 阻塞(blocking)赋值语句( b = a):-完成该赋值语句后才能做下一句的操作;-时序电路中,对于阻塞赋值,硬件没有对应的电路,因而综合结果未知。-阻塞赋值语句常用来表达组合逻辑电路。

第45页:数据类型对应的电路模型

综合时,网线数据类型的变量会被映射成硬件中的连线;寄存器数据类型的变量根据被赋值的具体情况,被映射成连线、触发器或者锁存器。下面详细讨论寄存器数据类型的变量。

第46页:acr 时序逻辑示例

寄存器型变量被综合成网线:wire acr,bar,fra;reg trg,sqp;…always @ (acr or bar or fra or trq)begintrq=bar&acr; sqp=trq|fra; end;

第47页:

第48页:module target 代码示例

寄存器的变量被综合成触发器:module target(clk,clr,rega,regb,mask); input clk,clr; input [3:0] mask, rega,; output [3:0] regb; reg [3:0] regb; always @ (posedge clk)if(!clr)regb <=4'b0000; elseregb <= rega& mask; endmodule;

第49页:

第50页:Verilog代码示例

寄存器的变量被综合成触发器2

  • module procedure_reg(clk,rst,a,c);
  • input clk,rst,a;
  • output c;
  • reg b,c;
  • always @(posedge clk or negedge rst)
  • //always @(rst or a)
  • if(!rst) b<=0;
  • else b<=a;
  • always @(posedge clk or negedge rst)
  • //always @(rst or b)
  • if(!rst) c<=1;
  • else c<=b;
  • endmodule问题:在电路开始上电工作时,复位信号有效,经过一小段时间后,复位信号无效,时钟信号开始工作,如果对于输入信号a由0变为1的波形,请画出信号b、c相应的波形图?clkDFFDQDQabDFFc

第51页:过程赋值语句的

限制!!!!对同一个赋值对象不能既使用阻塞赋值,又使用非阻塞赋值。!!!!在同一个过程块里面,不能既使用阻塞赋值,又使用非阻塞赋值。如://error1reg T1 , T2 , T3; reg Cout; always@(A or B or Cin)begin//CARRY_OUTT1<=A&B; T2<=B & Cin; T3<=A & Cin; Cout=T1 | T2 | T3; 

第52页:module dff 代码示例

改错:module dff(rst,clk,d,q);output q; reg q;elseq<=d; endmodule赋值的限制-举例;

第53页:常见过程块的线与

问题module dff(rst,clk,d,q);output q; regq; always @(negedge rst)if (!rst)q <=1'b0; always @(posedge clk)q<=d; endmodule上面示例为什么出错,如何修改?;

第54页:module dff 代码示例(续1)

答案:出现了线与问题,改正如下:module dff(rst,clk,d,q);output q; reg q; always @(posedge clk or negedge rst)if (!rst)q <=1'b0; elseq<=d; endmodule;

第55页:过程块内部使用的条件语句

过程块内部使用的条件语句知识点:

  • 4.4.1条件语句-if语句
  • 4.4.2条件语句-case分支语句

第56页:条件语句-if语句

if语句的语法如下
if(condition_1)beginprocedural _ statement _ 1endelse if(condition_2)beginprocedural _ statement _ 2endelseprocedural _ statement _ 3

第57页:if语句示例if

(Sum < 60)Total _A<=Total_A+1;else if(60< Sum<75)Total _B<=Total _ B +2;elseTotal _C<= Total _C+3;

第58页:条件语句-case分支语句

module compute (result, rega, regb, opcode); input [7: 0] rega, regb; input [2: 0] opcode; output [7: 0] result; reg [7: 0] result; always @( rega or regb or opcode)case (opcode)3'b000 :result = rega + regb; 3'b001 :result = rega-regb; 3'b010:3'b100 :result = rega & regb; default :result =8'b0; endcaseendmodulecase语句:在Verilog中重复说明case项是合法的,因为Verilog的case语句只执行第一个符合项。;

第59页:case语句是测试表达式与另外一系列表达

式分支是否匹配的一个多路条件语句。

  • Case语句进行逐位比较以求完全匹配(包括x和z)。
  • 多个default语句是非法的。重要内容:使用default语句是一个很好的编程习惯,特别是用于检测x和z。Casez和casex为case语句的变体,允许比较无关值。
  • case表达式或case项中的任何位为无关值时,在比较过程中该位不予考虑。
  • 在casez语句中,?和z被当作无关值。
  • 在casex语句中,?,z和x被当作无关值。4.4.2条件语句-case分支语句

第60页:过程块内部使用的循环语句

过程块内部使用的循环语句知识点:

  • 4.5.1循环语句
  • 4.5.2 for语句示例

第61页:循环语句

Verilog HDL中有四类循环语句,它们是:1) forever循环2) repeat循环3) while循环4) for循环For循环语句是典型的能用于综合的循环语句。一个for循环语句按照指定的次数重复执行过程赋值语句若干次。

第62页:repeat:将一块语句循环执行确定次数

。repeat(次数表达式)<语句>while:在条件表达式为真时一直循环执行while(条件表达式)<语句>forever:重复执行直到仿真结束forever<语句>for:在执行过程中对变量进行计算和判断,在条件满足时执行for(赋初值;条件表达式;计算)<语句>综合工具还不支持,了解

第63页:for语句示例

…input [31:0] addr; output [3:0] line; reg [3:0] line; integer n;always @ (posedge clk)for(n=3; n>=0; n=n-1)if(addr==n)line[n]<=1; elseline[n]<=0;

第64页:function和task的了解

function和task的了解知识点:

  • 4.6.1 Verilog的任务与函数
  • 4.6.2任务task
  • 4.6.3函数(function)
  • 4.6.4实际工程中Function语句实例
  • 4.6.5特别说明

第65页:Verilog的任务与函数

Verilog的任务与函数

  • 任务(task)
  • 通常用于调试
  • 可以包含时序控制
  • 可以有input,output,和inout参数
  • 可以调用其他任务或函数
  • 函数(function)
  • 通常用于数学计算,描述组合逻辑
  • 不能包含任何延迟;函数仿真时间为0
  • 只含有input参数
  • 由函数名返回一个结果
  • 可以调用其他函数,但不能调用任务
  • 任务和函数必须在module内定义和例化

第66页:任务task

任务既可表示组合逻辑又可表达时序逻辑,定义的形式如下:tasktask _ id;[declarations]procedural _ statementendtask任务可以没有或有一个或多个输入输出参数。值通过参数传入和传出。除input参数外,任务还能带有output参数(从任务中返回值)和inout参数。

第67页:task示例1moduleHas

_ Task……;….parameterMAXBITS =4'h8;taskReverse _ Bits;input[MAXBITS-1:0] Din;output[MAXBITS-1:0] Dout;integer k;beginfor (k = 0; k < MAXBITS; k = k + 1)Dout [MAXBITS-k] = Din[k] ;endendtask. . .endmodule

第68页:module mult 代码示例

modulemult(clk,a,b,out,en_mult); inputclk,en_adder; input[3:0]a,b; output[4:0]out; reg[4:0]out; always@(posedgeclk)adder_tme(a,b,en_adder,out);//任务定义input[3:0]add1,add2; inputen; output[4:0]result; if(en)result=add1+add2; endtaskendmoduletask示例2:任务调用时的参数按任务定义的顺序列出。;

第69页:函数

(function)函数表达的是组合逻辑。函数与任务的不同之处是函数只能返回一个值,它不能包含任何时延或时序控制(必须立即执行),函数必须带有至少一个输入,在函数中允许没有输出或输入输出说明。

第70页:module orand 代码示例

函数中不能有时序控制,但调用它的过程可以有时序控制。moduleorand(a,b,c,d,e,out); input[7:0]a,b,c,d,e; output[7:0]out; reg[7:0]out; always@(aorborcordore)out=f_or_and(a,b,c,d,e); function[7:0]f_or_and; input[7:0]a,b,c,d,e; if(e==1)f_or_and=(a|b)&(c|d); elsef_or_and=0; endfunctionendmodule;

第71页:主要特性:函数定义中不能包含任何时序控制

主要特性:

  • 函数定义中不能包含任何时序控制语句。
  • 函数至少有一个输入,不能包含任何输出或双向端口。
  • 函数只返回一个数据,其缺省为reg类型。
  • 传送到函数的参数顺序和函数输入参数的说明顺序相同。
  • 函数在模块(module)内部定义。
  • 虽然函数只返回单个值,但返回的值可以直接给信号连接赋值。这在需要有多个输出时非常有效。{o1,o2,o3,o4}=f_or_and(a,b,c,d,e);

第72页:module foo 代码示例

要返回一个向量值(多于一位),在函数定义时在函数名前说明范围。函数中需要多条语句时用begin和end。module foo; input [7: 0] loo; output [7: 0] goo;function[3: 0]zero_count; input [7: 0] in_ bus; reg [3:0] i;beginzero_count = 0; for (i = 4'h0; i < 4'h8; i = i + 1)if (! in_bus[ i ])zero_count = zero_count + 1; endendfunctionendmodule;

第73页:函数返回值可以声明为其它register

类型
integer。在任何表达式中都可调用函数module checksub (neg, a, b);input a, b;output neg;reg neg;functioninteger subtr;input [7: 0] in_a, in_b;subtr = in_a-in_b;endfunctionalways @ (a or b)if (subtr( a, b) < 0)neg = 1;elseneg = 0;endmodule

第74页:函数中可以对返回值的个别位进行赋值

。函数值的位数、函数端口甚至函数功能都可以参数化。. . .parameter MAX_BITS = 8;reg [MAX_BITS: 1] D;function[MAX_BITS: 1]reverse_bits;input [MAX_BITS-1: 0] data;integer K;for (K = 0; K < MAX_BITS; K = K + 1)reverse_ bits[MAX_BITS-K] = data [K];endfunctionalways @ (posedge clk)D< =reverse_bits (D) ;. . .

第75页:实际工程中Function语句实例

例一
function [22:0] uv_clamp;input [23:0]iuv;begin// Clamp to the most negative numberuv_clamp =(iuv[23:22]==2'd2)?23'h400001 :((iuv[23:22] == 2'd1)?23'h3fffff:iuv[22:0]);endendfunction

第76页:Verilog时序逻辑示例

always @(uvtmp_morei2tsw_u_morei2tsw_v_moruv_selorttt_uvtmp)case(uv_sel)2'd1:n_uvtmp = {ei2tsw_u_m, 5'b0}; 2'd2:// 2n_uvtmp = {ei2tsw_v_m, 5‘b0}; default:endcase// case (uv_sel);

第77页:例二:function [15

0]lod_clamp;input [16:0]ilod;beginlod_clamp=(ilod[16:15]==2 ' d2) ?16'h8000:((ilod[16:15] == 2'd1) ? 16'h7fff : ilod[15:0] );endendfunction

第78页:Verilog时序逻辑示例(续1)

always @(ei2tsw_lod_morlodtmp_morlod_selorttt_lodtmp)case (lod_sel)//synopsys parallel_case full_case2'd0:n_lodtmp = lodtmp_m; 2'd1:n_lodtmp = {ei2tsw_lod_m, 5‘b0}; default:endcase;

第79页:特别说明

特别说明

  • begin-end和fork-join1. begin-end并不是顺序语句块,内部语句用阻塞赋值语句,当然是顺序执行
  • 如果用非阻塞赋值语句,就是并行执行。2.实际工程中,描述可综合电路很少用fork-join。语句块-顺序语句块和并行语句块