Failed to use memory bits in fpga

78 Views Asked by At

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

1

There are 1 best solutions below

0
Mikef On

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.