aki_iic’s blog

己の欲せざる処人に施す事無かれ、狂人の真似するは即ち狂人なり

iverilog + gtkwave

 graphvizで復元したステートダイヤグラムからiverilogでverilogコードをシミュレーションして作成したvcdファイルをgtkwaveで波形表示出来るようになった。テストベンチがポンコツ過ぎて恥ずかしい限りだが過程を整理すると

0.実現したい回路のタイミングチャートを設定する

1.dot言語でステートダイヤグラムを記述してgravizで.pngファイル作成

2.それに基づきverilogでコードとテストベンチを書く

3.iverilogでシミュレーションしてvcdファイル作成

4.gtkwaveでvcdファイルを波形表示

5.期待した波形になる迄 2.〜4.を繰り返す。

ほんでもって生成されたアウトプットは:

0.実現したい回路のタイミングチャート(多分2016年頃に再検討したもの)

f:id:aki_iic:20211113111159p:plain

m68030_v0 dram timing chart(案)

1.ステートダイヤグラム(令和3年霜月十一日現在)

f:id:aki_iic:20211111221342p:plain

dramc state diagram (graphviz) 20211111

2.1 verilogコード dramc.v

// 2021/11/07 : 作業開始
// 2021/11/09 : ベースカウンタをジョンソンに戻す。
 
module dramc(sysclk,cpuclk,reset_b,as_b,dramara,refclk,ras_n,cas_n,ras_rfsh_n,cas_rfsh_n,dsack_n);
    input sysclk ; //system clock
    input reset_b ; //system reset
    input as_b ; //cpu address strobe
    input refclk ; //refresh clock
    input dramara ; //dram area

    output cpuclk ; //sysclk/2
    output ras_n ; //ras
    output cas_n ; // cas
    output ras_rfsh_n ; // ras rfsh
    output cas_rfsh_n ; // cas rfsh
    output dsack_n ; // dsack

    reg [2:0] drsq,ndrsq ; // dram sequencer
    reg [3:0] rfsq,nrfsq ; // dram refresh sequencer
    reg cpuclk ; // sysclk/2

    parameter S0=3'b000,S1=3'b001,S2=3'b011,S3=3'b111,S4=3'b110,S5=3'b100 ; // dram state 0-5
    parameter R0=4'b0000,R1=4'b0001,R2=4'b0011,R3=4'b0111,R4=4'b1111,R5=4'b1110,R6=4'b1100,R7=4'b1000 ; // rfsh state 0-7

// cpuclock
    always @( posedge sysclk or negedge reset_b ) begin
        if ( ~reset_b )
            cpuclk <= 1'b0 ;
        else
            cpuclk <= ~cpuclk ;
    end

// state register
    always @( posedge sysclk or negedge reset_b ) begin
        if ( ~reset_b )
            begin
                drsq <= S0 ;
                rfsq <= R0 ;
            end
        else
            begin
                drsq <= ndrsq ;
                rfsq <= nrfsq ;
            end
    end

// dram state sequencer
    always @( drsq or as_b or dramara or cpuclk or ~rfshcyc ) begin
        case ( drsq )
            S0 : if ( as_b == 0 && dramara && cpuclk && rfshcyc == 0 )
                    ndrsq <= S1 ;
                 else
                    ndrsq <= S0 ;
            S1 :    ndrsq <= S2 ;
            S2 : if ( cpuclk )
                    ndrsq <= S3 ;
                 else
                    ndrsq <= S2 ;
            S3 :    ndrsq <= S4 ;
            S4 :    ndrsq <= S5 ;
            S5 : if ( as_b )
                    ndrsq <= S0 ;
                 else
                    ndrsq <= S5 ;
        endcase
    end

    always @( rfsq or as_b or cpuclk or dramcyc or refclk ) begin
        case ( rfsq )
            R0 : if ( as_b && refclk && ~cpuclk && ~dramcyc )
                    nrfsq <= R1 ;
                else
                    nrfsq <= R0 ;
            R1 :    nrfsq <= R2 ;
            R2 :    nrfsq <= R3 ;
            R3 :    nrfsq <= R4 ;
            R4 :    nrfsq <= R5 ;
            R5 :    nrfsq <= R6 ;
            R6 :    nrfsq <= R7 ;
            R7 :    nrfsq <= R0 ;
        endcase

    end

    assign ras_n = ~drsq[1] ;
    assign drampx = drsq[2] ;
    assign cas_n = ~(~drsq[0] & drsq[2]) ;
    assign dsack_n = ~(~drsq[1] & drsq[2]) ;
    assign dramcyc = drsq[1] | drsq[2] ;
    assign cas_rfsh_n = ~rfsq[1] ;
    assign ras_rfsh_n = ~rfsq[2] ;
    assign rfshcyc = rfsq[1] | rfsq[3] ;

endmodule

2.2 テストベンチ dramc_tp.v

// 2021/11/07 : 作業開始
// 2021/11/09 : テストベンチ
module dramc_tp ;
    reg sysclk ; //system clock
    reg reset_b ; //system reset
    reg as_b ; //cpu address strobe
    reg refclk ; //refresh clock
    reg dramara ; //dram area

    wire cpuclk ; //sysclk/2
    reg rfshcyc ; //dram refresh cycle
    wire ras_n ; //ras
    wire cas_n ; // cas
    wire ras_rfsh_n ; // ras rfsh
    wire cas_rfsh_n ; // cas rfsh
    wire dsack_n ; // dsack

parameter STEP = 25000 ; // 25ns(25 x 1000ps)
parameter td1 = 15000 ; // 15ns

dramc dramc(sysclk,cpuclk,reset_b,as_b,dramara,refclk,ras_n,cas_n,ras_rfsh_n,cas_rfsh_n,dsack_n);

always begin
    sysclk = 1 ; #(STEP/2) ;
    sysclk = 0 ; #(STEP/2) ;
end

initial begin
    as_b = 1 ; reset_b = 0 ; refclk = 0 ; dramara = 0 ;
#(STEP*2)
    reset_b = 1 ;
#(STEP*2)
    dramara = 1 ;
#td1
    as_b = 0 ;
//#(STEP*2*3)
    wait(~dsack_n)

#(STEP)
    as_b = 1 ;
#(STEP*3)
    refclk = 1 ;
    wait(~ras_rfsh_n)
#(STEP*5)
    refclk = 0 ;
#(STEP*3)

    $finish ;
end

initial begin
    $dumpfile("dramc_tp.vcd");
    $dumpvars(0,dramc);
    $monitor("cpuclk = %b reset_b = %b as_b = %b dsack_n = %b refclk %b",cpuclk,reset_b,as_b,dsack_n,refclk);
end

endmodule

3-4.gtkwaveのシミュレーション結果波形

f:id:aki_iic:20211113171219p:plain

gtkwave waveform : dramc_tp.vcd



 無論シミュレーションなので実チップ(XC95108PC84を想定)にテクノロマッピングするには周辺回路を記述しなければならないがdramcの合成が出来るようになったので少しはやる気が出るかもしれない(出てる気がする)。ISEの環境は確保してある(Ubuntu 16.04LTSで。。。)のでコツコツ周辺回路を書き足して例のボード作成に繋げたいところではある(鬼が笑うような話ではあるが)。

2021/11/13 : 波形が見づらかった(ジジイの目の為かもしれない)のでprintイメージで出力。

f:id:aki_iic:20211113171314p:plain

gtkwave waveform : dramc_tp.pdf


2021/11/13 : 突然ステートダイヤグラムが発現するのは不自然過ぎるので実現したい回路のタイミングチャートを過去のpdfから発掘・切り抜いて 0.項を追記。