2.4 语句

过程语句 initialalways

  1. 在一个模块中,使用initialalways语句的次数是不受限制的;initial语句常用于仿真中的初始化,过程块中的语句仅执行一次;always块内的语句则是不断重复执行的。

  2. always语句

    1. 格式:

      always @ (<event_expression>)
      begin
          <......>
      end
      
    2. always过程语句通常是带有触发条件的,触发条件写在敏感信号表达式中,只有当触发条件满足时,其后的begin-end块语句才能被执行。

    3. 敏感信号表达式又称事件表达式或敏感信号列表,即当该表达式中变量的值改变时,就会引发块内语句的执行。其中应列出影响块内取值的所有信号,若有两个或两个以上信号时,它们之间用or连接。举例:

      @(a)                            // 当信号a的值发生改变
      @(a or b)                       // 当信号a或信号b的值发生改变
      @(posedge clock)                // 当clock的上升沿到来时
      @(negedge clock)                // 当clock的下降沿到来时
      @(posedge clk or negedge reset) // 当clk的上升沿或reset信号的下降沿到来
      
    4. posedgenegedge关键字:对于时序电路,事件通常是由时钟边沿触发的,为表达边沿概念,Verilog提供了这两个关键字来描述。

    5. 例:4选1数据选择器

      module mux4_1 (out, in0, in1, in2, in3, sel);
          output out;
          input in0, in1, in2, in3;
          input [1:0] sel; 
          reg out;
          
          always @ (in0 or in1 or in2 or in3 or sel)
          case(sel)
              2'b00: out=in0;
              2'b01: out=in1;
              2'b10: out=in2;
              2'b11: out=in3;
              default: out=2'bx;
          endcase
      endmodule
      
    6. 例:同步置数、同步清零的计数器

      module count(out, data, load, reset, clk);
          output [7:0] out;
          input [7:0] data;
          input load, clk, reset;
          reg [7:0] out;
          
          always @ (posedge clk)
          begin
              if(!reset) 
                  out=8'h00;      // 同步清0,低电平有效
              else
                  if(load) 
                      out=data;   // 同步预置
                  else 
                      out=out+1;  // 计数
          end
      endmodule
      

块语句 begin-end

  1. 块语句是由块标志符begin-end的一组语句,当块语句只包含一条语句时,块标志符可以缺省。

  2. begin-end串行块中的语句按串行方式顺序执行。比如:

    begin
        regb=rega;
        regc=regb;
    end
    

由于begin-end块内的语句顺序执行,在最后,将regbregc的值都更新为rega的值,该begin-end块执行完后,regbregc的值是相同的。

赋值语句 assign=<=

1. 连续赋值语句

assign为持续赋值语句,主要用于对wire型变量的赋值。如:

wire a, b, c;
assign c = a & b;

在上面的赋值中,abc三个变量皆为wire型变量,ab信号的任何变化都将随时反映到c上来。

2. 过程赋值语句 nonblockingblocking

过程赋值语句多用于对reg型变量进行赋值。

  1. 非阻塞(nonblocking)赋值:符号<=;例如:b<=a; 在整个过程块结束时才完成赋值操作,即b的值并不是立刻就改变的。

  2. 阻塞(blocking)赋值:符号=;例如:b=a; 阻塞赋值在该语句结束时就立即完成赋值操作,即b的值在该条语句结束后立刻改变。如果在一个块语句中,有多条阻塞赋值语句,那么在前面的赋值语句没有完成之前,后面的语句就不能被执行,仿佛被阻塞了一样,因此称为阻塞赋值方式。

3. 顺序与并发

两个或更多个always过程块、assign持续赋值语句、实例元件调用等操作都是同时执行的。在always模块内部,其语句如果是非阻塞赋值,也是并发执行的;而如果是阻塞赋值,则语句是按照指定的顺序执行的,语句的书写顺序对程序的执行结果有着直接的影响。

条件语句 if-elsecasecasezcasex

1. if-else语句

if <expression> <statement>;

if <expression> <statement1>;
else <statement2>;

if <expression1> <statement1>;
else if <expression2> <statement2>;
else if <expression3> <statement3>;
......
else if <expression_n> <statement_n>;
else <statement_n+1>;

2. case语句

  1. case:全等比较,即控制表达式和分支项表达式的值各对应位必须全等

    case (<expression>)
        key1: <statement1>;
        key2: <statement2>;
        ......
        key_n: <statement_n>;
        default: <statement_n+1>;
    endcase
    
  2. casez:如果表达式的值的某些位是z,那么对这些位的比较就不予考虑,只对非z位进行比较。

  3. casex:如果表达式的值的某些位是x或z,那么对这些位的比较就不予考虑,只对非x或非z位进行比较。

循环语句 forforeverrepeatwhile

  1. forever:连续地执行语句;多用在initial块中, 以生成时钟等周期性波形

  2. repeat:连续执行一条语句n次

    initial
    begin
        repeat(5)
            out = out + 1;
    end
    
  3. while:执行一条语句直到某个条件不满足

    initial
    begin
        i = 0;
        while(i < 10)
            i = i + 1;
    end
    
  4. for:有条件的循环语句

    initial
    begin
        for(i = 0; i < 4; i = i + 1)
            out = out + 1;
    end