I have an SV assertion which checks the property as below
propert my_property;
#(posedge clk) disable iff(reset) $rose(halt) ##0 ((rx_prio) > (expec_prio)) ##[0:$] $rose(rdy) |-> ##[1:100] (my_prio[rx_prio]==1'b1);
endproperty:my_property
I have the assertion as below:
MY_PROPERTY_CHECK:assert property (my_propert)
else
$error;
Here, the scenario is that, the antecedent is true and the consequent is checked between 1 & 100 clock cycles. After the antecedent, the clock is stopped due to clock gating for some time and then the clock starts ticking again. The signal my_prio[rx_prio] is asserted after the clock gating but again within 100 clock cycles. But I still get the assertion failure.
Not able to figure out the issue of failure. Does the clock gating in between the assertion check has an issue? Or any other reason failure?
Thanks.
There might be many threads starting. Try using local variables with display statements below. See IEEE Std 1800-2012 § 16.10 Local variables
propert my_property;
static int prop_cnt=0; // shared
local int prop_id; // Note: some require the "local", other need it omitted
#(posedge clk) disable iff(reset)
($rose(halt) ##0 ((rx_prio) > (expec_prio)),
prop_id=prop_cnt++,
$display("Spawn prop_id:%0d prop_cnt:%0d # %0t %m",
prop_id,prop_cnt,$time) )
##[0:$] ($rose(rdy),
$display("Trigger prop_id:%0d prop_cnt:%0d # %0t %m",
prop_id,prop_cnt,$time) )
|-> ##[1:100] (my_prio[rx_prio]==1'b1,
$display("Pass prop_id:%0d prop_cnt:%0d # %0t %m",
prop_id,prop_cnt,$time) );
endproperty : my_property
If you see Spawn-Spawn-Trigger, or Spawn-Trigger-Trigger, our anything outside of expected (i.e. Spawn-Triger-Pass) then there are unexpected threads.
If this is the case, then look into IEEE Std 1800-2012 § 16.9.8 First_match operation
first_match(
$rose(halt) ##0 ((rx_prio) > (expec_prio)) ##[0:$] $rose(rdy),
$display("Spawn-Trigger prop_id:%0d prop_cnt:%0d # %0t %m",
prop_id,prop_cnt,$time)
) |-> // ...
OR § 16.9.10 Sequence contained within another sequence
(
( $rose(halt) ##0 ((rx_prio) > (expec_prio)) ) within $rose(rdy)[->1],
$display("Spawn-Trigger prop_id:%0d prop_cnt:%0d # %0t %m",
prop_id,prop_cnt,$time)
) |-> // ...
You might want to create a sequence for the trigger.
As I don't know your setup, I could assume that you are maybe triggering on a clock further up the hierarchy that is not being gated, but you debug waves in the exact hierarchy where the clock is being gated.
If you are writing your assertions for an RTL block that cannot be retrofitted with assertions (it's VHDL/Verilog or you are not allowed to touch the file), use bind to instantiate your assertions inside that block: http://www.asic-world.com/systemverilog/assertions22.html
Related
Following is a assertion property. When o_dc_mode = 1 then o_mod_c_c == rego_dc_c_c. As you can see from the waveform, once the ASK_MOD_DC_MODE_PROPERTY hits the scenario, it stays at "finished" state never goes to inactive state even though o_dc_mode = 0.
property ASK_MOD_DC_MODE;
#(posedge OSC64MHZ)
o_dc_mode |-> (o_mod_c_c == rego_dc_c_c);
endproperty
ASK_MOD_DC_MODE_PROPERTY: assert property (ASK_MOD_DC_MODE)
$info("Assertion ASK_MOD_DC_MODE passed");
else
$error("Assertion ASK_MOD_DC_MODE failed");
As you know that in concurrent assertion, the simulator has a performance optimization that disables the evaluation of a single cycle assertion on the cycles where the assertion state is same as in the previous cycle.
For the example in the question:
property ASK_MOD_DC_MODE;
#(posedge OSC64MHZ)
o_dc_mode |-> ( (o_mod_a_c == rego_dc_a_c) && (o_mod_b_c == rego_dc_b_c) && (o_mod_c_c == rego_dc_c_c));
endproperty
ASK_MOD_DC_MODE_PROPERTY: assert property (ASK_MOD_DC_MODE)
$info("Assertion ASK_MOD_DC_MODE passed");
else
$error("Assertion ASK_MOD_DC_MODE failed");
In the above assertion, as soon as the simulator hits the property, it will update the finish_count = 1 (Fig.1) and never updates the state (also the finish_count) unless there is a failure.
This optimization can be turned off by using the compilation option ”-abvevalnochange “. You can see the effect in the Fig.2.
How do I access internal regs/signals without declaring them as input/output.
e.g., consider the following block, A & B are placed in TOP block and I need to access int_A from withing block B without declaring it as output in A and input in B.
You can do that by hierarchical reference.
However as far as I know you can only use that in test-benches.(I have never even dared to use that in RTL).
// Top level test-bench
wire int_A;
assign int_A = dut_0.int_A;
dut dut_0 ( // instance of dut
....
);
If inside the dut you have another instance use the same method:
module dut (
);
core core0 (
);
endmodule // dut
A signal inside the core can now be referenced from the top level as:
assign int_A = dut_0.core_0.int_A;
I have designed a module (A) in Verilog and I need to instantiate it four times in a top module. The two modules communicate with each other and some other modules. 'A' sends out some signals which the other instantiation of 'A' should accept. The signals are sent through an interface or a bus. I do not want to complicate the design by incorporating any standard bus protocols. I have created an inout port to avoid having the same type of ports for input as well as output.
Is there any way to assign an id or a code to every instantiation, so that every instantiation checks for that id and accepts the signals coming from a different ID than itself. Right now without the id or a standard bus protocol, the modules are accepting their own signals too which is not supposed to happen.
Here ways you can do this:
Add an ID input port When this port is tided to a constant, at power-up the device can detect its ID. Technically you could do dynamic ID with this, but usually you just connect the port to a constant value. This is the most flexible option, especially if you want your end product to be used as a configurable component.module A ( /* your_ports */, input [1:0] ID );
/* ... code ... */
endmodule
module top;
A inst0 ( .ID(2'd0), .* );
A inst1 ( .ID(2'd1), .* );
A inst2 ( .ID(2'd2), .* );
A inst3 ( .ID(2'd3), .* );
endmodule
Create an ID parameter Simulate to the ID input port except that the value is hard coded and the instance knows the ID value at compile time, before simulation or device power-up. Unique parameter values generate unique modules. If the ID is 0, it will be physically different than an ID with 1. module A #(parameter ID) ( /* your_ports */ );
/* ... code ... */
endmodule
module top;
A #( .ID(0) ) inst0 ( .* );
A #( .ID(1) ) inst1 ( .* );
A #( .ID(2) ) inst2 ( .* );
A #( .ID(3) ) inst3 ( .* );
endmodule
Why don't you set a parameter for each module and use it as an ID? Then set the parameter uniquely for each instance:
module A;
parameter ID = 0; //default value
case (ID)
0: //specific code for ID0
1: //specific code for ID1
2: //specific code for ID2
3: //specific code for ID3
endcase
endmodule
And your top module:
module top;
A #(.ID(0)) inst_0 (...);
A #(.ID(1)) inst_1 (...);
A #(.ID(2)) inst_2 (...);
A #(.ID(3)) inst_3 (...);
endmodule
A couple of other useful points:
You may want to check generate block or vectorized/array module instantiation, which allow you instantiate an array of modules.
Also, notice that in general, each module can see the entire hierarchy. Inside each module, you can access signals using a hierarchical expression:
module A;
reg s;
....
initial $display("The initial value of signal s in instance A_2 is:", top.inst_2.s);
endmodule
Beware though this is not recommended since your module description would be specific to your hierarchy.
I have some data from a 1 bit serial port which comes in multiples of bytes of variant lengths as such:
byte expected_1 [$] = {8'hBA, 8'hDD, 8'hC0, 8'hDE};
byte expected_2 [$] = {8'h01, 8'h23, 8'h45, 8'h67, 8'h89, 8'hAB, 8'hCD, 8'hEF};
At each positive clock edge, one bit is sent. I need to testbench hundereds of sequences ( maybe thousand in the future ) so I want to automate the process with assertions in system verilog. The new 2012 standard allows for queues to be passed to properties, but can the queues be sent though a recursive property? I received some error about hierarchical ref.
This is what I have so far (with help from #Greg here):
default clocking sck #(posedge sck); endclocking : sck
sequence seq_serial(logic signal, logic [7:0] expected); // check each bit
byte idx = 7;
(signal == expected[idx], idx--)[*8];
endsequence : seq_serial
property recurring_queue(bit en, logic data, byte data_e [$])
int queue_size = data_e.size;
logic [7:0] expected = data_e.pop_front();
if(queue_size != 0) (
!en throughout (seq_serial(data, expected) ##1 recurring_queue(en, data, data_e))
);
endproperty : recurring_queue
`define ez_assert(exp)
assert property (recurring_queue(en, data, exp))
else $error("Bad Sequence # time: %t. Info: %m", $time);
Calling the assertion in my testbench should be as easy as this:
A1 : `ez_assert(expected_1);
The error messages read:
1) passing hierarchical ref to be used in another hierarchical ref is not supported
2) Illegal SVA property in RHS of'##' expression
3) Local variable queue_size referenced in expression before getting initialized
I'm open to other ideas for asserting long variable-length serial sequences.
Try the same strategy as seq_serial:
sequence seq_queue_pattern(bit en, logic data, byte expt_queue [$]);
int qidx = 0;
( !en throughout (seq_serial(data,expt_queue[qidx]), qidx++)[*] )
##1 (qidx==expt_queue.size);
endsequence : seq_queue_pattern
asrt_expected_1 : assert property ( $fell(en) |-> seq_queue_pattern(en,data,expected_1));
asrt_expected_2 : assert property ( $fell(en) |-> seq_queue_pattern(en,data,expected_2));
This assertion will fail if en is high or the seq_serial chain does not match expected. Do not that parenthicy location matters:
en is don't care one clock after final seq_serial completes:
( !en throughout (seq_serial(data,expt_queue[qidx]), qidx++)[*] ) ##1 (qidx==expt_queue.size)
en must be low one clock after final seq_serial completes or failes and don't care after that
!en throughout ( (seq_serial(data,expt_queue[qidx]), qidx++)[*] ##1
(qidx==expt_queue.size) )
en must be low one clock after final seq_serial completes and don't care after that
!en throughout ( (seq_serial(data,expt_queue[qidx]), qidx++)[*] ##1
(qidx==expt_queue.size) ) ##1 (qidx==expt_queue.size)
Queues within sequences and properties are new and may not be fully supported by all simulators yet. To work around this limitation, use a parametrized macro to create a sequence for each expected queue stream:
`define asrt_qpat(en,monitor, expt_queue) \
sequence seq_queue_pattern__``expt_queue (bit en, logic data); \
int qidx = 0; \
(!en throughout (seq_serial(data,expt_queue[qidx]), qidx++)[*]) \
##1 (qidx==expt_queue.size); \
endsequence : seq_queue_pattern__``expt_queue \
\
asrt_``expt_queue : assert property( #(posedge clk) \
$fell(en) |=> seq_queue_pattern__``expt_queue (en,monitor) ) \
else $error("Bad Sequence # time: %t. Info: %m", $time);
`asrt_qpat(en,data[0],expected_1)
`asrt_qpat(en,data[1],expected_2)
I have tried looking for the answer to this, but to no avail. I am getting problems when I re-synthesise my code and I suspect that it is due to clock issues.
I am using a DCM to multiply an external crystal oscillator from 25MHz to 50MHz. However, I think that the tool won't know what frequency the crystal oscillator actually is, since it is an external physical component. My code is below:
//since our crystal oscillator is only 25Mhz, we use a DCM to multiply it by two since the desired is 50Mhz
DCM #(
.CLKFX_DIVIDE (2),
.CLKFX_MULTIPLY (4)
) dcm_master (
.CLKFB (CLK_FB),
.CLKIN (CLK_crystal),
.RST (DcmReset),
.CLK0 (MasterClk0Unbuf),
.CLK90 (),
.CLK180 (),
.CLK270 (),
.CLK2X (),
.CLK2X180 (),
.CLKFX (MasterClkFxUnBuf),
.CLKFX180 (),
.CLKDV (),
.LOCKED (DcmLocked),
.STATUS (),
.PSCLK (1'b0),
.PSEN (1'b0),
.PSINCDEC (1'b0),
.PSDONE ()
);
//we provide feedback to the DCM's phase input (possibly not neccessary)
BUFG bufg_master_dcm_clk_0 ( .I(MasterClk0Unbuf), .O(CLK_FB) );
BUFG bufg_master_dcm_clk_fx ( .I(MasterClkFxUnBuf), .O(CLK_FX) );
//code taken from xilinx. We toggle using a bufgmux between the onboard and external clock
// BUFGMUX: Global Clock Buffer 2-to-1 MUX
// Spartan-3
// Xilinx HDL Libraries Guide, version 13.2
BUFGMUX BUFGMUX_inst (
.O(CLK), // Clock MUX output
.I0(CLK_FX), // Clock0 input
.I1(CLK_local), // Clock1 input
.S(sw[6]) // Clock select input
);
Will this code in the ucf force the tool to recognize the output of my DCM as 50MHz?
PIN "bufg_master_dcm_clk_fx.O" TNM_NET = CLK50;
TIMESPEC TS_CLKBuf = PERIOD "CLK50" 100 MHz HIGH 50%;
Furthermore, am I using the BUFG's correctly? Xilinx says I should use an IBUFG to connect the external clock into my DCM, and I am getting errors saying my BUFG's can only address half the chip (which I imagine is going to become troublesome).
thanks,
Nathan
I think your clock constraints are off. You should be constraining the input to the DCM -- the DCM knows what to do with the outputs. Here's what I would use:
NET clk_in TNM_NET = tnm_clk_in;
TIMESPEC TS_clk_in = PERIOD tnm_clk_in 40ns;
where clk_in is the crystal (CLK_crystal in your case). Make sure that the crystal is connected to a clock pin on your device.
I would have liked to test this out first. For the Spartan-3 family of FPGAs, using one of the DCMs. This is the template that ISE produces.
Notice that there is a dedicated CLK2X.
Also, based on the user manual: .CLKFB should be driven by a BUFG source.
wire i_FeedBack;
wire o_FeedBack;
BUFG clkFBBuf(
.I(i_FeedBack),
.O(o_FeedBack)
);
DCM #(
[...]
.CLKFX_DIVIDE(1), // Can be any integer from 1 to 32
.CLKFX_MULTIPLY(2), // Can be any integer from 2 to 32
[..]
) DCM_inst (
.CLK0(i_FeedBack), // 0 degree DCM CLK output
.CLK2X(CLK2X), // 2X DCM CLK output
[...]
.CLKFX(CLKFX), // DCM CLK synthesis out (M/D)
.CLKFB(o_FeedBack), // DCM clock feedback
.CLKIN(clk), // Clock input (from IBUFG, BUFG or DCM)
[...]
);