找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3078|回复: 0
打印 上一主题 下一主题
收起左侧

Verilog数字系统设计

[复制链接]
跳转到指定楼层
楼主
ID:104287 发表于 2016-1-30 03:40 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
个人学习笔记,不喜勿喷。

绪论:
1.计算:算法和数据结构、编程语言、体系结构、软件、硬件设计方法。
2.算法:解决特定问题的有序步骤。
3.数据结构:解决特定问题的相应模型。
4.C程序是一行接一行依次执行的,属于顺序结构;而Verilog描述的硬件是可以在同一时间同时运行的,属于并行结构。


第一部分:Verilog数字设计基础


基本概念:
1.元件的输出口都规定在第一个端口;
2.#1表示延时1个时间单位;
3.并行性,层次结构性、可综合性、测试平台;
4.实例化或实例引用;
5.verilog程序由模块构成。每个模块的内容都是位于module和endmodule两个语句之间。每个模块实现特定的功能;
6.模块是可以进行层次嵌套的;
7.如果每个模块都是可以综合的,则通过综合工具可以把他们的功能描述全部转换为最基本的逻辑单元描述,最后可以用一个上层模块通过实例引用把这些模块连接起来,把他们整合成一个很大的逻辑系统;
8.模块分为两种:一种是为了让模块最终生成电路的结构,另一种只是为了测试所设计电路的逻辑功能是否正确;
9.每个模块要进行端口定义,并说明输入口、输出口,然后对模块的功能进行描述;
10.除了endmodule语句外,每个语句和数据定义的最后必须用分号。
11.注释:用//和/**/

模块的结构、数据类型、变量和基本运算符号:
1.模块中所有过程块、连续赋值语句、实例引用都是并行的;
2.他们表示的是一种通过变量名互相连接的关系;
3.同一模块中各个过程块、各条连续赋值语句和各条实例引用语句这三者出现的先后次序没有关系;
4.只有连续赋值语句(assign)和实例引用语句可以独立于过程块而存在于模块的功能定义部分;
5.被实例引用的模块,其端口可以通过不同名的连线或寄存器类型变量连接到别的模块相应的输出、输入信号端;
6.在always模块内被赋值的每一个信号必须定义成reg型。
7.模块的端口定义:
    模块名(连接端口1信号名,连接端口2信号名,连接端口3信号名,......);
    模块名(.端口1名(连接信号1名),.端口2名(连接信号2名),......);
8.输入口 input[信号位宽-1:0]端口名1;
   输出口output[信号位宽-1:0]端口名1;
   输入/输出口inout[信号位宽-1:0]端口名1;
   IO说明也可以写在端口声明语句中;
9.内部信号说明:
    reg [width-1:0] R变量1,R变量2...;
    wire[width-1:0] W变量1,W变量2...;
10.功能定义:用assign声明语句;用实例元件;用always块;
11.数字的表达方式:<位宽><进制><数字>;
12.X不定值,Z高阻值;
13.参数型常数经常用于定义延迟时间和变量宽度;
14.wire变量用来表示单个门驱动或连续赋值语句驱动的网络型数据,常用来表示以assign 关键字指定的组合逻辑信号;tir变量用来表示多驱动器驱动的网络型数据;
15.reg型变量是数据存储单元的抽象,其作用与改变触发器存储的值相当;常用来表示always模块内的指定信号,常代表触发器;在always模块内被赋值的每一个信号都必须定义为reg型;
16.Verilog中没有多维数组存在;用memory型变量说明;

运算符、赋值语句和结构说明语句:
1.位拼接运算符{},用一个信号名来表示由多位组成的复杂信号,其中每个功能信号可以有自己独立的名字和位宽;
2.阻塞语句有先有后;非阻塞语句在begin end之间的所有非阻塞语句都在同一时刻被赋值;
3.缩减运算符为单目运算符,第一步将操作数的第1位与第2位进行或、与、非运算;第2步将运算结果与第3位进行或、与、非运算,以此类推,直至最后一位。
4.非阻塞语句所赋的变量值不能立即就为下面的语句所用,块结束以后才能完成这次赋值操作,而所赋的变量值是上一次赋值所得到的,在编写可综合的时序逻辑模块时,这是最常用的赋值方法;
5.阻塞语句的赋值语句执行完成后,块才结束,在赋值语句执行完后立刻就改变,在时序逻辑中使用可能会产生意想不到的结果;
6. begin end语句用来表示顺序语句的,每条语句的延时时间是相对于前一条语句的仿真时间而言的;fork join语句用来标识并行执行的语句,块内每条语句的延时时间是相对于程序流程控制进入到块内的仿真时间而言的;

条件语句、循环语句、块语句与生成语句:
1.条件语句必须在过程块语句中使用。所谓的过程块语句是指initial和always语句引导的执行语句集合;
2.else总是与它最近的if配对;
3.casez用来处理不用考虑高阻值z的比较过程;casex则将高阻值z和不定值都视为不必关心的情况;
4.在always块内,如果在给定条件下变量没有赋值,这个变量将保持原值,也就是会生成一个锁存器;
5.forever语句连续执行的语句,用于产生周期性的波形作为仿真测试信号且必须写在initial块中;
6.repeat语句连续执行一条语句N次;
7.生成块:生成语句可以动态地生成Verilog代码,这一声明语句方便了参数化模块的生成。当对矢量中的多个位进行重复操作时,或当进行多个模块的实例引用的重复操作时,或在根据参数的定义来确定程序中是否应该包含某段Verilog代码时,使用生成语句能够大大简化程序的编写过程;
    生成语句能够控制变量的声明、任务或函数的调用,还能对实例引用进行全面的控制。编写代码时必须在模块中说明生成的实例范围,关键字generate endgenerate用来指定该范围;

结构语句、系统任务、函数语句和显示系统任务:
1.沿触发的always块常常描叙时序行为,如有限状态机;电平触发的always块常常用来描述组合逻辑行为;
2.always的OR事件控制,用“or”或“,”;
3.@*和@(*)都表示对其后面的语句块中所有输入变量的变化是敏感的。
4.函数和任务的区别:
    函数只能与主模块共用同一个仿真的时间单位,而任务可以定义自己的仿真时间单位;
    函数不能启动任务,而任务可以启动其他任务和函数;
    函数至少要有一个输入变量,而任务可以没有或有多个任何类型的变量;
    函数返回一个值,而任务不返回值;
    不管有多少任务启动,只有当所有的任务都完成后,控制才能返回;
5.函数的使用规则:
    函数的定义不能包含有任何的时间控制语句;
    函数不能启动任务;
    定义函数时至少要有一个输入参量;
    在函数的定义中必须有一条赋值语句给函数中的一个内部变量赋以函数的结果值,该内部变量具有和函数名相同的名字;
6.自动(递归)函数:automatic;自动函数中声明的局部变量不能通过层次名进行访问。而自动函数本身可以通过层次名进行访问;
7.$display(p1,p2,...,pn):p1 格式控制;p2,...,pn 输出表列 自动换行;%和表示进制的字符中间输入一个0自动调整显示输出数据宽度的方式。
8.$write(p1,p2,...,pn):p1 格式控制;p2,...,pn 输出表列 多行;
9.所有位不定值x;所有位高阻值z;部分位不定值X;部分位高阻值Z;
10.选通显示$strobe总是在同时刻的其他赋值语句执行完成后才执行,可以确保所有在同一时钟沿赋值的其他语句在执行完毕之后才显示数据;

调试用系统任务和常用的编译预处理语句:
1.在多模块调试的情况下,$monitor需配合$monitoron与$monitoroff使用;
2.$monitor是连续监测数据的变化,只要在测试模块initial块中调用一次就可以监视被测试模块的所有感兴趣的信号;
3. $time用在$monitor中,用来做时间标记;
4.$stop和$finish用在测试模块的initial模块中,配合时间延迟用来控制仿真的持续时间;
5.$random用来产生边沿不稳定的波形和随机出现的脉冲;
6.$readmem用来生成给定的复杂数据流。复杂数据可以用c语言产生,存在文件中。用 $readmem取出存入存储器,再按节拍输出,这在验证算法逻辑时特别有用;
7.当多个‘timescale定义的模块包含在一起时,只有最后一个才能起作用;
8 .宏定义字符串引用时或include等编译预处理必须用‘引导;
9.预处理命令以符号”`”开头;
10.宏定义命令的有效范围为定义命令之后到源文件结束; 在引用已定义的宏名时,必须在宏名的前面加上“`”,表示该名字是一个经过宏定义的名字;宏定义不必在宏名后面加分号;
11.条件执行仅能用于行为语句,系统任务关键字$test$plusargs ,用于测试调用的参数值;

第二部分:设计和验证部分

只有经过艰苦的练习才能掌握设计的诀窍;

Verilog HDL模型的不同抽象级别:
1.nand #10 nd1(a,data,clock,clear);在模块中使用了一个名为nd1的与非门,输入为data\clock\clear,输出为a,输出与输入的延时为10个单位时间;
2.D型主从触发器模块
3.能把行为级的Verilog模块自动转换为门级结构的工具叫做综合器;
4.#time(触发的时刻)->(时间名)
5.UDP只能有一个输出端,而且必定是端口说明列表的第一项;可以有多个输入端,最多允许10个输入端;所有端口变量必须是标量,也就是必须是1位的;在UDP的真值表中,只允许出现0,1,X三种逻辑值;只有输出端口才可以被定义为寄存器类型变量;initial语句用于为时序电路寄存器赋初值,只允许赋0,1,X的3种逻辑值,默认为X.

如何编写和验证简单的纯组合逻辑模块:
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
2.乘法器
module mult_4(X,Y,Product);
input[3:0]X,Y;
output[3:0] Product;
assign Product=X*Y;
endmodule
3.比较器
module compare_n(X,Y,XGY,XSY,XEY);
input[width-1:0] X,Y;
output XGY,XSY,XEY;
reg XGY,XSY,XEY;
parameter width=8;

always@(X or Y)
    begin
        if(X==Y)
            XEY=1;
        else XEY=0;
        if(X>Y)
            XGY=1;
        else XGY=0;
        if(X<Y)
            XSY=1;
        else XSY=0;
    end
endmodule
4.多路选择器

module Mux_8 (addr,in1,in2,in3,in4,in5,in6,in7,in8,Mout,nCS);
input[2:0]addr;
input[width-1:0]in1,in2,in3,in4,in5,in6,in7,in8;
input nCS;
output[width-1:0]Mout;
reg[width-1:0]Mout;
parameter width=8;

always@(addr or in1 or in2 or in3 or in4 or in5 or in6 or in7 or in8 or nCS)
begin
    if(!nCS)
        case(addr)
        3`b000:Mout=in1;
        3`b001:Mout=in2;
        3`b010:Mout=in3;
        3`b011:Mout=in4;
        3`b100:Mout=in5;
        3`b101:Mout=in6;
        3`b110:Mout=in7;
        3`b111:Mout=in8;
        endcase
    else
        Mout=0;
    end
endmodule
5.总线和总线操作  
module SampleOfBus(DataBus,link_bus,wirte);
inout[11:0] DataBus;
input link_bus;
reg[11:0]outsigs;
reg[13:0]insigs;

assign DataBus=(link_bus)?outsigs:12`hzzz;
always@(posedge write)
    begin
        insigs<=DataBus*3;
    end;
endmodule;
6.流水线

复杂数字系统构成:
1.组合逻辑:逻辑电路没有记忆部件;时序逻辑:逻辑电路有记忆部分;
2.同步有限状态机;
3.数据流动的控制;
4.在VerilogHDL设计中启用同步时序逻辑;确定下一个状态所使用的组合电路的延迟与时钟到各触发器的差值必须小于一个时钟周期的宽度:全局时钟网络布线时尽量使各分支的时钟保持一致;采用平衡树结构,在每一级加入缓冲器,使到达每个触发器时钟端的时钟同步。
     在后防真时,若逻辑与预想设计的不一样,可降低时钟频率,这就可能消除由于时钟过快引起的触发器输入端由延迟和冒险竞争造成的不稳定,从而使逻辑正确。
5.数据接口的同步方法:
    前级输出的延时是随机的,或者有可能变动,如何在后级完成数据的同步?可以使用使数据通过RAM或者FIFO的缓存再读取的方法,达到数据的同步的目的,这种做法的关键是必须要有堆栈满和空的指示信号来管理数据的写入和读取,以防止数据的丢失;
    数据有固定的帧格式,数据的起始位置如何确定?用同步头表示数据信号的起始,或者使用RAM\FIFO来缓存数据再传送到下一级。找到数据头的方法有两个,一个增加一条表示数据起始位置的信号线,第二种对于异步系统,在数据中插入一段有特殊码型的同步码,接收端通关相关运算检测到同步头。
    级联的两个模块的基本时钟是异步时域的,如何把前级输出的数据准确地传送到下一级模块中?对输入数据做两次以上的采样寄存。 只适用于允许发生少量错误的电路功能单元;
    为避免由异步时钟域产生的错误,经常使用双口的RAM、FIFO缓存的方法完成异步时钟域之间的数据传送。在输入端口使用前级时钟写数据,在输出端口使用本级时钟读数据,并有缓冲器空或满的控制信号来管理数据的读写。

同步状态机的原理、结构和设计:
1. 如果时序逻辑的输出不但取决于状态还取决于输入,成为Mealy状态机;而有些时序逻辑的输出只取决于当前状态,这样的电路称为Moore状态机;
2.在设计高速电路时,常常有必要使状态机的输出与时钟几乎完全同步。第一种方法是把状态变量直接用作输出;输出编码的状态指定;其输出组合逻辑部分只有连线,没有其他组合逻辑部件;第二种方法是在输出逻辑后面在加一组与时钟同步的寄存器输出流水线寄存器,让所有的输出信号在下一个信号时钟跳变沿同时存入寄存器组,即完全同步的输出,把这种输出称为流水线化的输出;
3.独热码;
4.在比较复杂的状态机设计过程中,往往把状态的变化与输出开关的控制分成两个部分来考虑;把每一个输出开关写成一个个独立的always组合块;
5.有限状态机设计的一般步骤:
    1】逻辑抽象,得出状态转换图  分析给定的逻辑问题,确定输入量和输出量以及电路的状态数;取原因为输入,取结果为输出;定义输入、输出逻辑状态的含义,并将电路状态顺序编号;按照要求列出电路的状态转换表或画出状态转换图;
    2】状态化简
    3】状态分配 状态编码 独热码
    4】选定触发器的类型并求出状态方程、驱动方程和输出方程
    5】按照方程得到逻辑图

设计可综合的状态机的指导原则:
1.综合的一般原则:
    1】综合之前一定要进行仿真;
    2】每一次布局布线之后都要进行仿真,在器件编程或流片之前要做最后的仿真;
    3】避免用综合器来设计异步状态机;用电路图输入的方法来设计;
    4】如果要为电平敏感的锁存器建模,使用连续赋值语句是最简单的方法;
2.语言指导原则:
    1】每个always块只能有一个事件控制“@(event-expression)”,而且要跟在always关键字的后面;
    2】不推荐使用always块即表示电平敏感的透明锁存器有同时表示组合逻辑;
    3】带有posedge或negedge关键字的事件表达式表示沿触发的时序逻辑,没有该关键字的表示组合逻辑或电平敏感的锁存器,或者两种都表示。在表示时序和组合逻辑的事件控制表达式中,如有多个沿和多个电平,期间必须用关键字“or”连接;
    4】每个表示时序always块只能由一个时钟跳变沿触发,置位或复位最好也有该时钟跳变沿触发;
    5】每个在always块中赋值飞信号都必须定义为reg型或整型;
    6】always块中应该避免组合反馈回路,也就是说,用always块设计组合逻辑电路时,在生成组合逻辑的always块中参与赋值的所有信号都必须有明确的值;
    7】对一个寄存器和整型变量给定位的赋值,只允许在一个always块内进行,如在另一always块中也对其赋值,这是非法的;
    8】把某一信号值赋为·bx,综合器就把他解释成无关状态,因而综合器为其生成的硬件电路最简洁;
3.状态机的异步复位与置位:列入always块的事件控制括号内就能触发always块的执行;
4.状态机的同步复位与置位:不要把set和reset信号列入always块的事件控制表达式,always块的执行只由时钟有效跳变沿触发。set和reset的电平持续时间必须大于时钟沿的间隔时间;

深入理解阻塞和非阻塞赋值的不同:
1.时序电路建模时用非阻塞赋值语句;
2.锁存器电路建模时使用非阻塞赋值语句;
3.用always块写组合逻辑时使用阻塞赋值语句;
4.在同一个always块中同时建立组合和时序逻辑电路时适应非阻塞赋值语句;
5.在同一个always块中不用同时使用阻塞语句和非阻塞赋值语句;
6.不要在多个always块中为同一个变量赋值;
7.用$strobe系统任务来显示用非阻塞赋值的变量值;
8.在赋值时不用#0延迟;
9.非阻塞赋值的操作 只能用于对寄存器类型变量进行赋值,只能用于initial块和always块等过程中,而非阻塞赋值不允许用于连续赋值;

对于大多数的电路系统工程师来说,应嘎尽量利用商业化的虚拟模块来设计自己的电路系统。

词汇代码的编写标准:
1. 每一个Verilog源文件中只准编写一个模块,也不要把一个模块分成几部分或写在几个源文件中;
2. 源文件的名字应该与文件内容有关,最好一致;
3.每行只写一个声明语句或说明;
4.用一层层缩进的格式来写;
5. 用户定义变量名的大小写应该自始至终一致(例如,变量名第一个字母大写);
6.用户定义变量名应该有意义,而且含有一定的有关信息。而局部变量名可以简单扼要的;
7.通过注释对Verilog源代码作必要的说明,对接口做必要的注释很重要;
8.尽可能多的使用参数和宏定义,而不要在源代码的语句中直接使用字母、数字和字符串;

可综合代码的编写标准:
1. 把设计分割成较小的功能块,每一块用行为风格去设计这些块。除了设计中对速度相应要求比较临界的部分外,都应避免使用门级描述;
2.应建立一个定义得很好的时钟策略,并在verilog源代码中清洗的体现这些策略(例如采用单时钟、多相位时钟、经过门产生的时钟和多时钟域等)。保证在Verilog源代码中的时钟和复位信号是干净的(即不是由组合逻辑或没有考虑到的门产生的);
3.要建立一个定义的很好的测试策略,并认真编写其Verilog代码,使所有的触发器都是可复位的,使测试能通过外部引脚进行,又没有冗余的功能;
4.每个源代码都必须遵守并符合在always声明语句中介绍过的某一种可综合标准模板;
5. 描述组合和锁存逻辑的always块,必须在always块开头的控制事件列表中列出所有的输入信号;
6. 描述组合逻辑的always块一定不能有不完全赋值,也就是说所有的输出变量必须被各输入值的组合赋值,不能有例外;
7.描述组合和锁存逻辑的always块一定不能包含反馈,也就是说在always快中已被定义为输出的寄存器变量绝不能在该always块中读进来作为输入信号;
8. 时钟沿触发的always必须是单时钟的,并且任何异步控制输入(通常为复位或置位信号)必须在控制事件列表中列出;
9.避免生成不需要的锁存器。在无时钟的always块中,由于有的输出变量被赋予某个信号的变量值,而该信号变量没有在always块的电平敏感控制事件中列出,这会在综合中生成不想要的锁存器;
10.避免不想要的触发器。在时钟边沿触发的always块中,用非阻塞语句对寄存器类型的变量赋值,综合后会生成触发器;或者当寄存器类型的变量在时钟边沿触发的always块中经过多次循环其值保持不变,综合后也会生成触发器;
11.所有内部寄存器必须是可复位的,这是为了使RTL级和门级描述能够被复位成同一个已知的状态以便进行门级逻辑验证,但这并不适用于流水线或同步寄存器;
12.对存在无效状态的有限状态机和其他时序电路,如果想要在这些无效状态下,硬件的行为也能够被完全被控制,那么必须用Verilog明确地描述所有的2的n次幂种状态下的行为,当然要包括无效状态。
13.赋值语句中不要使用延迟,而在Verilog块的RTL级描述中需要解决零延迟时钟的倾斜问题例外;
14.不要使用整型和time型寄存器,否则将分别综合成32位和64位总线;
15.仔细检查Verilog代码中使用动态指针、循环声明或算术运算部分,因为这类代码在综合后会生成大量的门,而且很难进行优化;

设计流程:
1 系统分析和指标确定
2 系统划分
    顶级模块
    模块大小估计
    预布局
3 模块级设计,对每一模块
    写RTL级Verilog
    综合代码检测
    写测试文件
    仿真
    写综合约束、边界条件和层次
    预综合以分析门的数量和延时
4 芯片综合
    写测试文件
    仿真
    综合
    门级仿真
5 测试
    修改门级网表以便进行测试;
    产生测试矢量;
    对可测试网表进行仿真;
6 布局布线以使设计的逻辑电路能放入芯片;
7 布局布线后仿真、故障覆盖仿真和定时分析;

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表