帰らざるMOS回路(40) 2相ノンオーバラップクロックをVerilogで設計もどき

Joseph Halfmoon

別件記事で古の8080用の2相ノンオーバラップクロックもどきを制作。標準ロジックIC2個、合計7ゲートのロジックを組むのが老人には辛いっす。この際FPGAでやれば自分で配線せずとも出来るじゃん。ということでFPGAにしてみることにしましたが、そのためには回路をHDLで書かないとなりません。久しぶりにVerilog?

※かえらざるMOS回路 投稿順 INDEX

Icarus Verilog

とりあえず手元にあるFPGAは、超お求めやすい価格だったのだけれど使い方が良く分からない(マニュアルが簡体字中国語。。。)ものなんであります。米国製のFPGAであればツールチェーンにVerilogやVHDLのシミュレータやら何やらも含まれていたりするのですが、これはFPGAに書き込むビットファイルは生成できますがシミュレータは含まれません。そこで代表的なフリーのVerilogコンパイラ/シミュレータであるIcarus Verilogを使用することにいたしました。使うの相当久しぶりだな。

Icarus Verilogのドキュメントのページはこちら(数年前にあった「公式ページ」は無くなったみたいデス。でも上記のリンクの方が情報多くなってる気がしないでもない。)

今回作成予定の回路

今回FPGA上に実装しようとしている回路は以下のようなものです。

    1. ボード上に24MHzのオシレータが搭載されているのでそれをクロック源とする
    2. 24MHzを12分周すれば2MHzになる(オリジナル8080の速度?)
    3. 2MHzのクロック出力は2相ノンオーバラップとする
    4. ついでに2MHzを2,4、8、16分周して1MHz、500kHz、250kHz、125kHzの単相クロックも出力できるようにする

別件の2相ノンオーバラップクロック生成回路では、物理的な遅延を使ってノンオーバラップ期間を確保していたのですが、今回は12分周のところで各フェースのON期間を5、OFF期間を7として、確実に「1」の隙間(とりあえず40nsくらい。後で調整はなんとでもなる筈)を作るという目標です。

後はVerilog書くだけなので以下のようです。まず全体回路。このレベルの入出力をFPGAから外に接続の予定。

module counter12
(
    input wire CLK_IN,
    input wire RST_N,
    output wire [3:0]CLK_OUT,
    output wire P1,
    output wire P2
);

freqdiv12 FD12 ( CLK_IN, RST_N, P1, P2 );
freqdiv16 FD16 ( P1, RST_N, CLK_OUT );

endmodule

内部に配置したfreqdiv12が元クロックの12分周回路、freqdiv16が2分周4段で16分周回路です。最初は12分周回路。この中で2フェーズノンオーバラップを作製。

module freqdiv12
(
    input wire CLK_IN,
    input wire RST_N,
    output wire P1,
    output wire P2
);

reg [3:0] count;
reg phase1;
reg phase2;
    
initial
begin
    count=4'b0000;
    phase1=0;
    phase2=0;
end

always @(posedge CLK_IN)
begin
    if (RST_N==1)
        count <= 4'b0000;
    else if (count == 4'b1011)
        count <= 4'b0000;
    else
        count <= count + 1;
end

always @(posedge CLK_IN)
begin
    if (count == 4'b0000)
        phase1 <= 1;
    else if (count == 4'b0101)
        phase1 <= 0;
end

always @(posedge CLK_IN)
begin
    if (count == 4'b0110)
        phase2 <= 1;
    else if (count == 4'b1011)
        phase2 <= 0;
end

assign P1 = phase1;
assign P2 = phase2;
endmodule

つづいて16分周回路。こんなもんで良いか?

module freqdiv16
(
    input wire CLK_IN,
    input wire RST_N,
    output wire [3:0]CLK_OUT
);

reg [3:0] count;
    
initial
begin
    count=4'b0000;
end

always @(posedge CLK_IN)
begin
    if (RST_N==1)
        count <= 4'b0000;
    else if (count == 4'b1111)
        count <= 4'b0000;
    else
        count <= count + 1;
end

assign CLK_OUT = count;
endmodule

ここまでが後で論理合成にかける予定の部分。

テストベンチ

通例手抜きのテストベンチが以下に。ボード上のクロック源は24MHzなんだけれども、計算メンドイという理由で25MHzクロックにしてるぞ。まあ遅延とか全然なシミュレーションなので雰囲気だけね~。いい加減な。

`timescale 1 ns / 100 ps

module counter8_tb;

reg CLK, RST;
wire [3:0] OUT;
wire P1;
wire P2;

parameter STEP = 40;

counter12 dut(CLK, RST, OUT, P1, P2);

initial begin
    $dumpfile("counter12.vcd");
    $dumpvars(-1, dut);
    $monitor("%d CLK=%d RST=%d OUT=%d P1=%d P2=%d", $stime, CLK, RST, OUT, P1, P2);
end

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

initial begin
    #0			RST = 1'b1;
    #STEP		RST = 1'b0;
    #(STEP*600) $finish;
end

endmodule
エラボレーション(ビルド)してシミュレーション

上記で作成のファイル4つをエラボレーション(ビルド。)

$ iverilog -o counter12.out counter12_tb.v counter12.v freqdiv12.v freqdiv16.v

生成されたオブジェクト counter12.outのシミュレーション実行

$ vvp counter12.out >counter12_out.txt

上記でテキスト出力されたシミュレーション結果の頭のところが以下に。

VCD info: dumpfile counter12.vcd opened for output.
         0 CLK=0 RST=1 OUT= 0 P1=0 P2=0
        20 CLK=1 RST=1 OUT= 0 P1=1 P2=0
        40 CLK=0 RST=0 OUT= 0 P1=1 P2=0
        60 CLK=1 RST=0 OUT= 0 P1=1 P2=0
        80 CLK=0 RST=0 OUT= 0 P1=1 P2=0
       100 CLK=1 RST=0 OUT= 0 P1=1 P2=0
       120 CLK=0 RST=0 OUT= 0 P1=1 P2=0
       140 CLK=1 RST=0 OUT= 0 P1=1 P2=0
       160 CLK=0 RST=0 OUT= 0 P1=1 P2=0
       180 CLK=1 RST=0 OUT= 0 P1=1 P2=0
       200 CLK=0 RST=0 OUT= 0 P1=1 P2=0
       220 CLK=1 RST=0 OUT= 0 P1=1 P2=0
       240 CLK=0 RST=0 OUT= 0 P1=1 P2=0
       260 CLK=1 RST=0 OUT= 0 P1=0 P2=0
       280 CLK=0 RST=0 OUT= 0 P1=0 P2=0
       300 CLK=1 RST=0 OUT= 0 P1=0 P2=1

また結果を波形ビューワー gtkwave で観察したところが以下に。counter12SIMwave

2相クロックの間に「隙間」は空いておる、と。

帰らざるMOS回路(39) セントロニクスI/Fのタイミングチャートを描く へ戻る

帰らざるMOS回路(41) 2相ノンオーバラップクロック生成回路をFPGA実装 へ進む