ためになるホームページ お問い合わせ




TOP > Verilog > $readmemhと$readmemb
外部ファイルの読み出し
システム・タスクを用いて外部ファイルを読み出す事ができる。例えば、あるレジスタ配列の初期値をセットする時などに使う。
$readmemhは、16進数の表記のデータを読み込み、$readmembは2進数表記のデータを読み込む。
(書式)  $readmemh ("入力ファイル名", メモリ名, [開始アドレス], [終了アドレス]);
開始アドレスと終了アドレスは、省略できる。指定した場合、データを格納するメモリの番地を指定する。

外部ファイルの書き方
外部ファイル内では、コメント・タブ・改行が記述できる。
メモリに読み込ませる値は、アンダースコア(_)で区切って記述できる。(この時、ビット幅・基数の指定はいらない)
また、外部ファイル内に格納するアドレスを指定することもできる。
(書式)@格納先アドレス  値...

外部ファイルの記述の例
//rom_data.hex
0_0_0_0_0_0_0_3
0_0_0_0_f_f_f_f


外部ファイル読み込み
外部ファイルを読み込ませる例は以下の通り。格納するメモリは、32ビットの10個のアドレスを持つ。

外部ファイルの読み込みのテストの例

外部ファイルの記述の例
//テストベンチ
module testbench;

reg CLK;
reg RST;
wire [11:0] ADDR;
wire [31:0] XDATA;

DUMMY_ROM DUMMY_ROM(
    .CLK(CLK),
    .RST(RST), 
    .ADDR(ADDR),
    .XDATA(XDATA)
);

DUMMY_ADDR DUMMY_ADDR(
    .CLK(CLK),
    .RST(RST),
    .XADDR(ADDR)
);

parameter STEP = 10;

always #(STEP / 2) CLK = ~CLK;

initial begin
  $dumpfile("wave.vcd");
  $dumpvars(0, testbench);
  $monitor ("%t: CLK = %b, RST = %b , ADDR = %h, XDATA = %h", $time, CLK, RST, ADDR, XDATA);
  CLK = 0;
  RST = 0;
  #10
  RST = 1;
  #10
  #100
  $finish;
end

endmodule

//レジスタ配列に格納(memory)
module DUMMY_ROM(CLK, RST, ADDR, XDATA);
input CLK;
input RST;
input [11:0] ADDR;
output [31:0] XDATA;
reg [31:0]ROM[0:9];
reg [31:0] XDATA;
initial $readmemh("test.hex", ROM);

always @(posedge CLK)
  begin
    if (~RST)
      XDATA <= 32'h0;
    else
      XDATA <= ROM[ADDR];
  end

endmodule

//レジスタ配列のアドレス生成
module DUMMY_ADDR(CLK, RST, XADDR);
input CLK;
input RST;
output [11:0]XADDR;
reg [11:0]XADDR;
always @(posedge CLK)
  begin
    if (~RST)
      XADDR <= 12'h0;
    else if (XADDR == 12'ha)
      XADDR <= 12'h0;
    else
      XADDR <= XADDR + 1;
  end
endmodule


//以下はtest.hexの内容
0_0_0_0_0_0_0_0
0_0_0_0_0_0_0_1
0_0_0_0_0_0_0_2
0_0_0_0_0_0_0_3
0_0_0_0_0_0_0_4
0_0_0_0_0_0_0_5
0_0_0_0_0_0_0_6
0_0_0_0_0_0_0_7
0_0_0_0_0_0_0_8
0_0_0_0_0_0_0_9






Copyright 2007 ためになるホームページ All Rights Reserved.