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.

Inferred VHDL dual port RAM template

Status
Not open for further replies.

shaiko

Advanced Member level 5
Joined
Aug 20, 2011
Messages
2,644
Helped
303
Reputation
608
Reaction score
297
Trophy points
1,363
Activity points
18,302
Hello,

Taken from this link:
https://www.intel.com/content/www/u...n-software/vhdl/vhd-single-clock-syncram.html

The following code is an Intel VHDL template for inference of "Single Clock Synchronous RAM".
Code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

ENTITY ram IS
	GENERIC
	(
		ADDRESS_WIDTH	: integer := 4;
		DATA_WIDTH	: integer := 8
	);
	PORT
	(
		clock			: IN  std_logic;
		data			: IN  std_logic_vector(DATA_WIDTH - 1 DOWNTO 0);
		write_address			: IN  std_logic_vector(ADDRESS_WIDTH - 1 DOWNTO 0);
		read_address			: IN  std_logic_vector(ADDRESS_WIDTH - 1 DOWNTO 0);
		we			: IN  std_logic;
		q			: OUT std_logic_vector(DATA_WIDTH - 1 DOWNTO 0)
	);
END ram;

ARCHITECTURE rtl OF ram IS
	TYPE RAM IS ARRAY(0 TO 2 ** ADDRESS_WIDTH - 1) OF std_logic_vector(DATA_WIDTH - 1 DOWNTO 0);

	SIGNAL ram_block : RAM;
BEGIN
	PROCESS (clock)
	BEGIN
		IF (clock'event AND clock = '1') THEN
			IF (we = '1') THEN
			    ram_block(to_integer(unsigned(write_address))) <= data;
			END IF;

			q <= ram_block(to_integer(unsigned(read_address)));
		END IF;
	END PROCESS;
END rtl;
As far as I understand - it will have a "Read Before Write" behavior when the same address is accessed.
Question:
Can you think of a way to change the above to behave as "Write Before Read" ?
 

For xilinx you can do this by making the ram storage a shared variable rather than signal. But this never used to work for write before read in altera. Your only choice was to instantiate an altsyncram yourself.

This may have changed, but you'll have to investigate. Imo, if you have an address collision and you're relying on write before read behaviour, you probably have a design problem.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
But this never used to work for write before read in altera
When was the last time you tried it ?

They do have a template that makes use of a shared variable - but it's for a "True Dual-Port RAM with a Single Clock".
https://www.intel.com/content/www/u...oftware/vhdl/vhd-true-dual-port-ram-sclk.html
From reading the code this should have "Read Before Write" behavior.

Imo, if you have an address collision and you're relying on write before read behaviour, you probably have a design problem.
This isn't necessarily true.
For example - I worked on a third party code that implements an histogram equalization algorithm.
It would function correctly as long as the RAM is set to work as "Read Before Write" and fail for "Write Before Read".
Not the most portable design - but I wouldn't call it a bug.
 

How important is portability vs vendor ip instantiation?

Just a brain dump - Based on the code presented you'll always have to wait 1 cycle after we='1' before your see write value pushed out onto the read q signal. Why not assign a valid signal associated with your read that is either delayed 'we' or a delayed ack of address change. The latency of which is 1 clk for read on address change and 2 clks for read on write change.

tldr - why not supply your own valid signal with read?

Regards,
Wes
 

Hi,
It'll be easier to understand what you're proposing if you post a code example.
 


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
process(clk) is
begin
    if rising_edge(clk) then
        prev_read_addr <= read_addr;
    end if;
end process;
 
process(clk) is
begin
    if rising_edge(clk) then
        if prev_read_addr /= read_addr then
            r_valid_slv(0) <= '1';
        elsif we='1' then
            r_valid_slv(0) <= '1';
        else
            r_valid_slv(0) <= '0';
        end if;
        r_valid_slv(2 downto 1) <= r_valid_slv(1 downto 0);
        r_valid_flag <= r_valid_slv(2);
    end if;
end process;

 

You could add an if-else condition on the assignment to "q" such that if read and write address are equal and write enable is also '1', then "q" should be assigned "data", else it should be assigned the value at read address from "ram_block".
 

You could add an if-else condition on the assignment to "q" such that if read and write address are equal and write enable is also '1', then "q" should be assigned "data", else it should be assigned the value at read address from "ram_block".

You have to be a little careful with the code, as if it goes too far from the template, inferrence may not work.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top