完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
可综合模型的结构
如果程序只用于仿真,那么几乎所有的语法和编程语句都可以使用。但如果程序是用于硬件实现,那么我们就必须保证程序的可综合性,即所编写的程序能被综合器转化为相应的电路结构。不可综合的HDL语句在用综合工具综合时将被忽略或者报错。作为设计者,应该对可综合模型的结构有所了解。 虽然不同的综合工具对Verilog HDL语法结构的支持不尽相同,但Verilog HDL中某些典型的结构是很明确地被所有综合工具支持或不支持的。 (1)所有综合工具都支持的结构:always,assign,begin,end,case,wire,tri,aupply0,supply1,reg,integer,default,for,function,and,nand,or,nor,xor,xnor,buf,not,bufif0,bufif1,notif0,notif1,if,inout,input,instantitation,module,negedge,posedge,operators,output,parameter。 (2)所有综合工具都不支持的结构:time,defparam,$finish,fork,join,initial,delays,UDP,wait。 (3)有些工具支持有些工具不支持的结构:casex,casez,wand,triand,wor,trior,real,disable,forever,arrays,memories,repeat,task,while。 因此,要编写出可综合的模型,应尽量采用所有综合工具都支持的结构来描述,这样才能保证设计的正确性和缩短设计周期。 建立可综合模型的原则 要保证Verilog HDL赋值语句的可综合性,在建模时应注意以下要点: (1)不使用初始化语句。 (2)不使用带有延时的描述。 (3)不使用循环次数不确定的循环语句,如forever、while等。 (4)不使用用户自定义原语(UDP元件)。 (5)尽量使用同步方式设计电路。 (6)除非是关键路径的设计,一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。 (7)用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号。 (8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位。 (9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。 (10)不能在一个以上的always过程块中对同一个变量赋值。而对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值。 (11)如果不打算把变量推导成锁存器,那么必须在if语句或case语句的所有条件分支中都对变量明确地赋值。 (12)避免混合使用上升沿和下降沿触发的触发器。 (13)同一个变量的赋值不能受多个时钟控制,也不能受两种不同的时钟条件(或者不同的时钟沿)控制。 (14)避免在case语句的分支项中使用x值或z值。 常用的RTL语法结构如下: ☆ 模块声明: module……endmodule ☆ 端口声明:input,output,inout(inout的用法比较特殊,需要注意) ☆ 信号类型:wire,reg,tri等,integer常用语for语句中(reg,wire时最常用的,一般tri和integer不用) ☆ 参数定义:parameter ☆ 运算操作符:各种逻辑操作符、移位操作符、算术操作符大多时可综合的(注:===与!==是不可综合的) ☆ 比较判断:if……else,case(casex,casez)……defaultendcase ☆ 连续赋值:assign,问号表达式(?:) ☆ always模块:(敏感表可以为电平、沿信号posedge/negedge;通常和@连用) ☆ begin……end(通俗的说,它就是C语言里的 “{ }”) ☆ 任务定义:task……endtask ☆ 循环语句:for(用的也比较少,但是在一些特定的设计中使用它会起到事半功倍的效果) ☆ 赋值符号:= 和 <= (阻塞和非阻塞赋值,在具体设计中时很有讲究的) 可综合的语法时verilog可用语法里很小的一个子集,用最精简的语句描述最复杂的硬件,这也正是硬件描述语言的本质。对于做RTL级设计来说,掌握好上面这些基本语法是很重要。 相信大家在看了这么多了verilog语法书籍以后一定有点烦了,那么现在我告诉大家一个好消息,对于一个RTL级的设计来说,掌握了上面的语法就已经足够了,无论多么牛逼的工程师,在他的代码里无非也就是上面一些语法而已。当然了,对于一个能够进行很好的仿真验证的代码,一般还需要在RTL级的设计代码中添加一些延时之类的语句,比如大家一定知道#10的作用,就是延时10个单位时间,这个语句虽然在仿真的时候是实实在在的延时,但是这个语句在综合后是会被忽略的,也就是说在我们综合并且布局布线最后烧进FPGA里,这个#10的延时是不会在硬件上实现的。所以说,上面给出的这些语法才是可以最后在硬件上实现的,其它的语法大多会在综合后被忽略。这么一来大家就要问了,为什么语法书里又要给出这么多的语法呢? 1. Testbench中时钟和数据比特流的简单设计方法 always clock = ~clock; always @(posedge clock) begin data_in_a = {$radom} % 2; // 产生-1到1之间随机的比特流 data_in_b = 16’b1101_1011_1110_0011; // 产生固定的比特流 $display(“a= %dn”, a); // 与C语言类似 end 2. Verilog语法中的并行与顺序模块 (1) 连续赋值语句、always模块之间、实例模块之间都是并行语句 (2) always模块内部是分情况而定,对于if…else…而言,总是有优先级的顺序的,对于case而言,无优先级,是完全顺序执行的,此外,还要对阻塞语句和非阻塞语句具体分析。 3. Verilog中四种最常见的变量 (1) wire,即线网形变量,它不能存储值,必须受到驱动器或者连续赋值语句的驱动,如果没有驱动,那么它将会是高阻态 (2) reg是数据存储单元的抽象,通过赋值语句可以改变寄存器存储的值,其作用与改变触发器存储的值相当。寄存器变量的初时值为不确定态。在always内部用到的变量必须是reg型的。 (3) prARMeter相当与VHDL中的constant 4. 注意区分集中容易混淆的运算符 (1) 位运算符,按位操作,~,|,&,^,其输出与输出一样位宽 (2) 逻辑运算符,输出0或者1,&&,||,! (3) 缩减运算符,按位递归运算,&,|,!,其输出仅仅是1或者0 5. 阻塞语句(blocking)与非阻塞赋值语句(non-blocking) (1) 非连续赋值语句(non-blocking)(b <= a) 在always块结束后才完成赋值操作,并且赋值后b不是立即就改变,在时序逻辑或者既有时序逻辑也有组合逻辑中一定要用这种赋值方式 (2) 阻塞语句(blocking)(b = a) 赋值之后,b就立即改变,也就是在赋值语句完成以后,always才结束,在综合时,如果不注意,将产生意想不到的结果 一个非常典型的例子: always @(clock) begin b = a; c = b; end always @(clock) begin c = b; b = a; end always @(clock) begin b <= a; c <= b; end 6. 使用if或者是case进行综合时,一定要覆盖所有可能的情况,防止锁存器的综合 7. 写testbench一些常见的保留字 $display(“print_word_value = %d”, print_word_value); // 与C语言类似 $display(“%h, %o”, 12’b1101_0100_0111); // 结果是 0xD47和o6507 $monitoron; // 监控开始 $mointor($time, “rxd = %b”, “txd = %b”, rxd, txd); // 打印当前时刻的监控值 $monitoroff; $finish; // 仿真结束 $readmemb(“数据文件名”, 存储器名); // 把数据读入到当前指定的存储器内 rand_data = {random} % 60; // 产生-59到59之间的随机数 |
|
相关推荐
1 个讨论
|
|
只有小组成员才能发言,加入小组>>
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-23 07:55 , Processed in 0.521896 second(s), Total 48, Slave 37 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号