Forum Discussion

KTsan's avatar
KTsan
Icon for New Contributor rankNew Contributor
7 years ago

How to implement a module for accessing single block of on-chip memory in systemverilog?

Let say I want to model a 8 x 1024 bits Ram.

I can generate a Single Port Ram Module from IP Catalog.

I can access the on-chip memory via a single instance of this "Single Port Ram" module.

However, I have multiple modules which may access this single block of on-chip memory.

By creating multiple instances of "Single Port Ram", it actually instantiate duplicated blocks of on-chip memory per "Single Port Ram" module.

So, I am look for a real example in systemverilog on how to model a module for accessing a single block of on-chip memory by multiple instances of modules.

Please kindly help.

2 Replies

  • Tricky's avatar
    Tricky
    Icon for Occasional Contributor rankOccasional Contributor

    You need an arbiter. With multiple masters for a single ram, you need some logic to decide who gets to access the ram in any given cycle.

    for example:

    always @(posedge clk)
    begin
      if (we(0) ) begin
        mem_we <= we[0];
        mem_din <= din[0];
      end
      else begin
        mem_we <= we[1];
        mem_din <= din[1];
      end
    end
        

    Here, channel 0 has priority over channel 1. With several masters, arbitration schemes can get more complicated - modes like round-robin or lowest port priority are pretty common.

  • KTsan's avatar
    KTsan
    Icon for New Contributor rankNew Contributor

    Sorry about that if I didn't clearly state the issue here. The real problem is : I cannot instantiate two modules for accessing single block of memory.

    Let say I have a single port ram module:

    module single_port_ram
    (
    	input [15:0] data,
    	input [7:0] addr,
    	input we, clk,
    	output [15:0] q
    );
     
    	// Declare the RAM variable
    	reg [15:0] ram[63:0];
    	
    	// Variable to hold the registered read address
    	reg [7:0] addr_reg;
    	
    	always @ (posedge clk)
    	begin
    	// Write
    		if (we)
    			ram[addr] <= data;
    		
    		addr_reg <= addr;
    		
    	end
    		
    	// Continuous assignment implies read returns NEW data.
    	// This is the natural behavior of the TriMatrix memory
    	// blocks in Single Port mode.  
    	assign q = ram[addr_reg];
    	
    endmodule

    I have a top module which connect to two single_port_ram modules for reading 16 bits data at addr1 and addr2 respectively.

    logic[15:0] data1, data2;
    logic[7:0] addr1, addr2;
    logic[15:0] out1, out2;
     
    single_port_ram ram1 (
      data(data1),
      addr(addr1),
      we(0),
      clk(clk),
      q(out1)
    );
     
    single_port_ram ram2 (
      data(data2),
      addr(addr2),
      we(0),
      clk(clk),
      q(out2)
    );

    You can see ram1 and ram2 are actually TWO separated ram blocks (which is not my intent) as I declare the single_port_ram module twice.

    What I want to do is : to have a single module (probably with port interface?) for accessing SINGLE block of memory so that I can create multiple instances of this module in different top modules for accessing same block of memory.

    A stackoverflow user had the same issue and someone suggest to create port interface.

    https://electronics.stackexchange.com/questions/79530/accessing-ram-instance-from-multiple-modules-in-verilog

    Since I am new to systemverilog, I am looking for a real example which can illustrate how it works.

    Ken