跳转至

块语句

概念:将两条或多条语句组合在一起,使其在格式上看更像一条语句

顺序块:标识顺序执行的语句

  • 块内的语句按顺序执行,上一条语句执行完后下面语句才能执行
  • 每条语句的延迟时间相对于前一条语句的仿真时间
  • 直到最后一条语句执行完,程序流程才跳出该语句块

    begin
        语句1;
        语句2;
    end
    
    begin: 块名 // 块的标识名
        语句1;
        语句2;
    end
    

  • 块内声明语句可以是参数声明语句、reg型变量声明语句、integer型变量声明语句和real型变量声明语句

    parameter d = 50;
    reg [7:0] r;
    begin
        #d r = 'h35;
        #d r = 'hE2;
        #d r = 'h00;
        #d r = 'hF7;
        #d -> end_wave; // ->用于触发事件(用于仿真, 无法综合)
    end
    

并行块:标识并行执行的语句

  • 块内语句同时执行
  • 块内每条语句的延迟时间相对于程序流程控制进入到块内的仿真时间
  • 延迟时间用来给赋值语句提供时序
  • 当按时间时序排在最后的语句执行完后或一个disable语句执行时,程序流程控制跳出块

    fork
        语句1;
        语句2;
    join
    
    fork: 块名
        语句1;
        语句2;
    join
    

  • 块内声明语句可以是参数声明语句、reg型变量声明语句、integer型变量声明语句、real型变量声明语句、time型变量声明语句和event声明语句

    fork
        #50 r = 'h35;
        #100 r = 'hE2;
        #150 r = 'h00;
        #200 r = 'hF7;
        #250 -> end_wave;
    join
    

并行块需避免竞争:不能存在两条语句同时对一个变量产生影响

特点:

  • 嵌套块:顺序块并行块混合使用

    initial begin
        x = 1'b0;
        fork
            #5 y = 1'b1;
            #10 z = {x, y};
        join
        #20 w = {y, x};
    end
    

  • 命名块:块可以具有自己的名字

    • 块名:在任何仿真时刻确认变量值的方法
      • 可在块内定义局部变量(只能在块内使用的变量)
      • 可以允许块被其他语句调用(如disable)
      • 所有变量是静态的,跳入或跳出块不影响存储在变量内的值
        module top; // 命名块
            initial begin: block1
                integer i; // 可通过top.block.1访问
            end
            initial fork:
                reg i; // top.block.i
            join
        endmodule
        
  • 命名块禁用

    • disable关键字:类似于break,可禁用任意一个命名块
      reg [15:0] flag;
      initial begin
          flag = 16'b0010_0000_0000_0000;
          i = 0;
          begin: block1
              while (i < 16) begin
                  if (flag[i]) begin
                      $display("Encountered a TRUE bit at element number %d", i);
                      disable block1;
                  end
                  i = i + 1;
              end
          end
      end
      

生成块

概念:动态地生成Verilog代码,能控制变量的声明、任务或函数的调用,还能对实例引用进行全面的控制

可生成实例类型:

  • 模块
  • 用户定义原语
  • 门级原语
  • 连续赋值语句
  • initialalways块 可声明数据类型:
  • net, reg
  • integer, real, time, realtime
  • event

循环生成:对模块或模块项进行多次实例引用 例:两条N位总线变量按位异或

module bitwise_xor(out, i0, i1);
    parameter N = 32;
    output [N-1: 0] out;
    input [N-1: 0] i0, i1;
    genvar j; // 临时循环变量, 设计时不存在
    generate
        for (j = 0; j < N; j = j + 1) begin: xor_loop
            xor g1 (out[j], i1[j], i1[j]);
        end
    endgenerate
    // xor可用always块替代
    reg [N-1: 0] out;
    generate
        for (j = 0; j < N; j = j + 1) begin: bit
            always @ (i0[j] or i1[j]) out[j] = i0[j] ^ i1[j];
        end
    endgenerate
endmodule

  • 在仿真开始前,仿真器会对生成块中的代码进行确定(展平),将生成块转换为展开时的代码,然后对展开后的代码进行仿真;本质时使用循环内的一条语句替代多条重复的Verilog语句
  • 关键字genvar用于声明生成变量,只能用在生成块之中;确立后的仿真代码不含生成变量;生成变量的值只能在循环生成语句中改变
  • 循环生成语句可以嵌套使用(使用同一个生成变量作为索引的生成语句不能相互嵌套)
  • xor_loop是循环生成语句名,对异或门的引用:xor_loop[0].g1

    重点在于想象循环生成语句被展平后的形式

例:脉动加法器

module ripple_adder(co, sum, a0, a1, ei);
    parameter N = 4;
    output [N-1:0] sum;
    output co;
    input [N-1:0] a0, a1;
    input ci;

    wire [N-1:0] carry;
    assign carry[0] = ci;

    genvar i;
    generate
        for (int i = 0; i < N; i = i + 1) begin: r_loop
            wire t1, t2, t3;
            xor g1 (t1, a0[i], a1[i]);
            xor g2 (sum[i], t1, carry[i]);
            and g3 (t2, a0[i], a1[i]);
            and g4 (t3, t1, carry[i]);
            or g5 (carry[i + 1], t2, t3);
        end
    endgenerate

    assign co = carry[N];
endmodule

条件生成语句:用条件地调用Verilog结构

例:参数化乘法器

module multiplier (product, a0, a1);
    parameter a0_width = 8;
    parameter a1_width = 8;
    // 本地参数不能使用defparam修改, 也不能在实例引用时通过传递参数语句修改
    localparam product_width = a0_width + a1_width;
    output [product_width - 1: 0] product;
    input [a0_width - 1: 0] a0;
    input [a1_width - 1: 0] a1;
    generate
        if (a0_width < 8 || a1_width < 8)
            cal_multiplier # (a0_width, a1_width) m0 (product, a0, a1);
        else
            tree_multiplier # (a0_width, a1_width) m0 (product, a0, a1);
    endgenerate
endmodule

case生成语句:多选一case构造,有条件调用Verilog结构

例:N位加法器

module adder(co, sum, a0, a1, ci);
    parameter N = 4;
    output [N-1: 0] sum;
    output co;
    input [N-1: 0] a0, a1;
    input ci;
    generate
        case (N)
            1: adder_1bit adder1 (co, sum, a0, a1, ci);
            2: adder_2bit adder2 (co, sum, a0, a1, ci);
            default: adder_cla # (N) adder3 (co, sum, a0, a1, ci);
        endcase
    endgenerate
endmodule