Error (suppressible): (vlog-7061) always_ff with ModelSim

Hello I got these suprresible errors with Modelsim.

** Error (suppressible): (vlog-7061) /home/mhernandez/Documents/mmu/systemV/tags_data_memories.sv(29): Variable ‘data_mem’ driven in an always_ff block, may not be driven by any other process. See /home/mhernandez/Documents/mmu/systemV/tags_data_memories.sv(21).
– Compiling module dm_cache_tag
** Error (suppressible): (vlog-7061) /home/mhernandez/Documents/mmu/systemV/tags_data_memories.sv(57): Variable ‘tag_mem’ driven in an always_ff block, may not be driven by any other process. See /home/mhernandez/Documents/mmu/systemV/tags_data_memories.sv(50).

This is the code, the problem seems to be on the always_ff, if I change those for normal always then there is not an error, but I do need the always_ff correct?

//Cache: data memory, single port, 1024 blocks
import cache_def::*;

timeunit 1ns; timeprecision 1ps;

module dm_cache_data(clk,
                     data_req,
                     data_write,
                     data_read
                    );

input  bit clk;
input  cache_req_type data_req;     //data request
input  cache_data_type data_write;  //write port (128-bit line)
output cache_data_type data_read;   //read port

cache_data_type data_mem[0:1023];

initial begin
   for (int i = 0; i < 1024; i++)
        data_mem[i] = '0;
end

assign data_read = data_mem[data_req.index];

always_ff @(posedge(clk)) begin

 if (data_req.we)
     data_mem[data_req.index] <= data_write;
end
endmodule

//cache: tag memory, single port, 1024 blocks
module dm_cache_tag(
                    clk,
                    tag_req,
                    tag_write,
                    tag_read
                   );

input  bit clk;
input  cache_req_type tag_req;    //tag request
input  cache_tag_type tag_write;  //write port
output cache_tag_type tag_read;   //read port

cache_tag_type tag_mem[0:1023];

initial begin
    for(int i = 0; i<1024; i++)
    tag_mem[i] = '0;
end

assign tag_read = tag_mem[tag_req.index];

always_ff @(posedge (clk)) begin
    if(tag_req.we)
      tag_mem[tag_req.index] <= tag_write;
end

endmodule

In reply to Divingintheocean:
We don’t discuss vendors in this forum. However, your problem is a misue of 1800.
Specifically,

1800’2017: 9.2.2.4 Sequential logic always_ff procedure
The always_ff procedure imposes the restriction that it contains one and only one event control and no blocking timing controls. Variables on the left-hand side of assignments within an always_ff procedure, including variables from the contents of a called function, shall not be written to by any other process.

You have


initial begin
   for (int i = 0; i < 1024; i++)
        data_mem[i] = '0;  // <---- written HERE, the violation
end
 
assign data_read = data_mem[data_req.index];
 
always_ff @(posedge(clk)) begin
 
 if (data_req.we)
     data_mem[data_req.index] <= data_write;  // And written here
end 

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


See Paper: VF Horizons:PAPER: SVA Alternative for Complex Assertions - SystemVerilog - Verification Academy

You can use the always. You do not need the always_ff; synthesis will object to the initial statement.
Ben systemverilog.us

In reply to hdlcohen:

Ok thank you very much to both of you, Ben and Hdlcohen.

I will check all the links that Ben shared, actually I am using Questa from Mentor, we have the suit tool for our university.

An super scalar processor was done with Verilog and now I am writing that same core with System Verilog so I am checking code here and there to acquire that knowledge by practice so I can quickly implement this cpu. The other thing that I want to do is to do first verification with System Verilog and then using UVM. If you some extra links to reach my goal I will really appreciate.

Regarding the always_ff I already changed for always and it works! ;)
I was thinking what system verilog says, you have to use the always_ff module but I think there is not a problem if I use only always for my cpu synthesis.

Thank you again, all the best to you guys,

In reply to diving:
A few comments:

  1. The DUT should not have an initialblock; this is for the testbench.
  2. I strongly recommend that you use assertions in your design as that will reaffirm your understanding of the requirements, it is a tool used for reviews of the design and the requirements, and is a good debugging resource. My SVA Handbook explans SVA and provides many many examples along with guidelines; check the TOC.
  3. For quick and dirty verification code of assertions or small partition, i use the following code, which is stored as an abbreviation in my Download PhraseExpress from the official source (an excellent abbreviation tool)
    I modified the template accordingly

import uvm_pkg::*; `include "uvm_macros.svh"
module top;
timeunit 1ns;     timeprecision 100ps;
bit clk, a, b;
default clocking @(posedge clk); endclocking
initial forever #10 clk=!clk;
initial begin
$timeformat(-9, 1, "ns", 8);
$display("%t", $realtime);
end
always  @(posedge clk)  begin
end
// Assertions here
// Simple subpartiton instanced here
initial begin
bit va, vb;
repeat(200) begin
@(posedge clk);
if (!randomize(va, vb)  with
{ va dist {1'b1:=1, 1'b0:=3};
vb dist {1'b1:=1, 1'b0:=2};
}) `uvm_error("MYERR", "This is a randomize error")
a <= va;
b <= vb;
end
$stop;
end
endmodule    
  1. If you don’t want to use UVM and its library, then follow the UVM spirit by including the following: data_item, transaction, sequence, Below is a model and testbench for a very funky counter with weird (on purpose for demo of assertions).

package counter_pkg;
timeunit 1ns; timeprecision 100ps;
`define TOP counter_tb
typedef enum {CT_LOAD, CT_RESET, CT_WAIT, CT_DONE} ct_scen_e;
endpackage : counter_pkg
/**********************************************************************************/
// requirements:
// Loadable counter, reset to 0 if reset_n==0,
// Min count -2, Max count ==5
// This is an activity counter, thus count must change at least
// every 8 cycles
module counter_max #(MAX_COUNT=9, MIN_COUNT=2)( // parameter port list
input logic[3:0] data_in,
input logic ld,
output logic[3:0] counter,
input logic clk, rst_n) ;
int cover_count=0;
int fail_count=0;
// ap_P:  assert property(@ (posedge clk) P )
// parameter MIN_COUNT=2; // module item parameter
// If use of parameter port list, then can't use defparam
default disable iff !rst_n;
property p_load;
logic[3:0] v_data_in; // local variable to property
(ld, v_data_in=data_in) |=> counter==v_data_in;
endproperty : p_load
ap_load: assert property ( @(posedge clk) p_load);
ap_count: assert property(@(posedge clk)
!ld && (counter!=MAX_COUNT) |=> counter==$past(counter)+1'b1);
ap_hold: assert property(@(posedge clk)
counter==MAX_COUNT |=> counter==$past(counter));
ap_min_load: assume property(@(posedge clk) disable iff (!rst_n)
ld |-> not(data_in<MIN_COUNT));
ap_max_load: assume property(@ (posedge clk) disable iff(!rst_n)
ld |-> not(data_in > MAX_COUNT))
cover_count++; else fail_count++ ;
ap_statble8: assume property(@(posedge clk)
$stable(counter)|-> ##[1:8] !$stable(counter));
always_ff @(posedge clk) begin : counter1
if(!rst_n) counter <= 0;
else if (ld) counter <= data_in;
else begin : counter2
counter <= counter + 1'b1;
end : counter2
end : counter1
endmodule : counter_max
/**************************************************************/
import uvm_pkg::*; `include "uvm_macros.svh"
import counter_pkg::*;
class data_item;
rand logic[3:0] data;
endclass : data_item
class transaction extends data_item;
rand logic ld=0;
int reset_cycles, idle_cycles;
rand ct_scen_e kind;
// constraint values { ld dist {1'b0 := 80, 1'b1 := 20}; } // 0 80% of time
constraint data_range { data > 2 && data <=9; }
constraint cst_xact_kind {
kind dist {
CT_LOAD := 5,
CT_RESET := 2,
CT_WAIT := 97,
CT_DONE := 1
};
} // cst_xact_kind
endclass : transaction
class simple_random_sequence;
transaction tx=new();
// randomize
virtual task run();
if (!randomize(tx)) `uvm_error("COUNTER", "This is a randomize error")
// ap_rand_seq: assert(randomize(tx));
endtask : run
endclass : simple_random_sequence
module counter_max_tb_simple;
parameter MAX_COUNT_TB=6, MIN_COUNT_TB=3;
// defparam counter_max1.MIN_COUNT=3;
// illegal because have parameter port list
logic[3:0] data_in=0, data=0;
logic ld=0;
logic[3:0] counter, counter2;
logic clk=1'b1, rst_n=1'b1;
simple_random_sequence seq=new();
counter_max #(.MAX_COUNT(MAX_COUNT_TB),
.MIN_COUNT(MIN_COUNT_TB)) counter_max1(.*);
// counter_max counter_max2(.counter(counter2), .*);
initial forever #10 clk=!clk;
// test using simple_random_sequence
always @ (negedge clk) begin : random1
rst_n <= 1'b1; ld <=1'b0;
repeat(3) @ (negedge clk) rst_n <= 1'b0;
repeat(3) @ (negedge clk)rst_n <= 1'b1;
// dada and load
for (int i=0; i<100; i++) begin : for1
@ (negedge clk);
seq.run();
case (seq.tx.kind)
CT_LOAD : begin
load_task(seq.tx.data);
end
CT_RESET : begin
reset_task();
end
CT_WAIT : begin
idle_task(seq.tx.data);
end
CT_DONE : begin
done_task();
end // seq.tx.idle_cycles);
endcase
// @ (negedge clk);
end : for1
$display("End of test");
$finish;
end : random1
// load counter
task load_task(int data);
data_in <= data;
ld <= 1'b1;
@ (negedge clk)ld <= 1'b0;
endtask : load_task
// reset
task reset_task();
ld <= 1'b0;
repeat(1) rst_n <= 1'b0;
@ (negedge clk)rst_n <= 1'b1;
endtask : reset_task
// IDLE
task idle_task(int data);// for now, make idle for 4 cycles
automatic logic[3:0] v=data;
for (int i=0; i<4; i++) begin
ld <= 1'b0;
if (!randomize(v)) `uvm_error("COUNTER", "This is a randomize error")
// assert(randomize(v));
data_in <= v;
@ (negedge clk);
end
endtask : idle_task
// DONE, for now, a do nothing
task done_task();
@ (negedge clk);
endtask : done_task
endmodule : counter_max_tb_simple
//compilation_command_multiple_files counter_pkg.sv counter_max.sv counter_max_tb_simple.sv
//simulation_command counter_max_tb_simple

  1. Above code has “flavors” or “styles” of UVM, but is not UVM; however, the use of classes and style allows you to easily migrate to UVM.

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


See Paper: VF Horizons:PAPER: SVA Alternative for Complex Assertions | Verification Academy

In reply to ben@SystemVerilog.us:

Hey Ben, thank you, I am still finishing an UART to do verification first with SV and then with OVM.

I will follow all your comments, thank you very much,

I already saw your book: Real Chip Design and Verification, sounds very interesting, thank you,

Mario Tonanboo

In reply to ben@SystemVerilog.us:

In reply to diving:
A few comments:
The DUT should not have an initialblock; this is for the testbench.

Hi Ben. FPGA synthesis tools allow initial blocks within RTL to initialize a BRAM. See here, for example.