逻辑仿真工具VCS使用

1 Makefile执行VCS仿真

# Makefile for simulating the full_adder.v with the simulator VCS

# ----------------------------------------------------------------------------------
# Macro variable
RTL := ./full_adder.v
TB  += ./full_adder_tb.v
SEED ?= $(shell date +%s) 

# Target : Dependency
all : compile simulate

compile:
  vcs -sverilog -debug_all -timescale=1ns/1ps -l com.log
 
simulate:
  ./simv -l sim.log

run_dve:
  dve -vpd vcdplus.vpd &

clean :
  rm -rf *.log csrc simv* *.key *.vpd DVEfiles coverage *.vdb


# ------------------------------------------------------------------------------------
# This all_cov target is used to collect the code coverage
all_cov: compile_coverage simulate_coverage

compile_coverage:
  vcs -sverilog -debug_all -cm line+cond+fsm+tgl+branch \
      -lca timescale.v full_adder.v full_adder_tb.v -l com.log

simulate_coverage:
  ./simv +ntb_random_seed=$(SEED) -cm line+cond+fsm+tgl+branch \
         -lca -cm.log cm.log -l sim.log

report_cov:
  urg -dir simv.vdb -format both -report coverage

dve_cov:
  dve -cov -covdir simv.vdb -lca

2 full_adder RTL

module fulladder (
  // module head : verilog-2001 format
  input wire a_in,
  input wire b_in,
  input wire c_in,
  output wire sum_out,
  output wire c_out
  );
  // method 1 Gate Level Describe
  assign sum_out = a_in ^ b_in ^ c_in;
  assign c_out = (a_in & b_in) | (b_in & c_in) | (c_in & a_in);

  // method 2 RTL design for Adder with the keyword "assign"
  // behavior of adder can be systhesizable
  // "assign" means connectivity ,which is used to describe a combinational circuit
  // assign {c_out,sum_out} = a_in + b_in + c_in;

  // method 3 RTL design for Adder with the keyword "always"
  //reg c_out,sum_out
  //always @ (a_in,b_in,c_in) begin

endmodule

3 Testbench

module full_adder_tb;
  
  reg ain,bin,cin; //drive the input port with the reg type 
  wire sumout,cout;//sample the output port with the wire type
  full_adder u_full_adder(
  //task 1. how to create an instance 
  // module head: verilog-2001 format
  /*input wire*/ .a_in  (ain),
  /*input wire*/ .b_in  (bin),
  /*input wire*/ .c_in  (cin),    //carry in 
  /*output reg*/ .sum_out  (sumout);
  /*output reg*/ .c_out (cout)    //carry out
  );
  // behavior of the adder can be systhesizable
  // "assign" means connectivity
  // assign {c_out,sum_out} = a_in + b_in + c_in;
  
  // task 2. clock and rest generator
  parameter CLK_PERIOD = 20
  reg clk,rest_n; // rest_n :active low
  
  initial begin
    clk = 0
    forever begin
      #(CLK_PERIOD/2) clk = ~clk
    end
  end
  
  initial begin 
    reset_n = 0;
    #100
    reset_n = 1;
  end
  
  //taske 3. drive the stimulus and capture the response
  //Here is a testcase
  initial begin 
    #110 ain=0;
         bin=0;
         cin=0;    //00
    #20  ain=0;
         bin=1;
         cin=0;    //01
    #20  ain=1;
         bin=0;
         cin=0;    //01
    #20  ain=1;
         bin=1;
         cin=0;    //01
    #20  ain=0;
         bin=1;
         cin=0;    //01
    #20  ain=1;
         bin=0;
         cin=0;    //01
    #20  ain=1;
         bin=1;
         cin=0;    //10
    #20  ain=0;
         bin=0;
         cin=1;    //01
    #20  ain=0;
         bin=1;
         cin=1;    //10
    #20  ain=0;
         bin=0;
         cin=1;    //01
    #20  ain=0;
         bin=1;
         cin=1;    //10
    #20  ain=1;
         bin=0;
         cin=1;    //10
    #20  ain=1;
         bin=1;
         cin=1;    //11
    #50 finish;  // Here is a system task which can stop the simulation
  end

  //task 4. check the result
  always @ (posedge clk) begin
    if (!reset_n) begin
      $dispaly("%t:%m:restting...",$time)  // counter 5 clock
    end
    else begin 
      $dispaly("%t:%m:restting finish!",$time)  // the 6th clock
    end
  end
  
  initial begin 
    #115 if ({cout,simout} != 2'b00) $display("Error:{cout,sumout}=%b,ain=%b,bin=%b,cin=%b",{cout,sumout},ain,bin,cin);
    #20 if ({cout,simout} != 2'b01) $display("Error:{cout,sumout}=%b,ain=%b,bin=%b,cin=%b",{cout,sumout},ain,bin,cin);
    #20 if ({cout,simout} != 2'b01) $display("Error:{cout,sumout}=%b,ain=%b,bin=%b,cin=%b",{cout,sumout},ain,bin,cin);
    #20 if ({cout,simout} != 2'b10) $display("Error:{cout,sumout}=%b,ain=%b,bin=%b,cin=%b",{cout,sumout},ain,bin,cin);
    #20 if ({cout,simout} != 2'b01) $display("Error:{cout,sumout}=%b,ain=%b,bin=%b,cin=%b",{cout,sumout},ain,bin,cin);
    #20 if ({cout,simout} != 2'b10) $display("Error:{cout,sumout}=%b,ain=%b,bin=%b,cin=%b",{cout,sumout},ain,bin,cin);
    #20 if ({cout,simout} != 2'b10) $display("Error:{cout,sumout}=%b,ain=%b,bin=%b,cin=%b",{cout,sumout},ain,bin,cin);
    #20 if ({cout,simout} != 2'b11) $display("Error:{cout,sumout}=%b,ain=%b,bin=%b,cin=%b",{cout,sumout},ain,bin,cin);
  end
  
  //task 5. dump waveform with the comiple option -debug_all
  initial begin
    $vcdpluson
  end
endmodule