verilog always语法_【华为】verilog语言编写规范(二)

。本次分享华为公司的《大规模逻辑设计指导书》中的内容。


5.1.3 Net and Register
  • 一个reg变量只能在一个always语句中赋值  。
  • 向量有效位顺序的定义一般是从大数到小数。

尽管定义有效位的顺序很自由, 但如果采用毫无规则的定义势必会给作者和读代码的人带来困惑, 如Data[-4 :0] ,则LSB[0][-1][-2][-3][-4]MSB ,或 Data[0 :4] ,则LSB[4][3][2][1][0]MSB, 这两种情况的定义都不太好 ,推荐 Data[4 :0] 这种格式的定义。

  • 对net和register类型的输出要做声明 (在PORT中)。如果一个信号名没做声明 Verilog将假定它为一位宽的wire变量。
  • 线网的多种类型 。寄存器的类型。
5.1.4 Expressions
  • 用括号来表示执行的优先级。尽管操作符本身有优先顺序, 但用括号来表示优先级对读者更清晰, 更有意义。
 If ((alpha < beta) && (gamma >= delta)).... 比下面的表达更合意 。If (alpha = delta)...
  • 用一个函数(function)来代替表达式的多次重复
如果代码中发现多次使用一个特殊的表达式 ,那么就用一个函数来代替。这样在以后的版本升级时更便利 ,这种概念在做行为级的代码设计时同样使用 ,经常使用的一组描述可以写到一个任务(task)中 。
5.1.5 IF 语句
  • 向量比较时 比较的向量要相等。
当比较向量时 ,verilog将对位数小的向量做 0 扩展以使它们的长度相匹配 ,它的自动扩展为隐式的。建议采用显示扩展 ,这个规律同样适用于向量同常量的比较。
 Reg Abc [7:0];
 Reg Bca [3:0];
 ......If (Abc = = {4’b0, Bca})begin
 .......If (Abc = = 8’b0) begin
  • 每一个If 都应有一个else 和它相对应。

在做硬件设计时 ,常要求条件为真时执行一种动作而条件为假时执行另一动作,即使认为条件为假不可能发生。没有else可能会使综合出的逻辑和RTL级的逻辑不同。如果条件为假时不进行任何操作,则用一条空语句.
 always @(Cond)
 beginif (Cond)
 DataOut <= DataIn;
 End// Else 
以上语句DataOut会综合成锁存器.
  • 应注意If ..else if ...else if ...else 的优先级
  • 如果变量在If-else 或case 语句中做非完全赋值, 则应给变量一个缺省值 ,即,
 V1 = 2’b00;
 V2 = 2’b00;
 V3 = 2’b00;If (a = = b) begin
 V1 = 2’b01; //V3 is not assigned
 V2 = 2’b10;
 EndElse if (a = = c) begin
 V2 = 2’b10; //V1 is not assigned
 V3 = 2’b11;
 EndElse ;;

5.1.6 case 语句

case语句通常综合成一级多路复用器 (图的右边部分), 而if-then-else则综合成优先编码的串接的多个多路复用器, 如图的左边部分。通常 ,使用case 语句要比if语句快 ,优先编码器的结构仅在信号的到达有先后时使用。条件赋值语句也能综合成多路复用器, 而case 语句仿真要比条件赋值语句快。

451cfe94da4be4278839f849f8cbf23c.png

所有的Case 应该有一个default case 允许空语句 Default : ;
5.1.7 Writing functions
在function的最后给function赋值.
 Function CompareVectors; // (Vector1, Vector2, Length)
 Input [199:0] Vector1, Vector2;
 Input [31:0] Length;//local variables
 Integer i;
 Reg Equal;
 Begin
  i = 0;
  Equal = 1;While ((i   If (Vector 2[i] !== 1’bx) beginIf (Vector1[i] !== Vector2[i])
    Equal = 0;Else ;
  End
   i = i + 1;
  End
  CompareVectors = Equal;
End
Endfunction //compareVectors
  • 函数中避免使用全局变量 否则容易引起HDL行为级仿真和门级仿真的差异 如
function ByteCompareinput [15:0] Vector1input [15:0] Vector2input [7:0] Lengthbeginif (ByteSel)
 // compare the upper byteelse
 // compare the lower byteendendfunction // ByteCompare
中使用了全局变量ByteSel, 可能无意在别处修改了 ,导致错误结果。最好直接在端口加以定义 。注意 函数与任务的调用均为静态调用。
5.1.8 Assignment
  • Verilog 支持两种赋值 :过程赋值(procedural) 和连续赋值(continuous)。过程赋值用于过程代码 initial,   always, task or function)中给reg 和 integer变量 time\realtimereal赋值,   而连续赋值一般给wire 变量赋值。
 Always @(敏感表 敏感表要完整 如果不完整 将会引起仿真和综合结果不一致
 always @(d or Clr)if (Clr)
   q = 1'b0;
 else if (e)
   q = d;
以上语句在行为级仿真时e的变化将不会使仿真器进入该进程,导致仿真结果错误
  • Assign/deassign 仅用于仿真加速 仅对寄存器有用  。
  • Force/release 仅用于debug 对寄存器和线网均有用 。
  • 避免使用Disable。
  • 对任何reg赋值用非阻塞赋值代替阻塞赋值 reg 的非阻塞赋值要加单位延迟 ,但异步复位可加可不加 。
=与 =的区别
 Always @(posedge Clk or negedge Rst_)
 BeginIf (!Rst_)  // prioritize the “if conditions” in if statement
   Begin
    Rega <= 0; //non_blocking assignment
    Regb <= 0;
   EndElse if (Soft_rst_all) 
   Begin
    Rega <= #u_dly 0; //add unit delay
    Regb <= #u_dly 0;
   EndElse if (Load_init)
   Begin
    Rega <= #u_dly init_rega;
   Regb <= #u_dly init_regb;
   EndElse
   Begin
    Rega <= #u_dly Rega <
    Regb <= #u_dly St_1;
   End
End // end Rega, Regb assignment.
5.1.9 Combinatorial Vs Sequential Logic
如果一个事件持续几个时钟周期 设计时就用时序逻辑代替组合逻辑 。如
Wire Ct_24_e4; //it ccarries info. Last over several clock cycles
 Assign Ct_24_e4 = (count8bit[7:0] >= 8’h24) & (count8bit[7:0] <= 8’he4);
那么这种设计将综合出两个8 比特的加法器 而且会产生毛刺 对于这样的电路 要采用时序设计 代码如下
 Reg Ct_24_e4;
 Always @(poseddge Clk or negedge Rst_)
 BeginIf (!Rst_)
   Ct_24_e4 <= 1’b0;Else if (count8bit[7:0] = = 8’he4)
   Ct_24_e4 <= #u_dly 1’b0;Else if (count8bit[7:0] = = 8’h23)
   Ct_24_e4 <= #u_dly 1’b1;
  Esle ; //内部总线不要悬空 在default状态 要把它上拉或下拉.
  Wire OE_default;
  Assign OE_default = !(oe1 | oe2 | oe3);
  Assign bus[31:0] =  oe1 ? Data1[31:0] :
       oe2 ? Data2[31:0] :
       oe3 ? Data3[31:0] :
       oe_default ? 32’h0000_0000 :32’hzzzz_zzzz;
5.1.10Macros
  • 为了保持代码的可读性 常用  “ `define ”   做常数声明。
  • 把“define”放在一个独立的文件中 参数 parameter 必须在一个模块中定义 不要传替参数到模块 仿真测试向量例外 “define”可以在任何地方定义 要把所有的“define”定义在一个文件中 在编译原代码时首先要把这个文件读入 如果希望宏的作用域仅在一个模块中 就用参数来代替。
5.1.11Comments
  • 对更新的内容更新要做注释。
  • 在语法块的结尾做标记。
 //style 1If (~OE_ && (state != PENDING)) begin
 ....
 End // if enable = = ture and ready//style 2 --- identical lables on begin and endIf (~OE_ && (state != PENDING)) begin //drive data
 ....
 End //drive data// Comment end with the name of the Function Calcparity //Data, ParityErr
 ....Endfunction // Calcparity
  • 每一个模块都应在模块开始处做模块级的注释 参考前面标准模块头 。
  • 在模块端口列表中出现的端口信号 都应做简要的功能描述。
5.1.12 FSM
  • VerilogHDL状态机的状态分配 VerilogHDL描述状态机时必须由parameter分配好状态,这与VHDL不同 VHDL状态机状态可以在综合时分配产生。

  • 组合逻辑和时序逻辑分开用不同的进程。组合逻辑包括状态译码和输出 时序逻辑则是状态寄存器的切换。
  • 必须包括对所有状态都处理 不能出现无法处理的状态 使状态机失控  。
  • Mealy机的状态和输入有关,而Moore机的状态转换和输入无关。
Mealy 状态机的例子如下:
 ...
 reg CurrentState, NextState, Out1;
 Parameter S0=0,S1=1;
 always @(posedge Clk or negedge Rst_)// state vector flip-flops (sequential)if (!Reset)
  CurrentState = S0;else
  CurrentState <= #u_dly NextState;
 always @(In1 or In2 or CurrentState)// output and state vector decode (combinational)case (CurrentState)
  S0: begin
  NextState <= #u_dly S1;
  Out1 <= #u_dly 1'b0;
 end
  S1: if (In1) begin
  NextState <= #u_dly S0;
  Out1 <= #u_dly In2;
  endelse begin
  NextState <= #u_dly S1;
  Out1 <= #u_dly !In2;
  end
  endcase
 endmodule
版权归华为公司所有,如有侵权,联系删除!
未完待续!! 欢迎关注,更精彩的内容等着你! 91bc9402246802b0f1651c15f9ab72a3.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值