Help us understand the problem. What is going on with this article?

タイミングチャートを描きたい

DoxygenのようにHDLモジュールのドキュメントを簡単に作れるツールが欲しいです。しかたなく、自作することにしました。

困っていること

(1)インターフェース
モジュールの左に入力信号、右に出力信号という感じで作図するのは簡単にできそう。でも、valid-readyのようにセットの信号が右と左に泣き別れになるのはよくないですよね。

(2)タイミングチャート
当たり前ですが、モジュールのGerericやPortを切り出しても、タイミングやプロトコルはさっぱりわからない。タイミングチャートとか手書きするしかないかな。

クロックと、ロジックやデータをかけばよいのですが、困るのがクロックとの位相関係がいろいろあること。クロックと同期して出力されるレジスタ、クロックと非同期の信号、クロックより少し遅れて出力がでてくるメモリ読み出しデータ。

これらをちゃんと書きわけられないと、チャートをみても因果関係がさっぱりわからない。

というわけで

タイミングチャートを描いてくれるページをつくりました。 ここです解説はご要望があれば。

 // 1行で1つの信号を記述
 // 基本形
 // <name>:<type>:<description>
 //
 // TYPE
 //  0 : キャプション
 //  1 : クロック
 //  2 : ロジック   <name>:2:<pos>[Pp]<dur>_annotation
 //       <pos>: 開始位置
 //       <dur>: 継続長
 //       P      : レジスタ出力を想定したパルス(クロック同期)
 //       p     :コンビネーション出力を想定したパルス
 //  3 : バス        <name>:2:<pos>[DdMm]<dur>_annotation
 //       D     : レジスタ出力を想定したバス出力(クロック同期)
 //       d     : コンビネーション出力を想定したバス出力
 //       M     : メモリ出力を想定したバス出力(クロック同期だが少し遅れる)
 //       m     : メモリ出力を想定したバス出力


 :0:キャプション
 CLK:1:  
 rd_en:2:3P
 data:3:3m1_data

コード

せっかくなのでQiitaらしくコードも置いておきます。
perl書きらしく刹那的なコードですが

//こんな感じにジオメトリ情報をセットして
 const WIDTH=400;
 const HEIGHT=300;
 //--
 const ROW_HEIGHT=20;//行の高さ
 const LOGIC_HEIGHT=15;//ハイレベルの高さ
 const NAME_LEFT=5;      //信号名開始位置

 const SIG_LEFT=50;     //信号描画領域左端
 const SIG_RIGHT=380;   //同 右端
 const SIG_WIDTH=(SIG_RIGHT-SIG_LEFT);
 //--
 const TICK_START=0;
 const CLK_OFSET=5; //クロックエッジまでの時間
 var TICK_COUNT=10; //作画するクロック数
 var TICK_WIDTH=SIG_WIDTH/TICK_COUNT;

 //コンテキストと、Y方向の位置、パラメータを指定してdraw_CLK()とかdraw_logic()とか呼ぶ
timechart.js
 // クロックと、偶数クロックの背景を描く
function draw_CLK(ctx,Y_BASE){
    //---背景
    ctx.fillStyle = "rgb(240,240,240)";ctx.lineWidth=1;
    for(var i=0;i<TICK_COUNT;i+=2){
        var x=i*TICK_WIDTH+SIG_LEFT+CLK_OFSET;
        var yh=Y_BASE-LOGIC_HEIGHT;
        ctx.fillRect(x,yh,TICK_WIDTH,HEIGHT-5-yh);
    }
    //
    ctx.moveTo(SIG_LEFT,Y_BASE);
    ctx.lineTo(SIG_LEFT+CLK_OFSET,Y_BASE);
    for(var i=0;i<TICK_COUNT;i++){
        var x=i*TICK_WIDTH+SIG_LEFT+CLK_OFSET;
        ctx.lineTo(x,Y_BASE-LOGIC_HEIGHT);
        ctx.lineTo(x+TICK_WIDTH/2,Y_BASE-LOGIC_HEIGHT);
        ctx.lineTo(x+TICK_WIDTH/2,Y_BASE);
        ctx.lineTo(x+TICK_WIDTH  ,Y_BASE);
    }
    ctx.stroke();
}

function draw_logic(ctx,Y_BASE,sLogic){
    var aLogic=sLogic.split(",");
    var pos=0,clogic="L",logic=0,dur="-1";
    var x=0*TICK_WIDTH+SIG_LEFT;
    //
    ctx.fillStyle = "blue";

    ctx.moveTo(x,Y_BASE);
    for(var i=0;i<aLogic.length;i++){
        var code=aLogic[i];
        var m=code.match(/^(\d*\.?\d*)([PpMm]?)(\d*\.?\d*)_?([A-z0-9]*)$/);
        if(m == null) return;
        var apos=0,dpos=1;
        // 1 apos, 2 logic, 3 dpos
        /*if(m[3] == null){//ロジック指定なし。反転
         dpos=m[1]+0;apos=0;
         }*/
        apos=Number(m[1]); dpos=Number(m[3]);
        if (dpos==0)dpos=1;

        var offset=0;
        if (m[2]==="p"){
            offset = CLK_OFSET/2;
        }
        if ((m[2]==="M") || (m[2]==="m")){
            offset = CLK_OFSET*2;
        }
        var newpos=apos;
        if (newpos >= pos){
            //あたらしいところまで線を引く
            x=newpos*TICK_WIDTH+SIG_LEFT+offset;
            ctx.lineTo(x,Y_BASE-logic*LOGIC_HEIGHT);
            // P
            logic=1;
            ctx.lineTo(x,Y_BASE-logic*LOGIC_HEIGHT);
            newpos += dpos;
            if(m[4] != null){
                ctx.fillText(m[4],NAME_LEFT+x,Y_BASE-LOGIC_HEIGHT/5);
            }

            x=newpos*TICK_WIDTH+SIG_LEFT+offset;
            ctx.lineTo(x,Y_BASE-logic*LOGIC_HEIGHT);
            logic=0;
            ctx.lineTo(x,Y_BASE-logic*LOGIC_HEIGHT);
            pos=newpos;
            //

        }
    }
    if(pos<TICK_COUNT){
        pos = TICK_COUNT;
        x=pos*TICK_WIDTH+SIG_LEFT;
        ctx.lineTo(x,Y_BASE-logic*LOGIC_HEIGHT);
    }
    ctx.stroke();
}
...

追記

こちらのサイトがよいかも https://wavedrom.com

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away