EDIT: Я опробовал методы, упомянутые ниже: я установил свой интерфейс для проводов вместо логики, и я управляю «Z» от драйвера, который хочет отказаться от управления сигнал, чтобы другой драйвер мог взять верх. Все еще не работает, поскольку я вижу, что u_slave_dut не выводится из моего интерфейса. Какие-нибудь подсказки о том, что не так? Мой рабочий пример: https://www.edaplayground.com/x/4SSPВождение внутреннего провода в моем модуле из моей задачи интерфейса
Я пишу testbench для модуля верхнего уровня, который имеет несколько подмодулей. Я хочу создать экземпляр интерфейса и подключить его к одному из моих подмодулей, скажем 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) Я изменил свой интерфейс на провода вместо логики. (2) Я повел сигналы в «hZ» в u_master_dut. Кажется, я все еще не могу управлять входами u_slave_dut из my_interface. Что мне здесь не хватает? У меня также есть еще 2 вопроса: (3) Я использую процедурное задание для подключения провода в моем интерфейсе. Как это разрешено? (4) У меня не будет доступа к внутреннему драйверу изнутри, чтобы установить его на «hZ, как я сделал в своем примере в u_master_dut. https://www.edaplayground.com/x/2Y6x – noobuntu
(2) Мне нужно будет увидеть обновленный код, чтобы узнать, что вы пропустили. (3) вы делаете приводы блоков синхронизации в провод, а не процедурные назначения. проверьте мою бумагу и LRM (4), вам может потребоваться использовать «force/release» –
https://www.edaplayground.com/x/2Y6x – noobuntu