在Verilog中推断真正的双端口RAM(Xilinx和Intel兼容)

在Verilog中推断真正的双端口RAM(Xilinx和Intel兼容),verilog,fpga,xilinx,intel-fpga,Verilog,Fpga,Xilinx,Intel Fpga,我试图编写自己真正的双端口内存模块,希望它可以推断为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

我试图编写自己真正的双端口内存模块,希望它可以推断为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
第1点让我印象最深,因为这意味着没有办法编写一个可移植的真正的双端口BRAM。我想知道这是我错了还是我应该只使用ip生成。谢谢

我不认为#1意味着你不能进行多次写入——只是你不能在同一个过程中进行写入。试着把它们分开:

always_ff @ (posedge clk) begin
    if (wr0 && ~rd0)
        mem[addr0] <= in0;
    if (rd0 && ~wr0)
        data0 <= mem[addr0];
end
always_ff @ (posedge clk) begin
    if (wr1 && ~rd1)
        mem[addr1] <= in1;
    if (rd1 && ~wr1)
        data1 <= mem[addr1];
end
始终\u ff@(posedge clk)开始
if(wr0&&rd0)

我明白了。本例中的进程是“始终”块的另一个术语。感谢您的帮助。
mem
由两人分配的
始终\u ff
不应合法。SystemVerilog LRM第9.2.2.4节“在
始终\u ff
过程中,赋值左侧的变量,包括来自被调用函数内容的变量,不得通过任何其他过程写入。如果
始终\u ff
过程中的行为不代表顺序逻辑,软件工具应执行附加检查以发出警告。“从技术上讲,将其更改为<代码>始终可以使LRM透视图合法,但合成工具通常要求寄存器仅由一个进程分配。好的一点是,<代码>始终更好。Xilinx合成工具将其推断为双端口RAM,这是它更喜欢的模板。
always_ff @ (posedge clk) begin
    if (wr0 && ~rd0)
        mem[addr0] <= in0;
    if (rd0 && ~wr0)
        data0 <= mem[addr0];
end
always_ff @ (posedge clk) begin
    if (wr1 && ~rd1)
        mem[addr1] <= in1;
    if (rd1 && ~wr1)
        data1 <= mem[addr1];
end