はじめに
Interfaceのmodportの機能を使用して回路を作成してみます。
バスのプロトコルは、validがHighのとき、スレーブに設定したアドレスとaddrが等しいときのdataが有効になります。
サンプルコード
tb.sv
テストベンチです。DUTをインスタンスしています。
クロック・リセット・入力データを生成しています。
module tb;
// クロックとリセットを生成
bit clk = 0;
bit rst_n = 0;
always #5 clk = ~clk;
initial begin
#10 rst_n = 1;
#200 $finish;
end
class data_gen;
randc bit [3:0] addr;
randc bit [3:0] din;
endclass
bit [3:0] addr;
bit [3:0] din;
data_gen a = new();
// 入力データを生成
always @(posedge clk) begin
a.randomize();
addr = a.addr;
din = a.din;
end
dut#(
.address0(1),
.address1(2)
) i_dut(
.clk(clk),
.rst_n(rst_n),
.addr(addr),
.din(din),
.dout0(),
.dout1()
);
endmodule
sample_if.sv
interfaceを定義します。modportでマスタとスレーブのポートを宣言します。
interface sample_if;
logic [3:0] addr;
logic [3:0] data;
logic valid;
modport master( // master側
input addr,
input data,
input valid
);
modport slave( // slave側
output addr,
output data,
output valid
);
endinterface
dut.sv
DUTのトップです。
module dut #(
parameter [3:0] address0 = '0,
parameter [3:0] address1 = '0
)(
input clk,
input rst_n,
input [3:0] addr,
input [3:0] din,
output logic [3:0] dout0,
output logic [3:0] dout1
);
sample_if dut_if(); // Interfaceをインスタンス
master i_master(
.clk(clk),
.rst_n(rst_n),
.addr(addr),
.din(din),
.master(dut_if.master) // sample_ifのmasterポートを接続
);
slave #(
.address(address0)
) i_slave_0(
.clk(clk),
.rst_n(rst_n),
.dout(dout0),
.slave(dut_if.slave) // sample_ifのslaveポートを接続
);
slave #(
.address(address1)
) i_slave_1(
.clk(clk),
.rst_n(rst_n),
.dout(dout1),
.slave(dut_if.slave) // sample_ifのslaveポートを接続
);
endmodule
master.sv
マスタです。テストベンチから入力されたデータをスレーブに与えます。
module master(
input clk,
input rst_n,
input [3:0] addr,
input [3:0] din,
sample_if.master master
);
assign master.valid = '1;
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
master.addr <= '0;
master.data <= '0;
end
else begin
master.addr <= addr;
master.data <= din;
end
end
endmodule
slave.sv
スレーブです。parameterのaddressがaddrと等しいときdataが有効となります。
module slave #(
parameter address = 0
)(
input clk,
input rst_n,
output logic [3:0] dout,
sample_if.slave slave
);
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
dout <= '0;
end
else begin
if (slave.valid & (slave.addr == address)) begin
dout <= slave.data;
end
end
end
endmodule
実行結果
slave0のアドレスは1、slave1のアドレスは2に設定しています。
addrが1のとき、dinの値がdout0から出力されています。
addrが2のとき、dinの値がdout1から出力されています。
コメント