eric2013 发表于 2013-1-14 15:37:56

Verilog经验谈(一)

先记下来:
1、 不使用初始化语句;
2、 不使用延时语句;
3、 不使用循环次数不确定的语句,如:forever,while等;
4、 尽量采用同步方式设计电路;
5、 尽量采用行为语句完成设计;
6、 always过程块描述组合逻辑,应在敏感信号表中列出所有的输入信号
   (在做FSMC通信的时候遇到到这个问题,暂时就把警告在哪里放着);
7、 所有的内部寄存器都应该可以被复位;
8、 用户自定义原件(UDP元件)是不能被综合的。

eric2013 发表于 2013-1-14 15:59:25

一:基本
Verilog中的变量有线网类型和寄存器类型。线网型变量综合成wire,而寄存器可能综合成WIRE,锁
存器和触发器,还有可能被优化掉。
二:verilog语句结构到门级的映射
1、连续性赋值:assign
连续性赋值语句逻辑结构上就是将等式右边的驱动左边的结点。因此连续性赋值的目标结点总是综合
成由组合逻辑驱动的结点。Assign语句中的延时综合时都将忽视。
2、过程性赋值:
过程性赋值只出现在always语句中。
阻塞赋值和非阻塞赋值就该赋值本身是没有区别的,只是对后面的语句有不同的影响。
建议设计组合逻辑电路时用阻塞赋值,设计时序电路时用非阻塞赋值。
过程性赋值的赋值对象有可能综合成wire, latch,和flip-flop,取决于具体状况。如,时钟控制下的非
阻塞赋值综合成flip-flop。
过程性赋值语句中的任何延时在综合时都将忽略。
建议同一个变量单一地使用阻塞或者非阻塞赋值。
3、逻辑操作符:
逻辑操作符对应于硬件中已有的逻辑门,一些操作符不能被综合:===、!==。
4、算术操作符:
Verilog中将reg视为无符号数,而integer 视为有符号数。因此,进行有符号操作时使用integer,
使用无符号操作时使用reg。
5、进位:
通常会将进行运算操作的结果比原操作数扩展一位,用来存放进位或者借位。如:
Wire A,B;
Wire C;
Assign C=A+B;
C的最高位用来存放进位。
6、关系运算符:
关系运算符:<,>,<=,>=
和算术操作符一样,可以进行有符号和无符号运算,取决于数据类型是reg,net还是integer。
7、相等运算符:==,!=
注意:===和!==是不可综合的。
可以进行有符号或无符号操作,取决于数据类型
8、移位运算符:
左移,右移,右边操作数可以是常数或者是变量,二者综合出来的结果不同。
9、部分选择:
部分选择索引必须是常量。
10、BIT选择:
BIT选择中的索引可以用变量,这样将综合成多路(复用)器。
11、敏感表:Always过程中,所有被读取的数据,即等号右边的变量都要应放在敏感表中,不然,
综合时不能正确地映射到所用的门。
12、IF:
如果变量没有在IF语句的每个分支中进行赋值,将会产生latch。如果IF语句中产生了latch,则IF
的条件中最好不要用到算术操作。Case语句类似。Case的条款可以是变量。
如果一个变量在同一个IF条件分支中先赎值然后读取,则不会产生latch。如果先读取,后赎值,则会
产生latch。
13、循环:
只有for-loop 语句是可以综合的。
14、设计时序电路时,建议变量在always语句中赋值,而在该always语句外使用,使综合时能准确
地匹配。建议不要使用局部变量。
15、不能在多个always块中对同一个变量赎值
16、函数
函数代表一个组合逻辑,所有内部定义的变量都是临时的,这些变量综合后为wire。
17、任务:
任务可能是组合逻辑或者时序逻辑,取决于何种情况下调用任务。
18、Z:
Z会综合成一个三态门,必须在条件语句中赋值
19、参数化设计:
优点:参数可重载,不需要多次定义模块
四:模块优化
1、资源共享:
当进程涉及到共用ALU时,要考虑资源分配问题。可以共享的操作符主要有:关系操作符、加减乘除
操作符。通常乘和加不共用ALU,乘除通常在其内部共用。
2、共用表达式:
如:C=A+B;
    D=G+(A+B);
两者虽然有共用的A+B,但是有些综合工具不能识别.可以将第二句改为:D=G+C;这样只需两个
加法器.
3、转移代码:
如循环语句中没有发生变化的语句移出循环
4、避免latch:
两种方法:1、在每一个IF分支中对变量赋值。2、在每一个IF语句中都对变量赋初值。
5:模块:
综合生成的存储器如ROM或RAM不是一种好方法,只是成堆的寄存器,很费资源。最好用库自带的
存储器模块。
五、验证:
1、敏感表:
在always语句中,如果敏感表不含时钟,最好将所有的被读取的信号都放在敏感表中。
2、异步复位:
建议不要在异步时对变量读取,即异步复位时,对信号赋以常数值。

eric2013 发表于 2013-1-15 15:15:17

在a lways 块中,被赋值的信号都必须定义为 reg 型,这是由时序逻辑电路的特点所决定的。
对于reg 型数据,如果未对它进行赋值,仿真工具会认为它是不定态。为了能正确地观察到
仿真结果,在可综合风格的模块中我们通常定义一个复位信号reset,当r eset为低电平时,
对电路中的寄存器进行复位。

eric2013 发表于 2013-1-15 15:22:34

同一组合逻辑电路分别用 always 块和连续赋值语句 assign 描述时,代码的形式大相径
庭,但是在always中适当运用default(在 case结构中)和else(在if…else 结构中),
通常可以综合为纯组合逻辑,尽管被赋值的变量一定要定义为r e g 型。不过,如果不使用
default 或else 对缺省项进行说明,则易生成意想不到的锁存器,这一点一定要加以注意。

eric2013 发表于 2013-3-2 14:43:36

如果always进程块的时钟触发速度比较高并且进程中要执行的语句有点复杂,可以将其分解到多个进程里面实现。

always @( posedgeclk)
begin
任务一;
任务二;
任务三;
任务四;
end
进程里面的几个任务是顺序执行的,这时可以讲四个任务分别放到四个进程里面。
always @( posedgeclk)
begin
任务一;
end

always @( posedgeclk)
begin
任务二;
end

always @( posedgeclk)
begin
任务三;
end

always @( posedgeclk)
begin
任务四;
end

eric2013 发表于 2013-3-8 20:53:34

always @(negedge rd)
    begin
      case (ab)
            3'b000:indata <= outa;
            3'b001:indata <= outb;         
            3'b010:indata <= rdy_task;
            3'b011:indata <= task8_gpt;            
            3'b100:indata <= task8_aot;   
            3'b101:indata <= outf;
            3'b110:indata <= outg;
            3'b111:indata <= outh;                        
            default: indata <= 16'hffff;
      endcase
    end
时常要读写的地址需要特别,比如task8_gpt,task8_aot,rdy_task最好提前就计算好,不要在里面再做计算,
这样很影响速度
页: [1]
查看完整版本: Verilog经验谈(一)