まあちゃんとマニュアル読めということなんだろうけど。
XilinxのIPには、AXI BRAM Controllerという、BlockRAMモジュールを繋げるためのIPが存在する。
これ、コントローラなので、BRAM本体は別売が正しい。最初はコントローラとBRAMが接続されているのかと思った。 インタフェースはAXI、BRAMとの接続はNativeなBRAM I/Fを用いる。
- s_axi_* : AXIのインタフェース
- bram*{a,b} : Block RAMのインタフェース
このインタフェースを接続するために、仮想のBlockRAMモデルを作った。この方が初期化とかがやりやすい。
module bram_model #(parameter width = 32, //% Data width (default is 32bit) parameter id_w = 4, //% Request ID width (default is 4) parameter words = 128, //% RAM size (default is 128words) parameter length = 7) //% Address size (ideally 2^length == words) ( input wire bram_clk_a, //% Port-0 clock input wire bram_clk_b, //% Port-1 clock input wire bram_rst_a, //% Port-0 clock input wire bram_rst_b, //% Port-1 clock input wire bram_en_a, //% Port-0 Request Valid input wire bram_en_b, //% Port-1 Request Valid input wire [width/8-1: 0] bram_we_a, //% Port-0 Write Request Valid input wire [width/8-1: 0] bram_we_b, //% Port-1 Write Request Valid input wire [width-1: 0] bram_wrdata_a, //% Port-0 Write Data Valid input wire [width-1: 0] bram_wrdata_b, //% Port-1 Write Data Valid input wire [length-1: 0] bram_addr_a, //% Port-0 Address input wire [length-1: 0] bram_addr_b, //% Port-1 Address output reg [width-1: 0] bram_rddata_a, //% Port-0 Read Data output reg [width-1: 0] bram_rddata_b //% Port-1 Read Data ); reg [width-1: 0] regs[words-1: 0]; //% Register instance. localparam addr_offset = width/8/4; /*! * Port-0 Read/Write operation. * bram_en_a & bram_we_a is needed to write RAM. * bram_en_a is needed to read RAM. */ wire [length-1:addr_offset] bram_addr_a_in; wire [width-1: 0] bram_wrdata_a_in, bram_wrdata_a_tmp; assign bram_addr_a_in = bram_addr_a[length-1:addr_offset]; assign bram_wrdata_a_tmp = regs[bram_addr_a_in]; genvar a_i; generate for (a_i = 0; a_i < width/8; a_i = a_i + 1) begin assign bram_wrdata_a_in[8*a_i+7:8*a_i] = bram_we_a[a_i] ? bram_wrdata_a[8*a_i+7:8*a_i] : bram_wrdata_a_tmp[8*a_i+7:8*a_i]; end endgenerate always @ (posedge bram_clk_a) begin bram_rddata_a <= regs[bram_addr_a_in]; if ((bram_en_a & |bram_we_a) == `Enable) begin regs[bram_addr_a_in] <= bram_wrdata_a_in; end end // always @ (posedge bram_clk_a) /*! * Port-1 Read/Write operation. * bram_en_b & bram_we_b is needed to write RAM. * bram_en_b is needed to read RAM. */ wire [length-1:addr_offset] bram_addr_b_in; wire [width-1: 0] bram_wrdata_b_in, bram_wrdata_b_tmp; assign bram_addr_b_in = bram_addr_b[length-1:addr_offset]; assign bram_wrdata_b_tmp = regs[bram_addr_b_in]; genvar b_i; generate for (b_i = 0; b_i < width/8; b_i = b_i + 1) begin assign bram_wrdata_b_in[8*b_i+7:8*b_i] = bram_we_b[b_i] ? bram_wrdata_b[8*b_i+7:8*b_i] : bram_wrdata_b_tmp[8*b_i+7:8*b_i]; end endgenerate always @ (posedge bram_clk_b) begin bram_rddata_b <= regs[bram_addr_b_in]; if ((bram_en_b & bram_we_b) == `Enable) begin regs[bram_addr_b_in] <= bram_wrdata_b_in; end end // always @ (posedge bram_clk_b) integer init_i; initial begin for (init_i = 0; init_i < words; init_i = init_i + 1) begin regs[init_i] = {width{1'b0}}; end end endmodule // axiram
これは論理合成できない、というか出来ても凄く効率が悪いので、論理合成するときは本物のBlockRAMのIPに置き換える。
http://www.xilinx.com/support/documentation/ip_documentation/blk_mem_gen_ds512.pdf