Sir, I am very new to system verilog and i have started writing code for dpram as shown below, I am facing 2 problems
- At constraint block, as my dpram specification is write enable(w_en)should be held high such that i can load randomdata(w_data)in random addresses(w_addr). i have tried writing using constraint block such that write(w_en)should come first and later(r_en) when i randomize. but i failed.
- I am unable to get my output(r_data)when am retrieving it from virtual interface from dut at driver display. Also i have synchronizing problem with driver and monitor. please do check the code in driver and monitor and let me know, where I am making mistake. So that i wont repeat such mistakes in writing other codes. thanks
/////////////////////////////////////////////////////DUT///////////////////////////////////////////////////////////////////////
module dpram( clk,rst,w_en,r_en,w_addr,r_addr,w_data,r_data);
input clk,rst,w_en,r_en;
input [1:0]w_data;
input [1:0]w_addr,r_addr;
output reg [1:0]r_data;
reg [1:0]mem[4];
always@(posedge clk)
begin
if(rst)
begin
for(int i = 0; i< 4; i++) begin
mem [i]<= 0;
end
end
else
begin
if (w_en)
mem[w_addr]<=w_data;
if (r_en)
r_data<=mem[r_addr];
end
end
endmodule
///////////////////////////////////////////////INTERFACE///////////////////////////////////////////////////////////////////////////
interface intf(input logic clk,rst);
logic [1:0]w_addr;
logic [1:0]r_addr;
logic [1:0]w_data;
logic [1:0]r_data;
logic w_en,r_en;
clocking driver_cb@(posedge clk);
default input #1 output #1;
input r_data;
output r_en;
output w_en;
output r_addr;
output w_data;
output w_addr;
endclocking
clocking monitor_cb@(posedge clk);
default input #1 output #1;
input r_data;
input w_data;
input r_en;
input w_en;
input w_addr;
input r_addr;
endclocking
endinterface
///////////////////////////////////////////TRANSACTION//////////////////////////////////////////////////////////////////
class transaction;
rand bit [1:0]w_addr;
rand bit [1:0]r_addr;
randc bit [1:0]w_data;
rand bit w_en;
rand bit r_en;
bit [1:0]r_data;
bit [1:0]cnt;
constraint wdc {w_en != r_en;}
constraint cond {unique{w_en,r_en};}
function void display(string name); $display(“[%0t],w_addr:%b,r_addr:%b,w_data:%b,w_en:%b,r_en:%b,r_data:%b”,$time,w_addr,r_addr,w_data,w_en,r_en,r_data);
endfunction
endclass
//////////////////////////////////////////GENERATOR///////////////////////////////////////////////////////////////////////////////
class generator;
rand transaction trans;
int repeat_count=8;
// Create a mailbox handle to put items
mailbox gen2driv;
event ended;
function new(mailbox gen2driv);
this.gen2driv=gen2driv;
endfunction
task send ();
$display("---------------------GENERATOR STARTED---------------");
for (int i = 0; i < repeat_count; i++) begin
trans =new();
if(!trans.randomize)
$fatal("Gen: randomization failed");
trans.display("generator");
gen2driv.put(trans);
end
-> ended;
endtask
endclass
/////////////////////////////////////////////DRIVER///////////////////////////////////////////////////////////////////////////////
class driver;
mailbox gen2driv;
int no_transactions;
virtual intf vif;
function new(virtual intf vif,mailbox gen2driv);
this.vif=vif ;
this.gen2driv=gen2driv;
endfunction
task reset;
wait(vif.rst);
$display(“[ DRIVER ]---------------- Reset Started ------------------”);
vif.driver_cb.w_addr <= 0;
vif.driver_cb.r_addr <= 0;
vif.driver_cb.w_data <=0;
vif.driver_cb.w_en <= 0;
vif.driver_cb.r_en <= 0;
$display(“reset:%0t, w_en:%b,r_en:%b,w_addr:%b,w_data:%b”,$time,vif.w_en,vif.r_en,vif.w_addr,vif.w_data);
wait(!vif.rst);
$display(“[ DRIVER ]----------------- Reset Ended ---------------------”);
$display(“reset:%0t, w_en:%b,r_en:%b,w_addr:%b,w_data:%b”,$time,vif.w_en,vif.r_en,vif.w_addr,vif.w_data);
endtask
task receive ();
transaction trans;
$display("---------------------DRIVER STARTED---------------");
forever begin
gen2driv.get(trans);
@(vif.driver_cb);
vif.w_addr<=trans.w_addr;
vif.r_addr<=trans.r_addr;
if(trans.w_en) begin
vif.driver_cb.w_en <= trans.w_en;
vif.driver_cb.w_addr <= trans.w_addr;
vif.driver_cb.w_data <= trans.w_data;
$display("[%0t] WENABLE- w_en:%b,r_en:%b,w_addr:%b,w_data:%b,r_data:%b",$time,trans.w_en,trans.r_en,trans.w_addr,trans.w_data,trans.r_data);
end
if(trans.r_en) begin
vif.driver_cb.r_en <= trans.r_en;
vif.driver_cb.r_addr <= trans.r_addr;
trans.r_data <= vif.driver_cb.r_data;
$display("[%0t] RENABLE r_en:%b,w_en:%b,w_addr:%b,w_data:%b,r_data:%b",$time,trans.r_en,trans.w_en,trans.w_addr,trans.w_data,trans.r_data);
end
no_transactions++;
end
endtask
endclass
///////////////////////////////////////////MONITOR////////////////////////////////////////////////////////////////////////////
class monitor;
virtual intf vif;
mailbox mon2scb;
function new (virtual intf vif, mailbox mon2scb);
this.vif=vif;
this.mon2scb=mon2scb;
endfunction
task send();
$display("--------------------- MONITOR STARTED---------------");
forever begin
transaction trans;
trans=new();
@( vif.monitor_cb);
if(vif.monitor_cb.w_en) begin
trans.w_addr = vif.monitor_cb.w_addr;
trans.w_en = vif.monitor_cb.w_en;
trans.w_data = vif.monitor_cb.w_data;
end
if(vif.monitor_cb.r_en) begin
trans.r_en = vif.monitor_cb.r_en;
trans.r_addr = vif.monitor_cb.r_addr;
trans.r_data = vif.monitor_cb.r_data;
end
// $display("[%0t] monitor checking r_en:%b,w_en:%b,w_addr:%b,w_data:%b,r_data:%b",$time,vif.r_en,vif.w_en,vif.w_addr,vif.w_data,vif.r_data);
mon2scb.put(trans);
// trans.display(“[monitor]”);
end
endtask
endclass
//////////////////////////////////////////////////ENVIRONMENT//////////////////////////////////////////////////////////////////////
class environment;
mailbox gen2driv;
mailbox mon2scb;
generator gen;
driver driv;
monitor mon;
virtual intf vif;
event ended;
function new(virtual intf vif);
this.vif=vif;
gen2driv=new();
mon2scb=new();
gen =new(gen2driv);
driv =new(vif,gen2driv);
mon =new(vif,mon2scb);
endfunction
task pre_test();
driv.reset();
endtask
task test();
fork
gen.send();
driv.receive();
mon.send();
join_any
endtask
task post_test();
wait(gen.ended.triggered);
wait(gen.repeat_count == driv.no_transactions);
endtask
task run;
pre_test();
test();
post_test();
$finish;
endtask
endclass
/////////////////////////////////////////////////PROGRAM////////////////////////////////////////////////////////////////////
program test(intf i_intf);
environment env;
initial begin
env=new(i_intf);
env.run();
end
endprogram
/////////////////////////////////////////////////TESTBENCHTOP//////////////////////////////////////////////////////////////////////
module top();
bit clk;
bit rst;
always #5 clk = ~clk;
initial begin
rst = 1;
#10 rst =0;
end
//creatinng instance of interface, inorder to connect DUT and testcase
intf i_intf(clk,rst);
//Testcase instance, interface handle is passed to test as an argument
test t1(i_intf);
//DUT instance, interface signals are connected to the DUT ports
dpram DUT (.clk(i_intf.clk),
.rst(i_intf.rst),
.w_en(i_intf.w_en),
.r_en(i_intf.r_en),
.w_addr(i_intf.w_addr),
.r_addr(i_intf.r_addr),
.w_data(i_intf.w_data),
.r_data(i_intf.r_data));
initial begin
$dumpfile(“dump.vcd”); $dumpvars;
end
endmodule
////////////////////////////////////////////////////////////////////////////////////////////////////