k0b0's record.

Computer Engineering, Arts and Books

VerilogHDLでクロック分周器を記述してみる

クロック分周器

FPGAボードを使って、7セグメントLEDに結果を表示させたい時がある。
けれど、MHz〜GHzで動作されたんでは確認できない。
という事で、クロック分周器(50MHz -> 1Hz)を2つ記述してみる。
(どちらの記述も分周するのだけれど、出力される波形が微妙に違うので、
適材適所で使い分けますかね。)

クロック分周器(clk_divider.v)

/* clk_divider.v */
`define HLZ_1     // 50MHzを1HZに分周 
//`define HLZ_1M  // 50MHzを1MHzに分周
//`define HLZ_16M // 50MHzを16MHzに分周
//`define HLZ_32M // 50MHzを32MHzに分周

module clk_divider(input   clk, rst,
                   output   en1hz);

reg  [25:0] cnt;

always @( posedge clk or posedge rst) begin
    if (rst)
        cnt <= 26'd0;
    else if ( en1hz_wire )
        cnt <= 26'd0;
    else
        cnt <= cnt + 26'd1;
end

`ifdef HLZ_1
    wire en1hz_wire = (cnt==26'd49_999_999);
`elsif HLZ_1M
    wire en1hz_wire = (cnt==26'd47);
`elsif HLZ_16M
    wire en1hz_wire = (cnt==26'd2);
`elsif HLZ_32M
    wire en1hz_wire = (cnt==26'd1);
`else
    wire en1hz_wire = (cnt==26'd49_999_999);
`endif

assign en1hz = en1hz_wire;

endmodule

clk_divider.vを論理合成した結果(Quartus PrimeのRTL Viewerで確認)

f:id:k0b0:20190525172127p:plain

クロック分周器 その2 (clk_divider_0.v)

こちらの記述がオーソドックスな分周器かな(?)
上記の記述(clk_divider.v)に比べて、カウントする値を少なくできる。

/* clk_divider_0.v */
/* 50MHz -> 1Hz */
module clk_divider_0(input   clk, rst,
                     output reg divid_clk);

reg [25:0] cnt;

wire cntend = (cnt==26'd24_999_999);

always @(posedge clk or posedge rst)
begin
    if(rst)
        cnt <= 26'd0;
    else if(cntend)
        cnt <= 26'd0;
    else
        cnt <= cnt + 26'd1;
end

always @(posedge clk or posedge rst) 
begin
    if(rst)
        divid_clk <= 1'b0;
    else if(cntend)
        divid_clk <= ~(divid_clk);
end

endmodule

clk_divider_0.vを論理合成した結果(Quartus PrimeのRTL Viewerで確認)

f:id:k0b0:20190529133105j:plain