FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

自作RISC-VコアをYosysで合成する試行 (1. 部品の合成試行)

f:id:msyksphinz:20220103010108p:plain

なんとなくYosysの使い方が分かってきたので、自作RISC-Vコアが合成できるのか試行してみようと思う。

まずは単純な部品から。以下のデザインが合成できるか確認してみる。

  • bus_or.sv
module bit_or
  #(
    parameter WIDTH = 32,
    parameter WORDS = 4
  )
(
  input logic [WIDTH-1:0]  i_data[WORDS],
  output logic [WIDTH-1:0] o_selected
);
  /* verilator lint_off UNOPTFLAT */
  logic [WIDTH-1:0] w_selected_array[WORDS];
  assign w_selected_array[0] = i_data[0];
  generate for (genvar i = 1; i < WORDS; i++) begin : loop
    assign w_selected_array[i] = w_selected_array[i-1] | i_data[i];
  end
  endgenerate
  assign o_selected = w_selected_array[WORDS-1];

endmodule

これを合成するために以下のスクリプトを作成した。

  • synth.ys
read_verilog -sv ../src/bit_or.sv
hierarchy -top bit_or

proc
opt
techmap
opt
write_verilog bit_extract_lsb.synth.v
yosys synth.ys
-- Executing script file `synth.ys' --

1. Executing Verilog-2005 frontend: ../src/bit_or.sv
Parsing SystemVerilog input from `../src/bit_or.sv' to AST representation.
../src/bit_or.sv:7: ERROR: syntax error, unexpected '[', expecting ',' or '=' or ')'

エラーが出た。SystemVerilogでサポートされていない文法があるらしい...以下にGitHub Issueが上がっていた。

github.com

仕方がないので、別のデザインを試してみる。

  • bit_extract_lsb.sv
/*
 * Extract bit from LSB
 * 1010001100101000
 * -->
 * 0000000000001000
 */
module bit_extract_lsb
  #(
    parameter WIDTH = 32
    )
(
 input logic [WIDTH-1:0]  in,
 output logic [WIDTH-1:0] out
 );

if (WIDTH == 1) begin
  assign out = in;
end else begin
  logic [WIDTH-1:0]         tree;
  bit_tree_lsb #(.WIDTH(WIDTH)) u_bit_tree (.in(in), .out(tree));
  assign out = tree ^ {tree[WIDTH-2:0], 1'b0};
end

endmodule // bit_extract_lsb
  • bit_tree_lsb.sv
module bit_tree_lsb
  #(
    parameter WIDTH = 32
    )
(
 input logic [WIDTH-1:0]  in,
 output logic [WIDTH-1:0] out
 );

localparam red_loop = $clog2(WIDTH);

/* verilator lint_off UNOPTFLAT */
logic [WIDTH-1:0]           in_shift_array[red_loop+1];

assign in_shift_array[0] = in;
generate for (genvar i = 1; i <= red_loop; i++) begin : bit_ff_loop
  assign in_shift_array[i] = in_shift_array[i-1] | (in_shift_array[i-1] << (1 << (i-1)));
end
endgenerate

assign out = in_shift_array[red_loop];

endmodule // bit_tree_lsb

以下のスクリプトを使った。

  • synth.ys
read -sv ../src/bit_extract_lsb.sv
read -sv ../src/bit_tree_lsb.sv
hierarchy -top bit_extract_lsb

proc
opt
techmap
opt
write_verilog bit_extract_lsb.synth.v

一応上手く行ったようだ。

module \$paramod\bit_tree_lsb\WIDTH=s32'00000000000000000000000000100000 (in, out);
  (* src = "../src/bit_tree_lsb.sv:12.27-12.29" *)
  input [31:0] in;
  wire [31:0] in;
  (* src = "../src/bit_tree_lsb.sv:19.29-19.43" *)
  wire [31:0] \in_shift_array[0] ;
  (* src = "../src/bit_tree_lsb.sv:19.29-19.43" *)
  wire [31:0] \in_shift_array[1] ;
  (* src = "../src/bit_tree_lsb.sv:19.29-19.43" *)
  wire [31:0] \in_shift_array[2] ;
/* ... 途中省略 ... */

module bit_extract_lsb(in, out);
  (* src = "../src/bit_extract_lsb.sv:19.29-19.33" *)
  wire [31:0] \genblk1.tree ;
  (* src = "../src/bit_extract_lsb.sv:12.27-12.29" *)
  input [31:0] in;
  wire [31:0] in;
  (* src = "../src/bit_extract_lsb.sv:13.27-13.30" *)
  output [31:0] out;
  wire [31:0] out;
  assign out[9] = \genblk1.tree [9] ^(* src = "../src/bit_extract_lsb.sv:21.16-21.46" *)  \genblk1.tree [8];
  assign out[10] = \genblk1.tree [10] ^(* src = "../src/bit_extract_lsb.sv:21.16-21.46" *)  \genblk1.tree [9];
/* ... 途中省略 ...*/
  \$paramod\bit_tree_lsb\WIDTH=s32'00000000000000000000000000100000  \genblk1.u_bit_tree  (
    .in(in),
    .out(\genblk1.tree )
  );
  assign out[0] = \genblk1.tree [0];