代码之家  ›  专栏  ›  技术社区  ›  cyber101

SystemVerilog条件语句语法错误

  •  0
  • cyber101  · 技术社区  · 5 年前

    我试图实践SystemVerilog,并试图实现一个基于此图的ALU(算术逻辑单元):

    enter image description here

    eda操场在线仿真系统verilog代码( https://www.edaplayground.com/x/mYi ):

    ALU:

    module alu(
      input  [31:0] a,
      input  [31:0] b,
      input  [2:0] f,
      output [31:0] result,
    
    );
    
      /*000*/
      if (f[0]==0 && f[1]==0 && f[2]===0)
        begin
        assign result = a & b;
        end
      /*001*/
      else (f[0]==0 && f[1]==0 && f[2]==1)
        begin
        assign result = a | b;
        end
      /*010*/
      else (f[0]==0 && f[1]==1 && f[2]==0)
        begin
        assign result = a + b;
        end
      /*011 not used*/ 
      else (f[0]==0 && f[1]==1 && f[2]==1)
        begin
        assign result = -1;
        end
      /*100*/
      else (f[0]==1 && f[1]==0 && f[2]==0)
        begin
        assign result = a & ~b;
        end 
      /*101*/  
      else (f[0]==1 && f[1]==0 && f[2]==1)  
        begin
        assign result = a | ~b;
        end
      /*110*/
      else (f[0]==1 && f[1]==1 && f[2]==0) 
        begin
        assign result = a - b;
        end
      /*111 slt*/
      else
        begin
        assign result = -1; 
        end
    
    endmodule
    

    部分试验台:

    module testharness();
      reg  [31:0] a;
      reg  [31:0] b;
      reg  [2:0] f;
      reg  [31:0] result;
    
    
    //DUT (Device Under Test)
    alu alu_0 (
      .a   (a),
      .b   (b),
      .f    (f),
      .result (result)
    );
    
    // Test program
    initial begin
         /*000*/
      f[0]=0; 
      f[1]=1;
      f[2]=0;
      /*0+0*/
      a[0]=0;
      b[0]=0;
    
      $display( "a (%d) + b (%d) = %d%d%d%d", a[0], b[0], result[0], result[1]);
       /*000*/
      f[0]=0;
      f[1]=1;
      f[2]=0;
      /*0+1*/
      a[0]=0;
      b[0]=1;
    
     $display( "a (%d) + b (%d) = %d%d", a[0], b[0], result[0], result[1]);
    
         /*000*/
      f[0]=0;
      f[1]=1;
      f[2]=0;
      /*1+1*/
      a[0]=1; 
      b[0]=1; 
    
      $display( "a (%d) + b (%d) = %d%d", a[0], b[0], result[0], result[1]);
    
      $finish;
    end
    
    endmodule
    

    我一直有这个错误:

    错误VCP2000“语法错误。意外的标记:(。需要标记:'???,';','总是','和','分配'….“”设计.sv“15 9

    这是电话线:

    else (f[0]==0 && f[1]==0 && f[2]==1)
        begin
        assign result = a | b;
        end
    

    我看不出任何明显的东西。

    谢谢

    0 回复  |  直到 5 年前
        1
  •  0
  •   Kaiser Keister    5 年前

    我认为你在用 always 陈述和连续作业。正如前面提到的其他用户,我也认为如果你能看看一些基本的verilog教程,这将是很好的。asic-world.com提供了一些很好的教程,例如, Verilog in One Day 作者:迪帕克·库马尔·塔拉。

    不过,让我试着向你解释一下。您在示例中使用的是 连续赋值语句 . 您可以在第103.2节中找到更多关于此的内容。 IEEE Std 1800-2012 . 手册上说:

    网络或变量的分配应是连续和自动的。在 换句话说,每当右边表达式中的操作数改变时 值时,应评估整个右侧。

    这里不是这样,因为所有赋值语句的右侧操作数都是相同的。它不是自动的,因为它取决于你的if语句。看看下面这个非常简单的例子。如果你一直想 result 成为 a & b 你可以使用下面的代码。然而,正如你可以想象的,对于更复杂的逻辑,这变得相当漫长。

    module alu(
      input  [31:0] a,
      input  [31:0] b,
      output [31:0] result,
    
    );
    
        assign result = (a & b);
    
    endmodule
    

    这就是为什么SystemVerilog提供 总是 , always_comb , always_latch always_ff (IEEE标准1800-2012第9节)。例如,您应该使用 一直梳 . 引用本手册第9.2.2.2节:

    systemverilog为建模提供了一个特殊的always_comb过程 组合逻辑行为。

    有了这个,我们可以重写你的代码

    module alu(
      input  [31:0] a,
      input  [31:0] b,
      input  [2:0] f,
      output [31:0] result,
    
    );
    
      reg [31:0] result_;   
    
      always_comb 
      begin
        /*000*/
        if (f[0]==0 && f[1]==0 && f[2]===0)
        begin
          result_ = a & b;
        end
        /*001*/
        else if (f[0]==0 && f[1]==0 && f[2]==1)
        begin
          result_ = a | b;
        end
        /*010*/
        else if (f[0]==0 && f[1]==1 && f[2]==0)
        begin
          result_ = a + b;
        end
        /*011 not used*/ 
        else if(f[0]==0 && f[1]==1 && f[2]==1)
        begin
          result_ = -1;
        end
        /*100*/
        else if (f[0]==1 && f[1]==0 && f[2]==0)
        begin
          assign result = a & ~b;
        end 
        /*101*/  
        else if (f[0]==1 && f[1]==0 && f[2]==1)  
        begin
          result_ = a | ~b;
        end
        /*110*/
        else if (f[0]==1 && f[1]==1 && f[2]==0) 
        begin
          result_ = a - b;
        end
        /*111 slt*/
        else
        begin
          result_ = -1; 
        end
      end // End of always_comb
    
      assign result = result_;
    
    endmodule
    

    请注意,你可以连续分配一个 wire ,但您需要将变量声明为 reg 在“总是”块中使用它。这就是我使用的原因 result_ ,而不是直接指定 结果 . 在代码块的末尾,我不断地指定 小精灵 结果 . asic-world.com还有一个关于 difference between regs and wires .

    如果你不想考虑是否使用 规则 电线 ,也可以使用新关键字 logic .

    编辑:正如奥尔德法特指出的,我根本忘了修正你的if…else语句。在你的代码中,你总是使用 else 而不是 else if . 这可能也是编译器向您抛出错误的直接原因。