2018年12月24日月曜日

SystemVerilog~シミュレーション~

SystemVerilogの書式など、備忘用にメモする。
VerilogHDL 1995, 2001を含む。

ファイル操作

readmemh(),writememh(),fopen(),fclose(),fdisplay()はVerilog1995のタスク。

  • readmemh()はファイルの読み込み用。主にプロセッサが実行するコードをメモリに書き込む(アノテートする)のに使う。hはhexのことで16進表記。bもある。
  • writememh()はreadmemhの逆で、指定したメモリデータをファイルへ書き出すのに使う。
  • fopen()はファイルを開くのに使う。主に、出力データの書き込み先ファイルのオープン用。
  • fclose()はファイルを閉じるのに使う。他の言語同様、ファイルハンドルを閉じる目的。
  • fdisplay()は指定した文字列をファイルへ書き出すのに使う。

コードフェッチ

logic [31:0] code_flash [0:1023]; // ビット幅,Array名,深さ

initial begin
 // <ファイル名>,<メモリ>,<開始アドレス>[,<終了アドレス>]
  readmemh("code.hex",code_flash,0,1023); 
end

ビット幅は幅を持った信号と同じ表現。メモリ名の後ろにアドレスの深さ(スライス数)を表現する。"開始アドレス:終了アドレス"で書く。実質的には配列と同じで、呼みだすときはそのアドレス(スライス番号)を角括弧内に記述することで指定する。MSB:LSBで書いても問題なく、レジスタセット扱いのときは違いが分かりやすいようにMSB:LSBで書く。

ファイル出力 #サンプル用未検証コード

typedef enum logic [3:0] {
  IDLE = 4'b0001,
  OPEN = 4'b0010,
  WAIT = 4'b0100,
  DONE = 4'b1000
} state;

state CUR_STATE, NXT_STATE;

always @ (posedge CLK) begin
  if (!nRST) begin
    CUR_STATE <= IDLE;
  end else begin
    CUR_STATE <= NXT_STATE;
  end
end
always_comb begin
  case (CUR_STATE)
    IDLE :
      begin
        if (rdy) begin
          NXT_STATE = OPEN;
        end else begin
          NXT_STATE = IDLE;
        end
      end
    OPEN :
      NXT_STATE = WAIT;
    WAIT :
      begin
        if (last) begin
          NXT_STATE = DONE;
        else begin
          NXT_STATE = WAIT;
        end
      end
    DONE :
      NXT_STATE = IDLE;
  endcase
end

logic [15:0] log_mem[0:2043];

initial begin
  while(sim_enable) begin
    if (CUR_STATE = OPEN) begin
      mcd = $fopen("dump.txt", a+);
    end else if (WAIT) begin
      log_mem[i] <= data;
      i<=i+1;
    end else if (CUR_STATE = DONE) begin
      $writememh(mcd, log_mem, 0, 2043);
      $fclose(mcd);
    end
  end
end

0 件のコメント:

コメントを投稿