我正在尝试为相位累加器创建一个uvm类型的测试平台,它将用于DDS链中。对于一个简单的阶段累加器来说,这样做可能有点过分,但是我对uvm/SystemVerilog还不熟悉,所以我想学习如何使用这些概念。我有几个问题。
我的杜特:
module phase_acc #(
parameter PHASE_ACC_WIDTH = 16,
parameter TUNNING_WORD_WIDTH = 8
) (
input wire clk,
input wire reset,
input wire load,
input wire [TUNNING_WORD_WIDTH-1 : 0] tuning_word,
output reg [PHASE_ACC_WIDTH-1 : 0] phase,
output wire cycle_end,
output wire [1:0] phase_quadrant
);
assign phase_quadrant = phase[PHASE_ACC_WIDTH-1:PHASE_ACC_WIDTH-2];
assign cycle_end = (phase + tuning_word) > {PHASE_ACC_WIDTH{1'b1}};
always @(clk) begin
if (reset == 1) begin
phase <= 0;
end else begin
phase <= phase + tuning_word;
end
end
endmodule
请注意,这是不完整的,并计划填写后,编写测试。
基本功能是phase_acc一次由tuning_word计数。在包装之前,它需要断言cycle_end。暂时忘掉phase_quadrant吧。
可以通过断言加载来加载新的tuning_word。
我创建了两个类来监视信号。一个用于输入刺激(tuning_word和load),当加载时触发的是时钟转换期间的一个。另一种是用于包含相位( cycle_end )的cycle_end输出。由于这些变化在每个时钟转换,需要创建这种类型的新对象在每个时钟边缘。监视器使用两个分析端口发送刺激包,并将数据包输出到记分板。
我的第一个问题是,这个设计有意义吗?我看到的大多数uvm示例都有一种行为,在创建刺激后,DUT给出一个输出,然后对其进行验证。(例如RAM )。然而,在我的例子中,DUT是免费运行的。
如果上面的设计是正确的,我还有第二个问题。
我的显示器代码是:
class monitor extends uvm_monitor;
`uvm_component_utils(monitor)
function new(string name = "monitor", uvm_component parent = null);
super.new(name, parent);
endfunction
uvm_analysis_port #(acc_stimulus) mon_stimulus_analysis_port;
uvm_analysis_port #(acc_output) mon_output_analysis_port;
virtual reg_if vif;
semaphore sema4;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual acc_if)::get(this, "", "acc_if", vif))
`uvm_fatal("MON", "Could not get vif")
sema4 = new(1);
mon_stimulus_analysis_port = new("mon_stimulus_analysis_port", this);
mon_output_analysis_port = new("mon_output_analysis_port", this);
endfunction
virtual task run_phase(uvm_phase phase);
super.run_phase(phase);
forever begin
fork
begin
@(vif.clk);
// output
acc_output out = new;
out.phase = vif.phase;
out.cycle_end = vif.cycle_end;
out.phase_quadrant = cif.phase_quadrant;
`uvm_info(get_type_name(), $sformatf("Monitor found ouout %s", out.convert2str()),
UVM_LOW)
mon_output_analysis_port.write(out);
end
begin
@(vif.clk);
// stimulus
if (vif.ld) begin
acc_stimulus stimulus = new;
stimulus.tunning_word = vif.tuning_word;
stimulus.load = vif.ld;
`uvm_info(get_type_name(), $sformatf("Monitor found stimulus %s",
stimulus.convert2str()), UVM_LOW)
mon_stimulus_analysis_port.write(stimulus);
end
end
join
end
endtask
endclass
但是,当我试图编译它时,我得到了一个错误的行,它说:
acc_output out = new;
我不知道我在那里做错了什么。例如,如果我要在if
条件下这样做:
begin
@(vif.clk);
if(vif.clk) begin
// output
acc_output out = new;
然后错误就消失了。
我不明白密码有什么问题。
发布于 2022-08-20 02:03:41
您得到了错误,因为在语句之后,您在一个out
块的中间声明了begin/end
变量:
begin
@(vif.clk); // This is a statement
// output
acc_output out = new; // This is a variable declaration
在begin/end
块中,必须在语句之前声明所有变量。
当您在if
子句中声明变量时,错误就消失了,因为它是begin
关键字之后的第一行代码。事实上,这是在一个if
条件下是无关的。关键是使用begin
关键字创建了一个新的代码块。
这也应该是可行的:
begin
// output
acc_output out = new;
@(vif.clk);
https://stackoverflow.com/questions/73424639
复制相似问题