SoC Verification HW #2 TA: Wei-Ting Tu Assignment: 04/12/06 Due: 04/26/06 Lab introductions Lab 1-3: examples Lab 4-6: exercises Lab requirements Implement each task in lab 4~6. References svtb.pdf: SystemVerilog TestBench Guide svtb_tutorial.pdf: SystemVerilog TestBench Tutorial SVTB_2005.06_SG.pdf: SystemVerilog Workshop Student Guide SVTB_2005.06_LG_01~3.pdf: SystemVerilog Workshop examples SVTB_2005.06_LG_04~6.pdf: SystemVerilog Workshop exercises i- 2 Workshop Goal Acquire the skills to write a SystemVerilog testbench to verify Verilog/SystemVerilog RTL code with coverage-driven random stimulus. i- 3 Target Audience Design or Verification engineers writing SystemVerilog testbenches to verify Verilog or SystemVerilog code. i- 4 Workshop Prerequisites You must have experience in the following areas: Familiarity with a UNIX text editor Basic programming skills in Verilog, VHDL or C Debugging experience with Verilog, VHDL or C i- 5 What Is the Device Under Test? A router: 16 x 16 crosspoint switch din [15:0] dout [15:0] frame_n[15:0] valid_n [15:0] frameo_n [15:0] router valido_n [15:0] reset_n clock i- 6 A Functional Perspective frame_n[0] valid_n[0] din[0] inputs outputs port port 0 0 frameo_n[0] valido_n[0] dout[0] 1 1 2 2 3 3 4 4 partial view i- 7 The Router Description Single positive-edge clock Input and output data are serial (1 bit / clock) Packets are sent through in variable length: Each packet is composed of two parts Header Payload Packets can be routed from any input port to any output port on a packet-by-packet basis No internal buffering or broadcasting (1-to-N) i- 8 Input Packet Structure frame_n: din: Falling edge indicates first bit of packet Rising edge indicates last bit of packet Header (destination address & padding bits) and payload valid_n: valid_n is low if payload bit is valid, high otherwise clock din[i] x A0 A1 A2 A3 valid_n[i] x x x x x d0 .... x dn-1 dn x frame_n[i] dest. address pad payload i- 9 Output Packet Structure Output activity is indicated by: frameo_n, valido_n, and dout Data is valid only when: frameo_n output is low (except for last bit) valido_n output is low Header field is stripped clock dout[i] x valido_n[i] x x d0 d1 x x d2 d3 dn-3 x dn-2 dn-1 x x frameo_n[i] i- 10 Reset Signal While asserting reset_n, frame_n and valid_n must be de-asserted reset_n is asserted for at least one clock cycle After de-asserting reset_n, wait for 15 clocks before sending a packet through the router clock reset_n frame_n[i] 15 clock cycles i- 11 The DUT: router.v The Design Under Test, router.v, is a Verilog file: Located under the rtl directory From the lab workspace: ../../rtl/router.v ~ solutions/ labs/ lab1/ lab2/ lab6/ lab1/ rtl/ lab6/ router.v lab work files i- 12 The SystemVerilog Test Environment Configure Generator Top level harness file Transactor Driver Checks completeness Coverage Self Check Observes data from DUT DUT Checks correctness Identifies transactions Transactor Test program Monitor interface i- 13 SystemVerilog Testbench Building Process router.v ntb_template -t router router.v Discard router.test_top.v router.vr.tmp router.test_top.sv router.if.sv Top level harness Interface router.if.vrh router.tb.sv Test program vcs –sverilog router.test_top.sv router.tb.sv router.if.sv router.v simv i- 14 Create Verilog Test Harness File Use VCS template generator ntb_template -t router router.v Generates three files: router.test_top.v Verilog test harness file router.if.vrh Discard (for OpenVera only) router.vr.tmp Discard (for OpenVera only) -t router Specifies DUT module name router.v DUT source code file router.test_top.v will be used to help build SystemVerilog testbench files i- 15 Creating SystemVerilog Interface File Create interface file from router.test_top.v cp router.test_top.v router.if.sv Encapsulate signals in interface block module router_test_top; parameter simulation_cycle = 100; reg SystemClock ; wire reset_n ; wire [15:0] din ; wire clock ; wire [15:0] frame_n ; wire [15:0] valid_n ; wire [15:0] dout ; wire [15:0] busy_n ; wire [15:0] valido_n ; wire [15:0] frameo_n ; `ifdef SYNOPSYS_NTB ... `endif router dut( … ); initial begin SystemClock = 0 ; forever begin #(simulation_cycle/2) SystemClock = ~SystemClock ; end end router.test_top.v endmodule Create from default harness file Change module to interface Delete all except wires interface router_io(input logic clock); logic reset_n ; Move clock to logic [15:0] din ; //wire clock; input argument logic [15:0] frame_n ; logic [15:0] valid_n ; router.if.sv logic [15:0] dout ; logic [15:0] busy_n ; logic [15:0] valido_n ; logic [15:0] frameo_n ; endinterface Change wire to logic i- 16 Define Test Program Interface Port By default all interface signals are asynchronous Synchronous signals can be created via clocking block and connected to test program via modport Create synchronous by placing signals into clocking block Define connection for test program with modport router.if.sv interface router_io(input logic clock); logic reset_n ; logic [15:0] din ; Configure logic [15:0] frame_n ; logic [15:0] valid_n ; Generator Coverage logic [15:0] dout ; logic [15:0] busy_n ; Transactor Self Check Transactor logic [15:0] valido_n ; logic [15:0] frameo_n ; clocking cb @(posedge clock); Driver Monitor default input #1 output #1; output reset_n; output din; DUT output frame_n; output valid_n; input dout; Sample/drive skew input busy_n; input valido_n; Direction w/respect to test input frameo_n; endclocking modport TB(clocking cb, output reset_n); endinterface Synchronous Asynchronous i- 17 Build Testbench Testbench is encapsulated in program block List interface signals in argument Both synchronous and asynchronous signals are encapsulated in modport router.tb.sv program automatic router_test(router_io.TB router); // develop test code in initial block: initial begin $vcdpluson; // Dumping file control $display(“Hello World”); end endprogram Configure Generator Coverage Transactor Self Check Driver Transactor Monitor DUT i- 18 Sample Testbench Develop test program code in initial block program automatic router_test(router_io.TB router); //testbench code in initial block: interface router_io(input logic clock); logic reset_n ; initial begin logic [15:0] din ; $vcdpluson; // Dumping file control logic [15:0] frame_n ; logic [15:0] valid_n ; // $display(“Hello World”); ... end clocking cb @(posedge clock); initial begin Asynchronous signals are default input #1 output #1; driven without reference to output reset_n; reset(); output din; clocking block end output frame_n; output valid_n; task reset(); ... router.reset_n <= 1’b0; endclocking modport TB(clocking cb, output reset_n); router.cb.frame_n <= 16’hffff; endinterface router.cb.valid_n <= ~(’b0); ##2 router.cb.reset_n <= 1’b1; // reset_n can be both synchronous and asynchronous repeat(15) @(router.cb); Synchronous signals are endtask driven via clocking block endprogram Advance clock cycles via clocking block i- 19 Driving Synchronous Device Signals [##num] interface.cb.signal <= <value> or <variable expression>; Must be driven with <= (non-blocking assignment) Can be specified with ##num of clocks delay ##1 router.cb.din[3] <= var_a; Equivalent to: repeat(num) @(router.cb); router.din[3] <= #input_skew_value var_a; clock var_a din[3] Statement executes here Variable expression evaluates Apply drive here Next statement executes router.cb.din[3] = 1’b1; // error (must be non-blocking) i- 20 Sampling Synchronous Device Signals variable = interface.cb.signal; No delay attribute (## num) Variable is assigned the sampled value Sampling of output signal is not allowed Examples: data[i] = router.cb.dout[7]; all_data = router.cb.dout; @(posedge router.cb.frameo_n[7]); $display(“router.cb.din = %b\n”, router.din); //error if(router.cb.din[3] == 1’b0) //error i- 21 Advancing Simulation Time Asynchronous (Verilog coding style): #delay; @(negedge interface.signal); Synchronous (advancing clock cycles): Verilog coding style: @(posedge interface.clock_signal); repeat (10) @(posedge interface.clock_signal); SystemVerilog coding style (clocking block): @(interface.clocking_block); repeat (10) @(interface.clocking_block); Each clocking block specifies a clock signal and edge: interface router_io(input logic clock); clocking cb @(posedge clock); ... endclocking endinterface i- 22 Create SystemVerilog Harness File Create harness file from router.test_top.v mv router.test_top.v router.test_top.sv Configure module router_test_top; parameter simulation_cycle = 100; reg SystemClock ; wire reset_n ; wire clock ; wire [15:0] frame_n ; wire [15:0] valid_n ; wire [15:0] dinall; wire declarations Delete wire [15:0] dout ; andbusy_n all OpenVera stuff wire [15:0] ; wire [15:0] valido_n ; wire [15:0] frameo_n ; `ifdef SYNOPSYS_NTB ... `endif router dut( … ); initial begin SystemClock = 0 ; forever begin #(simulation_cycle/2) SystemClock = ~SystemClock ; end end router.test_top.sv endmodule Generator Coverage Transactor Self Check Transactor Driver Monitor DUT module router_test_top; parameter simulation_cycle = 100; reg SystemClock ; router dut( … ); initial begin SystemClock = 0 ; forever begin #(simulation_cycle/2) SystemClock = ~SystemClock ; end end router.test_top.sv endmodule i- 23 Complete Top Level Harness File Instantiate test program and interface in harness file router.test_top.sv Instantiate interface Connect SystemClock to interface block module router_test_top; module router_test_top; parameter simulation_cycle = 100; parameter simulation_cycle = 100; reg SystemClock ; reg SystemClock; router dut( router_io top_io(SystemClock); .reset_n(reset_n), router_test test(top_io); .clock(clock), router dut(.reset_n(top_io.reset_n), Instantiate .frame_n(frame_n), .clock(top_io.clock), .valid_n(valid_n), test program .frame_n(top_io.frame_n), .din(din), .valid_n(top_io.valid_n), .dout(dout), .din(top_io.din), Update DUT .busy_n(busy_n), .dout(top_io.dout), instantiation using .valido_n(valido_n), .busy_n(top_io.busy_n), .frameo_n(frameo_n)); interface connection .valido_n(top_io.valido_n), initial begin .frameo_n(top_io.frameo_n)); SystemClock = 0 ; initial begin forever begin SystemClock = 0 ; #(simulation_cycle/2) forever begin SystemClock = ~SystemClock ; #(simulation_cycle/2) end SystemClock = ~SystemClock ; end end endmodule end endmodule i- 24 Compile RTL & Simulate w/ VCS NTB Configure router.tb.sv Generator Coverage Transactor Self Check Transactor Driver router.test_top.sv Monitor router.if.sv DUT router.v Compile HDL code: (generate simv simulation binary) > vcs –sverilog [-debug] router.test_top.sv \ router.tb.sv router.if.sv router.v Get vcs compiler switch summary: > vcs -help Simulate DUT with SystemVerilog testbench: (running simv) > ./simv i- 25