jeudi 27 février 2014

Systemverilog bind versus PSL vunit

Systemverilog bind is used to instantiate a module into another without having to modify the original code. It is an “out of scope” instanciation. Since this creates a new instance, the bound unit has its own scope, and its internal signal names do not have to match the ones from the target module. The new module communicates with the target through its pins (or with OOMR - Out Of Module Reference).

PSL vunit in opposition, is almost like an `include statement which is added externally to the target module. Similarly the latter does not have to be edited. Like an `include, a vunit does not create its own scope. Hence, the signals inside the vunit have to match the ones of the target module.

Delayed Blocking versus Non-Blocking Assignments

​Hi,
A question that I am often asked is how to write a simple delayed buffer model in verilog, especially when considering its behavior regarding input glitches.
There are several possible coding styles: blocking versus non-block assignments, and delayed evaluation versus delayed assignment.
Here is a little testcase presenting the effect of the 4 possible combinations of code. You will see that the most "natural" behavior is obtained from the third style, using Blocking and delayed assignment.
regards
- Regis

​module tb;
reg in = 1'b0;
initial begin
  #10 in <= 1;
  #10 in <= 0;
  #10 in <= 1;
  #3  in <= 0;
  #3  in <= 1;
  #9  in <= 0;
  #10 $finish;
end
reg o1 = 1'b0;
reg o2 = 1'b0;
reg o3 = 1'b0;
reg o4 = 1'b0;
always @(in) #5 o1  = in; // Blocking,     delayed evaluation (wait 5ns, then evaluate and assign immediately)
always @(in) #5 o2 <= in; // Non-Blocking, delayed evaluation (wait 5ns, then evaluate, then 
always @(in) o3  = #5 in; // Blocking,      delayed assignment
always @(in) o4 <= #5 in; // Non-Blocking,  delayed assignment

//              10   15    20         30  33  36   41   45    50
//              +----------+          +---+   +---------+
// in __________|          |__________|   |___|         |__________
//                   +----------+                   +---------+
// o1 _______________|          |___________________|         |_____
//                   +----------+                   +---------+
// o2 _______________|          |___________________|         |_____
//                                           35
//                   +----------+            +----------------+
// o3 _______________|          |____________|                |_____
//                   +----------+          +---+   +---------+
// o4 _______________|          |__________|   |___|         |__________
endmodule

Using UVM field access policy to manage bit bashing test

Hi,

If you're using UVM Register Layer, you might be interested by the predefined Test Sequences that are provided. I'm going to talk specifically about the uvm_reg_bit_bash_seq sequence. 
It is a bit-bashing test : it sequentially writes "1" dans "0" in each bit of all the registers, checking it is appropriately set or cleared, based on the field access policy.
The UVM 1.1 User Guide explains that the following attributes can be used on a register to skip it from the bit bashing test: NO_REG_BIT_BASH_TEST, NO_REG_TESTS
Unfortunately, these attributes act at register level, and not at field level, which would be useful to exclude individual fields or bits like a soft reset (to prevent the chip shutdown during the test).

Guess what ? In fact you can (exclude inividual fields/bits from the bit bashing). You just have to give your bits/fields the WO (write only) attribute. The test will not attempt to write to it because it has no means to read the written value back (write only means no read).

It is now extremely easy to prevent the soft reset to be triggered by the bit bashing test.

Note: you can also use these other filed attributes: WOC, WOS, WO1.

A few words about assertions, coverpoints and Verification Plan

Hi,
It might not be crystal clear how to use assertions and coverpoints, having in mind that these metrics are meant to be bound to a Verification Plan.​
Let's take an example. We have a 8 bit register in the design (a counter or whatever): 
  • We want to make sure each time the register value changes, it is as expected. somehwere in the bench you'd calculate the expected value, and an assertion would make sure expected and actual values always match.
  • But how do you know if all possible values of your register were actually verified ?
    • Bad idea: create one assertion per possible value. Any non-triggered assertion would tell you what was not covered. But of course 8 bits would need you to create 256 assertions... And what if N is 32 bits or more ???
    • Better: create a coverpoint that will give you an exhaustive status of the values that have actually been those of you register. In parallel a single "equation based" assertion would be enough.
  • You would then bind both the assertion and the coverpoint to yout vPlan.
Hope this helps,

regards

- regis

lundi 24 juin 2013

Re-usable Continuous-time analog systemverilog assertions

Hey, you can check-out my latest paper @CDN Live EMEA 2013 here:

This paper shows how SystemVerilog Assertions (SVA) modules can be bound to analog IP blocks, shall they be at behavioral or transistor-level, enabling the assertions to become a true IP deliverable that can be reused at SoC level. It also highlights how DPIs can fix analog assertions specificities, such as getting rid of hierarchical paths, especially when probing currents. This paper also demonstrates how to flawlessly switch models between digital (wreal) and analog models without breaking the assertions. Finally, it demonstrates how one can generate an adaptive clock to continuously assert analog properties whose stability over time is critical, such as current or voltage references or supplies.

mardi 4 décembre 2012

Basic Transaction Level Modeling (TLM) concept

1- Traditional Port-Based connection

 
Example of a possible (handshake) protocol implementation between a stimulus and a driver. 
  • A driver is connected to a DUT (Design Under Test)
  • It reads the data to send to the DUT from a stimulus block.
  • As soon as the driver tells it is ready (not busy anymore), the stimulus provides a new data together with a "data valid" signal.
  • The driver reacts on this valid signal and:
    • raises its "busy" flag
    • sends the data to the DUT based on whatever protocol (SPI, I2C, etc...)

                 module stimulus                                 module driver
+-------------------------------+            +---------------------------------+
|                               |   busy     | always @(posedge valid)         |
|  always @(negedge busy)       |<-----------| begin                           |
|  begin                        |            |   busy <= 1;                    |
|   data <= $random;            |            |   send_to_dut(data);            |
|   valid <= 1;                 |    data    |   busy <= 0;                    |
|  end                          |----------->| end                             |
|  always @(posedge busy)       |    valid   | task send_to_dut(input [7:0] d);|
|    valid <= 0;                |----------->|   <consume time>                |
|                               |            | endtask                         |
+-------------------------------+            +---------------------------------+

  • Advantages:   
    • very natural approach for designers
    • Each module can be designed independently
    • Signal names don't need to match port names
    • Any receiver that understands the producer (stimulus) interface can be connected 
  • Disadvantages:
    • very-low (signal) level of connection scheme
    • No easy scaling/re-use

2- Task-Based connection

The idea is to call from the stimulus tasks embedded in the driver.     
 
            module stimulus                           module driver
+-----------------------------------------+ +----------------------------------+
|                                         | | task send_to_dut(input [7:0] d)  |
|                                         | | begin                            |
| always @(posedge clk)                   | |   busy <= 1;                     |
|   if (driver_instance.is_busy() == 0)   | |     <consume time>               |
|   begin                                 | |   busy <= 0;                     |
|     data <= $random;                    | | endtask                          |
|     driver_instance.send_to_dut(data);  | |                                  |
|   end                                   | | function is_busy();              |
|                                         | |   return busy;                   |
|                                         | | endfunction                      |
+-----------------------------------------+ +----------------------------------+
  • Advantages:
    • Higher-level. No need to dive into signal complexity.
  • Disadvantages:
    • Tasks are called hierarchically 
    • Hence the code is not re-usable (will need to be edited if the driver instance name changes, i.e. in another project)


3- Transaction Level Modeling (TLM)

  • Instead of calling a task embedded in the driver, our stimulus now uses an instance of a "(non-blocking) put port". This "put port" provides a "put" method (task) with no actual implementation (just its declaration). It can be called from the "put port", but its implementation is somwhere else...
  • Symetrically, the driver uses an instance of the complement of a "port" called an "import". It is this "import" that actually details the implementation of the "put" method.
  • TLM Terminology:
    • Port: allows the stimulus to call a task implemented somewhere else.
    • Import: allows the driver to provide the implementation of the method (task).
  • OVM or UVM give port and import implementations and mechanisms to connect them together.
+------------------------------------+      +-----------------------------------+
| class stimulus extends ...         |      | class driver extends ...          |
| uvm_blocking_put_port #(byte) p;   |      | uvm_blocking_put_import #(byte) p;
|
|   ...                              |_     |   ...                             |
| p.put(data);  -------------------->|_|-->O|                                   |
|                                    |      | task put(byted);                  |
|                                    |      |   <consume time>                  |
|                                    |      | endtask                           |
+------------------------------------+      +-----------------------------------+
  • Disadvantages:
    • Class-based coding required
    • Not straightforward (software oriented) testbench for HW engineers
  • Advantages:
    • High-level. No signal detail
    • Task-based
    • Tasks are not hierarchically fixed
    • Re-usable code
    • Faster simulation


Additional TLM Terminology:

  •  Producer: component generating the data to exchange (the transacation) = transmitter
  • Consumer: component that receives the transaction = receiver
  • Initiator: component which initiates the communication = master
  • Target: component that responds to the initiator = slave

mercredi 27 juillet 2011

Understanding SystemVerilog Assertions (SVA)

  1. Definition. An assertion is basically a piece of code that is continuoiusly monitoring and checking, a functionality of the SoC. It is not triggered by the stimuli being applied to the SoC, but only by the SoC response to the stimuli. As such, an assertion can be written in usual verilog or even verilog-A/AMS (for example using an always statement).
  2. SystemVerilog Assertions (SVA). SystemVerilog provides a set of concise syntax constructs that makes assertion coding much simpler (hence less error-prone) than in traditional HDLs. SVA are split into two categories : immediate assertions and concurrent assertions.
  3. Immediate assertions. An immediate assertion is evaluated at the instant it is called. It is basically similar to an "if" statement. The difference being that its result (pass or fail) is recorded in the coverage results created by the simulator.
  4. Concurrent assertions. Concurrent assertions check SoC behaviors that span over time. The expected behavior can be represented by usual combinarotial boolean equations. But SystemVerilog provides higher-level constructs : sequences and properties.
  5. Sequences. A sequence is basically a time-organized list of boolean expressions. The sequence is true if all the successive expressions are true. The time is discrete and depends on a clock. A clock can be any eexpression that becomes true, or the start or end of execution of a named block, a task, a function or a class method. Several sequences can be made successive. Several new operators are used to describe sequence: the "cycle delay" noted ##,  the "same-cycle implication" noted |->, the "next-cycle implication" noted |=>, the "consecutive repetition" noted [*, the "non-consecutive repetition" noted [=, and the "goto repetinio" noted [->. Some system functions such as $rose(), $fell(), $stable(), $past() are also available to access sampled values of an expression.