UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor yash047
Visitor
794 Views
Registered: ‎02-14-2019

Sharing block ram to another entity vhdl

Hello,

I have written vhdl code to map text into pixels which I have stored in a std_logic_vector. I have assigned the array with an attribute of block ram_type. The pixels are calculated in a different entity and stored in the same array. However synthesis is taking forever. 

This is the code for my array declaration.

signal vram : std_logic_vector (H_480_272p_AV*V_480_272p_AV-1 downto 0) := (others => '0');
	attribute RAM_STYLE : string;
	attribute RAM_STYLE of vram: signal is "BLOCK";
begin
Inst_get_text : entity work.text_map PORT MAP(
CLK => WR_CLK,
reset => RST_I,
vram => vram,
text_details => text_passages
);

And this is the code of the entity calculating the pixels. I have already simulated this entity.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;

library digilent;
use digilent.video.ALL;

library work;
use work.common.all;

entity text_map is
PORT(
		CLK : in STD_LOGIC;
		reset : in STD_LOGIC;
		vram : out std_logic_vector(H_480_272p_AV*V_480_272p_AV-1 downto 0);
		text_details: in text_info_array(0 to 0)
		);
end text_map;

architecture Behavioral of text_map is
	signal vram_wraddr : integer range 0 to H_480_272p_AV*V_480_272p_AV-1;
	signal rom_addr : std_logic_vector(10 downto 0):= (others => '0');
	signal line_data : std_logic_vector(7 downto 0) := (others => '0');
	signal line_data_copy : std_logic_vector(7 downto 0) := (others => '0');
begin

	Inst_Get_Char: entity work.font_rom PORT MAP(
		clk => CLK,
		addr => rom_addr,
		data => line_data_copy
	);
Process (CLK)
	variable text_i : integer := 0;
	variable char_i : integer range 1 to 16 := 1;
	variable pix_line : integer range 0 to 16;
	variable x : integer := 0;
	variable y : integer := 0;
	variable curr_text : string(1 to 15) := text_details(0).text;
	variable len : integer range 0 to 15 := 0;
begin
	len := text_details(text_i).text_len;

	if reset = '1' then
		text_i := 0;
		char_i := 1;
		pix_line := 0;
		x := 0;
		y := 0;
		curr_text := text_details(0).text;	
		vram_wraddr <= 0;
		rom_addr <= (others => '0');
		line_data <= (others => '0');
		vram <= (others => '0');
	end if;
	
	if rising_edge(clk) then
		curr_text := text_details(text_i).text;
		rom_addr <= std_logic_vector(to_unsigned(character'pos(curr_text(char_i)), 7)) & std_logic_vector(to_unsigned(pix_line, 4));
		line_data <= line_data_copy;
		x := text_details(text_i).x;
		y := text_details(text_i).y;
		vram_wraddr <= (y + pix_line)*H_480_272p_AV + (x + (8*char_i));
		for n in 0 to 7 loop
			vram(vram_wraddr + n) <= line_data(n);
		end loop;
		pix_line := pix_line + 1;
	
		if pix_line = 16 then
			char_i := char_i + 1;
			pix_line := 0;
			if char_i = len + 1 then
				text_i := text_i +1;
				char_i := 1;
				if text_i = text_details'length then
					text_i := 0;
				end if;
			end if;
		end if;
	
	end if;
	
end process;

end Behavioral;

What is wrong with the code that synthsis is taking forever?

Tags (3)
0 Kudos
16 Replies
Scholar dpaul24
Scholar
783 Views
Registered: ‎08-07-2014

Re: Sharing block ram to another entity vhdl

@yash047,

What is wrong with the code that synthsis is taking forever?

Probably beacuse of the the way you have coded in VHDL.

process (clk, reset)
variable ...
..
..
begin
if reset = 1 then -- I have assumed async reset
..
..
elsif rising_edge(clk) then
..
..
end if;
end process;

 https://www.xilinx.com/support/answers/46515.html

Follow the Xilinx synthesis guide to infer block RAMs.

--------------------------------------------------------------------------------------------------------
FPGA enthusiast!
All PMs will be ignored
--------------------------------------------------------------------------------------------------------
0 Kudos
Visitor yash047
Visitor
772 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

I have tried that, still the same results.
Allow me to ask you how you would proceed if you had to map a list of texts ( including texts which are dynamic) into pixels. And then read the array to display those pixels.
0 Kudos
Scholar richardhead
Scholar
745 Views
Registered: ‎08-01-2012

Re: Sharing block ram to another entity vhdl

Have you got a circuit design you drew out before you started coding? if you dont, yu need to go back and draw one. There are too many problems with the code that means it needs completly re-writing if you want a ram.

RAMs can only access a single address per clock cycle - so you cannot output the entire array as a port. This is perfectly fine as video can easily be processing in an FPGA, and usually only arrives one pixel per clock.

0 Kudos
Visitor yash047
Visitor
707 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

Could you recommend me some sources; websites or documents or books where I can read more on how to read or write from RAM and ROM. I have tried to write only one bit at a time to the RAM but it still takes forever to synthesize. 

0 Kudos
Scholar richardhead
Scholar
693 Views
Registered: ‎08-01-2012

Re: Sharing block ram to another entity vhdl

A long synthesis time implies your code isn't getting inferred as a ram.  Xilinx UG901 has synthesis templates for rams. Can you post the ram code?

0 Kudos
Visitor yash047
Visitor
688 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

Here is the code, I just rewrote it from scratch.

 

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.ALL;

library work;
use work.common.all;
library UNISIM;
use UNISIM.VComponents.all;

entity main is
	 port(
		 CLK : in STD_LOGIC;
		 reset : in STD_LOGIC;
		 V_Out : out STD_LOGIC
	     );
end main;

--}} End of automatically maintained section

architecture main of main is

signal text : string (1 to 15) := "This is a Test.";
signal text_len : integer := 15;
signal x : integer := 50;
signal y : integer := 50;

signal vram : std_logic_vector(H_480_272p_AV*V_480_272p_AV-1 downto 0) := (others => '0');
attribute RAM_STYLE : string;
attribute RAM_STYLE of vram: signal is "BLOCK";
signal vram_we : std_logic;
signal vram_addr, vram_wraddr : INTEGER range 0 to H_480_272p_AV*V_480_272p_AV-1;
signal rom_addr : std_logic_vector(10 downto 0);
signal rom_data : std_logic_vector(7 downto 0);
begin
	
	inst_get_char : entity work.Font_Rom PORT MAP (
		clk => CLK,
		addr => rom_addr,
		data => rom_data	
	);
	
	Process (CLK)
	
	begin
		if vram_addr = H_480_272p_AV*V_480_272p_AV-1 then
			vram_addr <= 0;
		end if;	
		vram_addr <= vram_addr + 1;
		V_Out <= vram(vram_addr);
	end process;
	
	
	
	Process (CLK)
	variable char_count : integer := 1;
	variable pix_line : integer := 0;
	variable bit_count : integer := 0;
	variable curr_char : std_logic_vector(7 downto 0);
	variable bit_data : std_logic;
	begin
		if rising_edge(CLK) then
			if bit_count = 0 then 
				rom_addr <= std_logic_vector(to_unsigned(character'pos(text(char_count)), 7)) & std_logic_vector(to_unsigned(pix_line, 4));
			end if;
			bit_data := rom_data(bit_count);
			vram_wraddr <= (y + pix_line)*H_480_272p_AV + (x + bit_count + (8* char_count));
			vram(vram_wraddr) <= bit_data;
			
			if bit_count = 7 then
				bit_count := 0;
				if pix_line = 15 then
					pix_line := 0;
					if char_count = text_len then
						char_count := 1;
					else
						char_count := char_count + 1;
					end if;
				else
					pix_line := pix_line + 1;
				end if;
				
			else
				bit_count := bit_count + 1;
			end if;
		end if;
	end Process;

end main;
0 Kudos
Scholar richardhead
Scholar
679 Views
Registered: ‎08-01-2012

Re: Sharing block ram to another entity vhdl

Vivado won't synthesise a single slv as a ram. It has to be an array of slv, even if each element is a 1 bit slv.

 

There are other problems.  The vram read process is not synchronous as you don't have an if statement for the rising edge of the clock. 

0 Kudos
Visitor yash047
Visitor
676 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

Just corrected it, it still does not synthsize
0 Kudos
Visitor yash047
Visitor
675 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

Is this correct?

type vramt is array (0 to H_480_272p_AV*V_480_272p_AV-1) of std_logic_vector (0 downto 0);
signal vram : vramt := (others => (others => '0'));

I get the follow error for trying to read or write a bit to the vram.

# Error: COMP96_0617: main.vhd : (77, 12): Assignment target incompatible with right side. Cannot convert 'STD_LOGIC_VECTOR' to 'STD_ULOGIC'.

# Error: COMP96_0617: main.vhd : (96, 25): Assignment target incompatible with right side. Cannot convert 'STD_ULOGIC' to 'STD_LOGIC_VECTOR'.

0 Kudos
Scholar richardhead
Scholar
623 Views
Registered: ‎08-01-2012

Re: Sharing block ram to another entity vhdl

Remember that a std_logic is not the same as a std_logic_vector. You need top make sure you address slicing the vector for the output and assigning a vector not a std logic

0 Kudos
Visitor yash047
Visitor
613 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

I corrected the code, I get the following error:-

ERROR:Xst - basic_stringFATAL_ERROR:Xst:Portability/export/Port_Main.h:159:1.18 - This application has discovered an exceptional condition from which it cannot recover. Process will terminate. For technical support on this issue, please open a WebCase with this project attached at http://www.xilinx.com/support

This is my corrected code:-

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.all;
--use IEEE.NUMERIC_STD_UNSIGNED.all;

library work;
use work.common.all;
library UNISIM;
use UNISIM.VComponents.all;

entity main is
	 port(
		 CLK : in STD_LOGIC;
		 reset : in STD_LOGIC;
		 V_Out : out STD_LOGIC
	     );
end main;

--}} End of automatically maintained section

architecture main of main is

signal text : string (1 to 15) := "This is a Test.";
signal text_len : integer := 15;
signal x : integer := 50;
signal y : integer := 50;

type vramt is array (0 to H_480_272p_AV*V_480_272p_AV-1) of std_logic_vector (0 downto 0);
signal vram : vramt := (others => (others => '0'));

--signal vram : std_logic_vector(H_480_272p_AV*V_480_272p_AV-1 downto 0) := (others => '0');
attribute RAM_STYLE : string;
attribute RAM_STYLE of vram: signal is "BLOCK";
signal vram_we : std_logic;
signal vram_addr, vram_wraddr : INTEGER range 0 to H_480_272p_AV*V_480_272p_AV-1;
signal rom_addr : std_logic_vector(10 downto 0);
signal rom_data : std_logic_vector(7 downto 0);
begin
	
	inst_get_char : entity work.Font_Rom PORT MAP (
		clk => CLK,
		addr => rom_addr,
		data => rom_data	
	);
	
	Process (CLK)
	
	begin
		if rising_edge (CLK) then
		if vram_addr = H_480_272p_AV*V_480_272p_AV-1 then
			vram_addr <= 0;
		end if;	
		vram_addr <= vram_addr + 1;
		V_Out <= vram(vram_addr)(0);
		end if;
	end process;
	
	
	
	Process (CLK)
	variable char_count : integer := 1;
	variable pix_line : integer := 0;
	variable bit_count : integer := 0;
	variable curr_char : std_logic_vector(7 downto 0);
	variable bit_data : std_logic;
	begin
		if rising_edge(CLK) then
			if bit_count = 0 then 
				rom_addr <= std_logic_vector(to_unsigned(character'pos(text(char_count)), 7)) & std_logic_vector(to_unsigned(pix_line, 4));
			end if;
			bit_data := rom_data(bit_count);
			vram_wraddr <= (y + pix_line)*H_480_272p_AV + (x + bit_count + (8* (char_count-1)));
			vram(vram_wraddr)(0) <= bit_data;
			
			if bit_count = 7 then
				bit_count := 0;
				if pix_line = 15 then
					pix_line := 0;
					if char_count = text_len then
						char_count := 1;
					else
						char_count := char_count + 1;
					end if;
				else
					pix_line := pix_line + 1;
				end if;
				
			else
				bit_count := bit_count + 1;
			end if;
		end if;
	end Process;

end main;
0 Kudos
Visitor yash047
Visitor
581 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

I believe the fatal error might be because I'm inferring two block RAMs. I removed the entity font_ram from my main code and assigned a constant value to "rom_data", the code synthesized successfully. I still can't figure out exactly why I receive a fatal error when I use the entity font_rom.

Below is my code for the font_rom 

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity font_rom is
   port(
      clk: in std_logic;
      addr: in std_logic_vector(10 downto 0);
      data: out std_logic_vector(7 downto 0)
   );
end font_rom;

architecture arch of font_rom is
   constant ADDR_WIDTH: integer:=11;
   constant DATA_WIDTH: integer:=8;
   --signal addr_reg: std_logic_vector(ADDR_WIDTH-1 downto 0);
   type rom_type is array (0 to 2**ADDR_WIDTH-1)
        of std_logic_vector(DATA_WIDTH-1 downto 0);
   -- ROM definition size of 16K bits
   signal ROM: rom_type:=( 
some data  );
attribute RAM_STYLE : string;
attribute RAM_STYLE of ROM: signal is "BLOCK";

begin
   
   process (clk)
   begin
      if rising_edge(clk) then
        
		data <= ROM(to_integer(unsigned(addr)));
      end if;
   end process;
   
end arch;
0 Kudos
Scholar dpaul24
Scholar
577 Views
Registered: ‎08-07-2014

Re: Sharing block ram to another entity vhdl

@yash047,

Keep everything aside and concentrate 1st on writing a proper VHDL code for RAM inference.

First you need to decide yourself what type of RAM you want to infer - single port, dual port, true dual port, sync clk or async clk, word size & RAM depth, etc.

Then take the help of Xilinx UG901 and CAREFULLY go through the code snippets (Chapter 4) given for the type of RAM to be inferred. Adapt the one you need and you are good to go.

--------------------------------------------------------------------------------------------------------
FPGA enthusiast!
All PMs will be ignored
--------------------------------------------------------------------------------------------------------
0 Kudos
Visitor yash047
Visitor
526 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

Thanks for the source of information. It was really helpful, I managed to create a dual port BRAM. However, I narrowed down the main cause of the fatal error. The fatal error was not because of the RAMs, it is only due to this small portion of code. Can anyone help me how to fix this?

 

library ieee;
use ieee.std_logic_1164.all;
use IEEE.NUMERIC_STD.ALL;
use ieee.std_logic_arith.all;

library work;
use work.all;

entity main is
port (
clk : in std_logic;
v_out : out std_logic_vector (10 downto 0)
);

end main;

architecture main of main is
signal font_addr : std_logic_vector (10 downto 0) := "00000000000";
signal text : string (1 to 15) := "This is a test.";
signal pix_count : integer range 0 to 15 := 0;
signal char_count : integer range 1 to 15 := 1;


begin

v_out <= font_addr;	
process (clk)
begin
	if rising_edge(clk)	then
font_addr <= std_logic_vector(to_unsigned(character'pos(text(char_count)), 7)) & std_logic_vector(to_unsigned(pix_count,4));

	end if;
end process;


	
end main;
0 Kudos
Visitor yash047
Visitor
523 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

I wish to obtain the ASCII number of a specific character indicated by char_count in the string, text.
If I input the character directly, the code will synthesize.
font_addr <= std_logic_vector(to_unsigned(character'pos('T'), 8));

0 Kudos
Visitor yash047
Visitor
506 Views
Registered: ‎02-14-2019

Re: Sharing block ram to another entity vhdl

I'm going to start a new thread for this issue since it is not related to the title here.
0 Kudos