FC2カウンター FPGAの部屋 Verilog HDLでの log2 の求め方(Constant Functions in Verilog 2001)
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Verilog HDLでの log2 の求め方(Constant Functions in Verilog 2001)

Beyond Circuits は、Synchronous FIFO や LIFO などのXSTでの書き方が書いてある有用なWebページだ。

そこの、Constant Functions in Verilog 2001 を見ると、Verilog HDLによる log2 の求め方が書いてあった。

Constant Function とは、コンパイル時に値が決まる定数のFunction をビット幅の宣言時などに呼び出して、ビット幅を決定できる関数のことである。つまり、定数値をコンパイル時に決定するために使用し、実際の回路にはならない関数のことだ。これで log2 の演算を定義すると、ビット幅をメモリサイズから定義できるので、とっても便利だ。

Constant Functions in Verilog 2001 の記述を参照して、メモリ・モジュールを書いてみた。インプリメントするとBlockRAMにアサインされると思うが未確認だ。下に示す。(2013/06/26:変更)(2013/07/03:バグ修正)

// 8bit Memory Module

`default_nettype none

module memory_8bit #(
    parameter integer C_S_AXI_ADDR_WIDTH            = 32,
    parameter integer C_MEMORY_SIZE                    = 512    // Word (not byte)
)(
    input    wire    clk,
    input    wire    [C_S_AXI_ADDR_WIDTH-1:0]    waddr,
    input    wire    [7:0]    write_data,
    input    wire    write_enable,
    input    wire    byte_enable,
    input    wire    [C_S_AXI_ADDR_WIDTH-1:0]    raddr,
    output    reg        [7:0]    read_data
);

    // Beyond Circuts, Constant Function in Verilog 2001を参照しました
    // http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
    function integer log2;
        input integer addr;
        begin
            addr = addr - 1;
            for (log2=0; addr>0; log2=log2+1)
                addr = addr >> 1;
        end
    endfunction
    
    reg        [7:0]    mem    [0:C_MEMORY_SIZE-1];
    wire    [log2(C_MEMORY_SIZE)-1:0]    mem_waddr;
    wire    [log2(C_MEMORY_SIZE)-1:0]    mem_raddr;
    
    // The Address is byte address
    assign mem_waddr = waddr[(log2(C_MEMORY_SIZE)+log2((C_S_AXI_ADDR_WIDTH/8)))-1:log2((C_S_AXI_ADDR_WIDTH/8))];
    assign mem_raddr = raddr[(log2(C_MEMORY_SIZE)+log2((C_S_AXI_ADDR_WIDTH/8)))-1:log2((C_S_AXI_ADDR_WIDTH/8))];
    
    // Write
    always @(posedge clk) begin
        if (write_enable & byte_enable)
            mem[mem_waddr] <= write_data;
    end
    
    // Read
    always @(posedge clk) begin
        read_data <= mem[mem_raddr];
    end
endmodule

`default_nettype wire


(追加)
AR# 44586 13.2 Verilog $clog2 関数が正しくインプリメントされていない”に、定数関数 (Constant Function) のコードも書いてありました。
  1. 2013年06月25日 08:30 |
  2. 入門Verilog
  3. | トラックバック:0
  4. | コメント:6

コメント

$clog2

ieee 1800-2005 を見ると、
20.8.1 Integer math functions に、
$clog2 ってのがありますね。
こんなのが使える環境とは縁がありません T_T
  1. 2013/06/25(火) 08:59:25 |
  2. URL |
  3. astray #VWFaYlLU
  4. [ 編集 ]

Re: $clog2

> ieee 1800-2005 を見ると
う、見ていた文書は 1800-2012 でありました。
まだ寝ぼけてます。すんません m(_ _)m
  1. 2013/06/25(火) 09:03:28 |
  2. URL |
  3. astray #VWFaYlLU
  4. [ 編集 ]

Spartan-6 LX9 MicroBoard に載ってるCDCE913のPLL設定で log2 が出てきて、あれこれ30分悩んでしまいましたがコードになると一目瞭然w
カウンタのビット幅を指定したいだけだったんですね Orz
  1. 2013/06/25(火) 09:38:33 |
  2. URL |
  3. おる #qbIq4rIg
  4. [ 編集 ]

astray さん、$clog2 が使えるのかどうかよくわかりません。clogb2 が使えるのかもしれません。後でやってみたいと思います。

おるさん、log2ができると、数からビット幅を求めることができて、パラメタライズに書けますね。
  1. 2013/06/25(火) 11:22:03 |
  2. URL |
  3. marsee #f1oWVgn2
  4. [ 編集 ]

> reg [7:0] mem [0:C_MEMORY_SIZE];
> wire [log2(C_MEMORY_SIZE)-1:0] mem_waddr;

これ、よく考えると、1 行目は、
reg [7:0] mem [0:C_MEMORY_SIZE-1];
でなければならないと思われます。
1 行目を変更したくなければ、2 行目を、
wire [log2(C_MEMORY_SIZE + 1)-1:0] mem_waddr;
に変えるか。

log2 の引数には、アドレスの最大値ではなく
メモリの大きさを渡さないと妙なことになりそー。
またまた寝ぼけてるだけかもしれませんが ^_^;
  1. 2013/07/03(水) 18:50:37 |
  2. URL |
  3. astray #VWFaYlLU
  4. [ 編集 ]

astray さん、バグを指摘していただいて、ありがとうございました。
reg [7:0] mem [0:C_MEMORY_SIZE-1];
に修正させて頂きました。
  1. 2013/07/03(水) 19:58:40 |
  2. URL |
  3. marsee #f1oWVgn2
  4. [ 編集 ]

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/2504-4ba8447f
この記事にトラックバックする(FC2ブログユーザー)