なんとなく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が上がっていた。
仕方がないので、別のデザインを試してみる。
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];