2016-11-17 5 views
0

EDIT:私は以下の方法を試してみました:ロジックの代わりにワイヤにインターフェイスを設定し、ドライバのZを制御から放棄したい他の運転者が引き継ぐことができるように信号を送る。 u_slave_dutが私のインターフェースから駆動されていないのが分かるので、まだ動作しません。何が間違っているかの手がかりは?私の動作例:https://www.edaplayground.com/x/4SSP私のインターフェイスタスクから私のモジュールの内部ワイヤを動かす

いくつかのサブモジュールを持つトップレベルモジュール用のテストベンチを作成しています。インターフェイスをインスタンス化し、サブモジュールの1つに接続したいとします。my_submodule簡単に、私はmy_submoduleピンがトグルされたときに私のインターフェイスピンがトグルするのを見ることができます。これは大きな見通しです。

次に、タスクを使用して自分のインターフェイスからピンを自分自身に切り替えることができると決めました。私はこれが同じバス上の2人のドライバーにつながることを理解しています。だから私にこれをさせる方法はありますか?

edaplaygroundの小さなサンプルを実験用に作成しました。ここで私のタスクからの私の書き込みから実際にu_slave_dutのピンを切り替えることはありません。また、コンパイラからも私には気になる警告は出ません。

私の作業例はここにある:https://www.edaplayground.com/x/5fcP

testbench.sv

`include "my_interface.sv" 

module tb; 

    bit clk = 1'b1; 
    bit control = 1'b0; 

    initial begin 
    forever begin 
     #5 clk = ~clk; 
    end 
    end 

    my_interface my_vif(clk); 

    assign my_vif.addr = (control)? tb.u_top.u_slave_dut.i_addr : 'hz; 
    assign my_vif.wdata = (control)? tb.u_top.u_slave_dut.i_wdata : 'hz; 
    assign my_vif.write = (control)? tb.u_top.u_slave_dut.i_write : 'hz; 

    top u_top(.clk(clk)); 

    initial begin 
    #80 my_vif.master_write_something; 
    #160 $finish; 
    end 

    initial begin 
    $dumpfile("dump.vcd"); 
    $dumpvars(0); 
    end 
endmodule 

interface.sv

interface my_interface(input clk); 
    logic [3:0] addr; 
    logic  write; 
    logic [3:0] wdata; 
    logic [3:0] rdata; 
    logic  resp; 

    clocking master_cb @(posedge clk); 
    input resp, rdata; 
    output addr, write, wdata; 
    endclocking 

    clocking slave_cb @(posedge clk); 
    input addr, write, wdata; 
    output resp, rdata; 
    endclocking 

    task master_write_something; 
    @(master_cb); 
    master_cb.write <= 1'b1; 
    @(master_cb); 
    master_cb.wdata <= 3'b101; 
    master_cb.addr <= 3'b111; 
    @(master_cb); 
    master_cb.write <= 1'b0; 
    endtask 

    task slave_write_something; 
    @(slave_cb); 
    slave_cb.resp <= 1'b1; 
    @(slave_cb); 
    slave_cb.rdata <= 3'b101; 
    @(slave_cb); 
    slave_cb.resp <= 1'b0; 
    slave_cb.rdata <= 3'b000; 
    endtask 

endinterface 

design.sv

module slave_dut (
    input clk, 
    input [3:0] i_addr, 
    input [3:0] i_wdata, 
    input  i_write, 
    output  o_resp, 
    output [3:0] o_rdata 
); 

    reg  o_resp_reg; 
    reg [3:0] o_rdata_reg; 

    initial begin 
    o_resp_reg <= 1'b0; 
    o_rdata_reg <= 'h0; 
    end 

    always @(posedge clk) begin 
    if (i_write == 1'b1) begin 
     o_resp_reg <= 1'b1; 
     o_rdata_reg <= i_wdata; 
    end 
    else begin 
     o_resp_reg <= 1'b0; 
     o_rdata_reg <= 'h0; 
    end 
    end 

    assign o_resp = o_resp_reg; 
    assign o_rdata = o_rdata_reg; 

endmodule : slave_dut 

module master_dut (
    input clk, 
    output [3:0] o_addr, 
    output [3:0] o_wdata, 
    output  o_write, 
    input  i_resp, 
    input [3:0] i_rdata 
); 

    reg [3:0] o_addr_reg; 
    reg [3:0] o_wdata_reg; 
    reg  o_write_reg; 

    initial begin 
    o_addr_reg <= 'h0; 
    o_wdata_reg <= 'h0; 
    o_write_reg <= 'h0; 
    repeat (2) @(posedge clk); 
    o_addr_reg <= 'hF; 
    o_wdata_reg <= 'hB; 
    o_write_reg <= 1'b1; 
    @(posedge clk); 
    o_addr_reg <= 'h0; 
    o_wdata_reg <= 'h0; 
    o_write_reg <= 'h0; 
    repeat (2) @(posedge clk); 
    o_addr_reg <= 'h4; 
    o_wdata_reg <= 'hD; 
    o_write_reg <= 1'b1; 
    @(posedge clk); 
    o_addr_reg <= 'h0; 
    o_wdata_reg <= 'h0; 
    o_write_reg <= 'h0; 
    end 

    assign o_addr = o_addr_reg; 
    assign o_wdata = o_wdata_reg; 
    assign o_write = o_write_reg; 

endmodule : master_dut 

module top(input clk); 
    wire [3:0] addr; 
    wire [3:0] wdata; 
    wire  write; 
    wire  resp; 
    wire [3:0] rdata; 

    master_dut u_master_dut (
    .clk(clk), 
    .o_addr(addr), 
    .o_wdata(wdata), 
    .o_write(write), 
    .i_resp(resp), 
    .i_rdata(rdata) 
); 

    slave_dut u_slave_dut (
    .clk(clk), 
    .i_addr(addr), 
    .i_wdata(wdata), 
    .i_write(write), 
    .o_resp(resp), 
    .o_rdata(rdata) 
); 

endmodule 

どこが間違っているのですか?

答えて

1

私はあなたがシミュレータを実行するために選択した1つのシミュレータが警告またはエラーを出さないと思います。他のどのシミュレータでも、クロッキングブロックの手続き割当と連続割当をミックスすることに関するエラーが正しく表示されます。

2つの異なる場所から同じ信号を駆動する場合は、変数の代わりにワイヤを使用して対処する必要があります。また、ドライバの1つを高インピーダンス('z)に設定して、他のドライバが信号を制御できるようにする必要があります。これは、2つのドライバがデザイン内にあるか、デザインとテストベンチのどちらであるかにかかわらず、実行する必要があります。私は数年前にDVCon paperと書いてこれについて詳しく説明しています。

+0

ご回答ありがとうございます。私はその論文を読み、私が理解したことを実装しようとしました:(1)私は論理の代わりにワイヤーにインターフェイスを変更しました。 (2)私はu_master_dutで 'hZ'に信号を送りました。私はまだ、my_interfaceからu_slave_dutの入力を駆動することができないようです。私はここで何が欠けていますか?私はまた、2つの他の質問があります:(3)私は私のインターフェイスでワイヤを駆動する手続き割り当てを使用しています。これはどのように許可されますか? (4)私はu_master_dutの私の例で行ったように、内部ドライバから内部ドライバをアクセスして 'hZ'に設定することはできません。 https://www.edaplayground.com/x/2Y6x – noobuntu

+0

(2)あなたが逃したものを知るために、更新されたコードを見る必要があります。 (3)手順の割り当てではなく、クロッキングがワイヤをブロックすることになります。私の論文とLRMをチェックしてください(4)あなたは 'force/release'を使う必要があります –

+0

https://www.edaplayground.com/x/2Y6x – noobuntu

0

Daveは説明したように、一度に1人のドライバのみがネットを駆動できるようにすることで、マルチドライバネットを制御する唯一の方法です。また、ハードウェアの観点からも、一度に1つのドライバですべてのワイヤを駆動する必要があります。

これは、regを追加することによって、デザインで達成できます。

次のコードを参照してください。

module tb; 

    bit clk = 1'b1; 
    reg control = 1'b1; 

    initial begin 
    forever begin 
     #5 clk = ~clk; 
    end 
    end 

    my_interface my_vif(clk); 

    assign my_vif.addr = (control)? tb.u_top.u_slave_dut.i_addr : 'hz; 
    assign my_vif.wdata = (control)? tb.u_top.u_slave_dut.i_wdata : 'hz; 
    assign my_vif.write = (control)? tb.u_top.u_slave_dut.i_write : 'hz; 

    top u_top(.clk(clk)); 

    initial begin 
    #80 my_vif.master_write_something (control); 
    #160 $finish; 
    end 

    initial begin 
    $dumpfile("dump.vcd"); 
    $dumpvars(0); 
    end 


endmodule 

// Interface Task  
task master_write_something (ref reg x); 
    @(master_cb); 
    x = 1'b0; 
    master_cb.write <= 1'b1; 
    @(master_cb); 
    master_cb.wdata <= 3'b101; 
    master_cb.addr <= 3'b111; 
    @(master_cb); 
    master_cb.write <= 1'b0; 
endtask 

ダンプファイルは次のとおりです。

enter image description here

+0

私はあなたが言ったことを試して、それは動作しませんでした..上記の私の編集と実際の例を確認してください。 – noobuntu

+0

'1'b1'で' control'を初期化します(あなたの例では、 '1'b0'で初期化されます)。この場合、control = 1'b0で、タスクは '@(master_cb)シグナル(そのタスクからの制御信号を管理できます)を待つので、waveには1つのZ状態があります。しかしそれ以外は動作します –

+0

'control = 1'b0'を初期化すると、インターフェイス信号が最初に 'hZ'に設定されます。次に、私はインターフェイスから運転したいときに、 'control = 1'b1'をセットし、' master_write_something'を呼び出します。いずれにしても、私は 'control = 1'b1'を設定する方法を試みましたが、うまくいきませんでした。あなたは私の例を実行していますか?可能であれば私に波を見せてもらえますか? – noobuntu

関連する問題