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

2018年12月17日月曜日

SystemVerilog~モデリングの文法~

SystemVerilogの書式など、備忘用にメモする。

logic

SystemVerilogで追加されたデータ型の一つ。regと似た型で、概ねregと同じ使い方ができる。regとの違いはポートリストの型として使う場合。1995/2001では入力はwire、出力はreg、入出力はwireだが、logicは入力にも使える。SystemVerilogでは入出力の型を合わせる必要があり、接続相手がlogicであれば、入力ポートであってもlogicとする。ただし、1995/2001と同様にwireはreg型など別の型と接続でき、インスタンス間の接続はwireで行う。SystemVerilogでも双方向ポートはwireで宣言する。


function

functionはその名の通り関数なので、引数と戻り値を持つ。1995/2001では戻り値としてビット幅を指定できるが、型は呼び出し側で指定する。SystemVerilogでは型の指定ができる。戻り値を持たないvoid型もある。void型以外は1995/2001同様に呼び出し側に代入して使う。void型では引数に出力を指定することでデータを渡す。


Verilog HDL 1995

wire [31:0] IFStage;

function [31:0] FUNC_IF;
  input [31:0] PC;
  begin
    FUNC_IF = mem[PC];
  end
endfunction // FUNC_IF

assign IFStage = FUNC_IF(PC);

  • 戻り値の型は指定できない。型は呼び出し時に決定する。
  • functionは関数定義なので、呼び出し側でwireやregに戻り値を代入する定義分が必要。
  • ステートメントが複数行ある場合、begin~endで括る必要がある

Verilog HDL 2001

wire [31:0] IFStage;

function [31:0] FUNC_IF(
  input [31:0] PC
);
  begin
    FUNC_IF = mem[PC];
  end
endfunction // FUNC_IF

assign IFStage = FUNC_IF(PC);

  • 引数をANSI Cのようにfunction名の後の丸括弧内に記述できる。
あとは、Verilog95と同じ。

SystemVerilog

bit [31:0] IFStage;
function bit [31:0] FUNC_IF(
  input [31:0] PC
);
  return mem[PC];
endfunction : FUNC_IF

IFStage = FUNC_IF(PC);

  • 戻り値の型(function [<型>] [<ビット幅>] <名前>(<ポート宣言>) を指定できる
  • 戻り値を関数名とせず、retrunで指定できる
  • ステートメントが複数行あってもbegin~endは必要ない
  • function~endfinction : [<コメント>] とラベルが貼れる
  • 呼び出して使うのは従来通り。