diff --git a/coverage.png b/coverage.png new file mode 100644 index 0000000..509f9d1 Binary files /dev/null and b/coverage.png differ diff --git a/rtl/traffic.sv b/rtl/traffic.sv index e9f4434..bdcc4a9 100644 --- a/rtl/traffic.sv +++ b/rtl/traffic.sv @@ -1,56 +1,86 @@ -module traffic ( input pclk, - input presetn, - input [31:0] paddr, - input [31:0] pwdata, - input psel, - input pwrite, - input penable, - - // Outputs - output [31:0] prdata); - - reg [3:0] ctl_reg; // profile, blink_red, blink_yellow, mod_en RW - reg [1:0] stat_reg; // state[1:0] - reg [31:0] timer_0; // timer_g2y[31:20], timer_r2g[19:8], timer_y2r[7:0] RW - reg [31:0] timer_1; // timer_g2y[31:20], timer_r2g[19:8], timer_y2r[7:0] RW - - reg [31:0] data_in; - reg [31:0] rdata_tmp; - - // Set all registers to default values - always @ (posedge pclk) begin - if (!presetn) begin - data_in <= 0; - ctl_reg <= 0; - stat_reg <= 0; - timer_0 <= 32'hcafe_1234; - timer_1 <= 32'hface_5678; - end - end - - // Capture write data - always @ (posedge pclk) begin - if (presetn & psel & penable) - if (pwrite) +module traffic ( + input pclk, + input presetn, + input [31:0] paddr, + input [31:0] pwdata, + input psel, + input pwrite, + input penable, + output reg pready, + output reg pslverr, + output reg [31:0] prdata +); + + // Internal registers + reg [3:0] ctl_reg; + reg [31:0] timer_0; + reg [31:0] timer_1; + + typedef enum logic [1:0] { IDLE, SETUP, ACCESS, TRANSFER } state_t; + state_t state; + + // Reset and initialization + always @(posedge pclk or negedge presetn) begin + if (!(paddr inside {0, 4, 8})) begin pslverr <=1;end + if (!presetn) begin + // Reset all internal states and registers + state <= IDLE; + ctl_reg <= 4'b0; + timer_0 <= 32'hcafe1234; + timer_1 <= 32'hface5678; + prdata <= 32'h0; + pready <= 1'b0; + pslverr <= 1'b0; + $display("RESET: Registers reset to default values"); + end else begin + case (state) + IDLE: begin + pready <= 1'b0; // Ensure pready is deasserted + if (psel && !penable) begin + state <= SETUP; + $display("IDLE: Detected psel, moving to SETUP"); + end + end + + SETUP: begin + if (psel && penable) begin + state <= ACCESS; + $display("SETUP: Detected penable, moving to ACCESS"); + end + end + ACCESS: begin + if (psel && penable && (paddr<32)) begin + if (pwrite) begin + // Write operation + case (paddr) + 32'h0: ctl_reg <= pwdata[3:0]; + 32'h4: timer_0 <= pwdata; + 32'h8: timer_1 <= pwdata; + default: pslverr <= 1'b1; + endcase + $display("DUT WRITE: Addr=%h, Data=%h", paddr, pwdata); + end else begin + // Read operation case (paddr) - 'h0 : ctl_reg <= pwdata; - 'h4 : timer_0 <= pwdata; - 'h8 : timer_1 <= pwdata; - 'hc : stat_reg <= pwdata; + 32'h0: prdata <= {28'b0, ctl_reg}; + 32'h4: prdata <= timer_0; + 32'h8: prdata <= timer_1; + default: prdata <= 32'hDEADBEEF; + endcase + $display("DUT READ: Addr=%h, Data=%h", paddr, prdata); + end + pready <= 1'b1; // Indicate transaction completion + state <= TRANSFER; // Move to the next state + end else begin + pready <= 1'b0; // Ensure pready is low if not in a valid transaction + end + end +TRANSFER: begin + pready <= 1'b0; // Deassert pready after the transaction + state <= IDLE; // Return to IDLE for the next transaction + $display("TRANSFER: Transaction done, returning to IDLE"); +end endcase - end - - // Provide read data - always @ (penable) begin - if (psel & !pwrite) - case (paddr) - 'h0 : rdata_tmp <= ctl_reg; - 'h4 : rdata_tmp <= timer_0; - 'h8 : rdata_tmp <= timer_1; - 'hc : rdata_tmp <= stat_reg; - endcase - end - - assign prdata = (psel & penable & !pwrite) ? rdata_tmp : 'hz; - + end + end endmodule \ No newline at end of file diff --git a/tb/apb_driver.sv b/tb/apb_driver.sv index cd11b23..2dbddf3 100644 --- a/tb/apb_driver.sv +++ b/tb/apb_driver.sv @@ -35,29 +35,38 @@ class apb_driver extends uvm_driver #(apb_tr); end endtask - virtual task read ( input bit [31:0] addr, - output logic [31:0] data); - vif.paddr <= addr; - vif.pwrite <= 0; - vif.psel <= 1; - @(posedge vif.pclk); - vif.penable <= 1; - @(posedge vif.pclk); - data = vif.prdata; - vif.psel <= 0; - vif.penable <= 0; - endtask - - virtual task write ( input bit [31:0] addr, - input bit [31:0] data); - vif.paddr <= addr; - vif.pwdata <= data; - vif.pwrite <= 1; - vif.psel <= 1; - @(posedge vif.pclk); - vif.penable <= 1; - @(posedge vif.pclk); - vif.psel <= 0; - vif.penable <= 0; - endtask + virtual task write(input bit [31:0] addr, input bit [31:0] data); + vif.paddr <= addr; + vif.pwdata <= data; + vif.pwrite <= 1; + vif.psel <= 1; + @(posedge vif.pclk); + vif.penable <= 1; + + // Wait for pready to be asserted + wait (vif.pready == 1); + @(posedge vif.pclk); + $display("DRIVER WRITE: Addr=%h, Data=%h, pready=%b", addr, data, vif.pready); + + vif.psel <= 0; + vif.penable <= 0; +endtask + +virtual task read(input bit [31:0] addr, output logic [31:0] data); + vif.paddr <= addr; + vif.pwrite <= 0; + vif.psel <= 1; + @(posedge vif.pclk); + vif.penable <= 1; + + // Wait for pready to be asserted + wait (vif.pready == 1); + @(posedge vif.pclk); + data = vif.prdata; + $display("DRIVER READ: Addr=%h, Data=%h, pready=%b", addr, data, vif.pready); + + vif.psel <= 0; + vif.penable <= 0; +endtask + endclass diff --git a/tb/apb_if.sv b/tb/apb_if.sv index a9b53c0..e6ae855 100644 --- a/tb/apb_if.sv +++ b/tb/apb_if.sv @@ -1,9 +1,20 @@ -interface apb_if (input pclk, input presetn); - logic [31:0] paddr; - logic [31:0] pwdata; - logic [31:0] prdata; - logic pwrite; - logic psel; - logic penable; - logic presetn; +interface apb_if (input pclk, input presetn); // presetn as input + logic [31:0] paddr; + logic [31:0] pwdata; + logic [31:0] prdata; + logic pwrite; + logic psel; + logic penable; + logic pready; // If pready is used + logic pslverr; + // Assertion: pslverr should be asserted for invalid addresses +property invalid_address_check; + @(posedge pclk) (paddr inside {0, 4, 8}) or pslverr == 1'b1; +endproperty + +assert property (invalid_address_check) +else $error("Invalid address detected !"); + + + endinterface \ No newline at end of file diff --git a/tb/apb_monitor.sv b/tb/apb_monitor.sv index b938f4a..56bb028 100644 --- a/tb/apb_monitor.sv +++ b/tb/apb_monitor.sv @@ -7,28 +7,40 @@ class apb_monitor extends uvm_monitor; uvm_analysis_port #(apb_tr) mon_ap; virtual apb_if vif; - virtual function void build_phase (uvm_phase phase); - super.build_phase (phase); - mon_ap = new ("mon_ap", this); - uvm_config_db #(virtual apb_if)::get (null, "uvm_test_top.*", "apb_if", vif); - endfunction - - virtual task run_phase (uvm_phase phase); - fork - @(posedge vif.presetn); - forever begin + virtual function void build_phase(uvm_phase phase); + super.build_phase(phase); + mon_ap = new("mon_ap", this); + if (!uvm_config_db#(virtual apb_if)::get(null, "uvm_test_top.*", "apb_if", vif)) + `uvm_error("MONITOR", "Failed to get apb_if"); + endfunction + + + + virtual task run_phase(uvm_phase phase); + fork + @(posedge vif.presetn); // Wait for reset deassertion + forever begin @(posedge vif.pclk); - if (vif.psel & vif.penable & vif.presetn) begin - apb_tr tr = apb_tr::type_id::create ("tr"); - tr.addr = vif.paddr; - if (vif.pwrite) - tr.data = vif.pwdata; - else - tr.data = vif.prdata; - tr.write = vif.pwrite; - mon_ap.write (tr); - end - end - join_none - endtask + if (vif.psel && vif.penable && vif.presetn) begin + apb_tr tr = apb_tr::type_id::create("tr"); + tr.addr = vif.paddr; + + if (vif.pwrite) begin + tr.data = vif.pwdata; + tr.write = 1'b1; + $display("MONITOR: Captured WRITE - Addr=%h, Data=%h", tr.addr, tr.data); + end else begin + tr.data = vif.prdata; + tr.write = 1'b0; + $display("MONITOR: Captured READ - Addr=%h, Data=%h", tr.addr, tr.data); + end + + // Forward the transaction + mon_ap.write(tr); + end + end + join_none +endtask + + endclass diff --git a/tb/invalid_address_test.sv b/tb/invalid_address_test.sv new file mode 100644 index 0000000..293697c --- /dev/null +++ b/tb/invalid_address_test.sv @@ -0,0 +1,26 @@ +class invalid_address_test extends uvm_test; + `uvm_component_utils(invalid_address_test) + + traffic_env m_env; + uvm_sequence invalid_seq; + + function new(string name = "invalid_address_test", uvm_component parent = null); + super.new(name, parent); + endfunction + + virtual function void build_phase(uvm_phase phase); + super.build_phase(phase); + m_env = traffic_env::type_id::create("m_env", this); + endfunction + + virtual task main_phase(uvm_phase phase); + phase.raise_objection(this); + + // Create and run the invalid_address_sequence + + invalid_seq = invalid_address_sequence::type_id::create("invalid_seq"); + invalid_seq.start(m_env.m_agent.m_seqr); // Start the sequence on the APB sequencer + + phase.drop_objection(this); + endtask +endclass diff --git a/tb/reg_lib/ral_block_traffic_cfg.sv b/tb/reg_lib/ral_block_traffic_cfg.sv index 9409903..56c0a2a 100644 --- a/tb/reg_lib/ral_block_traffic_cfg.sv +++ b/tb/reg_lib/ral_block_traffic_cfg.sv @@ -1,4 +1,3 @@ -// These registers are grouped together to form a register block called "cfg" class ral_block_traffic_cfg extends uvm_reg_block; `uvm_object_utils(ral_block_traffic_cfg) @@ -10,32 +9,37 @@ class ral_block_traffic_cfg extends uvm_reg_block; uvm_reg_map reg_map; - function new(string name = "traffic_cfg"); - super.new(name, build_coverage(UVM_NO_COVERAGE)); + function new(string name = "ral_block_traffic_cfg"); + super.new(name, UVM_CVR_ALL); + `uvm_info("RAL_BLOCK", $sformatf("Creating instance: %s", name), UVM_LOW); endfunction + virtual function void build(); - this.reg_map = create_map("", 0, 4, UVM_LITTLE_ENDIAN, 0); + this.reg_map = create_map("", 0, 8, UVM_LITTLE_ENDIAN, 0); this.ctrl = ral_cfg_ctl::type_id::create("ctrl",,get_full_name()); - this.ctrl.configure(this, null, ""); this.ctrl.build(); + this.ctrl.configure(this, null, ""); this.reg_map.add_reg(this.ctrl, `UVM_REG_ADDR_WIDTH'h0, "RW", 0); this.timer[0] = ral_cfg_timer::type_id::create("timer[0]",,get_full_name()); - this.timer[0].configure(this, null, ""); this.timer[0].build(); + this.timer[0].configure(this, null, ""); + this.reg_map.add_reg(this.timer[0], `UVM_REG_ADDR_WIDTH'h4, "RW", 0); this.timer[1] = ral_cfg_timer::type_id::create("timer[1]",,get_full_name()); - this.timer[1].configure(this, null, ""); this.timer[1].build(); + this.timer[1].configure(this, null, ""); + this.reg_map.add_reg(this.timer[1], `UVM_REG_ADDR_WIDTH'h8, "RW", 0); this.stat = ral_cfg_stat::type_id::create("stat",,get_full_name()); - this.stat.configure(this, null, ""); this.stat.build(); + this.stat.configure(this, null, ""); + this.reg_map.add_reg(this.stat, `UVM_REG_ADDR_WIDTH'hc, "RO", 0); lock_model(); diff --git a/tb/reg_lib/ral_cfg_ctl.sv b/tb/reg_lib/ral_cfg_ctl.sv index 623aeb9..ddab359 100644 --- a/tb/reg_lib/ral_cfg_ctl.sv +++ b/tb/reg_lib/ral_cfg_ctl.sv @@ -1,27 +1,58 @@ -// Register definition for the register called "ctl" +import uvm_pkg::*; // Import UVM package +`include "uvm_macros.svh" // Include UVM macros class ral_cfg_ctl extends uvm_reg; - rand uvm_reg_field mod_en; // Enables the module - rand uvm_reg_field bl_yellow; // Blinks yellow - rand uvm_reg_field bl_red; // Blinks red - rand uvm_reg_field profile; // 1 : Peak, 0 : Off-Peak + rand uvm_reg_field mod_en; + rand uvm_reg_field bl_yellow; + rand uvm_reg_field bl_red; + rand uvm_reg_field profile; `uvm_object_utils(ral_cfg_ctl) - function new(string name = "traffic_cfg_ctrl"); - super.new(name, 32, build_coverage(UVM_NO_COVERAGE)); - endfunction: new + + + // Define the covergroup + covergroup cg(string name = "default_name"); + option.per_instance=1; + option.auto_bin_max=2; + coverpoint mod_en.get() { + + bins value[] = {0,1}; + } // Track the values of mod_en + coverpoint bl_yellow.get() { + bins yellow_value[] = {0, 1}; + } + coverpoint bl_red.get() { + bins red_value[] = {0, 1}; +} + + + endgroup + + function new(string name = "ral_cfg_ctl"); + super.new(name, 8, UVM_CVR_ALL); + cg = new(); // Initialize the covergroup + `uvm_info("RAL_CFG_CTL", $sformatf("Creating instance: %s", name), UVM_LOW); + + endfunction + + // Sample the covergroup whenever a transaction occurs + virtual function void sample_coverage(); + $display("Sampling coverage for ral_cfg_ctl"); + cg.sample(); + endfunction - // Build all register field objects virtual function void build(); - this.mod_en = uvm_reg_field::type_id::create("mod_en",, get_full_name()); - this.bl_yellow = uvm_reg_field::type_id::create("bl_yellow",,get_full_name()); - this.bl_red = uvm_reg_field::type_id::create("bl_red",, get_full_name()); - this.profile = uvm_reg_field::type_id::create("profile",, get_full_name()); + this.mod_en = uvm_reg_field::type_id::create("mod_en", , get_full_name()); + this.bl_yellow = uvm_reg_field::type_id::create("bl_yellow", , get_full_name()); + this.bl_red = uvm_reg_field::type_id::create("bl_red", , get_full_name()); + this.profile = uvm_reg_field::type_id::create("profile", , get_full_name()); + + this.mod_en.configure(this, 1, 0, "RW", 0, 1'h0, 1, 1, 1); + this.bl_yellow.configure(this, 1, 1, "RW", 0, 1'h0, 1, 1, 1); + this.bl_red.configure(this, 1, 2, "RW", 0, 1'h0, 1, 1, 1); + this.profile.configure(this, 1, 3, "RW", 0, 1'h0, 1, 1, 1); - // configure(parent, size, lsb_pos, access, volatile, reset, has_reset, is_rand, individually_accessible); - this.mod_en.configure(this, 1, 0, "RW", 0, 1'h0, 1, 0, 0); - this.bl_yellow.configure(this, 1, 1, "RW", 0, 3'h4, 1, 0, 0); - this.bl_red.configure(this, 1, 2, "RW", 0, 1'h0, 1, 0, 0); - this.profile.configure(this, 1, 3, "RW", 0, 1'h0, 1, 0, 0); + this.set_reset(32'h00000000, "SOFT"); // Reset value for ctl_reg endfunction + endclass \ No newline at end of file diff --git a/tb/reg_lib/ral_cfg_stat.sv b/tb/reg_lib/ral_cfg_stat.sv index 30e4063..5e2f25f 100644 --- a/tb/reg_lib/ral_cfg_stat.sv +++ b/tb/reg_lib/ral_cfg_stat.sv @@ -1,15 +1,17 @@ class ral_cfg_stat extends uvm_reg; - uvm_reg_field state; // Current state of the design + uvm_reg_field state; `uvm_object_utils(ral_cfg_stat) + function new(string name = "ral_cfg_stat"); - super.new(name, 32, build_coverage(UVM_NO_COVERAGE)); + super.new(name, 8, UVM_CVR_ALL); endfunction virtual function void build(); - this.state = uvm_reg_field::type_id::create("state",, get_full_name()); + this.state = uvm_reg_field::type_id::create("state", , get_full_name()); + this.state.configure(this, 2, 0, "RO", 0, 1'h0, 1, 1, 1); - // configure(parent, size, lsb_pos, access, volatile, reset, has_reset, is_rand, individually_accessible); - this.state.configure(this, 2, 0, "RO", 0, 1'h0, 0, 0, 0); + this.set_reset(32'h00000000, "SOFT"); // Reset value for stat_reg endfunction -endclass \ No newline at end of file +endclass + diff --git a/tb/reg_lib/ral_cfg_timer.sv b/tb/reg_lib/ral_cfg_timer.sv index ebac7b2..34d956a 100644 --- a/tb/reg_lib/ral_cfg_timer.sv +++ b/tb/reg_lib/ral_cfg_timer.sv @@ -4,7 +4,7 @@ class ral_cfg_timer extends uvm_reg; `uvm_object_utils(ral_cfg_timer) function new(string name = "traffic_cfg_timer"); - super.new(name, 32,build_coverage(UVM_NO_COVERAGE)); + super.new(name, 32,UVM_CVR_ALL); endfunction virtual function void build(); @@ -12,6 +12,6 @@ class ral_cfg_timer extends uvm_reg; // configure(parent, size, lsb_pos, access, volatile, reset, has_reset, is_rand, individually_accessible); this.timer.configure(this, 32, 0, "RW", 0, 32'hCAFE1234, 1, 0, 1); - this.timer.set_reset('h0, "SOFT"); + this.timer.set_reset(32'hCAFE1234, "SOFT"); endfunction endclass \ No newline at end of file diff --git a/tb/reg_rw_test.sv b/tb/reg_rw_test.sv index 98a3089..ac469dc 100644 --- a/tb/reg_rw_test.sv +++ b/tb/reg_rw_test.sv @@ -1,22 +1,30 @@ class reg_rw_test extends base_test; - `uvm_component_utils (reg_rw_test) - - my_sequence m_seq; - - function new (string name="reg_rw_test", uvm_component parent); - super.new (name, parent); + `uvm_component_utils(reg_rw_test) + + my_sequence m_seq; + reset_seq rst_seq; + + function new(string name = "reg_rw_test", uvm_component parent); + super.new(name, parent); endfunction virtual task main_phase(uvm_phase phase); - phase.raise_objection(this); - m_seq = my_sequence::type_id::create("m_seq"); - m_seq.model = m_ral_model; + // Create and run the reset sequence + rst_seq = reset_seq::type_id::create("rst_seq"); + rst_seq.start(null); // Null sequencer for direct execution of reset + // Create and run the main test sequence + m_seq = my_sequence::type_id::create("m_seq"); + + // Pass the Register Model to the Sequence + m_seq.model = m_env.m_ral_model; + // Run the main test sequence m_seq.start(m_env.m_agent.m_seqr); phase.drop_objection(this); endtask -endclass \ No newline at end of file +endclass + diff --git a/tb/seq_lib/invalid_address_sequence.sv b/tb/seq_lib/invalid_address_sequence.sv new file mode 100644 index 0000000..cc5bd45 --- /dev/null +++ b/tb/seq_lib/invalid_address_sequence.sv @@ -0,0 +1,22 @@ +class invalid_address_sequence extends uvm_sequence; + `uvm_object_utils(invalid_address_sequence) + + function new(string name = "invalid_address_sequence"); + super.new(name); + endfunction + + virtual task body(); + apb_tr tr; + tr = apb_tr::type_id::create("invalid_address_tr", null); + + // Drive invalid address + tr.addr = 32'hDEAD_BEEF; // Invalid address + tr.data = 32'hBAD_CAFE; + tr.write = 1; + + `uvm_info("INVALID_SEQ", $sformatf("Sending invalid address: %h", tr.addr), UVM_LOW); + + start_item(tr); + finish_item(tr); + endtask +endclass \ No newline at end of file diff --git a/tb/seq_lib/my_sequence.sv b/tb/seq_lib/my_sequence.sv index 1890839..1f4d70f 100644 --- a/tb/seq_lib/my_sequence.sv +++ b/tb/seq_lib/my_sequence.sv @@ -1,23 +1,51 @@ class my_sequence extends uvm_reg_sequence(); - `uvm_object_utils (my_sequence) - function new (string name = "my_sequence"); - super.new (name); + `uvm_object_utils(my_sequence) + + function new(string name = "my_sequence"); + super.new(name); endfunction - - virtual task body (); - - ral_block_traffic_cfg m_ral_model; - - uvm_reg_data_t rdata; - uvm_status_e status; - int reg_idx = 1; - - $cast(m_ral_model, model); - - write_reg(m_ral_model.ctrl, status, 32'd3); - write_reg(m_ral_model.timer[0], status, 32'b00000010000000000000100000000001); - write_reg(m_ral_model.timer[1], status, 32'd0); - read_reg(m_ral_model.timer[1], status, rdata ); - - endtask -endclass \ No newline at end of file + + virtual task body(); + uvm_status_e status; + uvm_reg_data_t rdata; + ral_block_traffic_cfg m_ral_model; + + if (!$cast(m_ral_model, model)) begin + `uvm_fatal("SEQ", "Failed to cast model to ral_block_traffic_cfg"); + end + + // Write and verify Registers + // Write to bl_yellow with value 0 + write_reg(m_ral_model.ctrl, status, 32'h20); + m_ral_model.ctrl.sample_coverage(); + + // Write to bl_yellow with value 1 + write_reg(m_ral_model.ctrl, status, 32'h2); // Assuming `bl_yellow` is bit 1 + m_ral_model.ctrl.sample_coverage(); + + // Write to bl_red with value 0 + write_reg(m_ral_model.ctrl, status, 32'h0); + m_ral_model.ctrl.sample_coverage(); + + // Write to bl_red with value 1 + write_reg(m_ral_model.ctrl, status, 32'h4); // Assuming `bl_red` is bit 2 + m_ral_model.ctrl.sample_coverage(); + + write_reg(m_ral_model.ctrl, status, 32'h1); + m_ral_model.ctrl.sample_coverage(); + + + write_reg(m_ral_model.timer[0], status, 32'hAAAA_BBBB); + m_ral_model.timer[0].mirror(status, UVM_CHECK); + read_reg(m_ral_model.timer[0], status, rdata); + `uvm_info("SEQ", $sformatf("Read Data from timer[0]: %h", rdata), UVM_LOW); + + write_reg(m_ral_model.timer[1], status, 32'hCCCC_DDDD); + m_ral_model.timer[1].mirror(status, UVM_CHECK); + + read_reg(m_ral_model.timer[1], status, rdata); + `uvm_info("SEQ", $sformatf("Read Data from timer[1]: %h", rdata), UVM_LOW); + + +endtask +endclass diff --git a/tb/seq_lib/reset_seq.sv b/tb/seq_lib/reset_seq.sv index 07e870c..43f13c3 100644 --- a/tb/seq_lib/reset_seq.sv +++ b/tb/seq_lib/reset_seq.sv @@ -1,18 +1,21 @@ class reset_seq extends uvm_sequence; - `uvm_object_utils (reset_seq) - function new (string name = "reset_seq"); - super.new (name); - endfunction + `uvm_object_utils(reset_seq) - virtual apb_if vif; + function new(string name = "reset_seq"); + super.new(name); + endfunction - task body (); - if (!uvm_config_db #(virtual apb_if) :: get (null, "uvm_test_top.*", "apb_if", vif)) - `uvm_fatal ("VIF", "No vif") + virtual apb_if vif; - `uvm_info ("RESET", "Running reset ...", UVM_MEDIUM); - vif.presetn <= 0; - @(posedge vif.pclk) vif.presetn <= 1; - @(posedge vif.pclk); - endtask + task body(); + if (!uvm_config_db #(virtual apb_if)::get(null, "uvm_test_top.*", "apb_if", vif)) begin + `uvm_fatal("VIF", "No vif found in configuration database!"); + end + + `uvm_info("RESET", "Waiting for reset to be deasserted...", UVM_MEDIUM); + + // Wait for reset deassertion + @(posedge vif.presetn); + `uvm_info("RESET", "Reset deasserted. Proceeding with test.", UVM_MEDIUM); + endtask endclass diff --git a/tb/top.sv b/tb/top.sv index 0cb04ec..0292902 100644 --- a/tb/top.sv +++ b/tb/top.sv @@ -1,6 +1,6 @@ -module top; + module top; import uvm_pkg::*; - import my_pkg::*; + // import my_pkg::*; parameter min_cover = 70; parameter min_transa = 2000; @@ -9,10 +9,11 @@ module top; always #10 pclk = ~pclk; - initial begin - presetn = 0; - #10 presetn = 1; - end + + initial begin + presetn = 0; // Assert reset + #50 presetn = 1; // Deassert reset after 50 time units + end apb_if apb_if (pclk, presetn); @@ -23,14 +24,17 @@ module top; .prdata (apb_if.prdata), .psel (apb_if.psel), .pwrite (apb_if.pwrite), - .penable (apb_if.penable)); + .pready (apb_if.pready), + .penable (apb_if.penable), + .pslverr(apb_if.pslverr)); initial begin + `ifdef XCELIUM $recordvars(); `endif `ifdef VCS - $vcdpluson; + // $vcdpluson; `endif `ifdef QUESTA $wlfdumpvars(); @@ -39,5 +43,19 @@ module top; uvm_config_db #(virtual apb_if)::set (null, "uvm_test_top.*", "apb_if", apb_if); run_test ("reg_rw_test"); + end + initial begin + $dumpfile("dump.vcd"); + $dumpvars; + #10000; + $finish(); + end + + + initial begin + $coverage_control("all", "on"); + $coverage_save("fcover.acdb"); + $display("Functional Coverage saved to fcover.acdb"); +end endmodule \ No newline at end of file