From 5b77cd0b26abf7e3c2dfebb6c1f6466c064a7212 Mon Sep 17 00:00:00 2001 From: Jiss Date: Sun, 22 Sep 2024 20:56:33 +0100 Subject: [PATCH 01/20] Implemented FSM and Pslverr signal --- rtl/traffic.sv | 125 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 105 insertions(+), 20 deletions(-) diff --git a/rtl/traffic.sv b/rtl/traffic.sv index e9f4434..6b9c167 100644 --- a/rtl/traffic.sv +++ b/rtl/traffic.sv @@ -7,6 +7,7 @@ module traffic ( input pclk, input penable, // Outputs + output reg pready, pslverr, output [31:0] prdata); reg [3:0] ctl_reg; // profile, blink_red, blink_yellow, mod_en RW @@ -16,41 +17,125 @@ module traffic ( input pclk, reg [31:0] data_in; reg [31:0] rdata_tmp; - + typedef enum {idle = 0, setup = 1, access = 2, transfer = 3} state_type; + state_type state = idle, next_state = idle; // Set all registers to default values always @ (posedge pclk) begin if (!presetn) begin + state <=idle; + prdata <=32'h00000000; + pready <= 1'b0; + pslverr<= 1'b0; 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) - case (paddr) + else + begin + case (state) + idle: + begin + + prdata <=32'h00000000; + pready <= 1'b0; + pslverr<= 1'b0; + data_in <= 0; + ctl_reg <= 0; + stat_reg <= 0; + timer_0 <= 32'hcafe_1234; + timer_1 <= 32'hface_5678; + if (psel == 1'b0) && (penable == 1'b0) + state<=setup; + end + + + setup: + begin + if ((psel == 1'b1) && (penable == 1'b0)) begin + if(paddr<32) begin + state<=access; + pready<=1'b1; + end + else begin + state <=access; + pready<=1'b0; + end + + else + state<= setup; + end + + + end + + access: + begin + if (psel && pwrite && penable) + begin + if(paddr<32) + begin + case (paddr) 'h0 : ctl_reg <= pwdata; 'h4 : timer_0 <= pwdata; 'h8 : timer_1 <= pwdata; 'hc : stat_reg <= pwdata; - 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 + state <= transfer; + pslverr<=1'b0; + + end + else + begin + state <= transfer; + pready <= 1'b1; + pslverr <= 1'b1; + + end + + else if (psel && penable && !pwrite) + + begin + if (paddr<32) + begin + case (paddr ) + 'h0 : rdata_tmp <= ctl_reg; + 'h4 : rdata_tmp <= timer_0; + 'h8 : rdata_tmp <= timer_1; + 'hc : rdata_tmp <= stat_reg; + endcase + state <= transfer; + pready <= 1'b1; + pslverr <= 1'b0; + end + else + begin + state <= transfer; + pready <= 1'b1; + pslverr <= 1'b1; + prdata <= 32'hxxxxxxxx; + end + + end + + + end + + end + + transfer: + begin + end + default: state<=idle; + endcase + assign prdata = (psel & penable & !pwrite) ? rdata_tmp : 'hz; + end + end + - assign prdata = (psel & penable & !pwrite) ? rdata_tmp : 'hz; + endmodule \ No newline at end of file From abeaf7647206e57b0a8e8cfbe9e77de2d614b583 Mon Sep 17 00:00:00 2001 From: Jiss Date: Mon, 30 Sep 2024 18:47:57 +0100 Subject: [PATCH 02/20] ctl_register_functional_coverage --- tb/reg_lib/ral_cfg_ctl.sv | 57 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/tb/reg_lib/ral_cfg_ctl.sv b/tb/reg_lib/ral_cfg_ctl.sv index 623aeb9..3a79d08 100644 --- a/tb/reg_lib/ral_cfg_ctl.sv +++ b/tb/reg_lib/ral_cfg_ctl.sv @@ -6,10 +6,63 @@ class ral_cfg_ctl extends uvm_reg; rand uvm_reg_field profile; // 1 : Peak, 0 : Off-Peak `uvm_object_utils(ral_cfg_ctl) +// new code start - function new(string name = "traffic_cfg_ctrl"); +////////////////////////adding coverpoints + + covergroup mod_cov; + + option.per_instance = 1; + + + coverpoint mod_en + { + bins low = {0}; + bins high = {1}; + } + + coverpoint bl_yellow; + coverpoint b1_red; + coverpoint profile; + + endgroup + + + ////////////////checking coverage and adding new method to covergroup + + function new (string name = "ral_cfg_ctl"); + super.new(name,32,UVM_CVR_FIELD_VALS); + + if(has_coverage(UVM_CVR_FIELD_VALS)) + mod_en = new(); + + endfunction + +////////////////////////////// implementation of sample and sample_Values + + + virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + mod_en.sample(); + endfunction + + + virtual function void sample_values(); + super.sample_values(); + + mod_en.sample(); + + endfunction + + + //new code end: jissjoseph1997 + + /* function new(string name = "traffic_cfg_ctrl"); super.new(name, 32, build_coverage(UVM_NO_COVERAGE)); - endfunction: new + endfunction: new */ // Build all register field objects virtual function void build(); From d025bf6cf2e7f6750e6e67e7ae0722ac42e8b65b Mon Sep 17 00:00:00 2001 From: Jiss Date: Tue, 7 Jan 2025 10:54:44 +0000 Subject: [PATCH 03/20] Added Pready signal --- tb/apb_if.sv | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tb/apb_if.sv b/tb/apb_if.sv index a9b53c0..b3a157a 100644 --- a/tb/apb_if.sv +++ b/tb/apb_if.sv @@ -1,9 +1,9 @@ -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 endinterface \ No newline at end of file From 297f1bb06bc271c525da052dead9eaf5cdf9fbc3 Mon Sep 17 00:00:00 2001 From: Jiss Date: Tue, 7 Jan 2025 15:47:25 +0000 Subject: [PATCH 04/20] Added FSM, APB protocol error signaling, reset op --- rtl/traffic.sv | 216 ++++++++++++++++++------------------------------- 1 file changed, 80 insertions(+), 136 deletions(-) diff --git a/rtl/traffic.sv b/rtl/traffic.sv index 6b9c167..49fdf6d 100644 --- a/rtl/traffic.sv +++ b/rtl/traffic.sv @@ -1,141 +1,85 @@ -module traffic ( input pclk, - input presetn, - input [31:0] paddr, - input [31:0] pwdata, - input psel, - input pwrite, - input penable, - - // Outputs - output reg pready, pslverr, - 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; - typedef enum {idle = 0, setup = 1, access = 2, transfer = 3} state_type; - state_type state = idle, next_state = idle; - // Set all registers to default values - always @ (posedge pclk) begin - if (!presetn) begin - state <=idle; - prdata <=32'h00000000; - pready <= 1'b0; - pslverr<= 1'b0; - data_in <= 0; - ctl_reg <= 0; - stat_reg <= 0; - timer_0 <= 32'hcafe_1234; - timer_1 <= 32'hface_5678; - end - else - begin - case (state) - idle: - begin - - prdata <=32'h00000000; +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 (!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; - data_in <= 0; - ctl_reg <= 0; - stat_reg <= 0; - timer_0 <= 32'hcafe_1234; - timer_1 <= 32'hface_5678; - if (psel == 1'b0) && (penable == 1'b0) - state<=setup; - end - - - setup: - begin - if ((psel == 1'b1) && (penable == 1'b0)) begin - if(paddr<32) begin - state<=access; - pready<=1'b1; - end - else begin - state <=access; - pready<=1'b0; - end - - else - state<= setup; - end - - - end - - access: - begin - if (psel && pwrite && penable) - begin - if(paddr<32) - begin - case (paddr) - 'h0 : ctl_reg <= pwdata; - 'h4 : timer_0 <= pwdata; - 'h8 : timer_1 <= pwdata; - 'hc : stat_reg <= pwdata; - endcase - state <= transfer; - pslverr<=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 - else - begin - state <= transfer; - pready <= 1'b1; - pslverr <= 1'b1; - - end - else if (psel && penable && !pwrite) - - begin - if (paddr<32) - begin - case (paddr ) - 'h0 : rdata_tmp <= ctl_reg; - 'h4 : rdata_tmp <= timer_0; - 'h8 : rdata_tmp <= timer_1; - 'hc : rdata_tmp <= stat_reg; - endcase - state <= transfer; - pready <= 1'b1; - pslverr <= 1'b0; - end - else - begin - state <= transfer; - pready <= 1'b1; - pslverr <= 1'b1; - prdata <= 32'hxxxxxxxx; - end - - end - - - end - - end - - transfer: - begin - end - default: state<=idle; - - endcase - assign prdata = (psel & penable & !pwrite) ? rdata_tmp : 'hz; + 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) + 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 - - 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 + end endmodule \ No newline at end of file From 5501ee269dcdbe2ca67a02e038d598642db78a64 Mon Sep 17 00:00:00 2001 From: Jiss Date: Tue, 7 Jan 2025 15:58:45 +0000 Subject: [PATCH 05/20] Read and write op to ctrl, timer reg with coverage --- tb/seq_lib/my_sequence.sv | 70 +++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 21 deletions(-) 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 From f51f1a857e8fb934022897ae883d895c05c329ff Mon Sep 17 00:00:00 2001 From: Jiss Date: Tue, 7 Jan 2025 16:06:21 +0000 Subject: [PATCH 06/20] Added coverage constructs and reset value --- tb/reg_lib/ral_cfg_ctl.sv | 108 +++++++++++++++----------------------- 1 file changed, 43 insertions(+), 65 deletions(-) diff --git a/tb/reg_lib/ral_cfg_ctl.sv b/tb/reg_lib/ral_cfg_ctl.sv index 3a79d08..ddab359 100644 --- a/tb/reg_lib/ral_cfg_ctl.sv +++ b/tb/reg_lib/ral_cfg_ctl.sv @@ -1,80 +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) -// new code start -////////////////////////adding coverpoints + - covergroup mod_cov; - - option.per_instance = 1; - - - coverpoint mod_en - { - bins low = {0}; - bins high = {1}; + // 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}; +} - coverpoint bl_yellow; - coverpoint b1_red; - coverpoint profile; - - endgroup - - ////////////////checking coverage and adding new method to covergroup - - function new (string name = "ral_cfg_ctl"); - super.new(name,32,UVM_CVR_FIELD_VALS); - - if(has_coverage(UVM_CVR_FIELD_VALS)) - mod_en = new(); - - endfunction - -////////////////////////////// implementation of sample and sample_Values - - - virtual function void sample(uvm_reg_data_t data, - uvm_reg_data_t byte_en, - bit is_read, - uvm_reg_map map); - - mod_en.sample(); - endfunction - + endgroup - virtual function void sample_values(); - super.sample_values(); - - mod_en.sample(); - - endfunction - - - //new code end: jissjoseph1997 + 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); - /* function new(string name = "traffic_cfg_ctrl"); - super.new(name, 32, build_coverage(UVM_NO_COVERAGE)); - endfunction: new */ + 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()); - // 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.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); + + this.set_reset(32'h00000000, "SOFT"); // Reset value for ctl_reg endfunction + endclass \ No newline at end of file From 47dc04685572162222275f3dfdca18d610f98677 Mon Sep 17 00:00:00 2001 From: Jiss Date: Tue, 7 Jan 2025 16:09:32 +0000 Subject: [PATCH 07/20] constructor modified to enable coverage --- tb/reg_lib/ral_block_traffic_cfg.sv | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) 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(); From bc9f6c1e99e4cde9c352c4ba4c1012b8233d2e30 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 07:23:20 +0000 Subject: [PATCH 08/20] added reset value --- tb/reg_lib/ral_cfg_stat.sv | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) 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 + From 1a9cb71a6e062af864690da81823180c342d07a6 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 07:26:30 +0000 Subject: [PATCH 09/20] enabled coverage and added reset value --- tb/reg_lib/ral_cfg_timer.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 41f9d4890b17f96d6010a9c2a6f4adfccc709740 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 07:41:35 +0000 Subject: [PATCH 10/20] Added APB pready signal config --- tb/apb_driver.sv | 59 ++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 25 deletions(-) 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 From 5f0b956e53e8a528674445cf86df439fc8a59a21 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 07:47:08 +0000 Subject: [PATCH 11/20] Added display task for better debug information --- tb/apb_monitor.sv | 58 ++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 23 deletions(-) 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 From d7ebcc25ba67ab1b4f42f98612a503eddf67d213 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 08:13:54 +0000 Subject: [PATCH 12/20] Reset display tasks for additional information --- tb/seq_lib/reset_seq.sv | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) 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 From c6b8e33078518e6b4729255333237a0db56a6c60 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 08:20:54 +0000 Subject: [PATCH 13/20] Added reset sequence to the read write test --- tb/reg_rw_test.sv | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) 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 + From b878e005fa142144ecc4fda810d86c572b521317 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 08:23:23 +0000 Subject: [PATCH 14/20] top mod port modification and included cov db save --- tb/top.sv | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/tb/top.sv b/tb/top.sv index 0cb04ec..b64ce60 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,10 @@ 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 +23,16 @@ module top; .prdata (apb_if.prdata), .psel (apb_if.psel), .pwrite (apb_if.pwrite), + .pready (apb_if.pready), .penable (apb_if.penable)); initial begin + `ifdef XCELIUM $recordvars(); `endif `ifdef VCS - $vcdpluson; + // $vcdpluson; `endif `ifdef QUESTA $wlfdumpvars(); @@ -39,5 +41,20 @@ 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 From e50cf66e52667d72d6966775aca08e45df04cec6 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 10:53:43 +0000 Subject: [PATCH 15/20] added assertions for address check --- tb/apb_if.sv | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tb/apb_if.sv b/tb/apb_if.sv index b3a157a..e6ae855 100644 --- a/tb/apb_if.sv +++ b/tb/apb_if.sv @@ -6,4 +6,15 @@ interface apb_if (input pclk, input presetn); // presetn as input 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 From f5cbf03718f8847f817dbd6cd2c6404c7e65deea Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 10:54:36 +0000 Subject: [PATCH 16/20] Added invalid address response --- rtl/traffic.sv | 1 + 1 file changed, 1 insertion(+) diff --git a/rtl/traffic.sv b/rtl/traffic.sv index 49fdf6d..bdcc4a9 100644 --- a/rtl/traffic.sv +++ b/rtl/traffic.sv @@ -21,6 +21,7 @@ module traffic ( // 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; From 3d0c120e3d1371e089435c82eb81b3888341d7d3 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 10:55:53 +0000 Subject: [PATCH 17/20] instantiated DUT with additional APB signals --- tb/top.sv | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tb/top.sv b/tb/top.sv index b64ce60..0292902 100644 --- a/tb/top.sv +++ b/tb/top.sv @@ -1,4 +1,4 @@ - module top; + module top; import uvm_pkg::*; // import my_pkg::*; @@ -9,6 +9,7 @@ always #10 pclk = ~pclk; + initial begin presetn = 0; // Assert reset #50 presetn = 1; // Deassert reset after 50 time units @@ -24,7 +25,8 @@ .psel (apb_if.psel), .pwrite (apb_if.pwrite), .pready (apb_if.pready), - .penable (apb_if.penable)); + .penable (apb_if.penable), + .pslverr(apb_if.pslverr)); initial begin @@ -56,5 +58,4 @@ $coverage_save("fcover.acdb"); $display("Functional Coverage saved to fcover.acdb"); end - endmodule \ No newline at end of file From 9438570d0c249eda3b329737e4cf2000aaec8746 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 10:59:52 +0000 Subject: [PATCH 18/20] New Test for invalid DUT address test --- tb/invalid_address_test.sv | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tb/invalid_address_test.sv 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 From 76eb5c54bd468ab70e1bfad76e2f542424daf109 Mon Sep 17 00:00:00 2001 From: Jiss Date: Wed, 8 Jan 2025 11:02:03 +0000 Subject: [PATCH 19/20] New sequence to check invalid address --- tb/seq_lib/invalid_address_sequence.sv | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tb/seq_lib/invalid_address_sequence.sv 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 From 4044f351cd462f1762ea6a277f646872d2a657d3 Mon Sep 17 00:00:00 2001 From: JISS JOSEPH Date: Wed, 8 Jan 2025 11:06:09 +0000 Subject: [PATCH 20/20] Add files via upload coverage report for ral_cfg_ctl register --- coverage.png | Bin 0 -> 36385 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 coverage.png diff --git a/coverage.png b/coverage.png new file mode 100644 index 0000000000000000000000000000000000000000..509f9d1f7a20d11739efb61424ff430557b0cd82 GIT binary patch literal 36385 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 literal 0 HcmV?d00001