为什么用verilog 延时赋值写得乒乓操作延时了2个周期。按道理不是只有一个吗?

扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
VerilogFPGA入门笔记(源于学习经验积累)
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口verilog&HDL总结
1. Assign 语句中赋值的变量不能定义为reg型。
2& Always块里面写的是触发信息。
测试模块里要包含所有的情况。如果可以先把波形图画出来,再按照波形图写测试模块会好写些,并且能写全。
4 在进行测试模块编程时,输入定义为寄存器类型,输出定义为线性。
5 信号初始化放在initial中。
可以用计数来实现分频。比如根据时钟的周期计算出记一个数所用的时间。高电平的时间内计多少数,低电平的时间记多少数。高低电平时间之和加起来就是周期。再求倒数就是频率。
7& 在always模块中被赋值的语句的变量应定义为reg型。
8& 被测试模块的输出信号定义为wire型。被测试模块的输入信号定义为reg型。
9& If块里面的语句如果有两句以上,要加上begin end 否则会出错。
else 里面的语句如有有两个以上,也要加上begin end。
10& If 语句中给RB赋值,要写成非阻塞赋值,RB《=0;如果写成阻塞,报错。
11 一般情况下,要有一个总体系统的复位信号,否则,由于初始状态不定,所以仿真时,第一个周期容易不准确
12& Always模块里面语句是时刻赋值,意思是,比如一个上升沿作为触发信号,
如果在模块里面你写f0=f1,你的意思是想把信号f1赋给f0,这是错误的,它只能将f1此刻的值赋给f0
13. if 可以和else不配对使用,if可以单独使用
14.If& else 里面可以再嵌套if else
& Eg& if(MSL==9)
&&&&&&&&&&&&&
if(MSH==9)
&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
MSH&=0;cn1&=1;
&&&&&&&&&&&&&&&&&
&&&&&&&&&&else
&&&&&&&&&&&&&&&&&&&
MSH&=MSH 1;
&&&&&&&&&&
MSL&=MSL 1;cn1&=0;
&&& 15. else
if 里面仍然可以嵌套if&& else语句
&&&&&&&&&&&&&&
&& else if(SL==9)
&&&&&if(SH==5)
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
SH&=0;cn2&=1;
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&
SL&=SL 1;cn2&=0;
16. 如果问题老是出在第一行,很可能是没有写endmodule
17.每个端口除了要声明是输入,输出,还是双向端口外,还要声明其数据类型
是连线性还是寄存器类型。如果没有声明,综合器默认为wire型
18. 输入和双向端口不能声明为寄存器类型
19.调用子模块时,里面变量的例化写法要一致。
U2(.RB(RBB),.CLK(CLK),.EN(FD),.Q(Q)); 是正确的
&&COUNT&&&
U2(RBB, CLK,.EN(FD), Q);是错误的。
20. reg&&&
[3:0]MSH,MSL,SH,SL,MH,ML=0;表示的是只将ML赋0,其他都没有赋0
verlog语法要点:
module endmodule之间由两部分构成:接口描述和逻辑功能描述
IO端口种类: input& output& inout
相同位宽的输入输出信号可以一起声明, input[3:0] a,b; 不同位宽的必须分开写
内部信号为reg类型,内部信号信号的状态: 0& 1&
3'bx1=3'bxx1 x/z会往左扩展& 3'b1=3'b001 数字不往左扩展
逻辑功能描述中常用assign描述组合逻辑电路,always既可以描述组合逻辑电路又可以描述时序逻辑电路,还可以用元件调用方法描述逻辑功能
always之间、assign之间、实例引用之间以及它们之间都是并行执行,always内部是顺序执行
常量格式: &
/-&&二进制位宽&&'&&进制&&该进制的数值&:
默认进制为10进制
默认位宽为32位
位宽是从二进制宽度角度而言的
由位宽决定从低位截取二进制数2'hFF=2'b11,通常由被赋值的reg变量位宽决定
parameter常用于定义延迟和变量位宽,可用常量或常量表达式定义
& 变量种类: wire reg& memory
IO信号默认为wire类型,除非指定为reg类型
wire可以用作任何输入输出端口
wire包括input output inout
wire不带寄存功能
assign赋值语句中,被赋值的信号都是wire类型
assign之所以称为连续赋值,是因为不断检测表达式的变化
reg类型可以被赋值后再使用,而不是向wire一样只能输出,类似VHDL中的buffer端口
reg类型变量初始值为x (VHDL中初始值为本类型最小值,通常是0)
always模块里被赋值的信号都必须定义为reg类型,因为always可以反复执行,而reg表示信号的寄存,可以保留上次执行的值
reg类型变量与integer变量不同,即使赋负值,实质上也是按二进制无符号数存储的,integer是有符号数
verilog中所有内部信号都是静态变量,因为它们的值都在reg中存储起来了
memory型只有一维数组,由reg型变量组成
memory初始化只能按地址赋值,不能一次性赋值
1*256的memory写法: reg
mema[255:0]&&&&
mema[3]=0;
不同位宽的变量之间赋值,处理之前都以被赋值的变量位宽为准扩展或截取
A[a:b] 无论a b谁大,a总是实际电路的信号高位,b总是实际电路的信号低位
算术运算中如果有X值则结果为X
for循环中的变量另外定义成integer,因为它不是实际信号,有正负;reg则以无符号数存在
== 和!=只比较0、1,遇到z或x时结果都为x (x在if中算做假条件),结果可能是1、0、x
===和!==比较更加苛刻,包括x和z的精确比较,结果可能是0、1
&&的结果只有1'b1或1'b0两种,
A&A的结果位宽则是与A相同的
{1,0}为 64'h,所以拼接运算中各信号一定要指定位宽
移位运算左移将保留 4'b1000&&1等于5'b10000,右移则舍弃
4'b0011等于4'b0001
数字电路里位运算应用普遍,包括按位逻辑运算、移位运算、拼接运算、缩减运算
非阻塞式赋值&=与阻塞式赋值=
阻塞:在同一个always过程中,后面的赋值语句要等待前一个赋值语句执行完,后面的语句被该赋值语句阻塞
非阻塞:在同一个always过程中,非阻塞赋值语句是同时进行的,排在后面的语句不会被该赋值语句阻塞
&&&&块结束后才能完成赋值
&&&&&&&&&&&&
块内所有&=语句在always块结束时刻同时赋值
&&&&&&&&&&&&
&=右边各变量的值是上一次时钟边沿时,这些变量当时的值
&&&&&&&&&&&&
用于描述可综合的时序电路
&&&&&&&&&&&&
=语句结束之后过程always才可能结束
&&&&&&&&&&&&
在always过程中,begin end块内按先后顺序立即赋值,在fork join内同时赋值(可能造成冲突)
&&&&&&&&&&&&
与assign连用描述组合电路
&&&&&&&&&&&&
begin end中阻塞的含义:begin& ...@(A)
B="C"...;& end&&
如果A事件不发生则永远不能执行下去,被阻塞了
由于时钟的延时(往往在ps级),多个always(posedge)之间究竟谁先执行是个未知数
使用原则:同一个always过程块内建立时序电路用&=
&&&&&&&&&&&&&&&&&&&
纯组合逻辑电路用=,生成的电路结构最简单,执行速度最快
&&&&&&&&&&&&&&&&&&&
同一个always块内不要混用&=和=
&&&&&&&&&&&&&&&&&&&
不要在多个always块内对同一个变量赋值(多源驱动)
if else的三种形式,第三种形式适合描述优先编码器
if条件中0/x/z当成假,1当成真,非0的数值也当成真
case语句的三种: case(四种状态的比较)&
casez(忽略z)& casex(忽略x和z,只看哪些位的信号有用)
case语句中所有表达式值的位宽必须相等,default中不能将n'bx用'bx代替
避免生成锁存器的方法: 电平触发时if后加else&&
case中加default&&&
使用casex会将不必要的状态视为无关项,使得综合出来的电路最简单
两种特殊的括号: begin 顺序语句...
fork 并行语句... join,其差别在于块内语句的起止时间、执行顺序、相对延时
块被命名后,其内部变量可以被调用,因为变量都是静态的(调用信号:对应电路中的一个信号线被引到另一处)
initial块只无条件执行一次& always块在满足条件时不断执行
initial常用来写测试文件, always块常用来写电路描述
always既可以描述组合逻辑电路又可以描述时序逻辑电路
always如果后面有敏感信号列表则不能用wait语句
always既可以描述电平触发又可以描述边沿触发,wait只能描述电平触发
assign常用于描述组合逻辑电路
测试文件中一般都是现initial 后always
生成语句:生成快的本质是使用循环内的一条语句代替多条重复的verilog语句,简化了用户的编程
&&&&&&&&&&&&&&
genvar用于声明生成变量,生成变量只能用在生成快之间
&&&&&&&&&&&&&&
仿真时,仿真器会将生成块中的代码展平,在确立后的方针代码中,生成变量是不存在的
&&&&&&&&&&&&&&
最好是先想象出来循环生成语句被展平后的电路样子,再写相关的描述语句
task和function的区别:
&&&&&&&&&&&&&&
task可以定义自己的仿真时间单位,function与主模块共用同一个仿真时间单位
&&&&&&&&&&&&&&
函数不能启动任务,任务能够启动函数
&&&&&&&&&&&&&&
函数至少要有一个输入变量,任务没有输入变量
&&&&&&&&&&&&&&
函数返回一个值,任务不返回值
一个模块的设计包括3个部分: 电路模块的设计& 测试模块的设计&
设计文档的编写
设计者通过布局布线工具生成具有布线延迟的电路,再进行后仿真,得到时序分析报告
从时序分析报告中可以知道电路的实际延迟t,同步电路内每个时钟周期要大于t,从而可确定该运算逻辑的最高频率
综合器之所以能够实现加法器、乘法器是因为库中已经存在可配置的参数化器件模型
FPGA内总线宽度容易自定义,以便实现高速数据流,三态数据总线相当于数据流的控制阀门
数字系统内数据流的控制: 开关(或三态数据总线)、数据暂存部件(寄存器)、 同步状态机控制(整个系统在一个时钟域内)
流水线操作pipe line:
K级流水线就是从组合逻辑的输入到输出恰好有K个寄存器组,上一级的输出是下一级的输入
&&&&&&&流水线操作获得第一个结果的时间要比不用流水线操作的时间长,但以后结果获得时间都只需要一个时钟周期,提高了数据吞吐量
流水线操作的保证:Tclk&K*(组合逻辑延迟
触发器的建立保持时间/触发时间),即时间片段要长于最大路径延迟
体现了面积换速度的思想,在综合时考虑的是以面积小为主还是以速度为主
本质上是一种同步逻辑
同步时序逻辑和异步时序逻辑:
同步时序逻辑指所有寄存器组由唯一时钟触发&&
always@(posedge clk)& 或always@(negedage clk)
异步时序逻辑指触发条件不唯一,任意一个条件都会引起触发& always@(posedge clk
or posedage reset)
目前的综合器是以同步时序逻辑综合的,因为同步时序逻辑较异步时序逻辑可靠
严格的同步要求时钟信号传递速度远远大于各部分的延迟,实际中clk要单独用线,而不要经过反相器等部件
always @(posedge.. )& begin
...&=... end& 表示同步时序逻辑(同时刻赋值)
不同速率数据接口的处理方法(异步数据的处理方法):帧同步&&&
FIFO& 双端口RAM
同步状态机:
包括moore和mealy型两种,及其反馈模型(是一种反馈控制系统,当前状态就是其内部状态变量)
状态机的开发步骤:
&&&&&&&&&&&&
根据实际问题列出输入输出变量和状态数
&&&&&&&&&&&&
画出状态图并化简
&&&&&&&&&&&&
写出状态转移真值表得到逻辑表达式
&&&&&&&&&&&&
用D触发器或JK触发器构建电路(目前用D触发器多)
verilog描述时只需要得到简化的状态图就可以描述
状态编码方式: 独热码&& 格雷码
状态机主体程序有单always描述方式和多always描述方式
采用case/casez/casex建立模型最好,因为x是无关态,生成的电路最简单
default: state='bx与实际情况更一致,效果等同于 default:
state&=idle
只有同步状态机才能被目前的综合
for语句会将所有变量的情况展开,占用巨量逻辑资源,替代办法是用计数器和case语句说明所有情况
有优先级的if else结构会消耗更多资源,建议用无优先级的case替代
模块的复用往往比代码上修改节省的资源多
PLL的分频、倍频、移相操作会增加设计精度
同步时序电路的延时:#x通常用于仿真测试,实际硬件延时是:长延迟用计数器,小延迟用D触发器,此方法用来取代延迟链
同步电路中,稳定的数据采用必须满足采样寄存器的建立和保持时间
reg类型在always中不一定综合成时序电路,也可能是组合逻辑电路
乒乓操作与作用& 异步时钟域同步问题
延迟包括门延迟和线延迟
组合逻辑产生的时钟仅能应用在时钟频率较低、精度要求不高的情况下
增减敏感信号得到的结果一样
补充部分:
verilog HDL起初是作为写testbench而产生的
verilog 有1995进入IEEE标准,为IEEE-1364, 于2001年进行了扩展,为IEEE
verilog AMS可用于模拟电路和数字电路的综合,目前正在不断发展和完善中;
verilog的标识符区分大小写,关键字使用小写;
用\\来进行单行注释,用\* *\来进行跨行注释;
标识符由字母、数字、下划线构成,并以字母开头;
关键字又叫保留字,只有小写的关键字才是保留字;
信号的状态有4种: 0 1 x z
x和z在描述电路时不区分大小写,在仿真时大小写有不同意义;
常量表达式中:
x z不区分大小写;
进制符号h o d b与H O D B不区分大小写;
十六进制中a~f不区分大小写;
下划线_用于提高可读性;
?在数中可以代替z;
x和z的左端补位;
字符和字符串都以ASICII码形式存在,也可以当成电路内的信号;
字符串必须包含在同一行,不能分成多行书写;
如果表达式或者赋值语句中将字符串当成操作数,则字符串中的每个字符都被看成8位的ASCII值序列;
可综合的信号类型:wire reg memory 它们用来描述数字电路
不可综合的数据类型:integer real 它们只用仿真,位于testbench中
wire是连线的抽象模型,不能保存数据,其值由驱动元的值决定;
wire不能用在always或initial块中;
wire的默认值为高阻z;
wire的使用情形: 1.作为模块的输出端口& 2.用连续赋值语句assign赋值;
reg是1位寄存器(触发器)的抽象模型,可以保存数据;
reg必须用在always或initial块中;
reg的默认值为x;
reg的使用情形:1.阻塞赋值&= 2.非阻塞赋值=
memory只能是一维的;
memory只能对每个单元分别初始化,方法:1.一个一个赋值& 2.
通过系统任务$readmem赋值
reg[3:0] fc;//一个4位寄存器&& reg
fc[3:0]& //4个一位寄存器
parameter的作用:仿真开始以前对其进行赋值,整个仿真过程中保持其值不变;
关系运算符将以逻辑1或逻辑0返回比较的结果;
== !=的返回值有0 1 x三种情况,=== !==的返回值只有0 1两种情况;
verilog由于是描述电路的,用于位的操作较多,有: 位逻辑操作,移位操作,并置操作,归约操作;
位逻辑运算的结果中,位数与原操作数一样多;
归约符是在原操作数的所有位上进行操作,并产生1位结果;
并置运算可以发生在bit与bit之间 bit与矢量之间 矢量与矢量之间
用于仿真的系统任务:
所有系统任务都必须在initial或always内;
所有系统任务都必须以$开头;
常见系统任务:
& 显示任务($diplay系列和$write系列)
& 监控任务($monitor系列)
& 探测任务($strobe系列)
& 文件打开、输入、关闭任务(&fopen
&fclose &fdisplay...)
& 读取文件任务($readmemb $readmemh)
& 仿真结束控制任务($finish& $stop)
& 随即信号任务($random)
过程块: initial块和always块
一个module内可以包含多个initial或always模块;
所有initial或always块在0时刻开始并行执行,各initial或always块内部顺序执行;
initial过程块主要是面向testbench的,通常不具有可综合性;
always过程块在描述电路时既可以描述组合逻辑电路(电平敏感)又可以描述时序逻辑电路(边沿敏感);
写testbench时initial通常用于初始化以及顺序波形的描述,always通常用于重复波形的描述;
任务task与函数function: 为了描述模块中被多次执行的部分以及为了增强代码的易读性
verilog中的高级程序语句如for循环语句只用在写testbench中;
begin end和fork join是两种特殊的括号
if语句的第三种形式适合描述优先编码器,case语句适合描述数据选择器和状态机;
case的条件表达式如果与分支项表达式长度不同,则在比较前将所有表达式都统一为这些表达式的最长长度;
casez忽略z,casex忽略z和x;
assign语句只在右端表达式发生变化时才重新计算并重新赋值,其余时间都是连续赋值;
assign语句可以指定bit、vector或是任意拼接操作的结果;
assign语句是连续赋值的,用于驱动网线wire, reg类型不需要连续赋值,reg类型一旦被赋值就会一直保存;
过程赋值语句有两种:阻塞式=和非阻塞式&=,只能在过程块initial和always中使用;
@对事件触发的控制与wait语句不能同时使用;
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。热搜TAGS:
常用设计思想
1. 一般性指导原则RTL级设计的评判标准很多,如时序性能、所占面积、可测试性、可重用性、功耗、时钟域的分配、复位信号的设计等。根据这些标准的组合,可以派生出很多设计原则,这里只讨论一般意义上的指导原则。1. 面积与速度互换原则“面积”是指一个设计所消耗的目标器件的硬件资源数量,对FPGA来说,用消耗的触发器(FF)和查找表(LUT)数量来衡量;“速度”是指一个设计在芯片上稳定运行时所能达到的最高频率。面积(Area)与速度(Speed)这两个指标贯穿于RTL设计的始终,是衡量设计的终极标准。面积与速度是对立统一的。作为矛盾的两方面,面积和速度的地位是不一样的,相比之下,满足时序、工作频率的要求更重要一些,所以当两者发生冲突时,应采用速度优先的原则。从理论上讲,如果一个设计的时序余量较大,所能跑的频率远远高于设计要求,那么就能通过功能模块复用减少整个设计所消耗的芯片面积,用速度优势换取面积的节约;反之,如果一个设计的时序要求很高,普通方法达不到设计频率,那么可以通过将数据流串并转换,并行复制多个操作模块,对整个设计采取“乒乓操作”和“串并转换”的思想进行处理,在芯片输出模块处再对数据进行“并串转换”,相当于用面积复制换取速度的提高。面积和速度互换的操作技巧很多,比如“流水线”、“模块复用/复制”、”乒乓操作”、“并串转换”等。2. 硬件原则Verilog HDL语言同软件语言(如C、C++)有本质区别,Verilog HDL的最终实现结果是芯片内部的实际电路。所以评判一个Verilog HDL设计优劣的最终标准是:电路功能以及所达到的性能(包括速度和面积两个方面)。评价一个设计的代码水平高低,仅仅是说这个设计由硬件向HDL代码这种表现形式转换的更流畅、更合理。而一个设计的最终性能,在更大程度上取决于设计工程师所构想的硬件事项方案的效率以及合理性。因此,Verilog HDL代码编写不需要追求代码的简洁、简短。合理的编码方法是:首先理解要实现的硬件电路,对该部分的硬件的结构和连接十分清楚,然后再用可综合的HDL语言描述出来,而不能凭空写代码,只有存在的电路才是可实现的。因此,并不是由了HDL就可以放弃硬件电路的基本知识了,相反,只有深入的理解了电路本身,才能通过HDL语言完成高质量的设计。3. 系统原则系统原则包含两层含义,一是实现的目标器件本身就可以看做一个系统,需要充分有效的发挥该系统每个单元的功效。因为当代FPGA都内嵌了很多固有的硬件资源,如何合理的使用这些硬件资源,对设计的全局有个宏观的合理安排,显得至关重要。从更高层看,任何一个硬件系统如何进行模块划分和任务分配,什么样的算法和功能适合放在可编程逻辑中实现,什么样的算法和功能适合放在DSP、CPU等微处理器中实现,如何划分软、硬件功能、安排模块接口设计等问题都非常重要。在系统上模块复用节省的面积远比代码上的小打小闹实惠的多。2. 同步设计原则和多时钟处理1. 同步设计原则简单比较一下异步电路与同步电路的异同:异步电路:电路的核心用组合逻辑实现,比如异步的FIFO/RAM读写信号、地址译码等电路电路的主要信号、输出信号不依赖与任何一个时钟性信号,不是由时钟信号驱动触发器(FF)产生的异步电路最大的缺点是容易产生毛刺不利于器件移植,包括FPGA器件族之间的移植和FPGA向结构化ASIC的移植不利于静态时序分析(STA)和验证设计时序的性能同步电路:电路的核心使用各种触发器实现电路的主要信号、输出信号由某个时钟信号沿驱动触发器产生同步时序电路可以很好的避免毛刺有利于器件移植利于静态时序分析(STA)和验证设计时序的性能比较分析(略),推荐使用同步时序设计方式。同步时序设计需要注意“异步时钟域的数据转换”、“组合逻辑电路的设计方法”、“同步时序电路的时钟设计”、“同步时序电路的延时:最常用的方法是分频、倍频的时钟或同步计数器完成。”2. 亚稳态异步时钟域数据转换的核心就是要保证下级时钟对上级数据采样的Setup时间和Hold时间,如果触发器的setup时间或者hold时间不能得到满足,则有可能会产生亚稳态,此时,经过决断时间(resolution time),Q端输出结果会稳定在0或者1,但是究竟是0还是1,结果是随机的,与输入没有关系。亚稳态的危害主要体现在破坏系统的稳定性上。由于输出在稳定下来之前可能是毛刺、振荡、固定的某一电压值,因此亚稳态将导致逻辑误判,严重情况下输出0~1之间的电压值还会使下一级产生亚稳态,即导致亚稳态的传播。只要系统中有异步原件存在,亚稳态就无法避免,因此在设计电路时,首先要减少由亚稳态而导致的错误;其次要使系统对产生的错误不敏感。前者主要靠同步设计实现,后者则根据不同的设计应用采用不同的处理方法来解决。使用两级以上的寄存器可以有效的降低亚稳态继续传播的概率。两级寄存器采样仅能降低亚稳态的概率,并不能保证第二级输出的稳态电平就是正确电平,这种方法不能排除采样错误的产生,这时要求系统对采样错误有一定的容忍度。3. 异步时钟域数据同步数据时钟域不同步的情况主要有两种:两个时钟域的频率相同,但是相位差不固定,或者相位差固定,但是不可测,简称同频异相问题两个时钟域的频率不同,简称异频问题两种不推荐的异步时钟域操作方法:通过Buffer等组合逻辑延时线调整采样时间在数字逻辑设计中,特别是FPGA/CPLD设计中,这种方法应该坚决避免,因为buffer和非门等单元是组合逻辑,容易产生毛刺,而且这种设计方法的时序余量差,一旦外界条件改变,采样时序就可能完全紊乱,造成电路瘫痪。另外,一旦芯片更新换代,就必须对延时重新进行调整,电路的可维护性和继承性都很差。盲目使用时钟正负沿调整数据采样初学者随意使用时钟的正负沿来调整采样,甚至还会产生一系列不同相位或不同占空比的时钟来使用其正负沿调整数据,这种方法是不推荐的。原因如下:1.使用一个时钟的双沿进行操作,相当于使用了一个同相的倍频时钟,此时,由于时钟频率提升了,所以约束会变更紧,不利于实现;2.芯片中的PLL、DLL一般只能保证某个时钟边沿Jitter、Skew、占空比等各种参数指标,而对另外一时钟沿的指标控制并不严格。所以,如果不是很清楚使用双边沿的注意事项,还不如直接使用同相倍频时钟更加简单、可靠。异步时钟域数据同步问题的解决方法:同频异相简单解决方法是使用后级时钟对前级数据采样两次,即通常说的用寄存器打两次,这种方法可以有效减少亚稳态的传播,单不能保证两次采样的数据时正确的电平值,所以,只适用于对少量错误不敏感的功能单元。可靠的方法是用DPRAM、FIFO或者一段寄存器Buffer完成异步时钟域的数据传输,因为时钟频率相同,所以DPRAM、FIFO两端的数据吞吐率一致,因此实现起来比较简单。异频解决异频问题的可靠方法是使用DPRAM、FIFO。需要注意的是,因为时钟频率不同,两端的数据吞吐率不同,需要设置好缓冲区的大小,通过监视信号(full、empty等)确保数据不会溢出。3. 组合逻辑的注意事项相对复杂一些的设计都由两部分组成:顺序逻辑(Sequential Logic)和组合逻辑(Combination Logic)。同步时序设计系统并不是不包含组合逻辑,而是更加合理的设计、划分组合逻辑。1. always组合逻辑信号敏感表正确的信号敏感表设计方法是将always模块中用到的输入信号和条件判断信号都列在信号敏感表中。希望通过信号敏感表的增减来实现某项逻辑功能是大错特错的,不完整的信号敏感表有时会综合前造成仿真与综合后仿真、布局布线后仿真的结果不一致。一般综合工具对不完整信号敏感表的默认做法是,将处理进程中用到的所有输入信号和条件判断信号都添加到敏感表中,并给出warning,提示用户敏感表不完整。2. 组合逻辑反馈环路组合逻辑反馈环路是数字同步设计的大忌,它最容易因震荡、毛刺、时序违规等问题引起整个系统的不稳定和不可靠。组合逻辑反馈环路是一种高风险设计,原因是组合反馈环的逻辑功能完全依赖于其反馈环路上组合逻辑的门延时和布线延时等,如果这些延时发生变换,则组合逻辑反馈单元的功能将彻底改变,改变后的逻辑功能很难确定。同步时序系统应该避免组合逻辑反馈环路,牢记任何反馈环路必须包含寄存器;检查综合、实现报告的Warning,发现Combinational Loops后立即进行相应的修改。3. 脉冲产生器异步脉冲序列产生电路又称为毛刺发生器,它利用组合反馈环路振荡而不断产生毛刺,组合反馈是同步设计必须避免的,所以必须避免使用。3. 慎用锁存器(Latch)同步时序设计要尽量慎用latch,特别要注意,如果综合处与设计意图不一致的latch,则将导致仿真和设计错误。对于一定要使用latch的设计,一定要明确该latch是否为有意设计的。综合处与设计不符的latch主要是使用不完全的条件判断语句,或者设计中有组合逻辑的反馈环路等异步逻辑。防止产生非目的性latch的方法:使用完备的if...else语句检查是否含有组合逻辑反馈环路为每个输入设计输出操作,为case语句设置default操作。在使用case语句时,附加综合属性为full case4. 时钟设计的注意事项1. 内部逻辑产生的时钟如果要使用内部逻辑产生时钟,则必须要在组合逻辑产生的时钟后面插入寄存器,如果直接使用组合逻辑产生的信号作为时钟信号或者异步置位/复位信号,则将使设计不稳定。因为组合逻辑会产生毛刺,这些毛刺信号对时钟信号、置位/复位信号的影响是致命的。所以,使用组合逻辑来产生内部时钟仅仅适用于时钟频率较低、时钟精度要求不高的情况。2. Ripple CounterRipple Counter就是行波计数器,这种计数器常常用于异步分频电路,是一种典型的异步时序逻辑,根据“同步设计原则”,应该严格避免Ripple Counter。3. 时钟选择在通信系统中,为了适应不同的数据速率要求,经常要进行始终切换,有时为了节省功耗,可能会把高速时钟切换为低速时钟,或者进行时钟休眠操作。切换时钟的最佳途径是使用芯片内部专用的Clock MUX,这些MUX反应速度快,锁定时间短。4. 门控时钟门控时钟即Gated Clock,是IC设计中一种常用的减少功耗的手段。但是Gated Clock不是同步时序电路,其门控逻辑Gated Logic会污染Clock的质量,产生毛刺,使适中的Jitter、Skew等指标恶化。在同步设计中,应该尽量避免使用Gated Clock。如果功耗成为首要问题,应该采用其他方法减少功耗,如低功耗芯片、芯片休眠、Clock MUX等。5. 时钟同步使能端大多数像寄存器这样的同步单元都支持时钟的同步使能(Synchronous Clock Enable),需要注意的是,虽然使能无效时这些单元没有输出,但是并不能像Gated Clock一样减少功耗。不过Synchronous Clock Enable能够非常方便的完成一些逻辑,可以有效节约芯片面积并提高设计频率。
文章热词:verilog hdl语言
延伸阅读:
PIC单片机是一种用来开发去控制外围设备的集成电路(IC)。Periphe

我要回帖

更多关于 verilog assign 延时 的文章

 

随机推荐