Verilog语法需要注意的一些要点

转自:http://blog.21ic.com/user1/1472/archives/2006/32484.html

Verilog语法需要注意的一些要点

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= %d\n”, 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之间的随机数

8.  比较下面代码,分别综合出什么,可能出现什么问题

module dff_en(I_en, I_data, I_clock, O_data);

input  I_clock;

input  I_en;

input  I_data;

output O_data;

reg  R_data;

assign O_data = R_data;

always @(I_clock)

begin

        if (I_en == 1) R_data <= I_data;

end

endmodule

有以下告警(用synplify综合)

(1)      Incomplete sensitivity list - assuming completeness

(2)      Referenced variable I_en is not in sensitivity list

(3)      Referenced variable I_data is not in sensitivity list

(4)      Latch generated from always block for signal

如果改always @(I_clock)为always @(posedge I_clock)就可以避免,并产生一个带使能的DFF

9.  下面逻辑有没有问题?

module dff_en(I_reset1, I_reset2, I_data, I_clock, O_data);

input  I_clock;

input  I_reset1;

input  I_reset2;

input  I_data;

output O_data;

reg    R_data;

assign O_data = R_data;

always @(negedge I_reset1 or posedge I_clock)  // 敏感变量I_reset2在时钟

begin

        if (I_reset1 == 0) R_data <= 0;

else if (I_reset2 == 0) R_data <= 1;

        else R_data <= I_data;

end

endmodule

综 合时不会有告警,产生一个带复位和置位的DFF,最好改always @(negedge I_reset1 or posedge I_clock)为always @(negedge I_reset1 or negedge I_reset2 or posedge I_clock)

10.逻辑综合结果是什么?

module mux2s1(I_sel, I_a, I_b, O_c, O_d)

    input I_sel, I_a, I_b;

    output O_c, O_d;

    reg R_c;

    reg R_d;

    assign O_c = R_c;

    assign O_d = R_d;

    always @(I_sel, I_a, I_b)

    begin

        case (I_sel)

            1'b0: R_c = I_a;    // 综合出latch

            1'b1: R_d = I_b;    // latch

        endcase

    end

endmodule

该逻辑将产生锁存器。

11.下面代码综合结果是什么?




module dff_sys(I_clock, I_data, O_data);

    input  I_clock, I_data;

    output O_data;

    reg    R_b, R_c, R_d;

    always @(posedge I_clock)

    begin

        R_c = R_b;

        R_b = I_data;

              R_d <= R_c;

    end

endmodule

module dff_sys(I_clock, I_data, O_data);

    input  I_clock, I_data;

    output O_data;

    reg    R_b, R_c, R_d;

    always @(posedge I_clock)

    begin

        R_c = R_b;

        R_d <= R_c;

R_b = I_data;

      end

endmodule




两段逻辑都没有任何区别,综合电路如下,这也说明了non-block语句的特点


      下面逻辑呢?

module dff_sys(I_clock, I_data, O_data);

          input  I_clock, I_data;

          output O_data;

          reg    R_b, R_c, R_d;

              assign O_data = R_d;

          always @(posedge I_clock)

          begin

              R_b = I_data;

              R_c = R_b;

              R_d <= R_c;

          end

endmodule


module dff_sys(I_clock, I_data, O_data);

    input  I_clock, I_data;

    output O_data;

    reg    R_b, R_c, R_d;

      assign O_data = R_d;

    always @(posedge I_clock)

    begin

        R_b <= I_data;

        R_c <= R_b;

        R_d <= R_c;

    end

endmodule


12.同一个物理电路的行为仿真验证与结构模块的仿真验证有什么区别?

      行为仿真是:对电路基本功能验证

      结构仿真是:对电路的逻辑网表验证

posted @ 2013-06-06 10:01  永不止步,永无止境  阅读(1068)  评论(0)    收藏  举报