I tried to write my own true dual-port memory module, hoping that it would infer as a BRAM:
module dp_async_ram (clk, rst, rd0, rd1, wr0, wr1, in1, in0, out1,out0, addr0, addr1);
parameter DEPTH = 16;
parameter WIDTH = 8;
parameter ADDR = 4;
input clk, rst;
input rd0, rd1;
input wr0, wr1;
input [WIDTH-1:0] in0, in1;
input [ADDR-1:0] addr0, addr1;
output [WIDTH-1:0] out0, out1;
//Define Memory
logic [WIDTH-1:0] mem [0:DEPTH-1];
logic [WIDTH-1:0] data0, data1;
//Write Logic
always_ff @ (posedge clk) begin
if (wr0 && ~rd0)
mem[addr0] <= in0;
if (wr1 && ~rd1)
mem[addr1] <= in1;
if (rd0 && ~wr0)
data0 <= mem[addr0];
if (rd1 && ~wr1)
data1 <= mem[addr1];
end
//Read Logic
assign out0 = (rd0 && (!wr0))? data0: {WIDTH{1'bz}}; //High Impedance Mode here
assign out1 = (rd0 && (!wr0))? data1: {WIDTH{1'bz}};
endmodule // dp_async_ram
After running synthesis in Vivado, in the report says the following:
WARNING: [Synth 8-4767] Trying to implement RAM 'mem_reg' in registers. Block RAM or DRAM implementation is not possible; see log for reasons.
Reason is one or more of the following :
1: RAM has multiple writes via different ports in same process. If RAM inferencing intended, write to one port per process.
2: Unable to determine number of words or word size in RAM.
3: No valid read/write found for RAM.
RAM "mem_reg" dissolved into registers
Number 1 Strikes me the most since this implies there is no way to code a portable true dual port BRAM. I was wondering if I am wrong with this or if I should just use ip generation. Thanks
I don't think #1 means that you can't do multiple writes--just that you can't do them from the same process. Try splitting them up:
always @ (posedge clk) begin
if (wr0 && ~rd0)
mem[addr0] <= in0;
if (rd0 && ~wr0)
data0 <= mem[addr0];
end
always @ (posedge clk) begin
if (wr1 && ~rd1)
mem[addr1] <= in1;
if (rd1 && ~wr1)
data1 <= mem[addr1];
end
For more information on how to infer things in Vivado, look in the 'UG901 Vivado Synthesis' doc. For TDP BRAM, look under "RAM HDL Coding Techniques".
Alternately, if you don't mind being locked in to Xilinx, you can use the xpm_memory_tdpram
module.