我的Verilog学习笔记1.doc

上传人:sk****8 文档编号:3528566 上传时间:2019-06-02 格式:DOC 页数:27 大小:505KB
下载 相关 举报
我的Verilog学习笔记1.doc_第1页
第1页 / 共27页
我的Verilog学习笔记1.doc_第2页
第2页 / 共27页
我的Verilog学习笔记1.doc_第3页
第3页 / 共27页
我的Verilog学习笔记1.doc_第4页
第4页 / 共27页
我的Verilog学习笔记1.doc_第5页
第5页 / 共27页
点击查看更多>>
资源描述

1、Verilog 学习笔记1.我的第一个 verilog 程序:三态门module three_status_device(in,out,oe);input in,oe;output out;assign out = (oe)? in : 1bz;endmodule其中 oe 为输出有效端,当 oe 置高则输入能顺利通过,否则输出高阻态。查看 Technology Schematic 后可知 three_status_device 模块使用的 FPGA 内部资源:分别是输入缓冲器 IBUF,非门 INV 和三态缓冲器 OBUFT。我们还可以通过 View Synthesis Report 来观察

2、到底使用了多少资源:我们可以看出所选的芯片类型为 V5 系列的 fx100,SPEED 等级为-2 ,使用了 1 个查找表,1个 Flip Flop 触发器和 3 个 IO 口。由于模块比较简单,我们直接进入后仿真阶段;最后,我们可以通过 中的 View HDL Instantiation Template 看到生成的 HDL 模板供我们调用实例:three_status_device instance_name (.in(in),.out(out),.oe(oe);小结:通过设计三态门,熟悉了 verilog 开发的主要流程和 ise 中的常用工具。反思:对于高阻态,一般 FPGA 内部是不

3、支持判断的。现在有些比较新的 FPGA 内部已经带有BUFT 三态门让用户直接调用(在 IOB 中) ,而对于市面上常用的 FPGA 则无法做到,因为内部并没有 BUFT 三态门,所以就需要用到 slice 资源中的 MUX 复用器,用 MUX 除了多占用LC/LE 的资源以外,受控信号(如数据总线等)会随着驱动源的增加而使延时加大。也有说法是使用 RAM 或 ROM 的总线结构提供高阻态的输出。在 FPGA 开发时,一般将不用的 IO 口设置为三态状态,如果 IO 口较多的时候既占用连线资源也占用 slice 资源,对系统产生延迟。2.组合逻辑:有毛刺怎么办?引用数字电路基础的描述,当一个逻

4、辑门的两个输入端的信号同时向相反方向变化,而变化的时间有差异的现象,称为竞争。由竞争而可能产生的输出干扰脉冲的现象就叫做冒险,也就是通俗上说的毛刺。书上还给出了常用的消除竞争冒险的方法: 消除互补相乘项:通过人为优化逻辑表 1达式,消去同一信号的同反相同时存在项,降低竞争的发生几率。 增加乘积项避免互补 2项相加:若组合逻辑表达式中,在某些信号取一定值的情况下,表达式可化为一个信号的同反相同时相乘或相加时,则需要人为加入相乘项以确保此时输出状态的稳定。那么在 verilog 如何实现消除毛刺呢?信号在 fpga 器件中通过逻辑单元连线时,一定存在延时。延时的大小不仅和连线的长短和逻辑单元的数目

5、有关,而且也和器件的制造工艺、工作环境等有关。因此,信号在器件中传输的时候,所需要的时间是不能精确估计的,当多路信号同时发生跳变的瞬间,就产生了“竞争冒险” 。这时,往往会出现一些不正确的尖峰信号,这些尖峰信号就是“毛刺” 。另外,由于 fpga 以及其它的 cpld 器件内部的分布电容和电感对电路中的毛刺基本没有什么过滤作用,因此这些毛刺信号就会被“保留”并传递到后一级,从而使得毛刺问题更加突出。尽管毛刺持续时间很短,但在高速电路中,这样的毛刺足以使后一级电路产生“误动作” 。要消除毛刺,我们先要了解 FPGA 内部毛刺的具体特点:由于布线延迟,和器件延迟,取决于 FPGA 内部结构,这个涉

6、及到约束问题,http:/ ,只要毛刺不出现在时钟跳变沿,毛刺信号就不会对系统造成危害。FPGA 中消除毛刺的常用方法是:1.触发器输出通过添加触发器,使输出信号在 clk 跳变沿进行读取,并输出,能有效地降低毛刺的发生几率。但这样的话,延时也就增大。但是,毛刺的产生是不定时的,如果毛刺在时钟跳变时期产生,则使用触发器的方法无法解决问题。2.信号延时法信号延时法,顾名思义,延时信号处理时期,等待信号稳定时再对数据进行处理。它的具体做法有很多:信号延时检测 1信号延时方法很多,如使用门级电路延时,fpga 的专用延时单元 lcell,毛刺的产生随机性,单凭延时是无法解决问题的。时钟延时 2像使用

7、触发器的原理类似,通过增加时钟计数器,对时钟进行分频,加大时钟间隔,来保证对信号进行处理的时候信号已经稳定;或者为防止在信号检测时钟跳变时,信号发生变化,延时对信号检测时间,比如加入标志位寄存器,信号跳变后的下一个检测时钟对其检测。这针对检测时期瞬变信号导致检测错误的方法。状态机检测 3使用状态机对信号进行多次检测,首先第一次检测信号,进入下一状态,再次检测信号并与前面进行比较,如果不同则重新开始检测知道检测一定次数后确定信号不变动后,进行数据处理。这种方法结合了上述方法,极好地消除了竞争冒险。信号延时法缺点是用速度换取电路的稳定性,我们只能择优而取。下面我们来看一些例子:按照设想 out=a

8、bc+bde;其时序图要求如下:(用 TimingDesigner 画图)下面我们一一验证一下不同方法所实现的逻辑组合的效果。/方法一,直接使用 assign 语句(数据流)assign out = a类似的描述组合逻辑方法还有:always (a or b or c or d or e)begintemp1 = a out = temp1endwire temp1,temp2;and myand1(temp1,a,b,c);and myand2(temp2,d,e,b);or myor(out,temp1,temp2);由于表达式 out=abc+bde 可转换成 out=b(ac+de),

9、因此 b 的取值至关重要,当输入信号 b变为 0 时,输出即变为 0,所以上述语句一般写成:wire temp;assign temp = aassign out = temp这样一来,当 b 变为 0,输出立即变化,这就是关键路径的选取。关键路径所生成的 RTL 结构如下:与没有选取关键路径相比:由行为仿真波形可以看出,这样的逻辑设计与设想相同:我们通过修改仿真文件.twf 对某些输入信号进行人为的延时,观察加入延时后出来的效果:输入信号波形代码段均写在 Initial 段中:(我们就在这里修改) ,为了保持毛刺持续时间尽量满足实际情况(一般为十几 ns)所以这里设置延时均为 10ns,即在

10、timescale 1ns/1ps 情况下,使用#10;语句进行延时动作。initial begin/ - Current Time: 490ns#490;a = 1b1; b = 1b1; c = 1b1; d = 1b1;/ -/ - Current Time: 1090ns#600; a = 1b0; c = 1b0;#10; e = 1b1;#10; b = 1b0;/ -/ - Current Time: 1690ns#600; b = 1b1;#10; e = 1b0;/ -/ - Current Time: 2290ns#600; e = 1b1;/ -/ - Current T

11、ime: 2690ns#400; e = 1b0;/ -/ - Current Time: 3090ns#400; e = 1b1;#10; b = 1b0; c = 1b1;/ -/ - Current Time: 3690ns#600; b = 1b1;#10; d = 1b0;#10; a = 1b1; / -end仿真出来的效果(毛刺出现了)可见,尽管做出了关键路径的选取,组合逻辑电路还是非常容易产生毛刺。下面我们使用上面的说法,加入寄存器后观察结果。reg out; wire temp;assign temp = aalways (posedge clk)out = temp;从 R

12、TL 结构图中可以直观看到加入 D 触发器(即寄存器)输出:依旧采用改动后的仿真文件,所得出的仿真波形如下:可见,上面的毛刺完全被消除了,而且不留一点痕迹。由于使用触发器免不了使用时钟,详细的使用放到后面的时序电路学习一节中。小结:从本节中,实现了简单的逻辑组合,并透过阅读修改仿真文件,了解毛刺的产生;通过观察 RTL 结构图,了解到代码风格与生成的模型之间的联系,并通过使用 D 触发器消除毛刺。反思:如果外部情况比较恶劣,延时级别大于 ns 级,或者输入信号的跳变在时钟跳变时期发生,会产生什么效果,这需要在后面的学习中逐步体会。3.使用组合逻辑:加法器的设计一个设计,其实现方案多样,而且不同

13、的实现方案,电路结构是不一样的,这将导致速度或使用资源的差异。所以,在学习过程中,需要对不同的方法进行比较,了解各种编码风格实现的差别,对将来的系统设计有极大的帮助。下面我们以加法器的设计为引导,延伸本节的讨论。首先,我们要知道一个加法器模型应该有的端口,他们分别为:加数,被加数,上级进位,和,进位这几个端口。注意 verilog 的编码规范,模块端口有高位至低位,从输出到输入进行描述:module adder(cout,sum,clk,rst,a,b,cin);(1 )实现方法一assign cout, sum = a + b + cin;这样看来,加法器的实现非常简单,从结构上看,它直接调

14、用了一个加法器(如图):但是对于“+” 号的综合,FPGA 内部是采用查找表所实现的,下面是由上述语句生成的二级查找表结构:(查找表的级数是延时的主要因素,降低查找表级数是代码优化的首要任务)其中 LUT3_E8 表示 3 输入查找表,E8 指查找表内部真值表的结果值。由于使用查找表实现,容易出现毛刺,我们回顾下上一节所用到的方法,我们再使用一次:再次出现了 D 触发器。 (仿真波形就不看了,大家可以自己试试)(2 )串行加法器wire 1:0 temp;assign temp0,sum0 = a0 + b0;assign temp1,sum1 = a1 + b1 + temp0;assign

15、 cout = temp1;虽然咋一看,与第一种方法相当类似,你确定是一样吗?我们看看生成的,如下图:我们可以看出,这样的代码,只使用了一级的 LUT,这样设计有助于降低延时,而且并没有增多 LUT 的使用量,反而少用一个 LUT。可见资源利用率是第二种略为节省些。(3 )查找法reg 1:0 sum; reg cout;always (posedge clk or negedge rst)beginif(!rst)cout,sum=3bzzz;elsecase( a,b )4b00_00:cout,sum=3b000; 4b00_01:cout,sum=3b001;4b00_10:cout,

16、sum=3b010; 4b00_11:cout,sum=3b011;4b01_00:cout,sum=3b001; 4b01_01:cout,sum=3b010;4b01_10:cout,sum=3b011; 4b01_11:cout,sum=3b100;4b10_00:cout,sum=3b010; 4b10_01:cout,sum=3b011;4b10_10:cout,sum=3b100; 4b10_11:cout,sum=3b101;4b11_00:cout,sum=3b011; 4b11_01:cout,sum=3b100;4b11_10:cout,sum=3b101; 4b11_11

17、:cout,sum=3b110;default:cout,sum=3bzzz;endcaseend我们看生成的 RTL 图如下:可见编译器知道我们的用意,使用了 ROM 作为查找的存储,加数为取址信号。通过观察.ngc 文件可知,这样的描述仍然使用了一级的 3 个 LUT,输出使用寄存器同步输出。(4 )卡诺图法我们写出他的真值表,通过卡诺图进行简化,得出各输出的逻辑表达式:assign sum0 = (a0assign sum1 = (a1assign cout = (a0这种方法是用门电路数目较多,延时参次不齐,而且使用不方便,但速度相对会快些。要注意,有时候适当的加上括号,除了有助于阅读

18、,还可以减少逻辑门的级数,下面再举个例子:assign out = (da + db) + (dc + dd);和 assign out = da + db + dc + dd;da + db + dc + dd 生成的模块内部图(da + db) + (dc + dd)所生成的模块内部图尽管使用的加法器个数一样,但级数变少了,这样的编码风格,提高了模块运行的速度,但由于 FPGA 内部使用 LUT 实现,所以最终对提高速度影响不大,但对于 ASIC(专用集成芯片)的模块设计,这样的考虑是很有必要的。(5 )超前加法器assign sum0 = a0 b0 cin;assign sum1 =

19、a1 b1 ( (a0 assign cout = ( a1 根据数电书上的解释,人为地观察进位与输入的关系,由输入直接导出进位是这种方法的核心思想。但我们仍然可以看出,当位数增加的时候,电路的设计变得非常复杂,下面我们通过调用模块来简化多位加法器的设计。(6 )调用模块module one_bit_adder(cout,sum,cin,ina,inb);input ina,inb,cin;output cout,sum;assign cout,sum = ina + inb + cin;endmodule/two bit adder (by using one bit adder)/This

20、 is a top modulemodule use_adder(cout,sum,c,x,y);input 1:0 x,y;input c;output 1:0 sum;output cout;wire c_temp;one_bit_adder u1(.cout(c_temp),.sum(sum0),.cin(c),.ina(x0),.inb(y0);one_bit_adder u2(.cout(cout),.sum(sum1),.cin(c_temp),.ina(x1),.inb(y1);endmodule这里先设计一位计数器(当然,计数器的设计可以使用上面的任何一个例子) ,然后通过对模

21、块端口的连线,而模块的调用有以下两种方法:模块端口的对齐:即按照模块原型声明的端口顺序 1模块端口对应连接:使用 .端口名(线名) ,.端口名(线名)这样的方式进行模块调 2用,当某一端口需要悬空,必须加上“, ”但可以不填写任何东西。(7 )流水线input3:0 a,b; input clk,cin;output3:0sum; output cout;reg3:0 tempa,tempb; reg tempci; reg cout; reg firstco;reg1:0 firstsum; reg2:0 firsta,firstb; reg3:0 sum;always(posedge clk)begintempa=a; tempb=b; tempci=cin;endalways(posedge clk)begin

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 实用文档资料库 > 策划方案

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。