好文档就是一把金锄头!
欢迎来到金锄头文库![会员中心]
电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

Verilog HDL模型的不同抽象级别.ppt

131页
  • 卖家[上传人]:re****.1
  • 文档编号:587835336
  • 上传时间:2024-09-06
  • 文档格式:PPT
  • 文档大小:3.57MB
  • / 131 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    • 第9章 Verilog HDL模型的不同抽象级别 概概 述述 由初级篇中可知,由初级篇中可知,VerilogVerilog模型可以是实际电路中不同级别模型可以是实际电路中不同级别的抽象所谓不同的抽象级别,实际上是指同一个物理电路,可的抽象所谓不同的抽象级别,实际上是指同一个物理电路,可以在不同的层次上用以在不同的层次上用VerilogVerilog语言来描述它语言来描述它从行为和功能的角度来描述某一电路模块,就称为从行为和功能的角度来描述某一电路模块,就称为从行为和功能的角度来描述某一电路模块,就称为从行为和功能的角度来描述某一电路模块,就称为行为模块;行为模块;行为模块;行为模块;如果从电路结构的角度来描述该电路模块,就称为如果从电路结构的角度来描述该电路模块,就称为如果从电路结构的角度来描述该电路模块,就称为如果从电路结构的角度来描述该电路模块,就称为结构模块结构模块结构模块结构模块 河北大学电信学院---基础教研部 第9章 Verilog HDL模型的不同抽象级别 抽象的级别和它们对应的模型类型共有以下五种l系统级(system)l算法级(algorithmic)lRTL级(RegisterTransferLevel):l门级(gate-level):l开关级(switch-level)河北大学电信学院---基础教研部 门级结构描述门级结构描述 一个逻辑电路是由许多逻辑门和开关所组成,因此用逻辑门的模型来描述逻辑电路是最直观的。

      Verilog HDL提供了一些门类关健字,可以用于门级结构建模门级建模:直观,但繁琐Verilog HDL中有关门类型的关键字共有26个,在本教材中只介绍最基本的8个河北大学电信学院---基础教研部 与非门、或门和反向器等及其说明语法 and--与门 nand -- 与非门 nor -- 或非门 or -- 或门 xor --异或门 xnor --异或非门 buf -- 缓冲器 not --非门 bufif1 -- 三态门 notif1l多输入门l多输出门河北大学电信学院---基础教研部 例:例:l nand #10 d1(a,data,clock,clear);l buf #10 b1(out1,out2……in);l not #10 n1(out1,out2……in), ………………….., n2(out1,out2……in);lbufif1 bu1(out, in, ctrl);lnotif0 no1(out, in, ctrl);<门类型门类型> <强度强度> <延时延时> <实例名实例名> ((<端口端口>);); nand (strong1, pull0) # 2 n1 (o, a, b); 省略驱动能力和延时是可选项河北大学电信学院---基础教研部 9.1.2 用门级结构描述D触发器河北大学电信学院---基础教研部 module flop(data,clock,clear,q,qb); input data,clock,clear; output q, qb; nand #10 nd1(a,data,clock,clear), nd2(b,ndata,clock), //表示nd1到nd8都是nand nd4(d,c,b,clear), nd5(e,c,nclock), nd6(f,d,nclock), nd8(qb,q,f,clear); nand #9 nd3(c,a,d), nd7(q,e,qb); not #10 iv1(ndata,data), iv2(nclock,clock);endmodule注意:可综合代码中不能出现“# d”延时控制语句!l//注意结束时用逗号,最后才用分号河北大学电信学院---基础教研部 l给电路中输入、输出引脚赋予端口名l每条内部连线取连线名l每个逻辑单元取名(调用名)l给所要描述的电路确定一个模块名l依照电路图确定连接关系模块模块引用引用9.1.3 由已经设计成的模块构成更高一层的模块河北大学电信学院---基础教研部 `include “flop.v”module hardreg(d,clk,clrb,q); input clk,clrb; input[3:0]d; output[3:0]q;flop f1(d[0],clk,clrb,q[0],), f2(d[1],clk,clrb,q[1],), f3(d[2],clk,clrb,q[2],), f4(d[3],clk,clrb,q[3],);endmodule如果已经编制了一个模块,可以在另外的模块中引用这个模块。

      引用的方法 (1) flop flop_d(d1,clk,clrb,q,qn);// module flop(data,clock,clear,q,qb) (2)flop flop_d(.clock(clk),.q(q),.clear(clrb),.qb(qn),.data(d1));结束时用逗号,最后才用分号请注意:请注意:当例引用已编模块当例引用已编模块flop时,由于不需要时,由于不需要flop端口端口中的中的qb口,故在引用时把它省去,但逗号仍需要保留口,故在引用时把它省去,但逗号仍需要保留河北大学电信学院---基础教研部 9.2 Verilog HDL的行为描述建模module hardreg(d,clk,clrb,q); Input clk,clrb; input[3:0] d; output[3:0] q;always@(posedge clk or posedge clrb) begin if(clrb) q=<0; else q<=d; endendmodulereg[3:0] q;对于上面两个例子,还可以用比较抽象Veritog描述方法来建立模型。

      【例9.3】 用行为描述的方法来描述带清零端的4位寄存器河北大学电信学院---基础教研部 例9.3的行为和例9.2的功能是完全一致的,实际上它们是同一物理电路的两种不同的表示方法 如果有一种工具能自动地把例9.3的描述转换为例9.2,再细化为由4个例9.1组成的结构,这样就把比较抽象的行为描述具体化为门级电路的描述 而门级描述表示的是电路结构,它是电路布线的依据设计的目的就是产生行为和功能准确的电路结构 电路结构看起来相当复杂,难以理解,而行为的描述比较直观我们可以用比较直观的行为描述来开始设计过程,通过Verilog语言的仿真测试验证其正确后,就完成了第一步设计工作 然后用一种工具把行为模块自动转化为门级结构,再次经过Verilog语言的仿真测试验证其正确后,便完成了前端的逻辑设计接下去可以进行后端制造的准备工作,这样做大大提高了设计的效率和准确性 这就是用Verilog语言设计复杂逻辑电路的基本思路 这种能把行为级的Verilog模块自动转换为门级结构的工具叫综合器(Synthesis Tool)河北大学电信学院---基础教研部 9.2.1 仅用于产生仿真测试信号的verilog HDL行为描述建模为了对已设计的模块进行检验,往往需要产生一系列信号,输入到已设计的模块,并检查已设计模块的输出,看它们是否符合设计要求。

      这就要求编写测试模块,也称做测试文件,常用带.tf扩展名的文件来描述测试模块,也可以用带.V扩展名的文件来描述测试模块module gen_clk ( clk, reset);output clk;output reset;reg clk, reset;initial begin reset = 1;//initial state clk=0; #3 reset = 0; #5 reset = 1; endalways #5 clk = ~clk; endmodule河北大学电信学院---基础教研部 stimulus要验证的设计要验证的设计DUT激励激励验证结果验证结果要验证的设计要验证的设计DUT•简单的简单的test bench向要验证的设计提供向量,人工验证输出向要验证的设计提供向量,人工验证输出•复杂的复杂的test bench是自检测的,其结果自动验证是自检测的,其结果自动验证 Testbench(testfixture)河北大学电信学院---基础教研部 Testbench编写编写module 模块名;//无端口列表输入、输出变量定义数据类型说明DUT调用激励信号定义(always、initial; task、function if-else、for…….)显示格式定义($display,$time,$monitor)endmoduleDUTDUT(( device under test )::• 模块名字:模块名字:与引用模块相同与引用模块相同• 实例名字:实例名字: 任意,但要符合任意,但要符合标记命名规则标记命名规则• 端口列表:端口列表: 与引用模块的次与引用模块的次序相同序相同河北大学电信学院---基础教研部 主要特点:l没有端口列表l激励信号必须定义为reg型l调用被测模块l一般用always、initial块定义激励信号波形l使用系统任务和系统函数定义显示格式有两种产生激励值的主要方法: 1)从一个从一个initial块中施加激励块中施加激励 2)从一个循环或从一个循环或always块施块施加激励加激励为什么没为什么没有端口?有端口?河北大学电信学院---基础教研部 module inline_ tb; reg [7: 0] data_ bus, addr; wire [7: 0] results; DUT u1 (results, data_ bus, addr); initial fork data_bus = 8'h00; addr = 8'h3f; #10 data_ bus = 8'h45; #15 addr = 8'hf0; #40 data_ bus = 8'h0f; #60 $finish; joinendmodule1) 从一个从一个initial块中施加激励块中施加激励线性激励河北大学电信学院---基础教研部 2)从一个循环或always块施加激励lmodule loop_tb;l reg clk;l reg [7:0] stimulus;l wire [7:0] results;l integer i;l DUT u1 (results, stimulus);l always beginl #5 clk = 1; #5 clk = 0; l endl initial beginl for (i = 0; i < 256; i = i + 1)l begin @( negedge clk) stimulus = i;endl #20 $finish;l endlendmodule循环激励河北大学电信学院---基础教研部 3)保存在文件中的矢量反过来可以作为激励(矢量回放)(矢量回放)module read_file_tb; parameter num = 256; reg [7:0] data_bus; reg [7:0] stim [num-1:0]; integer i; DUT u1 (results, data_bus) initial begin // Vectors are loaded $readmemb ("vec. txt", stim); for (i =0; i < num ; i = i + 1) #50 data_bus = stim[i]; endendmodule// 激励文件激励文件vec.dat001110000011100100111010001111000011000000101000000110000111100010111000河北大学电信学院---基础教研部 fork…join块在测试文件中很常用。

      他们的并行特性使用户可以说块在测试文件中很常用他们的并行特性使用户可以说明绝对时间,并且可以并行的执行复杂的过程结构明绝对时间,并且可以并行的执行复杂的过程结构module inline_ tb; reg [7: 0] data_ bus; initial fork data_bus = 8'b00;#10 data_bus = 8'h45;#20 repeat (10) #10 data_bus = data_bus + 1;#25 repeat (5) #20 data_bus = data_bus << 1;#140 data_bus = 8'h0f; joinendmoduleTime | data_ bus 0 | 8’b0000_000010 | 8’b0100_010130 | 8’b0100_011040 | 8’b0100_011145 | 8’b1000_111050 | 8’b1000_111160 | 8’b1001_000065 | 8’b0010_000070 | 8’b0010_000180 | 8’b0010_001085 | 8’b0100_010090 | 8’b0100_0101100 | 8’b0100_0110105 | 8’b1000_1100110 | 8’b1000_1101120 | 8’b1000_1110125 | 8’b0001_1100140 | 8’b0000_1111河北大学电信学院---基础教研部 regreg clkclk; ;initial begininitial begin # 10 # 10 clkclk = 0; = 0; forever forever # 10 # 10 clkclk = ! = !clkclk; ;endend如何建立时钟?如何建立时钟?always begin# tON Clk = 0;# tOFF Clk= 1;end改变占空比?河北大学电信学院---基础教研部 module hardreg_top; //仿真时需要包含文件“hardreg.v”和“flop.v”/* 如果仿真环境可以把有关的文件安排在一个项目中,只要底层模块经过编译,并记录在编译的库中,可以不用包含文件。

      / reg clock, clearb; reg [3:0] data; wire [3:0] qout; `define stim #100 data=4'b//宏定义stim,可使源程序简洁 event end_first_pass; //定义事件end_first_passhardreg reg_4bit (.d(data), .clk(clock), .clrb(clearb), .q(qout)); l/* 把本模块中产生的测试信号data,clock,clearb输入实例reg_4bit以观察输出信号qout实例reg_4bit实际上是已经设计好的模块hardreg实例引用的hardreg模块,根据包含文件的不同,可以是表示行为的模块也可以是表示结构的模块/hardreg模块 的测试文件河北大学电信学院---基础教研部 initial begin clock = 0; clearb = 1;end always #50 clock = ~clock;always @(end_first_pass) //每次出现end_first_pass事件时,执行过程块 clearb = ~clearb;always @(posedge clock)$display("at time %0d clearb= %b data= %d qout= %d", $time, clearb, data, qout);河北大学电信学院---基础教研部 initial begin repeat(4) //重复4次产生下面的data变化 begin data=4’b0000; `stim 0001; /************************************* 宏定义用stim引,等同于#100 data=4’b0001;。

      注意引用时要用`符号 **************************************/ `stim 0010; `stim 0011; `stim 0100; `stim 0101; `stim 1110; `stim 1111; #200一>end_first_pass; end $finish; endendmodule#time->(事件名) //表示等待time个时间单位后,立即触发事件河北大学电信学院---基础教研部 第第10章章 编写和验证纯组合逻辑模块编写和验证纯组合逻辑模块加法器加法器Ci = Xi Yi + Yi Ci-1 + Xi Ci-1Si = Xi Ci + Yi Ci + Ci-1 Ci + Xi Yi Ci-1 全加器和Si的表达式也可以表示为:Si = Pi ⊕ Ci-1 其中Pi = Xi ⊕ Yi Ci = Pi·Ci-1 + Gi 其中Gi = Xi·Yi A2 B2 A1 B1 A0 B0 C2 三位超前进位加法器 C-1 S2 S1 S00全加器Y1 X1S1 P0 G0 C0 P1 G1 C1 P2 G2 C2 P3 G3C-1 超前进位加法器 全加器Y0 X0S0全加器Y2 X2S2全加器Y3 X3S3图5.1 由四个一位全加器组成的超前进位四位加法器P* G*P* G*河北大学电信学院---基础教研部 10.1加法器加法器 module add_4( X, Y, sum, C); input [3 : 0] X, Y; output [3: 0] sum; output C;assign {C, Sum } = X + Y;endmodule而16位加法器只需要扩大位数即可:module add_16( X, Y, sum, C); input [15 : 0] X, Y; output [15 : 0] sum; output C;assign {C, Sum } = X + Y;endmodule河北大学电信学院---基础教研部 10.2 乘法器乘法器module mult_4( X, Y, Product);input [3 : 0] X, Y;output [7 : 0] Product;assign Product = X * Y;endmodule而8位乘法器只需要扩大位数即可,见下例:module mult_8( X, Y, Product);input [7 : 0] X, Y;output [15 : 0] Product;assign Product = X * Y;endmodule河北大学电信学院---基础教研部 10.3比较器比较器(( x>y ) = x.( ~y )x>y ) = x.( ~y )(( xY) XGY=1; //设置X大于Y的信号为1 else XGY=0; if(X

      在硬线逻辑构成的运算电路中只要电路的规模允许,我们可以比较自由地来确定总线的位宽,因此可以大大提高数据流通的速度适当的总线位宽,配合适当并行度的运算逻辑和步骤,就能显著地提高专用信号处理逻辑电路的运算能力l 各运算部件和数据寄存器组可以通过带控制端的三态门与总线的连接通过对控制端电平的控制来确定在某一时间片段内,总线归哪两个或哪几个部件使用(任何时间片段只能有一个部件发送,但可以有一个或几个接收)用Verilog描述总线和总线操作是非常简单的l下面是一个简单的与总线有接口的模块是如何对总线进行操作的例子:河北大学电信学院---基础教研部 10.5总线和总线操作总线和总线操作module bus_xcvr( bus_a, bus_b, en_a_b, en_b_a); inout bus_a, bus_b; input en_a_b, en_b_a; bufif1 b1 (bus_b, bus_a, en_a_b); bufif1 b2 (bus_a, bus_b, en_b_a);endmodule assign bus_b = en_a_b ? bus_a : 'bz; assign bus_a = en_b_a ? bus_b : 'bz;河北大学电信学院---基础教研部 l双向端口声明遵循下列规则:双向端口声明遵循下列规则:linout端口不能声明为寄存器类型,只能是端口不能声明为寄存器类型,只能是net类型。

      类型l不能对不能对net进行过程赋值,只能在过程块外部持续赋值,或将它连接到基本单元进行过程赋值,只能在过程块外部持续赋值,或将它连接到基本单元l在同一时间应只从一个方向驱动在同一时间应只从一个方向驱动inout端口l必须设计与必须设计与inout端口相关的逻辑以确保正确操作当把该端口作为输入使用时,端口相关的逻辑以确保正确操作当把该端口作为输入使用时,必须禁止输出逻辑必须禁止输出逻辑 module SampleOfBus(DataBus,read,write) inout [11:0] DataBus; //12位宽的总线双向端口 input linkbus; //向总线输出数据的控制电平 reg [11:0] outsigs; reg [13:0] insigs assign DataBus=(linkbus)?outsigs:12‘h zzz; always @(posedge write) begin //接收总线上数据 insigs<=DataBus*3; //把计算结果存入insigs end endmodule河北大学电信学院---基础教研部 10.6 流水线提高速度的有效方法:在已设计好的数字逻辑中插入寄存器,提高速度的有效方法:在已设计好的数字逻辑中插入寄存器,形成流水线,可以大大提高处理速度。

      形成流水线,可以大大提高处理速度总时间:max(max(T1,T3)+Tco+(T2+Tco))Tco<

      在大学生活中,某学生的在校的学习生活可以简单地概括为宿舍、教室、食堂之间的周而复始 地点------状态 功能------输出 河北大学电信学院---基础教研部 将“条件”认为是状态转移的“输入条件”,上图是一张标准的状态转移图,通过状态机的方式我们再次清晰地描述另一个学生的在校生活方式状态机特别适合描述那些有发生有先后顺序,或者有逻辑规律的事情——其实这就是状态机的本质河北大学电信学院---基础教研部 设计这样一个电路:设计这样一个电路:设计这样一个电路:设计这样一个电路:1 1 1 1)能记住自己目前所处的状态)能记住自己目前所处的状态)能记住自己目前所处的状态)能记住自己目前所处的状态 ;;;; 2 2 2 2)状态的变化只可能在同一个时钟的跳变沿时刻发生,而)状态的变化只可能在同一个时钟的跳变沿时刻发生,而)状态的变化只可能在同一个时钟的跳变沿时刻发生,而)状态的变化只可能在同一个时钟的跳变沿时刻发生,而不可能发生在任意时刻;不可能发生在任意时刻;不可能发生在任意时刻;不可能发生在任意时刻;3 3 3 3)在时钟跳变沿时刻,如输入条件满足,则进入下一状态,)在时钟跳变沿时刻,如输入条件满足,则进入下一状态,)在时钟跳变沿时刻,如输入条件满足,则进入下一状态,)在时钟跳变沿时刻,如输入条件满足,则进入下一状态,并记住自己目前所处的状态,否则仍保留原来的状态;并记住自己目前所处的状态,否则仍保留原来的状态;并记住自己目前所处的状态,否则仍保留原来的状态;并记住自己目前所处的状态,否则仍保留原来的状态;4 4 4 4)在进入不同的状态时刻,对系统的开关阵列做开启或关)在进入不同的状态时刻,对系统的开关阵列做开启或关)在进入不同的状态时刻,对系统的开关阵列做开启或关)在进入不同的状态时刻,对系统的开关阵列做开启或关闭的操作。

      闭的操作闭的操作闭的操作为什么要设计有限状态机?河北大学电信学院---基础教研部 clock 10nsS2开关S1tttSnS3tttS4产生任意复杂程度的时序逻辑产生任意复杂程度的时序逻辑河北大学电信学院---基础教研部 什么是有限状态机?什么是有限状态机?- - 有限状态机是由有限状态机是由寄存器寄存器组和组和组合逻辑组合逻辑构成的硬件时序电路构成的硬件时序电路;;- - 其状态(即由寄存器组的其状态(即由寄存器组的1 1和和0 0的组合状态所构成的有限个状态)的组合状态所构成的有限个状态)只能在只能在同一同一时钟时钟跳变沿的情况下才能从一个状态转向另一个状态跳变沿的情况下才能从一个状态转向另一个状态;;- - 究竟转向哪一状态不但取决于各个究竟转向哪一状态不但取决于各个输入值输入值,还取决于,还取决于当前状态当前状态 - 状态状态机可用于产生在时钟跳变沿时刻开关的复杂的控制逻辑,是机可用于产生在时钟跳变沿时刻开关的复杂的控制逻辑,是数字逻辑的控制核心数字逻辑的控制核心河北大学电信学院---基础教研部 12.1 状态机的结构 状态机可认为是组合逻辑和寄存器的组合,一般包括两部分:组合逻辑、寄存器。

      寄存器用于存储状态,组合电路用于状态是否改变和产生输出河北大学电信学院---基础教研部 12.2 Mealy状态机和状态机和Moore状态机的不同点状态机的不同点Mealy状态机---------输出不但取决于当前状态还取决于输入下一个状态=F(当前状态,输入信号);输出信号=G(当前状态,输入信号);河北大学电信学院---基础教研部 Moore状态机状态机-------输出只取决于当前状态输出只取决于当前状态下一个状态=F(当前状态,输入信号);输出信号=G(当前状态);河北大学电信学院---基础教研部 在设计高速电路时,把状态变量直接用作输出高速状态机设计方法1:河北大学电信学院---基础教研部 在输出逻辑G后面再加一组与时钟同步的寄存器输出流水线寄存器,即完全同步地输出,这种输出称为流水线化的输出(Pipelined outputs)的Mealy状态机高速状态机设计方法2:河北大学电信学院---基础教研部 状态机基本要素状态机的基本要素有3 个:状态、输出、输入 状态:也叫状态变量在逻辑设计中,使用状态划分逻辑 顺序和时序规律 比如:控制电路时,可以以电机的不同转速作为状态; 输出:输出指在某一个状态时特定发生的事件。

      如果电机转速过高,则输出为转速过高报警,也可以伴随减速指令或降温措施等 输入:指状态机中进入每个状态的条件,有的状态机没有输入条件,其中的状态转移较为简单,有的状态机有输入条件,当某个输入条件存在时才能转移到相应的状态河北大学电信学院---基础教研部 12.3 如何描述可综合风格状态机思路: 从状态变量入手如果一个电路具有时序规律或者逻辑顺序,我们就可以自然而然地规划出状态,从这些状态入手,分析每个状态的输入,状态转移和输出,从而完成电路功能状态机描述常用语法: wire 、、reg //定义变量 parameter //用于描述状态名称,增强源代码可读性,简化描述 always case/endcase 河北大学电信学院---基础教研部 图中所示状态转移图表示了一个4状态的有限状态机,它的同步时钟是Clock,输入信号是A和Reset,输出信号是K2和K1状态的转移只能在同步时钟(Clock)的上升沿时发生,往哪个状态的转移则取决于目前所在的状态和输入的信号(Reset和A)河北大学电信学院---基础教研部 河北大学电信学院---基础教研部 module fsm(Clock,Reset,A,K2,K1); input Clock,Reset,A; output K2,K1; reg K2,K1; reg [1:0] state; Parameter Idle=2’b00,Start=2’b01, stop=2’b10,Clear=2’b11; always @(posedge Clock) if(!Reset) begin state<=Idle;K2<=0;k1<=0; end else case(state) Idle: begin if(A) begin state<=Start; k1<=0; end else begin state<=Idle; K2<=0;k1<=0; endStart: begin if(!A) state<=Stop; else state<=Start;Stop: begin if(A) begin state<=Clear; K2<=1; end else begin state<= Stop; K2<=0;k1<=0; end endClear: begin if(!A) begin state<=Idle; K2<=0; K1<=1; end else begin state<=clear;k1<=0;k2<=0;end end default: state<=2’bxx; endcaseendmodule 河北大学电信学院---基础教研部 Binary、gray-code、one-hot 编码 one-hot 编码的最大优势在于状态比较时仅仅需要比较一个bit,一定程度上从而简化了比较逻辑,减少了毛刺产生的概率。

      对于用FPGA实现的有限状态机建议采用one-hot因为虽然独热编码多用了两个触发器,但所用组合电路可省一些,因而使电路的速度和可靠性有显著提高,而总的单元数并无显著增加 由于CPLD 更多地提供组合逻辑资源,所以CPLD 多使用gray-code 采用独热编码后出现多余的状态,即一些不可到达的状态,为此.在在case语句的最后需要增加default分支项parameter Idle = 4’b1000, Start = 4’b0100, Stop = 4’b0010, Clear = 4’b0001;FSM 的编码的编码河北大学电信学院---基础教研部 12.3.3 由输出指定的码表示状态的状态机 把状态码的指定与状态机控制的输出联系起来,把状态的变化直接用作输出,这样做可以提高输出信号的开关速度并节省电路器件这种设计方法常用在高速状态机中,,建议大家在设计高速状态机时采用例12.3的风格例中state[4]和state[0]分别表示前面两个例子中的输出K2和K1K2* * *K1Idle0 0 0 0 0 Start0 0 0 1 0 缺点:开关的维持时间必须与状态维持时间一致河北大学电信学院---基础教研部 【例12.3】module fsm(Clock,Reset,A,K2,K1);input Clock,Reset,A;output K2,K1;reg [4:0] state;assign K2=state[4]; assign K1=state[0]; parameter//----------K2-i---j--K1--输出编码状态分配Idle = 5’b00000,Start= 5’b00010,Stop= 5’b00100,Stoptoclear= 5’b11000Clear=5’b01010;Cleartoidle=5’b00111always @(posedge Clock)if(!Reset) begin state<= Idle; endelsecase(state)Idle: begin if(A) begin state<=Start; end else state<=Idle; endstop: if(A) state<= Stoptoclear; else state<=Stop; endstoptoClear: state<=clear; ……..default: state<= Idle;endcaseendmodule河北大学电信学院---基础教研部 12.3.4设计复杂的多输出状态机时常用的方法设计复杂的多输出状态机时常用的方法(推荐写法)l//1st always block, sequential state transition always @ (posedge clk or posedge nrst) if (nrst) CS <= IDLE; else CS <=NS;l//2nd always block, combinational condition judgment always @ (nrst or CS or i1 or i2) IDLE: begin if (~i1) NS = IDLE; if (i1 && i2) NS = S1;要点:将状态的转换、输出的控制分别写成独立的always过程块,有利于代码分析与调试。

      河北大学电信学院---基础教研部 //3rd always block, the sequential FSM output always @ (posedge clk or posedge nrst) if (nrst) {o1,o2,err} <= 3'b000; else begin case (NS) IDLE: {o1,o2,err}<=3'b000; S1: {o1,o2,err}<=3'b100;l输出的控制河北大学电信学院---基础教研部 【例12.4】reg[1:0] state,nextstate;………… always @(posedge Clock) if (!Reset) state <= Idle; else state <=nextstate;always @(state or A) case(state ) idle: if (A) nextstate = Start; else nextstate= idle; Start: if (!A) nextstate= stop;else nextstate = Start; ……………..//1st always block//2nd always block河北大学电信学院---基础教研部 always @(state or A or Reset) if(! Reset) k1=0; else if(state==clear&&!A) k1=1; else k1=0; always @(state or A or Reset) if(! Reset) k2=0; else if(state==stop && A) k2=1; else k2=0;//3rd always block河北大学电信学院---基础教研部 module t; reg a,clock rst; wire k2,k1; initial begin a=0; rst=1; clock=0; #22 rst=0; #133 rst=1; end always #50 clock=~clock; always@(posedge clock) begin #30 a={$random%2}; #(3*50+12); end initial begin #100000 $stop; end fsm m(.clock(clock),……..); endmodule仿真测试文件河北大学电信学院---基础教研部 河北大学电信学院---基础教研部 河北大学电信学院---基础教研部 [例例]一个状态机设计--序列检测器一个状态机设计--序列检测器 逻辑功能描述: 序列检测指的就是将一个指定的序列从数字码流中识别出来。

      本例中,我们将设计一个“10010”序列的检测器设X为数字码流输入,Z为检出标记输出,高电平表示“发现指定序列”,低电平表示“没有发现指定序列”考虑码流为“ 110010010000100101…” 则有下表:CLK12345678910111213141516171819X110010010000100101……Z000001001000000010……河北大学电信学院---基础教研部 状态转换图:其中状态A-E 表示5比特序列“10010”按顺序正确地出现在码流中考虑到序列重叠的可能,转换图中还有状态F、G 另外、电路的初始状态设为IDLE河北大学电信学院---基础教研部 Verilog HDL代码代码 module seqdet( x, z, clk, rst);input x,clk, rst;output z;reg [2:0] state; //状态寄存器wire z;parameter IDLE= 'd0, A='d1, B='d2, C='d3, D='d4, E='d5, F='d6, G='d7;assign z=(state==D && x==0) ? 1 :0;always @(posedge clk or posedge rst)if(rst)beginstate<=IDLE; endelse河北大学电信学院---基础教研部 casex( state)IDLE: if(x==1) state<=A; A: if (x==0) state<=B; B: if (x==0) state<=C; else state<=F; C:if(x==1) state<=D; elsestate<=G;D: if(x==0)state<=E;elsestate<=A;E: if(x==0)state<=C;elsestate<=A;F: if(x==1)state<=A; elsestate<=B;G: if(x==1)state<=F;default: state<=IDLE;endcaseendmodule河北大学电信学院---基础教研部 testbenchmodule t; reg clk, rst; reg [23:0] data; wire z,x; assign x=data[23]; initialbeginclk=0;rst=1;#2 rst=0;#30 rst=1; //复位信号data='b1100_1001_0000_1001_0100; //码流数据end河北大学电信学院---基础教研部 always #10 clk=~clk; //时钟信号always @ (posedge clk) // 移位输出码流data={data[22:0],data[23]};seqdet m ( .x(x), .z(z), .clk(clk), .rst(rst)); //调用序列检测器模块endmodule河北大学电信学院---基础教研部 例例 自动换量程频率计控制器设计自动换量程频率计控制器设计河北大学电信学院---基础教研部 状态机设计状态机设计进 入 100k量 程(A) Reset=1,sel=00 100k量 程 测 量(B) Reset=0,sel=00 进 入 10k量 程(C) Reset=1,sel=01 10k量 程 测 量(D) Reset=0,sel=01进入1k量程(E) Reset=1,sel=11 进入1k量程(F) Reset=0,sel=11 Clear=1 起始状态Cntover=1Cntlow=1Cntlow=1Cntlow=1Cntover=1Cntover=1河北大学电信学院---基础教研部 /*信号定义: clk: 输入时钟 clear: 频率计复位 reset: 量程转换时复位 sel: 选择标准时基 cntover: 超量程 cntlow: 欠量程 * / module ftest (sel,reset,clk,clear,cntlow,cntover); output[1:0] sel; output reset; input clk, cntover,clear,cntlow; reg[1:0] sel; reg reset; reg[5:0] cs,ns;parameter sf100k=6’b000001, f100kcnt=6’b000010, sf10k=6’b000100, f10kcnt=6’b001000, sf1k=6’b0010000, f1kcnt=6’b100000, aways@(posedge clk, posedge clear) begin if(clear) cs=sf10k;//起始 else cs=ns; end河北大学电信学院---基础教研部 aways@(cs, cntover,cntlow) begin case(cs) sf100k: ns= f100kcnt; f100kcnt: begin if(cntlow) ns= sf10k; else ns= sf100kcnt; end sf10k: ns= f10kcnt; f10kcnt: begin if(cntlow) ns= sf1k; else if(cntover) ns= sf100k; else ns=f10kcnt; end default:ns=sf10k; always@(cs) begin case(cs)sf100k: begin reset=1;sel=2’b00; endf100kcnt: begin reset=1;sel=2’b00; endsf10k: begin reset=1;sel=2’b01; endf10kcnt: begin reset=1;sel=2’b01; endsf1k: begin reset=1;sel=2’b11; endf1kcnt: begin reset=1;sel=2’b11; end default: reset=01;sel=2’b01; 河北大学电信学院---基础教研部 13.1 13.1 用用VerilogVerilog HDL HDL设计可综合的状态机的指导原设计可综合的状态机的指导原则则1、在采用FPGA设计状态机时最好用One—Hot编码;采用CPLD器件设计状态机时采用顺序编码方式(自然二进制数);2、采用case、casex或casez语句建立状态机模型,注意Default项,并将状态变量设为初始状态或’bx;3、状态机应该有一个异步或同步复位端,以便在加电时将电路复位到有效状态,CPLD/FPGA器件都支持异步复位;4、状态转换只能由一个时钟控制,即设计为同步状态机,否则综合工具将生成错误电路。

      5、如果一定要设计异步状态机,建议采用电路图输入的方法,或用实例引用的写法把几个引用的实例用异步时钟连接起来,而不要直接用Verilog RTL级别的描述方法通过综合来产生河北大学电信学院---基础教研部 状态分配的两种方法:使用参数(parameters)语句赋状态值 parameter state1=2’h1,state2=2’h2; …… current_state=state2; //把current state设置成2’h2 …. 使用宏定义(define)语句赋状态值 `define state1 2’h1 `define state2 2’h2 …… current_state=`state2; //把current state设置成2’h2河北大学电信学院---基础教研部 2.赋.赋 值值 (1) 对一个寄存器型(reg)和整型(integer)变量给定位的赋值,只允许在一个always块内进行,如在另一always块中也对其赋值,这是非法的即变量不能有多个驱动源即变量不能有多个驱动源。

      (2) 把某一信号值赋为’bx,综合器就把它解释成无关状态,因而综合器为其生成的硬件电路最简洁河北大学电信学院---基础教研部 综合工具通常不支持下列Verilog结构 initial循环:循环: repeat forever while 数据类型:数据类型: event real time UDP fork…join块块 wait disable # 操作符:操作符: = = = ! = =河北大学电信学院---基础教研部 13.5可综合风格的Verilog HDL模块实例:13.5.1 组合逻辑电路设计实例l[例13.1] 八位带进位端的加法器的设计实例(利用简单的算法描述)lmodule adder_8(cout,sum,a,b,cin);loutput cout;loutput [7:0] sum;linput cin;linput[7:0] a,b;lassign {cout,sum}=a+b+cin;lendmodule河北大学电信学院---基础教研部 //操作码的宏定义`define plus 3'd0`define minus 3'd1`define band 3'd2`define bor 3'd3`define ungate 3'd4module alu(out,opcode,a,b); output [7:0] out; input [2:0] opcode; input [7:0] a,b; reg [7:0] out; always @(opcode or a or b)//用电平敏感的always块描述组合逻辑begincase(opcode)//算术运算`plus: out=a+b;`minus: out=a-b;//位运算`band: out=a&b;`bor: out=a|b;//单目运算`ungate: out=~a;default:out=8'hx;endcaseendendmodule指令译码电路的设计实例河北大学电信学院---基础教研部 利用利用task和电平敏感和电平敏感的的always块设计比较后重组信号的组合逻辑块设计比较后重组信号的组合逻辑. module sort4(ra,rb,rc,rd,a,b,c,d); parameter t=3; output [t:0] ra, rb, rc, rd; input [t:0] a, b, c, d; reg [t:0] ra, rb, rc, rd; always @(a or b or c or d) begin :local reg [t:0] va, vb, vc, vd; {va,vb,vc,vd}={a,b,c,d}; sort2(va,vc); sort2(vb,vd); sort2(va,vb); sort2(vc,vd); sort2(vb,vc); {ra,rb,rc,rd}={va,vb,vc,vd}; endtask sort2; inout [t:0] x, y; reg [t:0] tmp; if( x > y ) begin tmp = x; x = y; y = tmp; end endtaskendmodule河北大学电信学院---基础教研部 比较器的设计实例(利用赋值语句设计组合逻辑)比较器的设计实例(利用赋值语句设计组合逻辑)module compare(equal,a,b); parameter size=8; output equal; input [size-1:0] a, b; assign equal =(a==b)? 1 : 0;endmodule河北大学电信学院---基础教研部 3-8译码器设计实例(利用赋值语句设计组合逻辑)译码器设计实例(利用赋值语句设计组合逻辑) module decoder(out,in);output [7:0] out;input [2:0] in;assign out = 1'b1<

      如果条件语句(case或if-else)中分支条件是互斥的话,综合器能自动地生成并行的多路器modul emux1(out, a, b, sel);output out;input a, b, sel;assign out = sel? a : b;endmodule河北大学电信学院---基础教研部 多路器设计方案之二多路器设计方案之二:module mux2( out, a, b, sel);output out;input a, b, sel;reg out;//用电平触发的always块来设计多路器的组合逻辑always @( a or b or sel )begincase( sel ) 1'b1: out = a; 1'b0: out = b; default: out = 'bx;endcaseendendmodule河北大学电信学院---基础教研部 多路器设计方案之三多路器设计方案之三:module mux3( out, a, b, sel); output out; input a, b, sel; reg out; always @( a or b or sel ) begin if( sel ) out = a; else out = b; endendmodule河北大学电信学院---基础教研部 奇偶校验位生成器设计实例奇偶校验位生成器设计实例0 00 01 10 01 11 10 01 1module parity(even_numbits,odd_numbits,input_bus); output even_numbits, odd_numbits; input [7:0 ] input_bus; assign odd_numbits=^input_bus; assign even_numbits=~odd_numbits; endmodule0 01 10 00 01 10 00 01 1河北大学电信学院---基础教研部 13.5.2 时序逻辑电路设计 ----------触发器设计实例触发器设计实例module dff( q, data, clk); output q; input data, clk; reg q; always @( posedge clk ) begin q <= data; endendmodule电平敏感型锁存器设计实例之一module latch1( q, data, clk); output q; input data, clk; assign q = clk? data : q;endmodule河北大学电信学院---基础教研部 带置位和复位端的电平敏感型锁存器设计实例之二带置位和复位端的电平敏感型锁存器设计实例之二module latch2( q, data, clk, set, reset); output q; input data, clk, set, reset; assign q= reset? 0 : ( set? 1:(clk? data : q ) );endmodule河北大学电信学院---基础教研部 电平敏感型锁存器设计实例之三电平敏感型锁存器设计实例之三lmodule latch3( q, data, clk);l output q;l input data, clk;l reg q;l always @(clk or data)l beginl if(clk)l q=data;l endl endmodule 注意:有的综合器会产生一警告信息,告诉你产生了一个电平敏感型锁存器。

      因为我们设计的就是一个电平敏感型锁存器,就不用管这个警告信息河北大学电信学院---基础教研部 移位寄存器设计实例移位寄存器设计实例module shifter( din, clk, clr, dout); input din, clk, clr; output [7:0] dout; reg [7:0] dout; always @(posedge clk) begin if(clr) //清零 dout = 8'b0; else begin dout = dout<<1;//左移一位 dout[0] = din;//把输入信号放入寄存器的最低位 end endendmodule河北大学电信学院---基础教研部 【例13.16】 8位计数器设计实例之一 module counter1(out,cout,data,load,cin,clk); output [7:0] out; output cout; input [7:0] data; input load,cin,clk; reg [7:0] out; always @(posedge clk) begin if(load) out<=data; else out<=out+cin; end assign cout=&out & cin;/*只有当cout[7:0]的所有位都为1,并且进位cin也为1时才能产生进位cout*/ endmoduleclkcindataloadcoutout河北大学电信学院---基础教研部 【例13.17】 8位计数器设计实例之二。

      module counter2(out,cout,data,load,cin,clk); output [7:0] out; output cout; input [7:0] data; input load,cin,clk; reg [7:0] out; reg cout; reg [7:0] preout; //创建8位寄存器 always @(posedge clk) begin out<=preout; end/*计算计数器和进位的下一个状态,注意:为提高性能不希望加载影响进位*/ always @(out or data or load or cin) begin {cout,preout}=out+cin; if(load) preout=data; end endmodule河北大学电信学院---基础教研部 13.6 状态机的置位与复位状态机的置位与复位 13.6.1 状态机的异步置位与复位 异步置位与复位是与时钟无关的异步置位与复位是与时钟无关的。

      当异步置位与复位到来时它们立即分别置触发器的输出为1或0,不需要等到时钟沿到来才置位或复位 (1)事件控制语法: @(<沿关键词沿关键词 时钟信号时钟信号 or 沿关键词沿关键词 复位信号复位信号 or 沿关键词沿关键词 置置 位信号位信号>)高电平有效的set,reset或上升沿触发的时钟---posedge低电平有效的set,reset或下降沿触发的时钟---negedge河北大学电信学院---基础教研部 (2)事件控制实例: ●异步高电平有效的置位(时钟的上升沿): @(posedge clk or posedge set) ●异步低电平有效的复位(时钟的上升沿): @(posedge clk or negedge reset) ●异步低电平有效的置位和高电平有效的复位(时钟的上升沿): @(posedge clk or negedge set or posedge reset)always @(posedge clk or posedge set or posedge reset) begin if(reset) begin ******** /*置输出为0*/ end else if(set) begin /*置输出为1*/ end else begin /*与时钟同步的逻辑*/ end end河北大学电信学院---基础教研部 ●带异步高电平有效的置/复位端的D触发器实例:module dff1( q, qb, d, clk, set, reset ); input d, clk, set, reset; output q, qb; //声明q和qb为reg类型,因为它需要在always块内赋值 reg q, qb; always @(posedge clk or posedge set or posedge reset ) begin if(reset) begin q<=0; qb<=1; end else if (set) begin q<=1; qb<=0; end else begin q<=d; qb<=~d; end end endmodule河北大学电信学院---基础教研部 上例仿真波形截图河北大学电信学院---基础教研部 同步置位与复位是指只有在时钟的有效跳变沿时刻置位或复位,信号才同步置位与复位是指只有在时钟的有效跳变沿时刻置位或复位,信号才能使触发器置位或复位。

      能使触发器置位或复位 因此不要把因此不要把set和和reset信号名列入信号名列入always块的事件控制表达式块的事件控制表达式 set或reset的电平维持时间必须大于时钟沿的间隔时间,否则set和reset不能每次都能有效地完成置位和复位的工作为此在编写测试模块时和设计与其配合的电路时要注意这个问题 (1)事件控制语法: @(<沿关键词沿关键词 时钟信号时钟信号>) 其中,沿关键词是指posedge或negedge (2)事件控制实例: ●正沿触发 @(posedge clk) ●负沿触发: @(negedge clk) 13.6.2 状态机的同步置位与复位河北大学电信学院---基础教研部 ●同步的具有高电平有效的置位/复位端的D触发器: module dff2(q,qb,d,clk,set,reset); input d,clk,set,reset; output q,qb; reg q,qb; always @(posedge clk) begin ……………………… end 河北大学电信学院---基础教研部 可综合设计要点l不使用初始化语句不使用初始化语句 l 不使用带有延时的描述不使用带有延时的描述. .l不使用循环次数不定的循环语句不使用循环次数不定的循环语句. forever while . forever while l尽量采用同步方式设计电路尽量采用同步方式设计电路l用用alwaysalways描述组合逻辑,在敏感信号列表中列出所有描述组合逻辑,在敏感信号列表中列出所有输入信号输入信号l所有内部寄存器都应能够被复位,使用FPGA时尽所有内部寄存器都应能够被复位,使用FPGA时尽量使用全局复位端做为系统总复位量使用全局复位端做为系统总复位lUDP元件是不可综合的 UDP元件是不可综合的 河北大学电信学院---基础教研部 第第1414章章 深入理解阻塞和非阻塞赋值的不同深入理解阻塞和非阻塞赋值的不同 阻塞和非阻塞赋值语句对应着两种不同的电路结构。

      阻塞赋值对应的电路结构往往与触发沿没有关系,只与输入电平的变化有关系而非阻塞赋值对应的电路结构往往与触发沿有关系,只有在触发沿时才有可能发生赋值的情况我们在前面曾提到过下面两个要点: (1)在描述组合逻辑的always块中用阻塞赋值,则综合成组合逻辑的电路结构; (2)在描述时序逻辑的always块中用非阻塞赋值,则综合成时序逻辑的电路结构 为什么一定要这样做呢?这是因为要使综合前仿真和综合后仿真一致的缘故如果不按照上面两个要点来编写Verilog代码,也有可能综合出正确的逻辑,但前后仿真的结果就会不一致河北大学电信学院---基础教研部 14.1 14.1 阻塞和非阻塞赋值的不同阻塞和非阻塞赋值的不同l阻塞赋值(=)------在赋值时先计算RHS的值,这时赋值语句不允许任何别的Verilog语句的干扰,直到现行的赋值完成时刻,即把RHS赋值给 LHS的时刻,它才允许别的赋值语句的执行一般可综合的阻塞赋值操作在RHS不能设定有延迟 l阻塞赋值的执行可以认为是只有一个步骤的操作 计算RHS并更新LHS,此时不能允许有来自任何其他Verilog语句的干扰 所谓阻塞的概念是指在同一个always块中,其后面的赋值语句从概念上(即使不设定延迟)是在前一句赋值语句结束后再开始赋值的。

      河北大学电信学院---基础教研部 l如果在一个过程块中阻塞赋值的RHS变量正好是另一个过程块中阻塞赋值的LHS变量,这两个过程块又用同一个时钟沿触发,即如果阻塞赋值的次序安排不好,就会出现竞争 例 用阻塞赋值的反馈振荡器 module fbosc1 (y1, y2, clk, rst); output y1, y2; input clk, rst; reg y1, y2; always @(posedge clk or posedge rst) if (rst) y1 = 0; // reset else y1 = y2; always @(posedge clk or posedge rst) if (rst) y2 = 1; // preset else y2 = y1; endmodule按照IEEE Verilog HDL的标准,两个always块是并行执行的,与前后顺序无关如果复位信号到0,前一个always块clk早到达,y1和y2都会取1,而如果后一个always块的clk先到,则y1和y2都会取0。

      这清楚地说明这个Verilog模块是不稳定的,必定会产生冒险和竞争的情况河北大学电信学院---基础教研部 l非阻塞赋值(<=)------在赋值操作时刻开始时计算非阻塞赋值符的RHS表达式,赋值操作时刻结束时更新LHS在计算非阻塞赋值的RHS表达式和更新LHS期间,其他的Verilog语句,包括其他的Verilog非阻塞赋值语句都能同时计算RHS表达式非阻塞赋值的操作可以看作为两个步骤的过程:l1)在赋值时刻开始时,计算非阻塞赋值在赋值时刻开始时,计算非阻塞赋值RHS表达式l2)在赋值时刻结束时,更新非阻塞赋值在赋值时刻结束时,更新非阻塞赋值LHS表达式l非阻塞赋值操作只能用于对寄存器类型变量进行赋值,因此只能用在"initial"块和"always"块等过程块中非阻塞赋值不允许用于连续赋值 河北大学电信学院---基础教研部 [例]. 用非阻塞赋值的反馈振荡器 module fbosc2 (y1, y2, clk, rst); output y1, y2; input clk, rst; reg y1, y2; always @(posedge clk or posedge rst) if (rst) y1 <= 0; // reset else y1 <= y2; always @(posedge clk or posedge rst) if (rst) y2 <= 1; // preset else y2 <= y1; endmodule两个always块是并行执行的。

      无论哪一个always块的有效沿先到,两个always块中的非阻塞赋值都在赋值开始时刻计算RHS表达式,而在结束时刻才更新LHS表达式所以,always块结束时,使y1为0而y2为1是确定的河北大学电信学院---基础教研部 14.2 Verilog模块编程要点:模块编程要点:l时序电路建模时,用非阻塞赋值时序电路建模时,用非阻塞赋值l锁存器电路建模时,用非阻塞赋值锁存器电路建模时,用非阻塞赋值l用用always块建立组合逻辑模型时,用阻塞赋值块建立组合逻辑模型时,用阻塞赋值l在同一个在同一个always块中建立时序和组合逻辑电路时,用非块中建立时序和组合逻辑电路时,用非阻塞赋值阻塞赋值l在同一个在同一个always块中不要既用非阻塞赋值又用阻塞赋值块中不要既用非阻塞赋值又用阻塞赋值l不要在一个以上的不要在一个以上的always块中为同一个变量赋值块中为同一个变量赋值l用用$strobe系统任务来显示用非阻塞赋值的变量值系统任务来显示用非阻塞赋值的变量值l在赋值时不要使用在赋值时不要使用 #0 延迟延迟 掌握可综合风格的Verilog模块编程的8个原则会有很大的帮助在编写时牢记这8个要点,并以此为绝大多数的Verilog用户解决在综合后仿真中出现的90%~100%的冒险竞争问题。

      河北大学电信学院---基础教研部 河北大学电信学院---基础教研部 河北大学电信学院---基础教研部 14.5 移位寄存器模型移位寄存器模型[例14.5] 不正确地使用的阻塞赋值来描述移位寄存器方式 #1) module pipeb1 (q3, q2, q1, d, clk); output q2, q1 ,q3; input d; input clk; reg q3, q2, q1; always @(posedge clk) begin q1 = d; q2 = q1; q3 = q2; end endmodule河北大学电信学院---基础教研部 例14.5 用阻塞赋值来描述移位寄存器也是可行的,但这种风格并不好方式 #2 )module pipeb2 (q3, q2, q1, d, clk); output q2, q1, q3; input d; input clk; reg q3, q2, q1; always @(posedge clk) begin q3 = q2; q2 = q1; q1 = d; end endmodule 阻塞赋值的顺序是经过仔细安排的,以便仿真的结果与移位寄存阻塞赋值的顺序是经过仔细安排的,以便仿真的结果与移位寄存器相一致。

      虽然该模块可被综合成图所示的移位寄存器,但不建议器相一致虽然该模块可被综合成图所示的移位寄存器,但不建议使用这种风格的模块来描述时序逻辑使用这种风格的模块来描述时序逻辑河北大学电信学院---基础教研部 [例14.6] (方式 #3) module pipeb3 (q3, q2, q1, d, clk); output q2, q1, q3; input d; input clk; reg q3, q2, q1;always @(posedge clk) q1 = d;always @(posedge clk) q2 = q1;always @(posedge clk) q3 = q2; endmodule 阻塞赋值分别被放在不同的always块里仿真时,这些块的先后顺序是随机的,因此可能会出现错误的结果这是Verilog中的竞争冒险按不同的顺序执行这些块将导致不同的结果但是,这些代码的综合结果却是正确的流水线寄存器也就是说,前仿真和后仿真的结果可能会不一致河北大学电信学院---基础教研部 正确的用非阻塞赋值来描述时序逻辑的设计风格正确的用非阻塞赋值来描述时序逻辑的设计风格module pipen2 (q3, q2, q1, d, clk); output q2, q1 ,q3; input d; input clk; reg q3, q2, q1; always @(posedge clk) begin q3 <= q2; q2 <= q1; q1 <= d; end endmodule如果用非阻塞赋值语句改写以上4个阻塞赋值的例子,每一个例子都可以正确仿真,并且综合为设计者期望的移位寄存器逻辑。

      河北大学电信学院---基础教研部 14.6 阻塞赋值及一些简单的例子阻塞赋值及一些简单的例子 module dffb (q, d, clk, rst); output q; input d, clk, rst; reg q; always @(posedge clk) if (rst) q = 1'b0; else q = d;endmodule 使用非阻塞赋值来描述D触发器是建议使用的风格 module dffx (q, d, clk, rst); output q; input d, clk, rst; reg q; always @(posedge clk) if (rst) q <= 1'b0; else q <= d; endmodule河北大学电信学院---基础教研部 14.7 时序反馈移位寄存器建模时序反馈移位寄存器建模lmodule lfsrb1 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; wire n1; assign n1 = q1 ^ q3;always @(posedge clk or negedge pre_n) if (!pre_n) begin q3 = 1'b1; q2 = 1'b1; q1 = 1'b1; endelse begin q3 = q2; q2 = n1; q1 = q3; end endmodulel[例15] 用阻塞赋值实现的线性反馈移位寄存器实际上并不具有LFSR的功能河北大学电信学院---基础教研部 [ [例例16] 16] 用阻塞赋值描述的线性反馈移位寄存器用阻塞赋值描述的线性反馈移位寄存器module lfsrb2 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always @(posedge clk or negedge pre_n) if (!pre_n) {q3,q2,q1} = 3'b111; else {q3,q2,q1} = {q2,(q1^q3),q3}; endmodulel其功能正确,但模型的含义较难理解。

      如果逻辑其功能正确,但模型的含义较难理解如果逻辑在复杂一些,单行等式难以编写、调试不推荐使在复杂一些,单行等式难以编写、调试不推荐使用河北大学电信学院---基础教研部 [ [例例17] 17] 用非阻塞语句描述的用非阻塞语句描述的LFSRLFSR,可综合其功能正确可综合其功能正确 module lfsrn1 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; wire n1; assign n1 = q1 ^ q3;always @(posedge clk or negedge pre_n) if (!pre_n) begin q3 <= 1'b1; q2 <= 1'b1; q1 <= 1'b1; endelse begin q3 <= q2; q2 <= n1; q1 <= q3; end endmodule推荐风格原则原则1 时序电路建模时序电路建模 用用《《=。

      原则原则2 锁存器建模用锁存器建模用《《=河北大学电信学院---基础教研部 14.8组合逻辑建模时应使用阻塞赋值:组合逻辑建模时应使用阻塞赋值: module ao4 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tmp2; always @(a or b or c or d) begin tmp1 <= a & b; tmp2 <= c & d; y <= tmp1 | tmp2; endendmodule 但是当always块中有多个赋值语句时,如例19所示的四输入与或门逻辑,使用没有延时的非阻塞赋值可能导致仿真结果不正确 如果always块中只有一条赋值语句,使用阻塞赋值或非阻塞赋值语句都可以,但是为了养成良好的编程习惯,应该尽量使用阻塞赋值语句来描述组合逻辑 always @(a or b or c or d or tmp1 or tmp2) 河北大学电信学院---基础教研部 [例例21] 使用阻塞赋值实现组合逻辑是推荐使用的编码风格。

      使用阻塞赋值实现组合逻辑是推荐使用的编码风格module ao2 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tmp2; always @(a or b or c or d) begin tmp1 = a & b; tmp2 = c & d; y = tmp1 | tmp2; end endmodule原则原则3 :用:用always块描述组合逻辑时,应采用阻塞赋值语句块描述组合逻辑时,应采用阻塞赋值语句河北大学电信学院---基础教研部 14.9 时序和组合的混合逻辑时序和组合的混合逻辑——使用非阻塞赋值使用非阻塞赋值 在一个always块中同时实现组合逻辑和时序逻辑应遵从时序逻辑建模的原则,使用非阻塞赋值, module nbex2 (q, a, b, clk, rst_n); output q; input clk, rst_n; input a, b; reg q; always @(posedge clk or negedge rst_n) if (!rst_n) q <= 1'b0; // 时序逻辑 else q <= a ^ b; // 异或,为组合逻辑 endmodule 原则原则4:在同一个:在同一个always块中描述时序和组合逻辑混合电路块中描述时序和组合逻辑混合电路时,用非阻塞赋值。

      时,用非阻塞赋值 河北大学电信学院---基础教研部 将组合和时序逻辑分别写在两个将组合和时序逻辑分别写在两个always块中块中 一个always块是采用阻塞赋值的纯组合部分,另一个是采用非阻塞赋值的纯时序部分 module nbex1 (q, a, b, clk, rst_n); output q; input clk, rst_n; input a, b; reg q, y; always @(a or b) y = a ^ b; always @(posedge clk or negedge rst_n) if (!rst_n) q <= 1'b0; else q <= y; endmodule河北大学电信学院---基础教研部 14.10其他阻塞和非阻塞混合使用的原则其他阻塞和非阻塞混合使用的原则always @(posedge clk or negedge rst_n) begin: ff reg tmp; if (!rst_n) q <= 1'b0; else begin tmp = a & b; q <= tmp; end原则原则5 5 不要在同一个不要在同一个alwaysalways块中同时使用阻塞和非阻塞赋值块中同时使用阻塞和非阻塞赋值应尽量避免使用这种风格的代码,在可综合模块中应严禁使用 if (!rst_n) q = 1'b0; else begin tmp = a & b; q <= tmp; 仿真时结果通常是正确的,但是综合时会出错 河北大学电信学院---基础教研部 原则原则6 严禁在多个严禁在多个always块中对同一个变量赋值。

      块中对同一个变量赋值 module badcode1 (q, d1, d2, clk, rst_n); output q; input d1, d2, clk, rst_n; reg q; always @(posedge clk or negedge rst_n) if (!rst_n) q <= 1'b0; else q <= d1; always @(posedge clk or negedge rst_n) if (!rst_n) q <= 1'b0; else q <= d2; endmodule在一个以上always块中对同一个变量进行多次赋值可能会导致竞争冒险 当综合工具(如Synopsys)读时,将产生以下警告信息: Warning: In design 'badcode1', there is 1 multiple-driver net with unknown wired-logic type.如果忽略这个警告,继续编译,将产生两个触发器输出到一个两输入与门。

      其综合级前仿真与综合后仿真的结果不完全一致 河北大学电信学院---基础教研部 常见的对于非阻塞赋值的误解常见的对于非阻塞赋值的误解1、非阻塞赋值和$display误解1: “使用$display命令不能用来显示非阻塞语句的赋值”事实是: 非阻塞语句的赋值在所有的$display命令执行以后才更新数值initial $monitor("\$monitor : a = %b", a); initial begin $strobe ("\$strobe : a = %b", a); a = 0; a <= 1; $display ("\$display: a = %b", a); #1 $finish; end下面是上面模块的仿真结果说明$display命令的执行是安排在活动事件队列中,但排在非阻塞赋值数据更新事件之前 $display: a = 0 $monitor: a = 1 $strobe : a = 1河北大学电信学院---基础教研部 2、、#0 延时赋值延时赋值误解误解2 2:: “ “##0 0延时把赋值强制到仿真时间步的末尾延时把赋值强制到仿真时间步的末尾””事实是:事实是: ##0 0延时将赋值事件强制加入停止运行事件队列中延时将赋值事件强制加入停止运行事件队列中。

      begin a = 0; b = 1; a <= b; b <= a; $monitor ("%0dns: \$monitor: a=%b b=%b", $stime, a, b); $display ("%0dns: \$display: a=%b b=%b", $stime, a, b); $strobe ("%0dns: \$strobe : a=%b b=%b\n", $stime, a, b); #0 $display ("%0dns: #0 : a=%b b=%b", $stime, a, b); end下面是上面模块的仿真结果说明#0延时命令在非阻塞赋值事件发生前,在停止运行事件队列中执行 0ns: $display: a=0 b=1 0ns: #0 : a=0 b=1 0ns: $monitor: a=1 b=0 0ns: $strobe : a=1 b=0原则原则7:用:用$strobe系系统任务来显示用非阻统任务来显示用非阻塞赋值的变量值塞赋值的变量值河北大学电信学院---基础教研部 3、对同一变量进行多次非阻塞赋值、对同一变量进行多次非阻塞赋值误解3: “在Verilog语法标准中未定义可在同一个always块中对某同一变量进行多次非阻塞赋值”。

      事实是: Verilog标准定义了在同一个always块中可对某同一变量进行多次非阻塞赋值但多次赋值中,只有最后一次赋值对该变量起作用initial begin a <= 0; a <= 1; end 结论:最后一个非阻塞赋值决定了变量的值结论:最后一个非阻塞赋值决定了变量的值河北大学电信学院---基础教研部 本节中所有的原则归纳如下:本节中所有的原则归纳如下:l原则原则1 1:时序电路建模时,用非阻塞赋值时序电路建模时,用非阻塞赋值l原则原则2 2:锁存器电路建模时,用非阻塞赋值锁存器电路建模时,用非阻塞赋值l原则原则3 3:用:用alwaysalways块写组合逻辑时,采用阻塞赋值块写组合逻辑时,采用阻塞赋值l原则原则4 4:在同一个:在同一个alwaysalways块中同时建立时序和组合逻辑电路块中同时建立时序和组合逻辑电路 时,用非阻塞赋值时,用非阻塞赋值l原则原则5 5:在同一个:在同一个alwaysalways块中不要同时使用非阻塞赋值和阻块中不要同时使用非阻塞赋值和阻 塞赋值。

      塞赋值l原则原则6 6:不要在多个:不要在多个alwaysalways块中为同一个变量赋值块中为同一个变量赋值l原则原则7 7:用:用$strobe$strobe系统任务来显示用非阻塞赋值的变量值系统任务来显示用非阻塞赋值的变量值l原则原则8 8:在赋值时不要使用:在赋值时不要使用 #0 #0 延迟延迟河北大学电信学院---基础教研部 结束河北大学电信学院---基础教研部 。

      点击阅读更多内容
      相关文档
      【全国硕士研究生入学统一考试政治】2020年考研政治真题.docx 【全国硕士研究生入学统一考试政治】2015年考研政治真题.docx 【全国硕士研究生入学统一考试政治】2010年考研政治真题.docx 【全国硕士研究生入学统一考试政治】1996年政治考研真题(理科)及参考答案.doc 【全国硕士研究生入学统一考试政治】2001年政治考研真题(理科)及参考答案.doc 【全国硕士研究生入学统一考试政治】2016年考研政治真题.docx 【全国硕士研究生入学统一考试政治】2000年政治考研真题(文科)及参考答案.doc 【全国硕士研究生入学统一考试政治】1997年政治考研真题(理科)及参考答案.doc 【全国硕士研究生入学统一考试政治】2007年考研政治真题.doc 【全国硕士研究生入学统一考试政治】1997年政治考研真题(文科)及参考答案.doc 【全国硕士研究生入学统一考试政治】2004年考研政治真题.doc 【全国硕士研究生入学统一考试政治】2003年考研政治真题.doc 【全国硕士研究生入学统一考试政治】2019年考研政治真题.docx 【全国硕士研究生入学统一考试政治】2009年考研政治真题.docx 【全国硕士研究生入学统一考试政治】2001年政治考研真题(文科)及参考答案.doc 【全国硕士研究生入学统一考试政治】2021年考研政治真题.doc 【全国硕士研究生入学统一考试政治】2014年考研政治真题.docx 【全国硕士研究生入学统一考试政治】2018年考研政治真题.docx 【全国硕士研究生入学统一考试政治】2008年考研政治真题.doc 【全国硕士研究生入学统一考试政治】2011年考研政治真题.docx
      关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
      手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
      ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.