Altera_Forum
Honored Contributor
11 years agoHas anyone successfully inferred read enable ports on true dual-port ram?
The megawizard successfully produces the following true dual-port altsyncram code with read enables:
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module ram_dp (
address_a,
address_b,
clock_a,
clock_b,
data_a,
data_b,
rden_a,
rden_b,
wren_a,
wren_b,
q_a,
q_b);
input address_a;
input address_b;
input clock_a;
input clock_b;
input data_a;
input data_b;
input rden_a;
input rden_b;
input wren_a;
input wren_b;
output q_a;
output q_b;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri1 clock_a;
tri1 rden_a;
tri1 rden_b;
tri0 wren_a;
tri0 wren_b;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif
wire sub_wire0;
wire sub_wire1;
wire q_a = sub_wire0;
wire q_b = sub_wire1;
altsyncram altsyncram_component (
.clock0 (clock_a),
.wren_a (wren_a),
.address_b (address_b),
.clock1 (clock_b),
.data_b (data_b),
.rden_a (rden_a),
.wren_b (wren_b),
.address_a (address_a),
.data_a (data_a),
.rden_b (rden_b),
.q_a (sub_wire0),
.q_b (sub_wire1),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus ());
Since I'd rather use inference, I started with the template wizard. The template wizard produces the following code for true dual-port ram: // Quartus II Verilog Template
// True Dual Port RAM with dual clocks
module true_dual_port_ram_dual_clock# (parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
(
input data_a, data_b,
input addr_a, addr_b,
input we_a, we_b, clk_a, clk_b,
output reg q_a, q_b
);
// Declare the RAM variable
reg ram;
always @ (posedge clk_a)
begin
// Port A
if (we_a)
begin
ram <= data_a;
q_a <= data_a;
end
else
begin
q_a <= ram;
end
end
always @ (posedge clk_b)
begin
// Port B
if (we_b)
begin
ram <= data_b;
q_b <= data_b;
end
else
begin
q_b <= ram;
end
end
endmodule
I've modified it to have read enables like so: // Quartus II Verilog Template// True Dual Port RAM with dual clocks
module true_dual_port_ram_dual_clock# (parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
(
input data_a, data_b,
input addr_a, addr_b,
input we_a, we_b, clk_a, clk_b,
input re_a, re_b,
output reg q_a, q_b
);
// Declare the RAM variable
reg ram;
always @ (posedge clk_a)
begin
// Port A
if (we_a)
begin
ram <= data_a;
q_a <= data_a;
end
else if (re_a)
begin
q_a <= ram;
end
end
always @ (posedge clk_b)
begin
// Port B
if (we_b)
begin
ram <= data_b;
q_b <= data_b;
end
else if (re_b)
begin
q_b <= ram;
end
end
endmodule
However that produces the following errors: Info (276014): Found 1 instances of uninferred RAM logic Info (276007): RAM logic "dual_port_ram:tdp|ram" is uninferred due to asynchronous read logic
Thinking maybe both output flops need the rden, I changed it to: // Quartus II Verilog Template// True Dual Port RAM with dual clocks
module true_dual_port_ram_dual_clock# (parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
(
input data_a, data_b,
input addr_a, addr_b,
input we_a, we_b, clk_a, clk_b,
input re_a, re_b,
output reg q_a, q_b
);
// Declare the RAM variable
reg ram;
always @ (posedge clk_a)
begin
// Port A
if (we_a)
begin
ram <= data_a;
if (re_a)
q_a <= data_a;
end
else if (re_a)
begin
q_a <= ram;
end
end
always @ (posedge clk_b)
begin
// Port B
if (we_b)
begin
ram <= data_b;
if (re_b)
q_b <= data_b;
end
else if (re_b)
begin
q_b <= ram;
end
end
endmodule
Which produced the same inference error. I've tried quite a few permutations. Any ideas?