'begin/end' 在设计模块中的使用

Usage of 'begin/end' in design modules

我尝试使用icarus verilog 模拟在EDA Playground 上制作BCD 计数器。在我的第一次尝试中,我在不使用 beginend 关键字的情况下编写了 always 块:

module bcdcounter(out, clock, reset);
  output [3:0] out;
  input clock, reset;
  
  reg [3:0] outstate= 4'd0;
  reg [1:0] state= 2'd0;
  
  always@(posedge reset)
    case(state)
      2'd0: state <=2'd1;
      2'd1: state <=2'd2;
      2'd2: state <=2'd0;
    endcase
  
  always@(posedge clock or state)
    if(!state) 
      outstate <= 4'd0;
  if(state == 2'd1) 
    if(outstate != 4'd9)
      outstate <= outstate +4'd1;
  else 
    outstate <= 4'd0;
  if(state == 2'd2) 
    outstate <= outstate;
  
  assign out = outstate;
    
endmodule

我检查时生成了以下输出:

design.sv:21: syntax error
design.sv:21: error: Invalid module instantiation
design.sv:23: syntax error
design.sv:23: error: Invalid module instantiation
design.sv:25: syntax error
design.sv:25: error: Invalid module instantiation
Exit code expected: 0, received: 1

但是,一旦我添加了一些 beginend 关键字,它确实可以正常工作:

module bcdcounter(out, clock, reset);
  output [3:0] out;
  input clock, reset;
  
  reg [3:0] outstate= 4'd0;
  reg [1:0] state= 2'd0;
  
  always@(posedge reset)
    case(state)
      2'd0: state <=2'd1;
      2'd1: state <=2'd2;
      2'd2: state <=2'd0;
    endcase
  
  always@(posedge clock or state)
    begin
      if(!state)
        outstate <=4'd0;
      if(state==2'd1)
        begin
          if(outstate!=4'd9)
            outstate<= outstate+4'd1;
          else outstate<= 4'd0;
        end
      if(state==2'd2)
        outstate<=outstate;
    end
  
  assign out = outstate;
    
endmodule

我们什么时候需要在设计模块中使用beginend关键字?任何帮助将不胜感激。

当您在特定块中有多个语句时,您需要 begin end。例子

//Single line statement hence no begin end needed
always@(posedge clk)
  a <= b &c;

 //Multiple lines hence begin end is needed
always@(posedge clk)
begin
 if(reset)
  a <= 'd0;
 else 
  a <= b & c;
end

同样适用于 if elsecase 语句等

begin/end 关键字在 always 块中有 多个 语句时是必需的。

在您的第一个 always 块中,您不需要 begin/end,因为 case 语句被视为单个语句。

但是,在您的第二个 always 块中,您有 3 个顶级 if 语句,这意味着您需要将它们组合在 begin/end 中。这是带有不同空格的代码,以清楚地显示单独的语句:

always@(posedge clock or state) begin

    // Statement 1
    if(!state) outstate <= 4'd0;

    // Statement 2
    if(state == 2'd1) 
        if(outstate != 4'd9)
            outstate <= outstate +4'd1;
        else 
            outstate <= 4'd0;

    // Statement 3
    if(state == 2'd2) outstate <= outstate;

end  

由于这段代码编译时没有语法错误,它说明了一些事情:

  1. 显示的 begin/end 个关键字是强制性的
  2. 不需要其他 begin/end 个关键字

但是,其他 begin/end 关键字是可选的。您可以决定在每个 if 语句中使用它们。这是另一种编写代码的方法:

always@(posedge clock or state) begin

    if (!state) begin 
        outstate <= 4'd0;
    end

    if (state == 2'd1) begin
        if (outstate != 4'd9) begin
            outstate <= outstate +4'd1;
        end else begin
            outstate <= 4'd0;
        end
    end

    if (state == 2'd2) begin
        outstate <= outstate;
    end

end  

相同的规则适用于 initialfinal 程序块,就像它们适用于 always 块一样。