ROMRTL記述

[] [] []


ROMは、アドレスを入力としデータを出力とするデコーダと同じだからcase文で書ける。

/* シングルポートROM - case文で書く*/

always @(posedge clk)

  case(adr)

  12'd0: dat <= 8'h00;

  12'd1: dat <= 8'h11;

  12'd2: dat <= 8'h22;

  ...

  12'd4095: dat <= 8'hff;

  default:  dat <= 8'bx;

  end

FPGAの場合、コンフィギュレーション時にブロックRAMに初期値がロードされるので、ライトなしのRAMRTL記述すればROMになる

コンフィギュレーション時の初期値代入はinitial文で書く。

/* シングルポートROM - initial文で値を列挙する */

reg[7:0] rom[0:4095];

always @(posedge clk) dat <= rom[adr];

initial

  begin

  rom[0] = 8'h00;

  rom[1] = 8'h11;

  rom[2] = 8'h22;

  ...

  rom[4095] = 8'hff;

  end

この書き方だとN-port ROMも簡単に書ける。(N-port ROMは、処理を並列にするため同じROM値を並列にリードするときに必要になる)

ただし、ISE14.7Vivado 2014.4では2ポートRAM 1個にマッピングしてくれたが、QuartusII14.1ではなぜか1ポートRAM 2個にマッピングされてしまった。

/* デュアルポートROM - initial文で値を列挙する */

reg[7:0] rom[0:4095];

always @(posedge clk) dat0 <= rom[adr0];

always @(posedge clk) dat1 <= rom[adr1];

initial

  begin

  rom[0] = 8'h00;

  rom[1] = 8'h11;

  rom[2] = 8'h22;

  ...

  rom[4095] = 8'hff;

  end

◇◇

ユーザガイドには、$readmemh()でテキストファイルから値を読み込む方法が載っているが、ソースファイルとテキストファイルに分けてしまうと管理しにくくなるのでよくない。

/* シングルポートROM - initial文で値をファイルから読み込む */

reg[7:0] rom[0:4095];

always @(posedge clk) dat <= rom[adr];

initial

  begin

  $readmemh("rom.txt",rom);

  end

/* rom.txt */

00

11

22

...

ff

◇◇◇

もし値が数式で表せるならばfor文で書いてもよい。

/* シングルポートROM - initial文で値を数式で与える */

reg[7:0] rom[0:4095];

always @(posedge clk) dat <= rom[adr];

integer i;

initial

  begin

  for(i=0; i<4096; i=i+1) rom[i] = (i%255);

  end


[] [] []