SystemVerilog included a range of new features intended to improve verification productivity and the most significant are probably:
- Object Oriented programming
- Constrained randomsation
Functional verification in simulation is entirely a software problem, so by including classes the verification community acquired all of the productivity gains of traditional OO programming (although from ~10 years ago - the lack of reflection and limits of introspection mean that libraries written in SystemVerilog like UVM are massively dependent on the pre-processor rather than the language itself).
By adding constrained randomisation, the language enforces compliant simulators must provide a constrains solver. This allows the testspace to be defined by a set of rules and the simulator to generate test sequences. A classic analogy would be Sudoku, by defining the problem in terms of constrains the simulator can solve the problem rather than the verification engineer having to think of stimulus to exercise the DUT. Typically this makes it possible to hit corner cases that might have been missed with directed testing.
Another improvement in SystemVerilog was the DPI layer, which makes it easier to interface to external languages.
SystemC is a slightly different beast - it can be used for modelling, interfacing to other languages, high-level synthesis etc.
You asked for a comparison of code; I use Python for verification so I don't have any good System[C|Verilog] examples, but Python is an OOP and therefore this example might be useful.
From a testbench I created of the OpenCores JPEG encoder:
def compare(i1, i2):
"""
Compare the similarity of two images
From http://rosettacode.org/wiki/Percentage_difference_between_images
"""
assert i1.mode == i2.mode, "Different kinds of images."
assert i1.size == i2.size, "Different sizes."
pairs = izip(i1.getdata(), i2.getdata())
dif = sum(abs(c1-c2) for p1,p2 in pairs for c1,c2 in zip(p1,p2))
ncomponents = i1.size[0] * i1.size[1] * 3
return (dif / 255.0 * 100) / ncomponents
@cocotb.coroutine
def process_image(dut, filename="", debug=False, threshold=0.22):
"""Run an image file through the jpeg encoder and compare the result"""
cocotb.fork(Clock(dut.clk, 100).start())
driver = ImageDriver(dut)
monitor = JpegMonitor(dut)
stimulus = Image.open(filename)
yield driver.send(stimulus)
output = yield monitor.wait_for_recv()
if debug: output.save(filename + "_process.jpg")
difference = compare(stimulus, output)
dut.log.info("Compressed image differs to original by %f%%" % (difference))
if difference > threshold:
raise TestFailure("Resulting image file was too different (%f > %f)" %
(difference, threshold))
You can see that the use of a structured testbench and OOP makes this code very understandable and quick to create. There was a pure verilog testbench for this block and although it doesn't have the same level of functionality the comparison is still interesting.
The answer I've got (thanks to user3467290) :
There is a very important difference between these forms.
In the first, the register value will be generated, using all defined constraints, + the constraint you wrote in this action (field1 == 1). The new generated value will be written to the DUT.
In the second code, what you state is that you want to modify only one field of the register - field1. What will happen is that vr_ad will get the current value of the register from the e model (the shadow model), change field1 - and will write the new value the the register in the DUT. None of the other register's fields will be changed. Also - there is no check that the value you assign to field1 complies with the constraints defined on this register.
Best Answer
A test vector is a sting of bits that are used to represent the state of the system or an input stimulus to the system. If you registers are tied together on a scan chain then this long string of 1's and 0's can be used to exercise the system at different states.
Block level is typically more complete and explores all or most of the corner cases for rigourous coverage. The system level may not be able to put each block into all of the blocks possible cases. The system level will need to be less complex and have less coverage.