見出し画像

Google XLSでDDR3メモリコントローラーを設計してみる

背景

Googleがオープンソースで公開した高位合成処理系(半導体設計ソフトウェア)XLSをインストールしてみた。使い方を忘れないうちに実用回路を設計してみよう。

事前練習

xlsを使って、8bitカウンターを設計してみる
procを使ってみる。

(中略)

エラーとなり、進みません。
結論

まとめ

今のバージョンの DSLX では、チャネルを proc メンバーにして config や next で使うことが仕様的に不可能。
エラーを回避する手段は実質的にない (チャネル関連を除去するしかない)。
I/O が必要なら、より新しい XLS のバージョンや実装にアップデート してください。
これが現在判明している最終的な結論になります。

ChatGPT

過去の事前練習

xlsを使って、8bitカウンターを設計してみる

※(バイナリコードのxlsではなく、ソースからコンパイルしました。n100のPCでコンパイルに一晩以上かかりました。SSDの容量も100GB以上は必要です。)

コードはfnを使いました。procではどうやってもエラーとなり、verilogまで変換できない。

fn counter8(state: bits[8], rst_input: bits[1]) -> bits[8] {
  // リセットが有効な場合、状態をリセット
  if rst_input == bits[1]:1 {
    bits[8]:0
  } else {
    // カウンタをインクリメント
    state + bits[8]:1
  }
}

Makefile一発で変換

# Variables
TOP = counter8
INPUT_FILE = counter8.x
IR_FILE = $(TOP).ir
OPT_IR_FILE = $(TOP)_opt.ir
OUTPUT_DIR = /home/haruhiko/xls/bazel-bin
OUTPUT_FILE = counter8.v

# Tools
INTERPRETER = $(OUTPUT_DIR)/xls/dslx/interpreter_main
IR_CONVERTER = $(OUTPUT_DIR)/xls/dslx/ir_convert/ir_converter_main
OPT_MAIN = $(OUTPUT_DIR)/xls/tools/opt_main
CODEGEN_MAIN = $(OUTPUT_DIR)/xls/tools/codegen_main

# Default target
all: codegen

# Targets with dependencies
ir_convert: interpret
	$(IR_CONVERTER) --top=$(TOP) $(INPUT_FILE) > $(IR_FILE)

optimize: ir_convert
	$(OPT_MAIN) $(IR_FILE) > $(OPT_IR_FILE)

codegen: optimize
	$(CODEGEN_MAIN) \
	--pipeline_stages=1 \
	--delay_model=unit \
	--module_name=counter8 \
	$(OPT_IR_FILE) > $(OUTPUT_FILE)


interpret:
	$(INTERPRETER) $(INPUT_FILE)

# Clean intermediate files
clean:
	rm -f $(IR_FILE) $(OPT_IR_FILE) $(OUTPUT_FILE)

実行すると、、

haruhiko@haruhiko-Default-string:~/Program/GoogleXLS_test-main$ make
/home/haruhiko/xls/bazel-bin/xls/dslx/interpreter_main counter8.x
[===============] 0 test(s) ran; 0 failed; 0 skipped.
/home/haruhiko/xls/bazel-bin/xls/dslx/ir_convert/ir_converter_main --top=counter8 counter8.x > counter8.ir
/home/haruhiko/xls/bazel-bin/xls/tools/opt_main counter8.ir > counter8_opt.ir
/home/haruhiko/xls/bazel-bin/xls/tools/codegen_main \
--pipeline_stages=1 \
--delay_model=unit \
--module_name=counter8 \
counter8_opt.ir > counter8.v
haruhiko@haruhiko-Default-string:~/Program/GoogleXLS_test-main$ 

生成されたVerilogコードは、

module counter8(
  input wire clk,
  input wire [7:0] state,
  input wire rst_input,
  output wire [7:0] out
);
  // ===== Pipe stage 0:

  // Registers for pipe stage 0:
  reg [7:0] p0_state;
  reg p0_rst_input;
  always_ff @ (posedge clk) begin
    p0_state <= state;
    p0_rst_input <= rst_input;
  end

  // ===== Pipe stage 1:
  wire [7:0] p1_add_23_comb;
  wire [7:0] p1_and_25_comb;
  assign p1_add_23_comb = p0_state + 8'h01;
  assign p1_and_25_comb = p1_add_23_comb & {8{~p0_rst_input}};

  // Registers for pipe stage 1:
  reg [7:0] p1_and_25;
  always_ff @ (posedge clk) begin
    p1_and_25 <= p1_and_25_comb;
  end
  assign out = p1_and_25;
endmodule

こうなりました。
人間並みのコードになりました。あ、まだまだダメですね。
procを使う必要があるようです。
次は実用回路を設計してみようか・・・

(今日は寝れそう・・)

過去の事前練習

xlsで、カウンターを設計してみる。

proc counter8 {
  // 出力チャネル(カウンタ値出力)
  count_out: chan<bits[8]> out;
  // クロック入力チャネル
  clk_in: chan<bits[1]> in;
  // リセット入力チャネル
  rst_in: chan<bits[1]> in;

  // 初期状態としてカウンタを0で初期化
  init { bits[8]:0 }

  // configでプロセスのI/Oチャネルをバインドします
  config(count_out: chan<bits[8]> out, clk_in: chan<bits[1]> in, rst_in: chan<bits[1]> in) {
    (count_out, clk_in, rst_in)
  }

  // nextで状態更新ロジックを定義
  next(state: bits[8]) {
    // クロックとリセットの値を受信
    let (tok_clk, clk_val) = recv(join(), clk_in);
    let (tok_rst, rst_val) = recv(tok_clk, rst_in);

    // リセットが有効なら次状態は0、そうでなければclkが1のときにカウントアップ
    let next_state = if rst_val == bits[1]:1 {
      bits[8]:0
    } else {
      if clk_val == bits[1]:1 {
        state + bits[8]:1
      } else {
        state
      }
    };

    // 次状態を出力チャネルに送信
    let tok_out = send(tok_rst, count_out, next_state);

    // 次状態を返すことで、次サイクルのstateとなる
    next_state
  }
}

実行すると

nishimura@nishimura-Default-string:~/Program$ interpreter_main counter8.x 
[===============] 0 test(s) ran; 0 failed; 0 skipped.

→OK

verilogに変換

module __counter8__counter8_0_next(
  input wire clk,
  input wire rst_in,
  input wire counter8__clk_in,
  input wire counter8__clk_in_vld,
  input wire counter8__rst_in,
  input wire counter8__rst_in_vld,
  input wire counter8__count_out_rdy,
  output wire [7:0] counter8__count_out,
  output wire counter8__count_out_vld,
  output wire counter8__clk_in_rdy,
  output wire counter8__rst_in_rdy
);
  reg [7:0] ____state;
  reg __counter8__clk_in_reg;
  reg __counter8__clk_in_valid_reg;
  reg __counter8__rst_in_reg;
  reg __counter8__rst_in_valid_reg;
  reg [7:0] __counter8__count_out_reg;
  reg __counter8__count_out_valid_reg;
  wire counter8__count_out_valid_inv;
  wire p0_all_active_inputs_valid;
  wire counter8__count_out_valid_load_en;
  wire counter8__count_out_load_en;
  wire p0_stage_done;
  wire nor_94;
  wire counter8__clk_in_valid_inv;
  wire counter8__rst_in_valid_inv;
  wire [7:0] add_85;
  wire [1:0] concat_110;
  wire counter8__clk_in_valid_load_en;
  wire counter8__rst_in_valid_load_en;
  wire [7:0] one_hot_sel_111;
  wire and_118;
  wire counter8__clk_in_load_en;
  wire counter8__rst_in_load_en;
  wire [7:0] next_state;
  assign counter8__count_out_valid_inv = ~__counter8__count_out_valid_reg;
  assign p0_all_active_inputs_valid = __counter8__clk_in_valid_reg & __counter8__rst_in_valid_reg;
  assign counter8__count_out_valid_load_en = counter8__count_out_rdy | counter8__count_out_valid_inv;
  assign counter8__count_out_load_en = p0_all_active_inputs_valid & counter8__count_out_valid_load_en;
  assign p0_stage_done = p0_all_active_inputs_valid & counter8__count_out_load_en;
  assign nor_94 = ~(__counter8__rst_in_reg | ~__counter8__clk_in_reg);
  assign counter8__clk_in_valid_inv = ~__counter8__clk_in_valid_reg;
  assign counter8__rst_in_valid_inv = ~__counter8__rst_in_valid_reg;
  assign add_85 = ____state + 8'h01;
  assign concat_110 = {__counter8__rst_in_reg & p0_stage_done, nor_94 & p0_stage_done};
  assign counter8__clk_in_valid_load_en = p0_stage_done | counter8__clk_in_valid_inv;
  assign counter8__rst_in_valid_load_en = p0_stage_done | counter8__rst_in_valid_inv;
  assign one_hot_sel_111 = add_85 & {8{concat_110[0]}} | 8'h00 & {8{concat_110[1]}};
  assign and_118 = (__counter8__rst_in_reg | nor_94) & p0_stage_done;
  assign counter8__clk_in_load_en = counter8__clk_in_vld & counter8__clk_in_valid_load_en;
  assign counter8__rst_in_load_en = counter8__rst_in_vld & counter8__rst_in_valid_load_en;
  assign next_state = (__counter8__clk_in_reg ? add_85 : ____state) & {8{~__counter8__rst_in_reg}};
  always_ff @ (posedge clk) begin
    if (rst_in) begin
      ____state <= 8'h00;
      __counter8__clk_in_reg <= 1'h0;
      __counter8__clk_in_valid_reg <= 1'h0;
      __counter8__rst_in_reg <= 1'h0;
      __counter8__rst_in_valid_reg <= 1'h0;
      __counter8__count_out_reg <= 8'h00;
      __counter8__count_out_valid_reg <= 1'h0;
    end else begin
      ____state <= and_118 ? one_hot_sel_111 : ____state;
      __counter8__clk_in_reg <= counter8__clk_in_load_en ? counter8__clk_in : __counter8__clk_in_reg;
      __counter8__clk_in_valid_reg <= counter8__clk_in_valid_load_en ? counter8__clk_in_vld : __counter8__clk_in_valid_reg;
      __counter8__rst_in_reg <= counter8__rst_in_load_en ? counter8__rst_in : __counter8__rst_in_reg;
      __counter8__rst_in_valid_reg <= counter8__rst_in_valid_load_en ? counter8__rst_in_vld : __counter8__rst_in_valid_reg;
      __counter8__count_out_reg <= counter8__count_out_load_en ? next_state : __counter8__count_out_reg;
      __counter8__count_out_valid_reg <= counter8__count_out_valid_load_en ? p0_all_active_inputs_valid : __counter8__count_out_valid_reg;
    end
  end
  assign counter8__count_out = __counter8__count_out_reg;
  assign counter8__count_out_vld = __counter8__count_out_valid_reg;
  assign counter8__clk_in_rdy = counter8__clk_in_load_en;
  assign counter8__rst_in_rdy = counter8__rst_in_load_en;
endmodule

これ。。
カウンターにはなってますが、
ここまで読みにくいVerilogコードが作成されてしまいます。
Settingがどこかにあるのでしょうが、
この設計ソフトを使うことにメリットあるのでしょうか?

最後

一旦、xlsで設計するのは止めます。
→conter8.xを数度、書き直しましたがダメでした。
これ以上は止めます。
組み合わせ回路の設計に使用するなら、メリットがあると思います。

いいなと思ったら応援しよう!