![]() |
1 |
BSV(Bluespec SystemVerilog) (4) |
![]() |
モジュールインタフェースの引出し
Vivadoにより合成をかける場合に、前稿のモジュールmkFibOneのように出力の信号が無いと、何もしないものとみなされ最適化され、全てのロジックが削除されてしまいます。従って、mkFibOneモジュールに、計算した値を出力するインタフェースを設ける修正を行います。合わせて、テストベンチ記述がモジュール内に混入されていたものを、テストベンチに移します。
BSVではモジュールとインタフェースは明確に分離されています。修正したファイル(ファイル名FibOne.bsv)を示します。前述のように\$displayや\$finishはテストベンチへ移しました。
モジュールファイル:FibOne.bsv
interface Fib_ifc; method int read(); endinterface (* synthesize, always_ready, always_enabled *) module mkFibOne(Fib_ifc); Reg#(int) this_fib <- mkReg(0); Reg#(int) next_fib <- mkReg(1); rule fib; this_fib <= next_fib; next_fib <= this_fib + next_fib; // note that this uses stale this_fib endrule: fib method int read(); return this_fib; endmethod endmodule: mkFibOne
ここで、
Reg#(int) this_fib <- mkReg(0);
これは前稿で2行になっていたレジスタのインスタンシエーションの省略記法で、
Interface_type identifier <- module_name;
という文法を持ちます。この意味は、「Interface_typeの型を持つインタフェースを提供するモジュールmodule_nameをインスタンス化し、インタフェースのハンドルidentifierを取得する」ということです。
Verilogの生成
BSVプログラムに対して、bscによりverilog生成を実行すれば、
\$ bsc -verilog FibOne.bsv
Verilog file created: mkFibOne.v
合成されたverilog(ファイル名mkFibOne.v)は以下のようになります。
モジュールファイル:mkFibOne.v
// // Generated by Bluespec Compiler (build 38534dc) // // On Wed Mar 25 09:12:14 JST 2020 // // // Ports: // Name I/O size props // read O 32 reg // CLK I 1 clock // RST_N I 1 reset // // No combinational paths from inputs to outputs // // `ifdef BSV_ASSIGNMENT_DELAY `else `define BSV_ASSIGNMENT_DELAY `endif `ifdef BSV_POSITIVE_RESET `define BSV_RESET_VALUE 1'b1 `define BSV_RESET_EDGE posedge `else `define BSV_RESET_VALUE 1'b0 `define BSV_RESET_EDGE negedge `endif module mkFibOne(CLK, RST_N, read); input CLK; input RST_N; // value method read output [31 : 0] read; // signals for module outputs wire [31 : 0] read; // register next_fib reg [31 : 0] next_fib; wire [31 : 0] next_fib$D_IN; wire next_fib$EN; // register this_fib reg [31 : 0] this_fib; wire [31 : 0] this_fib$D_IN; wire this_fib$EN; // value method read assign read = this_fib ; // register next_fib assign next_fib$D_IN = this_fib + next_fib ; assign next_fib$EN = 1'd1 ; // register this_fib assign this_fib$D_IN = next_fib ; assign this_fib$EN = 1'd1 ; // handling of inlined registers always@(posedge CLK) begin if (RST_N == `BSV_RESET_VALUE) begin next_fib <= `BSV_ASSIGNMENT_DELAY 32'd1; this_fib <= `BSV_ASSIGNMENT_DELAY 32'd0; end else begin if (next_fib$EN) next_fib <= `BSV_ASSIGNMENT_DELAY next_fib$D_IN; if (this_fib$EN) this_fib <= `BSV_ASSIGNMENT_DELAY this_fib$D_IN; end end // synopsys translate_off `ifdef BSV_NO_INITIAL_BLOCKS `else // not BSV_NO_INITIAL_BLOCKS initial begin next_fib = 32'hAAAAAAAA; this_fib = 32'hAAAAAAAA; end `endif // BSV_NO_INITIAL_BLOCKS // synopsys translate_on endmodule // mkFibOne
テストベンチ
修正したVerilogテストベンチtbmkFibOne.vを以下に示します。前稿ではクロックとリセットを下位モジュールに供給するだけだったのを、データ表示とシミュレーションの停止機能をモジュールから移動しています。
テストベンチファイル:tbmkFibOne.v
`timescale 1ns/1ps module tb_mkFibOne; /*AUTOREGINPUT*/ // Beginning of automatic reg inputs (for undeclared instantiated-module inputs) reg CLK; // To mkFibOne of mkFibOne.v reg RST_N; // To mkFibOne of mkFibOne.v // End of automatics /*AUTOWIRE*/ // Beginning of automatic wires (for undeclared instantiated-module outputs) wire [31:0] read; // From mkFibOne of mkFibOne.v // End of automatics mkFibOne mkFibOne (/*AUTOINST*/ // Outputs .read (read[31:0]), // Inputs .CLK (CLK), .RST_N (RST_N)); initial begin RST_N = 1'b0; #30; RST_N = 1'b1; forever begin if (CLK) $display("%0d", read); if (read > 10000) $finish; #10; end end initial begin CLK = 1'b0; forever begin #5 CLK = ~CLK; end end initial begin $dumpfile("tbmkFibOne.vcd"); $dumpvars(0,mkFibOne); end endmodule
Verilogシミュレーション
準備ができたので、iverilogによるverilogシミュレーションを実行します。
\$ iverilog tbmkFibOne.v mkFibOne.v -o mkFibOne.exev
\$ ./mkFibOne.exev
VCD info: dumpfile tbmkFibOne.vcd opened for output.
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
前稿と同様の結果になりました。
Vivadoによるシミュレーション
VivadoのIPインテグレータにより、生成されたverilogを取り込み、IPインテグレータ上で最上位のテストベンチを作成します。先に作成したテストベンチ(ファイル名tbmkFibOne.v)はシミュレーション用で合成できないため、IPインテグレータで上位を作成します。図の左からZynqのPS部、クロックリセット生成、対象回路となっています。

vivado上でbehaviorシミュレーションを実施した結果です。iverilogの結果と同一になっています。
