Forum Discussion

AEsqu's avatar
AEsqu
Icon for Contributor rankContributor
3 years ago

Dual port RAM Cyclone 5

Hello,

I'm used to use this RTL code in Synplify to instantiate dual port ram for other FPGA's than the cyclone 5:

module dp_block
(
// memory port 1
p1_clk,
p1_addr,
p1_din,
p1_dout,
p1_we,
p1_re,
p1_ena,
// memory port 2
p2_clk,
p2_addr,
p2_din,
p2_dout,
p2_we,
p2_re,
p2_ena
)/*synthesis syn_ramstyle="no_rw_check"*/;

// memory parameter
parameter ADDR_BIT_WIDTH = 8;
parameter DATA_BIT_WIDTH = 16;

// memory port 1
input p1_clk;
input [ADDR_BIT_WIDTH-1:0] p1_addr;
input [DATA_BIT_WIDTH-1:0] p1_din;
input p1_we;
input p1_re;
input p1_ena;
output [DATA_BIT_WIDTH-1:0] p1_dout;
reg [DATA_BIT_WIDTH-1:0] p1_dout;

// memory port 2
input p2_clk;
input [ADDR_BIT_WIDTH-1:0] p2_addr;
input [DATA_BIT_WIDTH-1:0] p2_din;
input p2_we;
input p2_re;
input p2_ena;
output [DATA_BIT_WIDTH-1:0] p2_dout;
reg [DATA_BIT_WIDTH-1:0] p2_dout;

// memory
reg [DATA_BIT_WIDTH-1:0] mem [0:(2**ADDR_BIT_WIDTH)-1];

always @(posedge p1_clk) begin
if (p1_ena)
begin
if (p1_we)
mem[p1_addr] <= p1_din;
p1_dout <= mem[p1_addr];
end
end

always @(posedge p2_clk) begin
if (p2_ena)
begin
if (p2_we)
mem[p2_addr] <= p2_din;
p2_dout <= mem[p2_addr];
end
end

endmodule

This is not working for the cyclone 5 apparently (write conflict),

Synplify team told me that Cyclone 5 M10K block only supports new data instead of old data at the read port.

In the Intel coding style reference for the Cyclone 5 document,

I do not see the verilog code example for dual port ram with 2 clocks, like above.

What would be the RTL code to make it work with the cyclone 5?

I have attached a ip configuration picture that would match the RTL code (unfortunately I couldn't find a way in Quartus 21.1 to create verilog/vhdl code for the dual port,

only netlist generation, which is not for me as I use it for different ram sizes and want to keep it generic with only one RTL code for Synplify.

Kind Regards,

Alexandre.

7 Replies

  • sstrell's avatar
    sstrell
    Icon for Super Contributor rankSuper Contributor

    In the Quartus text editor true dual port RAM (dual clock) template (Text Editor Edit menu -> Insert Template), it's a bit different from what you have. New data would imply that on write, you should have, along with writing to the RAM:

    p1_dout <= p1_din; //similar for p2

    You're also missing in your if statements an else check for if p1_we (or p2_we) are low:

    p1_dout <= mem[p1_addr]; //again similar for p2

    I'm also not sure if there are separate RAM enable signals like what you have (p1_ena and p2_ena). They are not in the template.

    Any of these could affect how the RAM gets inferred and whether extra external logic gets added to match your behavioral description.

    • AEsqu's avatar
      AEsqu
      Icon for Contributor rankContributor

      Thank you,

      I couldn't reach the edit/insert template as it only popups when a file is open with the Quartus editor.

      I think the template generator should always be available.

      I will create one from it and try, thanks again sstrell.

  • AEsqu's avatar
    AEsqu
    Icon for Contributor rankContributor

    Synplify still errors out when using the RAM close to the Quartus template (on a ram bigger than 32 bits, using 7 8 bits blocks of dp_block):

    @E:MF212 : dp_block.v(30) | Cannot map ....mem.I_dp_block_6.ram_1[7:0] due to multiple write clocks.

    Looks like a synplify bug.

    I have attached the file where both your remarks are in.

  • sstrell's avatar
    sstrell
    Icon for Super Contributor rankSuper Contributor

    Again, I don't think p1_ena or p2_ena are valid signals for the RAM. They're still in your code.

    • AEsqu's avatar
      AEsqu
      Icon for Contributor rankContributor

      Thank You, Synplify is indeed able to map the RAM in the cyclone 5 when the enables are removed.

      • ShengN_altera's avatar
        ShengN_altera
        Icon for Super Contributor rankSuper Contributor

        Hi,

        Looks like the issue addressed had been resolved.
        I'll now transition this thread to community support.
        If you have a new question, feel free to open a new thread to get the support from Intel experts.

        Thank you.

        Best regards,
        Sheng
        p/s: If any answer from the community or Intel support are helpful, please feel free to give Kudos.

  • AEsqu's avatar
    AEsqu
    Icon for Contributor rankContributor

    Synopsys provided me an updated m_altera file for Synplify, that supports the enable in the dual port ram RTL code,

    (that was supported for the xilinx mapper).

    The code below is now compiling well for the cyclone V.

    module dp_block
    #(parameter DATA_BIT_WIDTH=16, parameter ADDR_BIT_WIDTH=8)
    (
      input [(DATA_BIT_WIDTH-1):0] p1_din, p2_din,
      input [(ADDR_BIT_WIDTH-1):0] p1_addr, p2_addr,
      input p1_we, p2_we, p1_clk, p1_re, p1_ena, p2_clk, p2_re, p2_ena,
      output reg [(DATA_BIT_WIDTH-1):0] p1_dout, p2_dout
    )/*synthesis syn_ramstyle="no_rw_check"*/;
    
      // Declare the RAM variable
      reg [DATA_BIT_WIDTH-1:0] ram[2**ADDR_BIT_WIDTH-1:0];
    
      always @ (posedge p1_clk)
        begin
          if (p1_ena)
            begin
              if (p1_we) 
                begin
                  ram[p1_addr] <= p1_din;
                  p1_dout <= p1_din;
                end
              else 
                begin
                  p1_dout <= ram[p1_addr];
                end 
            end
        end
    
      always @ (posedge p2_clk)
        begin
          if (p2_ena)
            begin 
              if (p2_we) 
                begin
                  ram[p2_addr] <= p2_din;
                  p2_dout <= p2_din;
                end
              else 
                begin
                  p2_dout <= ram[p2_addr];
                end 
            end
        end
    
    endmodule