Integration of a DUT with two top_level modules in a UVM SV testbench

Hello all,

I have a design with two top-level modules, these two tops are used based on the memory model i choose (whether it is a single or dual port memory)

my question isas follows : in my top level testbench ,can I instantiate the two modules in the same file or should I create a top testbench for each of the modules ?

Same question for the system verilog interfaces , can I define two interfaces in the same file or not?

thank you for your feedback.

In reply to verif_25:

You do not provide enough information to give you a correct advice.
The number of modules in a file doe’t matter. But you can have also more than 1 DUT module in the toplevel module.

In reply to chr_sue:

Hello thank you for your answer.
I’ll try to detail more : so basically in my design I have the two following verilog files : “memory_rw.v” for single core memory (holding memory_rw top level module ) and an other file called “memory_2rw.v” which holds the memory_2rw module.
as I said these two are two independent top level modules that I need to verify.

my question is about how to verify them in my testbench : should I instantiate both modules in a single testbench module or should I create two different top testbench modules in for each .
same question for the DUT interfaces.

I hope now it is more clear for you.
Thanks.

In reply to verif_25:

Normally independent designs have independent test benches. This is so they can provide independent stimulus and end the test when needed. Even if the stimulus is the same, uou probably want to stop a test as soon as one of the designs fails so that you don’t waste CPU time in simulation.

In reply to verif_25:

It is not of interest which files do you have. Important is only which kind of pinlevel interfaces you have.
It might be a solution to differentiate between the single-port RAM and the dual-port solution using macros when the functional interfaces are the same.
But you could also create 2 UVM environments reusing the agents from the single-port approach in the dual-port solution.

Hello Thank you for your replies.
indeed my memory wrapper IP which holds these two top level modules ( single and dual port memories ) have almost the same pinlevel interfaces except the memory signals which are addr, wr_en; rd_en; wdata; rdata in case of single port mem while for the dual port memory design we have the same signal but twice for each port A & B (addr_a ,addr_b ,wr_en_a,wr_en_b etc…)

I have already built the uvm environment for my memory wrapper but for now it supports only the single port memory model and I really don’t want to duplicate all of the components ( agent , scoreboard etc ) I have already created.

I just want to find a way to make the actual testbench used to verify both designs, is that feasible ?

In reply to verif_25:

There is still not enough information available to answer this question.
Which interface protocoll is used in the DUTs? Is it all the same or do you have differnt functional (pinlevel) interfaces?
Can you share the DUT interfaces please?

In reply to verif_25:

yes as I said in my previous reply Only the name of the module and the memory ports are different ( mem_* I/O ). All other features are identical (APB, Power, BIST, Redundancy, etc.)
below you can see both interfaces, I hope I provided all the needed infos
interface memory_wrapper_rw_if#(
parameter MODE = “ASIC” ,
parameter MEM_NB_WORDS = 32 ,
parameter MEM_SIZE_WORDS = 8 ,
parameter APB_ADDR_WIDTH = 6 ,
parameter ENABLE_ECC = 0 ,
parameter ENABLE_APB = 1 ,
parameter ENABLE_LATCH = 0 ,
parameter ASIC_ENABLE_BIST = 1 ,

// Inputs
logic rst_n_i;
logic mem_wr_clk_i ;
logic mem_wr_rst_n_i ;
logic mem_wr_ena_i ;
logic [$clog2(MEM_NB_WORDS)-1:0] mem_wr_add_i ;
logic [MEM_SIZE_WORDS-1:0] mem_wr_ben_i ;
logic [MEM_SIZE_WORDS-1:0] mem_wr_dat_i ;
logic mem_rd_clk_i ;
logic mem_rd_rst_n_i ;
logic mem_rd_ena_i ;
logic [$clog2(MEM_NB_WORDS)-1:0] mem_rd_add_i ;
logic [MEM_SIZE_WORDS-1:0] mem_rd_dat_o ;
logic pwr_halt_i ;
logic pwr_rdy_o ;
logic core_clk_i ;
logic core_rst_n_i ;
logic apb_pclk_i ;
logic apb_prst_n_i ;
logic [APB_ADDR_WIDTH-1:0] apb_paddr_i ;
logic apb_psel_i ;
logic apb_penable_i ;
logic apb_pwrite_i ;
logic [7:0] apb_pwdata_i ;
logic apb_pstrb_i ;
logic apb_pready_o ;
logic [7:0] apb_prdata_o ;
logic apb_pslverr_o ;
logic test_ena_i ;
logic test_scan_i ;

/////////////////////////////////////////////////////////////////////

interface memory_wrapper_2rw_if#(
parameter MODE = “ASIC” ,
parameter MEM_NB_WORDS = 32 ,
parameter MEM_SIZE_WORDS = 8 ,
parameter APB_ADDR_WIDTH = 6 ,
parameter ENABLE_ECC = 0 ,
parameter ENABLE_APB = 1 ,
parameter ENABLE_LATCH = 0 ,
parameter ASIC_ENABLE_BIST = 1 ,

// Inputs
logic rst_n_i;
[b]logic mem_a_clk_i ;
logic mem_a_rst_n_i ;
logic mem_a_ena_i ;
logic mem_a_rdwen_i ;
logic [$clog2(MEM_NB_WORDS)-1:0] mem_a_add_i ;
logic [MEM_SIZE_WORDS-1:0] mem_a_wr_ben_i;
logic [MEM_SIZE_WORDS-1:0] mem_a_wr_dat_i;
logic [MEM_SIZE_WORDS-1:0] mem_a_rd_dat_o;

logic mem_b_clk_i ;
logic mem_b_rst_n_i ;
logic mem_b_ena_i ;
logic mem_b_rdwen_i ;
logic [$clog2(MEM_NB_WORDS)-1:0[b]] mem_b_add_i ;
logic [MEM_SIZE_WORDS-1:0] mem_b_wr_ben_i;
logic [MEM_SIZE_WORDS-1:0] mem_b_wr_dat_i;
logic [MEM_SIZE_WORDS-1:0] mem_b_rd_dat_o;
logic pwr_halt_i ;
logic pwr_rdy_o ;
logic core_clk_i ;
logic core_rst_n_i ;
logic apb_pclk_i ;
logic apb_prst_n_i ;
logic [APB_ADDR_WIDTH-1:0] apb_paddr_i ;
logic apb_psel_i ;
logic apb_penable_i ;
logic apb_pwrite_i ;
logic [7:0] apb_pwdata_i ;
logic apb_pstrb_i ;
logic apb_pready_o ;
logic [7:0] apb_prdata_o ;
logic apb_pslverr_o ;
logic test_ena_i ;
logic test_scan_i ;

In reply to verif_25:

Thanks, this helps:
Only another short question. The dual port ram allows concurrent access for read and write. Right?

In reply to chr_sue:

yes right

In reply to verif_25:

I’m struggeling with your interfaces.
memory_wrapper_rw_if has 2 clocks/resets/ena. How does this work with a single port mem?

In reply to chr_sue:

we distinguish 1R1W 2P memories ( but it is not a dual port mem as we can not perform for example 2 write Operations simultaneously in both ports) and 2RW DP memories.

Anyway thanks for your help so far , I’ll try to figure it out myself as I don’t think that we are converging as my question is not related to how many clocks or resets I have.

my question is a general one and I wanted to know what is the best practice when we have such design with many top level modules with some common pins.

In reply to verif_25:

The problem is never related to the number of clocks or resets, but it is related to the functional interfaces and how they are working together.
In your case it looks like you have APB bus-based interfaces for the memory access.
And you have 2 access methods:
(1) exclusive read and write
(2) concurrent read and write.
In the UVM you can do anything. The question is whether you are limiting the (re-)usability of your architecture by packing to much functionality into the resulting environment.