I have planned to write verification for dual port ram with assertions but when I try to bind the property below. I have not used any rd pins or rst pins I have take my dut from
module dpram_property(
input [7:0] data_a, data_b,
input [5:0] addr_a, addr_b,
input we_a, we_b, clk,
output [7:0] q_a,
output [7:0] q_b
);
property dp_ram_PORT_A_write;
@(posedge clk) if(!we_a) (q_a-8'b1)==$past(q_a);
endproperty
property dp_ram_PORT_B_write;
@(posedge clk) if(!we_b) (q_b-8'b1)==$past(q_b);
endproperty
initial
begin
#20;
assert property(dp_ram_PORT_A_write)
$display($stime,,,"\n\t\t DP_RAM PORT-A WRITE CHECK PASS USING $past q_a=%d q_a_past=%d\n",q_a,$past(q_a));
else
$display($stime,,,"\n\t\t DP_RAM PORT-A WRITE CHECK FAIL USING $past q_a=%d q_a_past=%d\n",q_a,$past(q_a));
#20;
assert property(dp_ram_PORT_A_write)
$display($stime,,,"\n\t\t DP_RAM PORT-A WRITE CHECK PASS USING $past q_a=%d q_a_past=%d\n",q_a,$past(q_a));
else
$display($stime,,,"\n\t\t DP_RAM PORT-A WRITE CHECK FAIL USING $past q_a=%d q_a_past=%d\n",q_a,$past(q_a));
#5120;
assert property(dp_ram_PORT_B_write)
$display($stime,,,"\n\t\t DP_RAM PORT-B WRITE CHECK PASS USING $past q_b=%d q_b_past=%d\n",q_b,$past(q_b));
else
$display($stime,,,"\n\t\t DP_RAM PORT-B WRITE CHECK FAIL USING $past q_b=%d q_b_past=%d\n",q_b,$past(q_b));
#20;
assert property(dp_ram_PORT_B_write)
$display($stime,,,"\n\t\t DP_RAM PORT-B WRITE CHECK PASS USING $past q_b=%d q_b_past=%d\n",q_b,$past(q_b));
else
$display($stime,,,"\n\t\t DP_RAM PORT-B WRITE CHECK FAIL USING $past q_b=%d q_b_past=%d\n",q_b,$past(q_b));
end
endmodule
verification Testbench:
`include "dpram_property.sv"
`include "dpram.sv"
module testbench();
logic clk,we_a, we_b ;
logic [5:0] addr_a;
logic [7:0] data_a;
logic [5:0] addr_b;
logic [7:0] data_b;
wire [7:0] q_a;
wire [7:0] q_b;
dpram u1(.clk(clk),.we_a(we_a),.we_b(we_b),.addr_a(addr_a),.addr_b(addr_b),.data_a(data_a),.data_b(data_b),.q_a(q_a),.q_b(q_b));
bind dpram dpram_property inst(.clk(clk),.we_a(we_a),.we_b(we_b),.addr_a(addr_a),.addr_b(addr_b),.data_a(data_a),.data_b(data_b),.q_a(q_a),.q_b(q_b));
covergroup cg;
option.per_instance=1;
type_option.merge_instances=1;
coverpoint q_a
{
bins range[256]={[0:255]};
bins b1=(0=>1);
bins b2=(1=>2);
}
coverpoint q_b
{
bins range[256]={[0:255]};
// Transaction bins
bins b1=(0=>1);
bins b2=(2=>3);
}
coverpoint addr_a
{
bins range[64]={[0:63]};
}
coverpoint addr_b
{
bins range[64]={[0:63]};
}
coverpoint we_a;
coverpoint we_b;
endgroup
cg cg_inst=new();
always@(posedge clk)
begin
cg_inst.sample();
end
initial
begin
clk=1'b1;
forever #5 clk=~clk;
end
initial
begin
we_a=1'b0;we_b=1'b0;;
for(int i=1; i<=64;i++)
begin
we_a=1'b1;
data_a<=i;
addr_a=i-1;
#10;we_a=1'b0;
addr_a=i-1;
#10;
end
for(int i=1; i<=64;i++)
begin
we_a=1'b1;
data_a<=i+64;
addr_a=i-1;
#10;we_a=1'b0;
addr_a=i-1;
#10;
end
for(int i=1; i<=64;i++)
begin
we_a=1'b1;
data_a<=i+127;
addr_a=i-1;
#10;we_a=1'b0;
addr_a=i-1;
#10;
end
for(int i=1; i<=64;i++)
begin
we_a=1'b1;
data_a<=i+191;
addr_a=i-1;
#10;we_a=1'b0;
addr_a=i-1;
#10;
end
#20;we_a=1'b0;
//port b writing and reading
for(int i=1; i<=64;i++)
begin
we_b=1'b1;
data_b=i;
addr_b=i-1;
#10;we_b=1'b0;
addr_b=i-1;
#10;
end
for(int i=1; i<=64;i++)
begin
we_b=1'b1;
data_b=i+63;
addr_b=i-1;
#10;we_b=1'b0;
addr_b=i-1;
#10;
end
for(int i=1; i<=64;i++)
begin
we_b=1'b1;
data_b=i+127;
addr_b=i-1;
#10;we_b=1'b0;
addr_b=i-1;
#10;
end
for(int i=1; i<=64;i++)
begin
we_b=1'b1;
data_b=i+191;
addr_b=i-1;
#10;we_b=1'b0;
addr_b=i-1;
#10;
end
#20;we_b=1'b0;
$finish;
end
always @(posedge clk)
begin
$display($stime,,,"clk=%b we_a=%b we_b=%b addr_a=%b data_a=%b addr_b=%b data_b=%b q_a=%d q_b=%d",clk,we_a, we_b,addr_a,data_a,addr_b,data_b,q_a, q_b);
end
endmodule
I got the following error:
dpram_property inst (.clk(clk), .we_a(we_a), .we_b(we_b), .addr_a(addr_a), .addr_b(addr_b), .data_a(data_a), .data_b(data_b), .q_a(q_a), .q_b(q_b));
|
ncelab: *E,ICDPAV (./INCA_libs/irun.lnx86.15.20.nc/.cdssvbind/cds_tmp_svbind_single_00000011_11ac6e15_1.sva,4|129): Illegal combination of driver and procedural assignment to variable q_a detected (procedural assignment found in always block at line 12 in file ./dpram.sv).
`line directed : file : ./testbench.sv, line : 14
dpram_property inst (.clk(clk), .we_a(we_a), .we_b(we_b), .addr_a(addr_a), .addr_b(addr_b), .data_a(data_a), .data_b(data_b), .q_a(q_a), .q_b(q_b));
|
ncelab: *E,ICDPAV
(./INCA_libs/irun.lnx86.15.20.nc/.cdssvbind/cds_tmp_svbind_single_00000011_11ac6e15_1.sva,4|140): Illegal combination of driver and procedural assignment to variable q_b detected (procedural assignment found in always block at line 26 in file ./dpram.sv).
`line directed : file : ./testbench.sv, line : 14
irun: *E,ELBERR: Error during elaboration (status 1), exiting.
I have also shared my code below what modifications should I do?
module dpram
(
input [7:0] data_a, data_b,
input [5:0] addr_a, addr_b,
input we_a, we_b, clk,
output reg [7:0] q_a, q_b
);
// Declare the RAM variable
reg [7:0] ram[63:0];
// Port A
always @ (posedge clk)
begin
if (we_a)
begin
ram[addr_a] <= data_a;
q_a <= data_a;
end
else
begin
q_a <= ram[addr_a];
end
end
// Port B
always @ (posedge clk)
begin
if (we_b)
begin
ram[addr_b] <= data_b;
q_b <= data_b;
end
else
begin
q_b <= ram[addr_b];
end
end
endmodule
You declare q_a
and q_b
as output
in the dpram_property
module. Change them to input
in that module:
module dpram_property (
input [7:0] data_a, data_b,
input [5:0] addr_a, addr_b,
input we_a, we_b, clk,
input[7:0] q_a, q_b
Inside your bound module (dpram_property
), you don't want to drive signals which are driven in the target module (dpram
) to avoid contention.
I posted your code on edaplayground, and there are no more compile errors on Cadence Incisive.
Cliff Cummings has a nice discussion on bind
in this paper: SystemVerilog Assertions Design Tricks and SVA Bind Files