9.ステートメント

ステートメントは、initial_statementや、always_statementのなかで使われる手続き構文です。

<statement>
::=<blocking_assignment> ;
||= <non_blocking_assignment> ;
||= if ( <expression> ) <statement_or_null>
||= if ( <expression> ) <statement_or_null> else <statement_or_null>
||= case ( <expression> ) <case_item>+ endcase
||= casez ( <expression> ) <case_item>+ endcase
||= casex ( <expression> ) <case_item>+ endcase
||= forever <statement>
||= repeat ( <expression> ) <statement>
||= while ( <expression> ) <statement>
||= for ( <assignment> ; <expression> ; <assignment> ) <statement>
||= <delay_or_event_control> <statement_or_null>
||= wait ( <expression> ) <statement_or_null>
||= -> <name_of_event> ;
||= <seq_block>
||= <par_block>
||= <task_enable>
||= <system_task_enable>
||= disable <name_of_task> ;
||= disable <name_of_block> ;
||= assign <assignment> ;
||= deassign <lvalue> ;
||= force <assignment> ;
||= release <lvalue> ;



9.7 implicit event expression list(Verilog2001)
 Verilog2001になって、最も恩恵があるのは、この機能でしょう。具体的には、

event_control ::=
@event_identifier
|@(event_expression )
|@*
|@(*)

で、@* や、@(*)が追加されました。どちらも同じ意味で、いちいちSensitibity Listを書かなくてもよいのです。たくさん ある Sensitibity Listの一つを忘れて、意図回路と合成回路が違うという、誰でも一度は犯しただろうバグを回避できます。(なんと、その効用は、LRMにも書いてあります。?)

下の例は、YACC ALUです。 @*を使って、簡単に記述することができます。

module alu (a,b,alu_func,alu_out);
parameter   [3:0] ALU_NOTHING                      =4'b0000,
                              ALU_ADD              =4'b0001,
                              ALU_SUBTRACT         =4'b0010,
                              ALU_LESS_THAN_UNSIGNED =4'b0101, //Jul.5.2004
                              ALU_LESS_THAN_SIGNED   =4'b0100, //Jul.5.2004
                              ALU_OR                 =4'b0011,
                              ALU_AND                =4'b0110,
                              ALU_XOR                =4'b0111,
                              ALU_NOR                =4'b1000;

        input [31:0] a,b;
        output [31:0] alu_out;
        input [3:0] alu_func;

        reg [31:0] alu_out;
        reg [32:0] sum;

        always @* begin //Jan.20.2005 @(a , b ,alu_func,sum) begin
                case (alu_func)
                        ALU_NOTHING    : alu_out=32'h0000;
                        ALU_ADD        : alu_out=a+b;
                        ALU_SUBTRACT   : alu_out=a+~b+1'b1;//a-b;
                        ALU_OR         : alu_out=a | b;
                        ALU_AND        : alu_out=a & b;
                        ALU_XOR        : alu_out=a ^ b;
                        ALU_NOR        : alu_out=~(a | b);
                        ALU_LESS_THAN_UNSIGNED : alu_out=a < b;//Jun.29.2004
                        ALU_LESS_THAN_SIGNED: begin 
                                                 sum={a[31],a}+~{b[31],b}+1'b1;//a-b                                                                      $signed(a) > $signed(b);
                                                 alu_out={31'h0000_0000,sum[32]}; 
                                               end                      
                        default : alu_out=32'h0000_0000;


                endcase
        end







endmodule

次の例はマルチプレクサです。

module MPX_17 (address,R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,Y);
        input [4:0] address;
        input [7:0] R0,R1,R2,R3,R4,R5,R6,R7     ;
        input [7:0] R8,R9,R10,R11,R12,R13,R14,R15,R16     ;
        output [7:0] Y;
        wire [7:0]  R0,R1,R2,R3,R4,R5,R6,R7     ;
        wire [7:0] R8,R9,R10,R11,R12,R13,R14,R15,R16     ;
        reg   [7:0] Y;
        always @* //@(address or R0 or R1 or R2 or R3 or R4 or R5 or R6 or R7 or
                  //       R8 or  R9 or R10 or R11 or R12 or  R13 or R14 or R15 or R16 )
                case(address)
                    5'b00000: Y=R0;
                    5'b00001: Y=R1;
                    5'b00010: Y=R2;
                    5'b00011: Y=R3;
                    5'b00100: Y=R4;
                    5'b00101: Y=R5;
                    5'b00110: Y=R6;
                    5'b00111: Y=R7;
                    5'b01000: Y=R8;
                    5'b01001: Y=R9;
                    5'b01010: Y=R10;
                    5'b01011: Y=R11;
                    5'b01100: Y=R12;
                    5'b01101: Y=R13;
                    5'b01110: Y=R14;
                    5'b01111: Y=R15;
                    5'b10000: Y=R16;
                    5'b10001: Y=R16;
                    5'b10010: Y=R16;
                    5'b10011: Y=R16;
                    5'b10100: Y=R16;
                    5'b10101: Y=R16;
                    5'b10110: Y=R16;
                    5'b10111: Y=R16;
                    5'b11000: Y=R16;
                    5'b11001: Y=R16;
                    5'b11010: Y=R16;
                    5'b11011: Y=R16;
                    5'b11100: Y=R16;
                    5'b11101: Y=R16;
                    5'b11110: Y=R16;
                    5'b11111: Y=R16;
                endcase
endmodule

イベントリストのショートカットみたいなものです。(実際、シミュレータの中では、@*以下の全てのステートメントをScanして内部イベントリストを作っています。その後のシミュレータの内部動作としては、ショートカットであろうがなかろうが、なんら変わりません。)

便利な記述ですが、気をつけることがあります。それは、HW合成する際は、その性質上、組み合わせ回路に限られるということです。

always @ (posedge clock , posedge async reset) => always @*..

なんてしてしまったら、全く意図しない回路になってしまいます。

右辺に現れる信号は、全て内部Sensitibity Listに加えられます。functionや、taskのパラメータも加えられます。
つまり、

always @* begin
                if (mode==3) begin
                      a<=b;
                      $display(" triggered m=%d k=%d mem=%b",m,k,mem[m][k]);
                end 
        end


の場合、mode, b,m,kが、内部Sensitibity Listに加えられます。また、
次のLHSのインデックス a もenに加えて、内部Sensitibity Listに加えられます。

always @* begin // same as @(a or en)
                y = 8'hff;
                y[a] = !en;
        end

ただし、Event文のSensitibity Listは加えられません。

        always @* begin // equivalent to @(b)
                @(j) dik = b; // j is not added to @*
        end