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プロジェクトのページをご参照ください。