FC2カウンター FPGAの部屋 2013年11月19日
FC2ブログ

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

FPGAの部屋

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

XST に Dual Port Memory を推論させる (Verilog HDL)

XST に Dual Port Memory を推論させようと思い、Verilog HDL のコードを書いて、XST で論理合成、そしてインプリメントを行った。使用するFPGAはZynq-7020、使用するISEのバージョンは14.7。

関連するブログ記事、”VerilogでXSTにBlock RAMを推論させる

Dual Port Memory を実装する Verilog HDL コード、Dual_Port_Memory_test.v を下に示す。(追記:initial文を追加しました)

`default_nettype none

module Dual_Port_Memory_test(/*autoport*/
//output
           dout,
//input
           clk,
           we,
           waddr,
           raddr,
           din);
    input  wire clk;
    input  wire we;
    input  wire [9:0]   waddr;   // 1024
    input  wire [9:0]   raddr;   // 1024
    input  wire [31:0]  din;
    output reg    [31:0]  dout;

    reg  [31:0]  ram  [0:1023];

    initial begin : memory_initialize
        integer i;
        for (i=0; i<1024; i=i+1)
            ram[i] = 0;
    end

    always  @(posedge  clk) begin
        if  (we)
            ram[waddr]  <=  din;

        dout  <=  ram[raddr];
    end

endmodule

`default_nettype wire


論理合成、インプリメント後の Project Navigator を下に示す。
DPM_1_131119.png

FPGA Editor を起動した時の画面を下に示す。
DPM_2_131119.png

RAMB36E1 を1個使用していた。この Verilog HDL コードは使えそうだ。

(追加)
汎用 Dual Port Memory IPとして使えるように書き換えました。

`default_nettype none

module Dual_Port_Memory_test #(
  parameter integer C_MEMORY_SIZE =   1024, // Word Memory Size (not byte)
  parameter integer DATA_BUS_WIDTH =  32    // RAM Data Width
)
(
    input  wire clk,
    input  wire we,
    input  wire [log2(C_MEMORY_SIZE)-1:0]   waddr,
    input  wire [log2(C_MEMORY_SIZE)-1:0]   raddr,
    input  wire [DATA_BUS_WIDTH-1:0]  din,
    output reg  [DATA_BUS_WIDTH-1:0]  dout
);

    // 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  [DATA_BUS_WIDTH-1:0]  ram  [0:C_MEMORY_SIZE-1];

    initial begin : memory_initialize
        integer i;
        for (i=0; i<C_MEMORY_SIZE; i=i+1)
            ram[i] = 0;
    end

    always  @(posedge  clk) begin
        if  (we)
            ram[waddr]  <=  din;

        dout  <=  ram[raddr];
    end

endmodule

`default_nettype wire


”parameter integer C_MEMORY_SIZE = 2048”にすると、2つの RAMB36E1 が使われました。
  1. 2013年11月19日 05:39 |
  2. XST
  3. | トラックバック:0
  4. | コメント:0