1
\$\begingroup\$

I have a Cyclone V GX starter kit. It comes with 4884 bits on-chip memory. I want to write a module for accessing the on-chip memory. So, I have generated the RAM IP reference design from the IP catalog like this:

module onchipmem (
    aclr,
    address,
    clken,
    clock,
    data,
    rden,
    wren,
    q);

    input     aclr;
    input   [7:0]  address;
    input     clken;
    input     clock;
    input   [15:0]  data;
    input     rden;
    input     wren;
    output  [15:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
    tri0      aclr;
    tri1      clken;
    tri1      clock;
    tri1      rden;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire [15:0] sub_wire0;
wire [15:0] q = sub_wire0[15:0];

altsyncram  altsyncram_component (
          ...
          );

I can write / read data by creating an instance of this module:

onchipmem write_mem (
    .aclr(reset),
    .address(address),
    .clken(ce),
    .clock(clk),
    .data(data),
    .rden(1'b0),
    .wren(1'b1),
    .q()
    );

I want to save data by onchipmem in one module and read data from the same instance of onchipmem from another module. However, creating multiple instances of onchipmem will allocate duplicated block of RAM per instance.

In other words, a single RAM module cannot be called by multiple modules. So how to implement a share RAM module for multiple modules to access?

I found this answer that suggested using an arbiter. He provided some sample codes of an arbiter but it is not completed.

I am new to FPGA and cannot get how it works.

So I am looking for a real and completed example so that I can learn and test it in ModelSim.

Please advise.

\$\endgroup\$
2
  • \$\begingroup\$ well, you will need an arbiter, yes. So, the easiest way is to learn enough HDL to understand what the code does in principle. It's really not that much code, and I don't think you'll have much success elsewhere when you can't formulate a follow-up question to the code you're given. So work on it! \$\endgroup\$ Aug 17, 2018 at 11:57
  • \$\begingroup\$ You need to understand that a verilog module is not called by another module. Modules are connected by wires and those connections are fixed. \$\endgroup\$ Aug 17, 2018 at 14:33

1 Answer 1

2
\$\begingroup\$

An Arbiter is the general way of doing it.

An Arbiter is essentially a block that is connected to your RAM and reads/writes data from/to the RAM.

The arbiter exports interfaces (can be an arbitrary count) to other modules. Through these interfaces, modules can access the RAM via the arbiter. The arbiter internally handles the request from its input. There are several ways of handling requests:

  • The different modules have different priorities.
  • The requests are processed in a round-robin-loop
  • etc.

The specific implementation highly depends on the interface used. The interface from the arbiter to the RAM is given by the RAM module you use. However, these interface standards are mostly not usable for the input ports of an arbiter as they are not able to handle variable timings. If a module wants to write to the RAM but another is given access at the moment the arbiter has to stall the interface until it can process the request.

On Altera systems, the AvalonMM bus is a common way and compatible with many Altera IP cores. But you could also go with Wishbone or a custom bus.

I don't have a complete example because it highly depends on your requirements. However, a simple arbiter is a nice project for learning.


Another quick way to connect two modules to a RAM is generating a dual-port RAM with the Altera Wizard. This RAM has 2 independently usable RAM ports.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.