Why does my sim with a clock never finish? - simulation

I added a clock generator to my module, and now the simulation never finishes.
always #10 clk = ~clk;
Why does the sim not finish after all initial code is done?
module test;
reg clk;
initial begin
clk = 0;
$display("Hello");
end
always #10 clk = ~clk;
endmodule
Sim results on EDA Playground: http://www.edaplayground.com/s/4/15

When you're using an always block, you need to have $finish statement in one of your initial blocks to finish the sim.
Fixed code:
module test;
reg clk;
initial begin
clk = 0;
$display("Hello");
$finish(); // <-- FIX
end
always #10 clk = ~clk;
endmodule
Sim results here: http://www.edaplayground.com/s/4/16
That said, if you also have a SystemVerilog program in your environment, the sim will automatically finish after all the initial code in your program blocks is done. From section 24.3 of IEEE 1800-2012 standard:
When all initial procedures within a program have reached their end,
that program shall immediately terminate all descendent threads of
initial procedures within that program. If there is at least one
initial procedure within at least one program block, the entire
simulation shall terminate by means of an implicit call to the $finish
system task immediately after all the threads and all their descendent
threads originating from all initial procedures within all programs
have ended.

There's no fundamental difference between initial and always: always is just initial forever. As long as anything is scheduled for future execution, then the simulation will continue (unless it is explicitly stopped); your statement continuously re-schedules the clock assignment, so the sim never stops. There really is nothing special about initial: it's not even guaranteed to run before any always blocks.
This wasn't an SV question (which I know nothing about), but I was interested to see VL's comment about automatically finishing the sim when the initial code is finished. This would break Verilog compatibility, and I'd be interested to see an LRM reference that confirms this.

Related

event control "#" in systemverilog in uvm defined AFTER assignments

I'm trying to understand the UVM driver code defined in a "verificationguide.com" UVM env example : https://www.edaplayground.com/x/5r89
In the mem_driver.sv file, in the drive() task, the following code can be found :
if(req.wr_en) begin // write operation
DRIV_IF.wr_en <= req.wr_en;
DRIV_IF.wdata <= req.wdata;
#(posedge vif.DRIVER.clk);
end
How is the event control #(posedge vif.DRIVER.clk); line written AFTER the events being controlled?
Help me understand the intent of the developer in this case?
It's there to make sure wr_en is held active for at least one clock cycle before the next requested transaction. Otherwise the next transaction would immediately set it back to 0.

How to use System-Verilog Assertions on modules within top level DUT

I'm trying to write a memory scheduling testbench and to verify that I am accessing the correct addresses and writing the correct values at the right time I want to compare what is going on with the signals inside my top module with my schedule that I developed.
I've tried looking up "dot notation" and using my simulator (ModelSim) to access the signal (which I can do on the waveform fine) but I want to be able to use SVAs to check I have the correct values.
module top(input d, output q)
//wires
wire sub1_output
// Instantiate submodule
sub_module1 sub1(.sub1_output(sub1_output));
always begin
// logic
end
endmodule
module tb_top();
reg d;
wire q;
DUT top(.*);
initial begin
// This is where I want to access something within my DUT
assert(DUT.sub1_output == 1'b1)
end
endmodule
When I try this my code compiles and runs, but if I write the assertion such that it should fail and stop my code, nothing happens.
DUT.sub1_output
Is the correct format to use assertions on signals within top level instantiations.

System verilog:: Static Variable non-blocking Assignent outside program-block?

I'm new to system verilog and i'm stuck with a basic concept, kindly provide rationale behind the following behavior:
In System verilog, Why Static class properties declared in other than program-block scope cannot be assigned with blocking assignment from program block?
2.Why is that, even if static variable is assigned with non-blocking statement, the change in that static variable is no visible ($display) immediately, it is available after a delay of say #1.
Example:
class A ;
static int i;
endclass
program main ;
A obj;
initial
begin
obj.i = 123; // Not Allowed, can only be done using <= ... WHY ??
$display(obj.i);
#1 $display(obj.i);
end
endprogram
There is no such rule in the IEEE 1800-2012 LRM Earlier version of SystemVerilog had more restrictions on the types of assignments allowed, but those have all been removed. I do not recommend that anyone use program blocks anymore. There are a big source of unnecessary confusion. See http://go.mentor.com/programblocks
The purpose of "program" block in SystemVerilog is to guarantee that there will not be any race condition between the testbench and the DUT if the user encloses his testbench in program block(s) and keeps the DUT outside of program block(s). Another way to avoid race conditions is implemented by limiting DUT/testbench interaction to interfaces/clocking blocks. Also note that:
a) blocking assignments (since they are executed immediately and therefor the result of the execution can vary with the order of execution of threads) can lead to race conditions
b) hardware (RTL) variables can only be static
Given the whole scenario, the compiler makes out that the blocking statement could lead to a race condition between the DUT and the testbench. And hence the error.
When you use non-blocking assignment, the assignment is scheduled and not executed immediately. It would get executed once the scheduler gets a chance to execute it. And that would happen only after the present thread yields because of a blocking expression that involves time increment. In the given code snippet that happens once the executing thread encounters #1; the $display after #1 sees the result of the non-blocking assignment while the one before does not.

System Verilog Clocking block

I am trying to perform a simple test with demo code of Clocking block, but encountered the error.
The code could be find at "EDA playground" http://www.edaplayground.com/x/3Ga
And the error says:
** Error: testbench.sv(38): A default clocking block must be specified to use the ##n timing statement.
** Error: testbench.sv(40): A default clocking block must be specified to use the ##n timing statement.
I think the clocking block has already been specified in the code.
Any Help?
As the error message says, you have to define the clocking block as default:
default clocking cb_counter #(posedge Clock);
Full code here: http://www.edaplayground.com/x/37_
The SV 2012 standard specifies that the ##n operator can only be used if there is a default clocking block defined for the module/program/interface, otherwise it wouldn't be able to know what clock event to use for the delay.
##N delays are not a very useful feature unless you can put them in the same module or interface that the clocking block is defined in. That is typically not the case because you usually put your driver code inside a class inside a package.
repeat (N) #cb_counter;
This works uniformly, even if referencing the cb through a virtual interface.
To resolve the error add default clocking cb_counter; after your clocking block.
SystemVerilog IEEE1800-2012 Section 14 Covers Clocking Blocks.
// Test program
program test_counter;
// SystemVerilog "clocking block"
// Clocking outputs are DUT inputs and vice versa
clocking cb_counter #(posedge Clock);
default input #1step output #4;
output negedge Reset;
output Enable, Load, UpDn, Data;
input Q;
endclocking
default clocking cb_counter; //<-- Set default clocking
// Apply the test stimulus
initial begin
//..
Below I have included a my method of creating a testbench clock, with the initial it is easy to work out when it will be triggered, compared to the original always the time for the first trigger my vary depending on how when the Clk is initialised.
initial begin
Clk = 0;
forever begin
#5ns Clk = ~Clk;
end
end
If you simulator allows system-verilog, I would use #5ns so that it does not rely on the timestep, I find this to more readable and reliable for code reuse.
The version from the question, used an always block.
timeunit 1ns;
// Clock generator
always
begin
#5 Clock = 1;
#5 Clock = 0;
end

Must use non-blocking assignment in a procedural block in System Verilog?

I've met a situation where I think I have to use blocking assignment in a #(posedge clk) block. The snippet below is from a tsetbench. I want to input the data to a DUT through the testbench. input_intf is the name of an interface and wcb is a clocking block synchronizing to wclk.
#(posedge input_intf.wclk)
begin
input_intf.winc = 1;
input_intf.wcb.wdata = 8'd7;
input_intf.winc = 0;
end
I want to do the following: after the positive clock edge, inc=1 and data reading is enabled. After data is read, let inc=0. I guess maybe winc signal has no need to be synchronous with wclk? If it's the case then the snippet should be like following.
input_intf.winc = 1;
#(posedge input_intf.wclk)
input_intf.wcb.wdata <= 8'd7;
input_intf.winc = 0;
So is it true that we must use non-blocking assignment in a procedural block? When learning Verilog, I was told it's true.
Thanks!
The statement input_intf.wcb.wdata = 8'd7; is illegal. You do not use blocking or non-blocking assignments to drive clocking block outputs. See 14.16.1 Drives and non-blocking assignments in the IEEE Std 1800-2012 LRM. For other non-clocking block variables inside your interface, you use the same rules that you learned with Verilog: use non-blocking assignments to write to variables that are synchronous to a clock, and will be read by other procedural blocks on the same clock edge. That is how you avoid races.
The use of clocking blocks is generally an all or nothing approach. you should not be mixing writing to clocking block and non-clocking variables in the same procedure, and you should only be using the clocking block event to synchronize your code.
#(input_intf.wcb) // do not use posedge of any signal here.
input_intf.wcb.wdata <= 8'd7;
There are exceptions to these rules, of course, but I would make sure you know exactly how clocking blocks work before going there.