3.14 ステートに名前を付ける

WaveformViewを見ていても数字の羅列で分かりにくい事があります。Verilog3.1では、enumを使って記述できるのですが、Verilog3.1がメジャーになり、普通に合成ツールのサポートされるまで、まだ数年かかるでしょう。Veritakで実装することも考えたのですが、当面、`ifdef Veritakで、記述がスマートでなくなってしまうし、、と思っていたところ、あるUser様より素晴らしいアイデアを頂戴しました。

その方法は、名前をパラメータのリストで実現するものです。
たとえば、次のような記述になります。

勿論、Verilog言語仕様に完全に合致する記述です。

    module sub (clock,a);
        parameter [3:0] as0=4'h0,as1=4'h1,asx=4'bxxxx,asz=4'bzzzz,
                                    as2=4'h2,as3=4'h3,as4=4'h4,as5=4'h5;
        parameter[3:0] astate=4'h0,bstate=4'h1,cstate=4'h2,dstate=3;    
        input clock;
        input [3:0] a;
        wire [3:0] a_func_result=a_func(a);
                function [3:0] a_func;
                        input [3:0] a;
                        case (a)
                                astate:a_func=as0;
                                bstate:a_func=as1;
                                cstate:a_func=as2;
                                dstate:a_func=as3;
                                default:a_func=asx;
                        endcase
                endfunction

                
endmodule    

これを、WaveformViewで見ると、下図のようになります。断然分かりやすいですね。ToolTipで、数字も出しています。


ところで、これをするには、WaveformView上で、信号とステート名の対応付けを指定してやる必要があります。下のように信号右クリック=>表示選択=>enum選択を指定します。


するとパラメータを選択するダイアログが現れるので、指定します。


なお、ダイアログ内に表示されるのは、インスタンス展開した後の、モジュール内パラメータリストで、記述順に並びます。Veritak内部では、この記述順で、対応(バインディング)を管理しています。(従って、順番が変わらなければ、中身が変わっても関知しませんが、Scopeが変わると消失します。)

Note:

次の例は、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 @(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

TIPS

Verilo2001では、$sformat($sprintf)を使い、上図のように逆アセンブラも容易に書くことができます。YACCプロジェクトのページをご参照ください。