Sunday, August 17, 2014

Progressing from Verilog to SysteVerilog: Program

Verilog:
module testbench #(parameter WIDTH=4)();
reg clk, rst, en, pld, mode;
reg [WIDTH-1:0] pld_data;
wire detect;
wire [WIDTH-1:0] result;
counter #(4) C1 (
               .clk (clk),
               .reset (rst),
               .enable (en),
               .preload (pld),
               .preload_data (pld_data),
               .mode (mode),
               .detect (detect),
               .result (result));

initial begin
$monitor ("t=%t: result=%d, detect=%b", $time, result, detect);
clk = 0; 

rst = 1; en = 0; pld = 0; mode = 0;
@(posedge clk) rst=0;

@(posedge clk);
en = 1;

repeat(10)@(posedge clk);
en = 0;

repeat (10)@(posedge clk);
$finish;
end

always
#5 clk = ~clk;
endmodule



SystemVerilog
Note that in the above testbench, the testbench is a module like RTL. This may cause issues. Using a "program" block essentially directs the tool to handle the RTL and stimulus generation aka testcase in separate delta cycle. 
The same code as above, put inside a "program testcase". A module testbench will hookup RTL and testcase. Also note that a program block cannot have always statements. So clock generation is performed in testbench. Initializing clk = 0 in initial block prevents clk = X.
I also had a test when I needed to issue $fisnish if things are idle for say 20 clock cycles. I put the check in testbench using an always block + counter. In my recent project at work, I added this check right in the driver module with a fork-join.  

program testcase #(parameter WIDTH=4)( input wire clk, 
                   input wire detect,
                   input  wire [WIDTH-1:0]  result,
                   output logic rst, 
                   output logic en, 
                   output logic pld, 
                   output logic mode,
                   output logic [WIDTH-1:0]  preload_data);

initial begin
$monitor("check");
$monitor ("t=%t: result=%d, detect=%b", $time, result, detect);

rst = 1; en = 0; pld = 0; mode = 0;

@(posedge clk);
rst=0;

@(posedge clk);
en = 1;
repeat(15)@(posedge clk);

en = 0;
repeat (10)@(posedge clk);

$finish;
end
endprogram


module testbench #(parameter WIDTH=4)();
logic clk;
logic [WIDTH-1:0] pld_data, result1;
testcase #(4) P1 (
               .clk (clk),
               .rst (rst),
               .en (en),
               .pld (pld),
               .preload_data (pld_data),
               .mode (mode),
               .detect (detect1),
               .result (result1)
);

counter #(4) C1 (
               .clk (clk),
               .reset (rst),
               .enable (en),
               .preload (pld),
               .preload_data (pld_data),
               .mode (mode),
               .detect (detect1),
               .result (result1)
);

initial begin
clk = 0;
end

always
#5 clk = ~clk;

endmodule

Run:
vcs +vcs+lic+wait +v2k -sverilog -R -l vcs.log testbench.sv testcase.sv counter.v

No comments:

Post a Comment