概述
。本次分享华为公司的《大规模逻辑设计指导书》中的内容。
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)来代替表达式的多次重复
5.1.5 IF 语句
- 向量比较时 比较的向量要相等。
Reg Abc [7:0];
Reg Bca [3:0];
......If (Abc = = {4’b0, Bca})begin
.......If (Abc = = 8’b0) begin
每一个If 都应有一个else 和它相对应。
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 语句仿真要比条件赋值语句快。 所有的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变量 timerealtimereal赋值, 而连续赋值一般给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机的状态转换和输入无关。
...
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
版权归华为公司所有,如有侵权,联系删除!
未完待续!! 欢迎关注,更精彩的内容等着你!
最后
以上就是舒心可乐为你收集整理的verilog always语法_【华为】verilog语言编写规范(二)的全部内容,希望文章能够帮你解决verilog always语法_【华为】verilog语言编写规范(二)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复