- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi to everyone, I'm trying to infer a tdpram with rden port , because I need the rden port I insert it in the entity and I tried to use the rden signal . I used the VHDL template for tdpram with mixed port dimensions (asymmetric tdpram) . I tried to synth it with quartus 11.1_sp2 but it shows the error : Error (276001): Cannot synthesize dual-port RAM logic "ram"
it seems that there is a asynchronous read that cause the error.... Also there another error the synth think that the rden port seems an another wren port ??? you specified logic that acts as RAM with at least two write ports, but Analysis & Synthesis can map the RAM write logic only to the same process block. Here a part of the VHDL code :
ibrary ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use std.textio.all;
entity mixed_width_true_dual_port_ram is
generic (
o_ff_a : boolean :=true;
o_ff_b : boolean := true;
DATA_WIDTH1 : natural := 8;
ADDRESS_WIDTH1 : natural := 10;
ADDRESS_WIDTH2 : natural := 8 ;
is_Stratix_V : boolean := true);
port (
we1 : in std_logic;
we2 : in std_logic;
rden_a : in std_logic;
rden_b : in std_logic;
clk_a : in std_logic;
clk_b : in std_logic;
addr1 : in std_logic_vector (ADDRESS_WIDTH1-1 downto 0);
addr2 : in std_logic_vector (ADDRESS_WIDTH2-1 downto 0);
data_in1 : in std_logic_vector(DATA_WIDTH1 - 1 downto 0);
data_in2 : in std_logic_vector(DATA_WIDTH1 * (2 ** (ADDRESS_WIDTH1 - ADDRESS_WIDTH2)) - 1 downto 0);
data_out1 : out std_logic_vector(DATA_WIDTH1 - 1 downto 0);
data_out2 : out std_logic_vector(DATA_WIDTH1 * 2 ** (ADDRESS_WIDTH1 - ADDRESS_WIDTH2) - 1 downto 0));
end mixed_width_true_dual_port_ram;
architecture rtl of mixed_width_true_dual_port_ram is
constant RATIO : natural := 2 ** (ADDRESS_WIDTH1 - ADDRESS_WIDTH2) ;
constant DATA_WIDTH2 : natural := DATA_WIDTH1 * RATIO;
constant RAM_DEPTH : natural := 2 ** ADDRESS_WIDTH2;
constant numwords_a : integer := (2**ADDRESS_WIDTH1);
constant numwords_b : integer := (2**ADDRESS_WIDTH2);
-- Use a multidimensional array to model mixed-width
type word_t is array(RATIO - 1 downto 0) of std_logic_vector(DATA_WIDTH1 - 1 downto 0);
type ram_t is array (0 to RAM_DEPTH - 1) of word_t;
-- declare the RAM
-- signal ram : ram_t;
shared variable ram : ram_t;
signal w1_local : word_t;
signal q1_local : word_t;
signal data_out1_int : std_logic_vector(DATA_WIDTH1 - 1 downto 0);
signal data_out1_int_d1 : std_logic_vector(DATA_WIDTH1 - 1 downto 0);
signal data_out2_int : std_logic_vector(DATA_WIDTH1 * 2 ** (ADDRESS_WIDTH1 - ADDRESS_WIDTH2) - 1 downto 0);
signal data_out2_int_d1 : std_logic_vector(DATA_WIDTH1 * 2 ** (ADDRESS_WIDTH1 - ADDRESS_WIDTH2) - 1 downto 0);
signal rden_a1 : std_logic;
signal rden_b1 : std_logic;
signal addr_1 : std_logic_vector (ADDRESS_WIDTH1-1 downto 0);
signal addr_2 : std_logic_vector (ADDRESS_WIDTH2-1 downto 0);
begin
process (addr1, addr2)
variable v_add_1 : std_logic_vector(ADDRESS_WIDTH1-1 downto 0);
variable v_add_2 : std_logic_vector(ADDRESS_WIDTH2-1 downto 0);
begin
v_add_1 := addr1;
v_add_2 := addr2;
-- synthesis translate_off
if conv_integer(addr1)>=numwords_a then
v_add_2 := (others=>'0');
end if;
if conv_integer(addr2)>=numwords_b then
v_add_2 := (others=>'0');
end if;
-- synthesis translate_on
addr_1 <= v_add_1;
addr_2 <= v_add_2;
end process;
-- rtl
-- Re-organize the write data to match the RAM word type
unpack: for i in 0 to RATIO - 1 generate
w1_local(i) <= data_in2(DATA_WIDTH1*(i+1) - 1 downto DATA_WIDTH1*i);
data_out2_int(DATA_WIDTH1*(i+1) - 1 downto DATA_WIDTH1*i) <= q1_local(i);
end generate unpack;
Stratix_IV :
if is_Stratix_V=false generate
begin
--port A
process(clk_a)
begin
if(rising_edge(clk_a)) then
if (rden_b='1') then
q1_local <= ram(conv_integer(addr2));
end if;
if(we2 = '1') then
ram(conv_integer(addr_2)) := w1_local;
end if;
-- q1_local <= ram(conv_integer(addr_2)); --example by Quartus
end if;
end process;
-- port B
process(clk_b)
begin
if(rising_edge(clk_b)) then
if (rden_a='1') then
data_out1_int <= ram(conv_integer(addr1) / RATIO )(conv_integer(addr1) mod RATIO); -- example by Quartus
end if;
if(we1 ='1') then
ram(conv_integer(addr_1) / RATIO)(conv_integer(addr_1) mod RATIO) := data_in1;
end if;
-- data_out1_int <= ram(conv_integer(addr_1) / RATIO )(conv_integer(addr_1) mod RATIO);
end if;
end process;
end generate ;
Stratix_V :
if is_Stratix_V=true generate
begin
--port A
process(clk_a)
begin
if(rising_edge(clk_a)) then
-- q1_local <= ram(conv_integer(addr2));
if(we2 = '1') then
ram(conv_integer(addr_2)) := w1_local;
end if;
if (rden_a='1')then
q1_local <= ram(conv_integer(addr_2)); --example by Quartus
end if;
end if;
end process;
-- port B
process(clk_b)
begin
if(rising_edge(clk_b)) then
-- data_out1_int <= ram(conv_integer(addr1) / RATIO )(conv_integer(addr1) mod RATIO); -- example by Quartus
if(we1 ='1') then
ram(conv_integer(addr_1) / RATIO)(conv_integer(addr_1) mod RATIO) := data_in1;
end if;
if (rden_b='1') then
data_out1_int <= ram(conv_integer(addr_1) / RATIO )(conv_integer(addr_1) mod RATIO);
end if;
end if;
end process;
end generate ;
process(clk_a,clk_b)
begin
if rising_edge(clk_a) then
data_out1_int_d1<=data_out1_int;
end if;
if rising_edge(clk_b) then
data_out2_int_d1<=data_out2_int;
end if;
end process;
data_out1 <= data_out1_int_d1 when o_ff_a= true else data_out1_int ;
data_out2 <= data_out2_int_d1 when o_ff_a= true else data_out2_int ;
end rtl;
Most of the code has been reused from the Quartus tdpram mixed template, the only differences are the introduction of 2 clocks and the rden_a and rden_b port, In the Quartus Handbook there are no examples of using rden port from inferring Rams so could not be inferred the rden port?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- the only differences are the introduction of 2 clocks and the rden_a and rden_b port --- Quote End --- "The only difference" actually matters. Your code requests synthesis of a RAM output register, that holds the previous value if rd_en is inactive. But there's no equivalent register avaible in the hardware. Please notice that the clocked read action you are associating with rd_en is actually "absorbed" by the register level at the RAM input, so it's not available at the RAM output. I don't clearly see, what's the purpose of the rd_en action in your design. The RAM itself doesn't require it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My question is possible to infer the read enable port in a Vhdl model for Altsyncram without using Altera Megawizard? In some our projects we had some rams generated with megawizard with an effective rden signal (not cabled to '1' value), for portability coding we want to infer Rams directly in VHDL code . Could give us an example of infering a ram with rden enable synthetizable by Quartus II?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You didn't yet answer about the intended function of the rd_en. Do you have a register holding previous values in your compatible projects?
As I already mentioned, it's impossible to have an synchronous output register and no additional delay of one clock cycle with Altera RAM blocks. You can either implement a transparent latch or a register with delay.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This sounds interesting to know.. "P

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page