systemverilog的interface内的信号和clocking块内的信号区别与调度

参考文献1:Setup and Hold time and clocking block in system verilog
参考文献2:https://verificationguide.com/systemverilog/systemverilog-scheduling-semantics/
参考文献3:SystemVerilog Event Regions,Race Avoidance & Guidelines

interface内的clocking block用来进行信号的同步,具体说明如下:
Clocking blocks have been introduced in SystemVerilog to address the problem of specifying the timing and synchronisation requirements of a design in a testbench.

A clocking block is a set of signals synchronised on a particular clock. It basically separates the time related details from the structural, functional and procedural elements of a testbench. It helps the designer develop testbenches in terms of transactions and cycles. Clocking blocks can only be declared inside a module, interface or program.

先说结论:

  1. clocking块内的输入信号是对接口信号的采样,即clocking块内的信号是采样后的输出信号。如果input delay非0,则clocking内的采样后的信号和接口信号从仿真波形上看差1拍
  2. clocking块内的输出信号由testbench进行驱动,如果output delay非0,则clocking块内的输出信号延迟输出指定的delay时间后反应在接口的输出信号上,即二者在波形上为同一拍,但是存在output delay的延迟

即:

 1. The input will be sampled before #setup_time @posedge of CLK. 
 2. Output will be driven after #hold_time @posedge of CLK

setup和hold非零

仿真代码如下:

interface master_interface();
	logic pclk;
	logic prest_n;
	logic [31:0] pwdata;
	logic [31:0] prdata;
	
	clocking drv_cb @(posedge pclk);
		default input #1 output #1;
		output pwdata;
		input prdata;
	endclocking
	
	clocking mon_cb @(posedge pclk);
		default input #1 output #1;
		input pwdata;
		input prdata;
	endclocking
	
endinterface

module harness;
	logic clk;
	logic rst_n;
	logic [31:0] prdata;

	master_interface m_if();

	assign m_if.pclk = clk;
	assign m_if.prest_n = rst_n;
	assign m_if.prdata = prdata;

    always #5 clk = ~clk;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            prdata <= 32'h5a5a_5a5a;
        end else begin
            prdata <= ~prdata;
        end
    end

	initial begin
		clk = 'b0;
		rst_n = 'b0;
		#12;
		rst_n = 'b1;
	end

	initial begin
        repeat(1000) @(m_if.mon_cb);    
		$finish();
	end

	initial begin
        $display("@%0t: n0", $realtime);
        @(posedge rst_n);
        $display("@%0t: n2", $realtime);
        repeat (100) begin
            repeat(1) @(m_if.drv_cb);    
            m_if.drv_cb.pwdata <= 32'h5555_5555;
            $display("@%0t: pwdata = 32'h5555_5555", $realtime);
            repeat(1) @(m_if.drv_cb);    
            m_if.drv_cb.pwdata <= 32'haaaa_aaaa;
            $display("@%0t: pwdata = 32'haaaa_aaaa", $realtime);
        end
	end

	initial begin
		$fsdbDumpfile("wave.fsdb");
		$fsdbDumpvars;
	end
endmodule

仿真脚本如下:

comp:
	@vcs \
	-full64 \
	-kdb -lca \
	-sverilog \
	-debug_access+all \
	+libext+.sv+.v \
	-timescale=1ns/1ps \
	-l cmp.log \
	*.sv

run:
	@./simv \
 	+fsdb+delta \
 	-l simv.log	

all:
	@make clean && make comp && make run

verdi:
	@verdi -ssf wave.fsdb &

clean:
	@rm -rf simv* csrc ucli* vc_hdrs.h

仿真波形:

systemverilog的interface内的信号和clocking块内的信号区别与调度_第1张图片

setup和hold全零

systemverilog的interface内的信号和clocking块内的信号区别与调度_第2张图片

可以看到在monitor的clocking块内部,采到pwdata(drv_cb中的输出信号)为上一拍的值,而prdata(drv_cb中的输入信号)为当前拍的值。

打开region mode和event sequence,显示如下:
systemverilog的interface内的信号和clocking块内的信号区别与调度_第3张图片
事件的调度如下:
systemverilog的interface内的信号和clocking块内的信号区别与调度_第4张图片
从上面仿真波形可以看出,在NBA region,非阻塞赋值被调度,/harness/m_if/prdata[31:0]变为0xa5a5_a5a5,在Active(1)region,更新/harness/m_if/mon_cb/prdata[31:0],变为0xa5a5_a5a5,因此波形上看到的mon_cb内的prdata的值为0xa5a5_a5a5.

而mon_cb内的pwdata在Active(1)region更新为0xaaaa_aaaa。

你可能感兴趣的:(Design,Verification,systemverilog,interface,delta,cycle,clocking,block)