Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

I have a problem with True dual port definition in xilinx FPGA

Status
Not open for further replies.

hamed_sotoudi

Full Member level 3
Full Member level 3
Joined
Aug 1, 2007
Messages
156
Helped
15
Reputation
30
Reaction score
5
Trophy points
1,298
Location
Germany Hamburg
Activity points
2,195
Hi every body
I want to define true dual port block ram in my code but when I synthesis the report is read fist. I want to define write first. how can I define the mode of memory(write first or read first)?
 

when you are generating through coregen you can choose the option, whether to write first or read first
 

how do you define it? via coregen or via behavioural code?
 

hi thanks for your quick replies
I implemented in behavioural code and I finally found it. here is code for who one wants to use:

True dual port Ram with Block RAM and write mode or Read mode

constant ADDR_WIDTH : integer := 10;
constant DATA_WIDTH : integer := 16;

type RAM is array (2** ADDR_WIDTH - 1 downto 0) of signed (DATA_WIDTH - 1 downto 0);
shared variable Receive_Buffer : RAM := (others => (others => '0'));
signal Add_A : unsigned(ADDR_WIDTH - 1 downto 0) := (others => '0');
signal Add_B : unsigned(ADDR_WIDTH - 1 downto 0) := to_unsigned(10,ADDR_WIDTH);

signal WEA : std_logic := '0'; -- write enable for portA
signal WEB : std_logic := '0'; -- write enable for portA

signal ClockA : std_logic := '0';
signal ClockB : std_logic := '0';

signal DoutA : signed(DATA_WIDTH-1 downto 0);
signal DoutB : signed(DATA_WIDTH-1 downto 0);

signal DinA : signed(DATA_WIDTH-1 downto 0);
signal DinB : signed(DATA_WIDTH-1 downto 0);

PORTA_Proc:process(ClockA)
begin
if rising_edge(ClockA) then
if Enable = '1' then
DoutA <= Receive_Buffer(to_integer(Add_A));
if WEA = '1' then
Receive_Buffer (to_integer(Add_A)) := DinA;
---- uncomment for Write First Mode
--DoutA <= DinA;
end if;
end if;
end if;
end process PORTA_Proc;

PORTB_Proc:process (ClockB)
begin
if rising_edge(ClockB) then
if Enable = '1' then
DoutB <= Receive_Buffer(to_integer(Add_B));
if WEB = '1' then
Receive_Buffer (to_integer(Add_B)) := DinB;
---- uncomment for Write First Mode
--DoutB <= DinB;
end if;
end if;
end if;
end process PORTB_Proc;
 

first of all, Im not sure you're allowed to use the same enable in both clock domains. For one thing, it would not be properly cynchronised to one of the clocks, and so would cause problems.

Secondly, Im not sure about Xilinx, but I know Altera will not infer true dual port, dual clock ram (ie. read and write on both sides) from behavioural code - you have to use their equivalent of core gen. Xilinx may have a similar problem.

But getting it to infer write first from using a shared variable I have seen discuessed in the past, and was a hit and miss affair accross several synthesisors, but I thought it actually worked for Xilinx. Looks like it may have changed.

The safest thing will be to use core-gen.
 

Secondly, Im not sure about Xilinx, but I know Altera will not infer true dual port, dual clock ram (ie. read and write on both sides) from behavioural code - you have to use their equivalent of core gen. Xilinx may have a similar problem.

...

The safest thing will be to use core-gen.

Agreed. I personally prefer coregen over behavioral for this. Too often I have been bitten by how creative the tools are in how they infer things. This could entirely be my fault by not using the "right" behavioral code. But all in all, using coregen gives me correct results in less time.

Another option I sometimes use is to use coregen first, let it generate the module. And then take a look at the module and see how it uses the primitives. This way you can make your own module with those primitives in it, but with your own tweaks.
 
Last edited:

The enable signal is global enable in code so if you want you can change it to dedicated Enable for each port. but it works well I tested it. Shared variable is using to declare synthesizer that this is dual port Ram so there is no problem in Xilinx. and at the last coregen is very easy but there is a problem coregens are not efficient all the time and they are not flexible when you want to carry your code from one version to another so I prefer behavioural code to coregen where I can do it.
 

Hang on a minute - for the write before read behaviour put the write above the read - and it might actually give you write before read. In your current code you're doing read before write.

change to this:

Code:
PORTB_Proc:process (ClockB)
begin
  if rising_edge(ClockB) then
    if Enable = '1' then

      if WEB = '1' then
        Receive_Buffer (to_integer(Add_B)) := DinB;

      end if;

      DoutB <= Receive_Buffer(to_integer(Add_B));
    end if;
  end if;
end process PORTB_Proc;


---------- Post added at 20:20 ---------- Previous post was at 20:19 ----------

You have to remember the difference between variable and signals
 

Hang on a minute - for the write before read behaviour put the write above the read - and it might actually give you write before read. In your current code you're doing read before write.

change to this:

Code:
PORTB_Proc:process (ClockB)
begin
  if rising_edge(ClockB) then
    if Enable = '1' then

      if WEB = '1' then
        Receive_Buffer (to_integer(Add_B)) := DinB;

      end if;

      DoutB <= Receive_Buffer(to_integer(Add_B));
    end if;
  end if;
end process PORTB_Proc;


---------- Post added at 20:20 ---------- Previous post was at 20:19 ----------

You have to remember the difference between variable and signals


Dear TrickDicky
as you see my code I wrote
---- uncomment for Write First Mode
--DoutB <= DinB;
so putting DoutB <= Receive_Buffer(to_integer(Add_B));
above the write operation is essential because if you want to become write first uncommnet above line which is inside the write operation and if write condition occured
this section will be overwriten by DoutB <= DinB;
so it will be write first but if you put DoutB <= Receive_Buffer(to_integer(Add_B));
below DoutB <= DinB;
will be overwriten by DoutB <= Receive_Buffer(to_integer(Add_B));
so this will be read first.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top