From 18b6fa484d07daee601e752bed22a4019bc95495 Mon Sep 17 00:00:00 2001 From: Raghav <223111766+Raghavan-04@users.noreply.github.com> Date: Sat, 25 Jul 2026 07:09:17 +0000 Subject: [PATCH 1/2] [apb-timer/dv] Add functional coverage groups for timer, PWM, and IRQ Refs #1 --- uvm/tb/apb_timer_tb_top.sv | 24 +++++++++--- uvm/tb/timer_cov.sv | 75 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 uvm/tb/timer_cov.sv diff --git a/uvm/tb/apb_timer_tb_top.sv b/uvm/tb/apb_timer_tb_top.sv index d2440aa..e570bcd 100644 --- a/uvm/tb/apb_timer_tb_top.sv +++ b/uvm/tb/apb_timer_tb_top.sv @@ -5,7 +5,7 @@ module apb_timer_tb_top; logic pclk; logic presetn; - // Clock generation + // Clock generation (100MHz / 10ns period) initial begin pclk = 0; forever #5 pclk = ~pclk; @@ -18,11 +18,24 @@ module apb_timer_tb_top; end // Interfaces - apb_if apb_vif (pclk, presetn); + apb_if apb_vif (pclk, presetn); timer_if timer_vif (pclk, presetn); - // Connect TB TIMER loopback - // (No loopback needed for timer) + // Bind Functional Coverage module to DUT wrapper + bind apb_timer_wrapper timer_cov u_timer_cov ( + .clk (clk), + .rst_n (rst_n), + .timer_en (ctrl_reg[0]), + .oneshot_en (ctrl_reg[1]), + .pwm_en (ctrl_reg[2]), + .prescaler (ctrl_reg[31:16]), + .timer_val (timer_val), + .reload_val (reload_reg), + .compare_val (compare_reg), + .irq_en (irq_en_reg[1:0]), + .irq_stat (irq_stat_reg[1:0]), + .pwm_out (pwm_out) + ); // DUT instantiation apb_timer_wrapper #( @@ -46,10 +59,11 @@ module apb_timer_tb_top; .o_timer_irq (timer_vif.o_timer_irq) ); + // Pass virtual interfaces to UVM config DB & run test initial begin uvm_config_db#(virtual apb_if)::set(null, "uvm_test_top.env.m_apb_agent.*", "apb_vif", apb_vif); uvm_config_db#(virtual timer_if)::set(null, "uvm_test_top.env.m_timer_agent.*", "timer_vif", timer_vif); run_test(); end -endmodule +endmodule \ No newline at end of file diff --git a/uvm/tb/timer_cov.sv b/uvm/tb/timer_cov.sv new file mode 100644 index 0000000..0ec497f --- /dev/null +++ b/uvm/tb/timer_cov.sv @@ -0,0 +1,75 @@ +// SystemVerilog Functional Coverage for APB Timer IP Core +module timer_cov ( + input logic clk, + input logic rst_n, + input logic timer_en, + input logic oneshot_en, + input logic pwm_en, + input logic [15:0] prescaler, + input logic [31:0] timer_val, + input logic [31:0] reload_val, + input logic [31:0] compare_val, + input logic [1:0] irq_en, + input logic [1:0] irq_stat, + input logic pwm_out +); + + // --------------------------------------------------------------------------- + // 1. Control & Prescaler Coverage + // --------------------------------------------------------------------------- + covergroup cg_ctrl @(posedge clk); + option.per_instance = 1; + + cp_timer_en: coverpoint timer_en; + cp_oneshot_en: coverpoint oneshot_en; + cp_pwm_en: coverpoint pwm_en; + + cp_prescaler: coverpoint prescaler { + bins zero = {16'h0000}; + bins one = {16'h0001}; + bins max = {16'hFFFF}; + bins mid_range = {[16'h0002 : 16'hFFFE]}; + } + + // Cross timer mode and prescaler classes + cross_mode_prescale: cross cp_oneshot_en, cp_prescaler; + endgroup + + // --------------------------------------------------------------------------- + // 2. Reload vs Compare Duty Cycle Relation + // --------------------------------------------------------------------------- + covergroup cg_timer_cfg @(posedge clk); + option.per_instance = 1; + + cp_rel_cmp_rel: coverpoint (compare_val < reload_val) { + bins compare_less_than_reload = {1'b1}; + bins compare_gte_reload = {1'b0}; + } + + cp_rel_cmp_equal: coverpoint (compare_val == reload_val) { + bins compare_equals_reload = {1'b1}; + } + endgroup + + // --------------------------------------------------------------------------- + // 3. Interrupt Events & Write-1-to-Clear Coverage + // --------------------------------------------------------------------------- + covergroup cg_irq @(posedge clk); + option.per_instance = 1; + + cp_overflow_irq: coverpoint irq_stat[0] { + bins overflow_triggered = {1'b1}; + } + cp_compare_irq: coverpoint irq_stat[1] { + bins compare_triggered = {1'b1}; + } + + cross_irq_mask: cross cp_overflow_irq, irq_en; + endgroup + + // Instantiate covergroups + cg_ctrl cg_ctrl_inst = new(); + cg_timer_cfg cg_timer_cfg_inst = new(); + cg_irq cg_irq_inst = new(); + +endmodule \ No newline at end of file From 2dc5a4d62a2a11da0cd1b6ecaefd36f6471242db Mon Sep 17 00:00:00 2001 From: Raghav <223111766+Raghavan-04@users.noreply.github.com> Date: Wed, 5 Aug 2026 14:39:55 +0000 Subject: [PATCH 2/2] [apb-timer/dv] Fix coverage bind connections, reset gating, W1C IRQ transitions, and filelist --- filelist.f | 4 ++- uvm/tb/apb_timer_tb_top.sv | 26 +++++++------- uvm/tb/timer_cov.sv | 71 ++++++++++++++++++++++++++++---------- 3 files changed, 69 insertions(+), 32 deletions(-) diff --git a/filelist.f b/filelist.f index 1b0f9d0..8cb8ce9 100644 --- a/filelist.f +++ b/filelist.f @@ -16,4 +16,6 @@ uvm/tb/apb_if.sv uvm/tb/timer_if.sv uvm/tb/apb_timer_uvm_pkg.sv -uvm/tb/apb_timer_tb_top.sv +uvm/tb/timer_sva.sv +uvm/tb/timer_cov.sv +uvm/tb/apb_timer_tb_top.sv \ No newline at end of file diff --git a/uvm/tb/apb_timer_tb_top.sv b/uvm/tb/apb_timer_tb_top.sv index 8843a34..38c809c 100644 --- a/uvm/tb/apb_timer_tb_top.sv +++ b/uvm/tb/apb_timer_tb_top.sv @@ -21,20 +21,20 @@ module apb_timer_tb_top; apb_if apb_vif (pclk, presetn); timer_if timer_vif (pclk, presetn); - // Bind Functional Coverage module to DUT wrapper + // Bind Functional Coverage module to DUT wrapper using internal wrapper signals bind apb_timer_wrapper timer_cov u_timer_cov ( - .clk (clk), - .rst_n (rst_n), - .timer_en (ctrl_reg[0]), - .oneshot_en (ctrl_reg[1]), - .pwm_en (ctrl_reg[2]), - .prescaler (ctrl_reg[31:16]), - .timer_val (timer_val), - .reload_val (reload_reg), - .compare_val (compare_reg), - .irq_en (irq_en_reg[1:0]), - .irq_stat (irq_stat_reg[1:0]), - .pwm_out (pwm_out) + .clk (i_timer_pclk), + .rst_n (i_timer_presetn), + .timer_en (w_timer_en), + .oneshot_en (w_timer_oneshot), + .pwm_en (w_timer_pwm_en), + .prescaler (w_timer_prescaler), + .timer_val (w_timer_val), + .reload_val (w_timer_reload), + .compare_val (w_timer_compare), + .irq_en (u_apb_if.r_irq_en[1:0]), + .irq_stat (u_apb_if.r_irq_stat[1:0]), + .pwm_out (o_timer_pwm) ); // DUT instantiation diff --git a/uvm/tb/timer_cov.sv b/uvm/tb/timer_cov.sv index 0ec497f..d72f37b 100644 --- a/uvm/tb/timer_cov.sv +++ b/uvm/tb/timer_cov.sv @@ -1,4 +1,6 @@ // SystemVerilog Functional Coverage for APB Timer IP Core +`timescale 1ns/1ps + module timer_cov ( input logic clk, input logic rst_n, @@ -15,9 +17,9 @@ module timer_cov ( ); // --------------------------------------------------------------------------- - // 1. Control & Prescaler Coverage + // 1. Control & Prescaler Coverage (Gated by rst_n) // --------------------------------------------------------------------------- - covergroup cg_ctrl @(posedge clk); + covergroup cg_ctrl @(posedge clk iff rst_n); option.per_instance = 1; cp_timer_en: coverpoint timer_en; @@ -25,10 +27,10 @@ module timer_cov ( cp_pwm_en: coverpoint pwm_en; cp_prescaler: coverpoint prescaler { - bins zero = {16'h0000}; - bins one = {16'h0001}; - bins max = {16'hFFFF}; - bins mid_range = {[16'h0002 : 16'hFFFE]}; + bins zero = {16'h0000}; + bins one = {16'h0001}; + bins max = {16'hFFFF}; + bins mid_range = {[16'h0002 : 16'hFFFE]}; } // Cross timer mode and prescaler classes @@ -36,35 +38,68 @@ module timer_cov ( endgroup // --------------------------------------------------------------------------- - // 2. Reload vs Compare Duty Cycle Relation + // 2. Reload, Compare, Counter & PWM Coverage (Gated by rst_n) // --------------------------------------------------------------------------- - covergroup cg_timer_cfg @(posedge clk); + covergroup cg_timer_cfg @(posedge clk iff rst_n); option.per_instance = 1; cp_rel_cmp_rel: coverpoint (compare_val < reload_val) { - bins compare_less_than_reload = {1'b1}; - bins compare_gte_reload = {1'b0}; + bins compare_less_than_reload = {1'b1}; + bins compare_gte_reload = {1'b0}; } cp_rel_cmp_equal: coverpoint (compare_val == reload_val) { - bins compare_equals_reload = {1'b1}; + bins compare_equals_reload = {1'b1}; + } + + // Counter value coverage + cp_timer_val: coverpoint timer_val { + bins zero = {32'h0000_0000}; + bins max_val = {32'hFFFF_FFFF}; + bins mid_val = {[32'h0000_0001 : 32'hFFFF_FFFE]}; + } + + // PWM output activity & transitions + cp_pwm_out: coverpoint pwm_out { + bins low = {1'b0}; + bins high = {1'b1}; + bins low_to_high = (1'b0 => 1'b1); + bins high_to_low = (1'b1 => 1'b0); } endgroup // --------------------------------------------------------------------------- - // 3. Interrupt Events & Write-1-to-Clear Coverage + // 3. Interrupt Events, Masking & Write-1-to-Clear (Gated by rst_n) // --------------------------------------------------------------------------- - covergroup cg_irq @(posedge clk); + covergroup cg_irq @(posedge clk iff rst_n); option.per_instance = 1; - cp_overflow_irq: coverpoint irq_stat[0] { - bins overflow_triggered = {1'b1}; + // Bit 0: Overflow IRQ, Bit 1: Compare Match IRQ + cp_irq_stat: coverpoint irq_stat { + bins none_asserted = {2'b00}; + bins overflow_pending = {2'b01}; + bins compare_pending = {2'b10}; + bins both_pending = {2'b11}; } - cp_compare_irq: coverpoint irq_stat[1] { - bins compare_triggered = {1'b1}; + + cp_irq_en: coverpoint irq_en { + bins none_enabled = {2'b00}; + bins overflow_enabled = {2'b01}; + bins compare_enabled = {2'b10}; + bins both_enabled = {2'b11}; + } + + // Write-1-to-Clear (W1C) transitions + cp_overflow_w1c: coverpoint irq_stat[0] { + bins overflow_cleared = (1'b1 => 1'b0); + } + + cp_compare_w1c: coverpoint irq_stat[1] { + bins compare_cleared = (1'b1 => 1'b0); } - cross_irq_mask: cross cp_overflow_irq, irq_en; + // Cross status against both mask bits + cross_irq_mask: cross cp_irq_stat, cp_irq_en; endgroup // Instantiate covergroups