0

This is a code for a 2 port data memory. When I compile it on quartus, number of memory bits are zero and is implemented as logic elements and doesn't infere a ram. How to solve that?

module dataMemoryTwoPorts( PAaddress , PBaddress , PAwriteData , PBwriteData , PAreadData , PBreadData,
                                 PAwriteEn , PBwriteEn , PAreadEn , PBreadEn , clk);

    // Inputs

    // clock
    input clk;

    // Enables allow reading from memory from port A and port B 
    input PAreadEn , PBreadEn;

    // Enables allow writing on memory through port A and port B
    input PAwriteEn , PBwriteEn;

    // Address of location to be accessed by port A and port B
    input [31:0] PAaddress , PBaddress;

    // Data to be written through port A and port B
    input [31:0] PAwriteData , PBwriteData;

    // Outputs

    // Data to be read from port A and port B
    output [31:0] PAreadData , PBreadData;

    // Creating the memory vector
    reg [7:0] dataMemory [0:8191];

    //Initialize memory 
    initial begin
        $readmemh("dataMemory.txt", dataMemory); 
    end

    // Read operation, read only if the address is aligned and the read port is activated
    assign PAreadData = ( PAreadEn  ) ? { dataMemory[ PAaddress + 3 ] , dataMemory[ PAaddress + 2 ] , dataMemory[ PAaddress + 1] , dataMemory[PAaddress] } : 32'bx ;
    assign PBreadData = ( PBreadEn ) ? { dataMemory[ PBaddress + 3 ] , dataMemory[ PBaddress + 2 ] , dataMemory[ PBaddress + 1] , dataMemory[PBaddress] } : 32'bx ;

    // Write operation
    always @ ( posedge  clk ) begin

        // for port A
        if ( PAwriteEn ) begin

            dataMemory [PAaddress  ] <= PAwriteData[7 :0 ];
            dataMemory [PAaddress+1] <= PAwriteData[15:8 ];
            dataMemory [PAaddress+2] <= PAwriteData[23:16];
            dataMemory [PAaddress+3] <= PAwriteData[31:24];

        end     

        // for port B
        if ( PBwriteEn ) begin

            dataMemory [PBaddress  ] <= PBwriteData[7 :0 ];
            dataMemory [PBaddress+1] <= PBwriteData[15:8 ];
            dataMemory [PBaddress+2] <= PBwriteData[23:16];
            dataMemory [PBaddress+3] <= PBwriteData[31:24];

        end  
    end

endmodule

i don't want to change the functionality of the data memory. read operation happen asynchronously write operations happens at posetive edge of the clock memory is byte addresable

4
  • Why would it infer a RAM? You have declared a block of 8,192 byte-wide registers here. Commented Mar 18, 2024 at 20:52
  • @TimRoberts i just followed the templates intel provides to make a ram (ram defined as array of registers) Commented Mar 18, 2024 at 21:04
  • The array should be [8191:0], right? Does your device actually have block RAM? Not all of them do. Commented Mar 19, 2024 at 4:12
  • Have you ran the simulation? What's the ouptut? Commented Mar 19, 2024 at 6:53

1 Answer 1

0

I don't want to change the functionality ... read operation happens asynchronously.

  1. The post sort of has two write ports and one read port. This would require block ram; distributed ram does not have two write ports and one read. Sometimes this is called "True Dual Port" In Xilinx 7-series and beyond (Vivado tools), block ram reads are always synchronous. Very likely is the same in Altera (research to be certain). If you model this in RTL, then the only thing the tool can do is to use flop flops and combinational logic to provide the design behavior.
    This table from ug901-vivado-synthesis helps understand.
    I don't know what the corresponding Altera document is.
    enter image description here
    Here is a related SO post saying something similar, applying it to most FPGAs. why-do-block-rams-have-synchronous-reading-instead-of-async-reading

  1. Actually the design infers eight ports for write. Specifying eight addresses require eight physical ports in hardware (BRAM).
    Four ports here
            dataMemory [PAaddress  ] <= PAwriteData[7 :0 ];
            dataMemory [PAaddress+1] <= PAwriteData[15:8 ];
            dataMemory [PAaddress+2] <= PAwriteData[23:16];
            dataMemory [PAaddress+3] <= PAwriteData[31:24];

Another four ports here

            dataMemory [PBaddress  ] <= PBwriteData[7 :0 ];
            dataMemory [PBaddress+1] <= PBwriteData[15:8 ];
            dataMemory [PBaddress+2] <= PBwriteData[23:16];
            dataMemory [PBaddress+3] <= PBwriteData[31:24];

The physical hardware has two ports, so again its going to build what you have described out of flip flops and combinational logic, not out of BRAM because physical BRAMS don't have the features you are asking for.


If you want to infer a block ram, then begin with the vendors RTL model and synthesize to verify block RAM inference. Use the exact vendors model temporarily as a part of your design. Then modify to suit your needs, and synthesize again. If you model something the hardware and tools are not capable of implementing (like asynchronous read BRAMS, or 8 port BRAMS) then the tool will tell you that in its log messaging or by observing what it does infer.

One way to get everything you want might be to use the synchronous BRAM model, and have a small state machine controller, which would pre fetch a few data locations into some registers/flip flops which can be accessed with 0 latency.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.