FPGARelated.com
Forums

xilinx bram instantation template in vhdl?

Started by David Ashley September 11, 2006
I want to create a 1152 by 6 bit rom and I want to use
a bram. It can be clocked or not clocked, but I'd prefer
not clocked. Can someone point me to a template?

Something like this takes a long time to synthesize...
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity fontrom is
	port (
		addr : in unsigned ( 10 downto 0);
		data : out std_logic_vector ( 5 downto 0)
	);
end fontrom;

architecture rtl of fontrom is
begin

process ( addr)
begin
	case addr is
		when "00000000000" => data <= "000000";
		when "00000000001" => data <= "000000";
		when "00000000010" => data <= "000000";
		when "00000000011" => data <= "000000";
		when "00000000100" => data <= "000000";
		when "00000000101" => data <= "000000";
		when "00000000110" => data <= "000000";
...
		when "10001111100" => data <= "111111";
		when "10001111101" => data <= "111111";
		when "10001111110" => data <= "111111";
		when "10001111111" => data <= "111111";
		when others => data <= "00000";
	end case;
end process;
end rtl;

Thanks--
Dave
-- 
David Ashley                http://www.xdr.com/dash
Embedded linux, device drivers, system architecture
David Ashley wrote:
> I want to create a 1152 by 6 bit rom and I want to use >[cut]
I found this thread... http://groups.google.com/group/comp.lang.vhdl/browse_thread/thread/9d83482446592315/cb311613c24c9d31?lnk=st&q=this_rom+small_rom+a_length&rnum=3#cb311613c24c9d31 Tues Nov 13 2001 Mike Treseler suggests something, see my attempt below. This synthesizes quickly but doesn't seem to use a BRAM, it uses 400+ LUTs to do it...want to use BRAMS as they're unused, and LUT's are in short supply... -Dave library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std.all; entity fontrom is port ( addr : in unsigned ( 10 downto 0); data : out std_logic_vector ( 5 downto 0) ); end fontrom; architecture rtl of fontrom is type small_rom is array (0 to 1151) of std_logic_vector(5 downto 0); constant this_rom : small_rom := ( 0 => "000000", 1 => "000000", 2 => "000000", 3 => "000000", 4 => "000000", ... 1143 => "111111", 1144 => "111111", 1145 => "111111", 1146 => "111111", 1147 => "111111", 1148 => "111111", 1149 => "111111", 1150 => "111111", 1151 => "111111", others => "000000" ); begin data <= this_rom(to_integer(addr)); end architecture rtl; -- David Ashley http://www.xdr.com/dash Embedded linux, device drivers, system architecture
On 2006-09-11, David Ashley <dash@nowhere.net.dont.email.me> wrote:
> I want to create a 1152 by 6 bit rom and I want to use > a bram. It can be clocked or not clocked, but I'd prefer > not clocked. Can someone point me to a template?
There's a whole PDF of them called "xst.pdf" which you can google. -- Ben Jackson AD7GD <ben@ben.com> http://www.ben.com/
Ben Jackson wrote:
> On 2006-09-11, David Ashley <dash@nowhere.net.dont.email.me> wrote: > >>I want to create a 1152 by 6 bit rom and I want to use >>a bram. It can be clocked or not clocked, but I'd prefer >>not clocked. Can someone point me to a template? > > > There's a whole PDF of them called "xst.pdf" which you can google. >
Thank you very much! That's what I was after. Well I'll be busy reading for a while... -Dave -- David Ashley http://www.xdr.com/dash Embedded linux, device drivers, system architecture
David Ashley wrote:

> David Ashley wrote: > >>I want to create a 1152 by 6 bit rom and I want to use >>[cut] > > > I found this thread... > http://groups.google.com/group/comp.lang.vhdl/browse_thread/thread/9d83482446592315/cb311613c24c9d31?lnk=st&q=this_rom+small_rom+a_length&rnum=3#cb311613c24c9d31 > > Tues Nov 13 2001 Mike Treseler suggests something, see my attempt below. > This synthesizes quickly but doesn't seem to use a BRAM, it > uses 400+ LUTs to do it...want to use BRAMS as they're > unused, and LUT's are in short supply... >
BRAM must be clocked. Your design does not clock the memory, therefore it is forced to use LUT RAM.
Ray Andraka wrote:
> BRAM must be clocked. Your design does not clock the memory, therefore > it is forced to use LUT RAM.
I added a clock and now it's using BRAM + the LUT use count went down to 102 from 400+. That was easy. Thanks! -Dave -- David Ashley http://www.xdr.com/dash Embedded linux, device drivers, system architecture
If you can infer the brams from a constant as shown earlier, it will
simulate much faster than instantiated BRAMS. Also, the code would be
portable to other architectures/vendors.

Andy


David Ashley wrote:
> Ben Jackson wrote: > > On 2006-09-11, David Ashley <dash@nowhere.net.dont.email.me> wrote: > > > >>I want to create a 1152 by 6 bit rom and I want to use > >>a bram. It can be clocked or not clocked, but I'd prefer > >>not clocked. Can someone point me to a template? > > > > > > There's a whole PDF of them called "xst.pdf" which you can google. > > > > Thank you very much! That's what I was after. > > Well I'll be busy reading for a while... > > -Dave > > -- > David Ashley http://www.xdr.com/dash > Embedded linux, device drivers, system architecture
Hi David,

I just finished an 8 by 8 bit font for hex nibble outputs, 0 to F.
I did this for a Xilinx Virtex4 SX35 ML402 dev board in VHDL.
The code below might give you some ideas about how to proceed.
You can see the font better if you replace the 0s with periods,
and back again, when you are ready to synthesize.

Brad Smallridge
Ai Vision

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

library UNISIM;
use UNISIM.VComponents.all;

entity vga_font is
 port (
 clk  : in std_logic;
 rst  : in std_logic;
 addr : in std_logic_vector(14 downto 0);
 q    : out std_logic );
end vga_font;

architecture behavioral of vga_font is

 type init_array_type is array(natural range <>) of bit_vector(7 downto 0);
 constant vga_font_data : init_array_type :=(

 "00000000",
 "00111000",
 "01111100",
 "11000110",
 "11000110",
 "11000110",
 "01111100",
 "00111000",

 "00000000",
 "00011000",
 "00111000",
 "00011000",
 "00011000",
 "00011000",
 "00011000",
 "00111100",

 "00000000",
 "01111000",
 "11001100",
 "00011000",
 "00110000",
 "01100000",
 "11000000",
 "11111110",

 "00000000",
 "01111100",
 "00000110",
 "00000110",
 "00011100",
 "00000110",
 "00000110",
 "01111100",

 "00000000",
 "11001100",
 "11001100",
 "11001100",
 "01111110",
 "00001100",
 "00001100",
 "00001100",

 "00000000",
 "11111110",
 "11000000",
 "11000000",
 "01111000",
 "00011100",
 "00001110",
 "11111100",

 "00000000",
 "00001100",
 "00011000",
 "00110000",
 "01111100",
 "11000110",
 "01100110",
 "00111000",

 "00000000",
 "11111110",
 "00000110",
 "00001100",
 "00011000",
 "00110000",
 "01100000",
 "11000000",

 "00000000",
 "00111000",
 "11000110",
 "11000110",
 "01111100",
 "11000110",
 "11000110",
 "00111000",

 "00000000",
 "00111000",
 "11000110",
 "11000110",
 "00111100",
 "00011000",
 "00110000",
 "01100000",

 "00000000",
 "00111000",
 "01101100",
 "01101100",
 "01111100",
 "11000110",
 "11000110",
 "11000110",

 "00000000",
 "11111100",
 "11000110",
 "11000110",
 "11111100",
 "11000110",
 "11000110",
 "11111100",

 "00000000",
 "00111100",
 "11000110",
 "11000000",
 "11000000",
 "11000000",
 "11000110",
 "00111100",

 "00000000",
 "11111000",
 "11001100",
 "11000110",
 "11000110",
 "11000110",
 "11001100",
 "11111000",

 "00000000",
 "11111110",
 "11000000",
 "11000000",
 "11110000",
 "11000000",
 "11000000",
 "11111110",

 "00000000",
 "11111110",
 "11000000",
 "11000000",
 "11111000",
 "11000000",
 "11000000",
 "11000000",

  X"00",X"FF" -- also does this format
 );

   function stuff_it
 (
   init_array  : init_array_type;
   init_xx     : integer
 ) return bit_vector is
   variable result : bit_vector(255 downto 0);
 variable i : integer ;
 variable j : integer ;
 variable temp : bit_vector(7 downto 0);
   begin
 result := 
X"0000000000000000000000000000000000000000000000000000000000000000";
 i      := 0 ;
 j      := 32*init_xx ;
 while( (j < init_array'length) and (i<256) )
 loop
   -- result( (i+7) downto (i) ) := init_array(j) ;
   temp := init_array(j);
   -- mirror bit vector
   result(i+7) := temp(0);
   result(i+6) := temp(1);
   result(i+5) := temp(2);
   result(i+4) := temp(3);
   result(i+3) := temp(4);
   result(i+2) := temp(5);
   result(i+1) := temp(6);
   result(i)   := temp(7);
   i := i + 8 ;
   j := j + 1 ;
   end loop;
   return result;
   end function stuff_it;

 signal dob     : std_logic_vector(31 downto 0);

begin

   RAMB16_1 : RAMB16
   generic map (
   DOA_REG => 0, -- Optional output registers on the A port (0 or 1)
   DOB_REG => 1, -- Optional output registers on the B port (0 or 1)
   INIT_A => X"000000000", --  Initial values on A output port
   INIT_B => X"000000000", --  Initial values on B output port
   INVERT_CLK_DOA_REG => FALSE, -- Invert clock on A port output registers 
(TRUE or FALSE)
   INVERT_CLK_DOB_REG => FALSE, -- Invert clock on B port output registers 
(TRUE or FALSE)
   RAM_EXTENSION_A => "NONE", -- "UPPER", "LOWER" or "NONE" when cascaded
   RAM_EXTENSION_B => "NONE", -- "UPPER", "LOWER" or "NONE" when cascaded
   READ_WIDTH_A => 9, -- Valid values are 1,2,4,9,18 or 36
   READ_WIDTH_B => 1, -- Valid values are 1,2,4,9,18 or 36
   SIM_COLLISION_CHECK => "ALL", -- "ALL", "WARNING_ONLY", "GENERATE_X_ONLY" 
or "NONE"
   SRVAL_A => X"000000000", --  Port A ouput value upon SSR assertion
   SRVAL_B => X"000000000", --  Port B ouput value upon SSR assertion
   WRITE_MODE_A => "READ_FIRST", --  WRITE_FIRST, READ_FIRST or NO_CHANGE
   WRITE_MODE_B => "READ_FIRST", --  WRITE_FIRST, READ_FIRST or NO_CHANGE
   WRITE_WIDTH_A => 9, -- Valid values are 1,2,4,9,18 or 36
   WRITE_WIDTH_B => 9, -- Valid values are 1,2,4,9,18 or 36

   INIT_00 => stuff_it(vga_font_data,16#00#),
   INIT_01 => stuff_it(vga_font_data,16#01#),
   INIT_02 => stuff_it(vga_font_data,16#02#),
   INIT_03 => stuff_it(vga_font_data,16#03#),
   INIT_04 => stuff_it(vga_font_data,16#04#),
   INIT_05 => stuff_it(vga_font_data,16#05#),
   INIT_06 => stuff_it(vga_font_data,16#06#),
   INIT_07 => stuff_it(vga_font_data,16#07#),
   INIT_08 => stuff_it(vga_font_data,16#08#),
   INIT_09 => stuff_it(vga_font_data,16#09#),
   INIT_0A => stuff_it(vga_font_data,16#0A#),
   INIT_0B => stuff_it(vga_font_data,16#0B#),
   INIT_0C => stuff_it(vga_font_data,16#0C#),
   INIT_0D => stuff_it(vga_font_data,16#0D#),
   INIT_0E => stuff_it(vga_font_data,16#0E#),
   INIT_0F => stuff_it(vga_font_data,16#0F#),

   INIT_10 => stuff_it(vga_font_data,16#10#),
   INIT_11 => stuff_it(vga_font_data,16#11#),
   INIT_12 => stuff_it(vga_font_data,16#12#),
   INIT_13 => stuff_it(vga_font_data,16#13#),
   INIT_14 => stuff_it(vga_font_data,16#14#),
   INIT_15 => stuff_it(vga_font_data,16#15#),
   INIT_16 => stuff_it(vga_font_data,16#16#),
   INIT_17 => stuff_it(vga_font_data,16#17#),
   INIT_18 => stuff_it(vga_font_data,16#18#),
   INIT_19 => stuff_it(vga_font_data,16#19#),
   INIT_1A => stuff_it(vga_font_data,16#1A#),
   INIT_1B => stuff_it(vga_font_data,16#1B#),
   INIT_1C => stuff_it(vga_font_data,16#1C#),
   INIT_1D => stuff_it(vga_font_data,16#1D#),
   INIT_1E => stuff_it(vga_font_data,16#1E#),
   INIT_1F => stuff_it(vga_font_data,16#1F#),

   INIT_20 => stuff_it(vga_font_data,16#20#),
   INIT_21 => stuff_it(vga_font_data,16#21#),
   INIT_22 => stuff_it(vga_font_data,16#22#),
   INIT_23 => stuff_it(vga_font_data,16#23#),
   INIT_24 => stuff_it(vga_font_data,16#24#),
   INIT_25 => stuff_it(vga_font_data,16#25#),
   INIT_26 => stuff_it(vga_font_data,16#26#),
   INIT_27 => stuff_it(vga_font_data,16#27#),
   INIT_28 => stuff_it(vga_font_data,16#28#),
   INIT_29 => stuff_it(vga_font_data,16#29#),
   INIT_2A => stuff_it(vga_font_data,16#2A#),
   INIT_2B => stuff_it(vga_font_data,16#2B#),
   INIT_2C => stuff_it(vga_font_data,16#2C#),
   INIT_2D => stuff_it(vga_font_data,16#2D#),
   INIT_2E => stuff_it(vga_font_data,16#2E#),
   INIT_2F => stuff_it(vga_font_data,16#2F#),

   INIT_30 => stuff_it(vga_font_data,16#30#),
   INIT_31 => stuff_it(vga_font_data,16#31#),
   INIT_32 => stuff_it(vga_font_data,16#32#),
   INIT_33 => stuff_it(vga_font_data,16#33#),
   INIT_34 => stuff_it(vga_font_data,16#34#),
   INIT_35 => stuff_it(vga_font_data,16#35#),
   INIT_36 => stuff_it(vga_font_data,16#36#),
   INIT_37 => stuff_it(vga_font_data,16#37#),
   INIT_38 => stuff_it(vga_font_data,16#38#),
   INIT_39 => stuff_it(vga_font_data,16#39#),
   INIT_3A => stuff_it(vga_font_data,16#3A#),
   INIT_3B => stuff_it(vga_font_data,16#3B#),
   INIT_3C => stuff_it(vga_font_data,16#3C#),
   INIT_3D => stuff_it(vga_font_data,16#3D#),
   INIT_3E => stuff_it(vga_font_data,16#3E#),
   INIT_3F => stuff_it(vga_font_data,16#3F#),

   INITP_00 => 
X"0000000000000000000000000000000000000000000000000000000000000000",
   INITP_01 => 
X"0000000000000000000000000000000000000000000000000000000000000000",
   INITP_02 => 
X"0000000000000000000000000000000000000000000000000000000000000000",
   INITP_03 => 
X"0000000000000000000000000000000000000000000000000000000000000000",
   INITP_04 => 
X"0000000000000000000000000000000000000000000000000000000000000000",
   INITP_05 => 
X"0000000000000000000000000000000000000000000000000000000000000000",
   INITP_06 => 
X"0000000000000000000000000000000000000000000000000000000000000000",
   INITP_07 => 
X"0000000000000000000000000000000000000000000000000000000000000000")

   port map (
   CASCADEOUTA => open,            -- 1-bit cascade output
   CASCADEOUTB => open,            -- 1-bit cascade output
   DOA         => open,            -- 32-bit A port Data Output
   DOB         => dob,             -- 32-bit B port Data Output
   DOPA        => open,            -- 4-bit  A port Parity Output
   DOPB        => open,            -- 4-bit  B port Parity Output
   ADDRA       => (others=>'1'),   -- 15-bit A port Address Input
   ADDRB       => addr,            -- 15-bit B port Address Input
   CASCADEINA  => '0',             -- 1-bit cascade A input
   CASCADEINB  => '0',             -- 1-bit cascade B input
   CLKA        => '0',             -- Port A Clock
   CLKB        => clk,             -- Port B Clock
   DIA         => (others=>'1'),   -- 32-bit A port Data Input
   DIB         => (others=>'1'),   -- 32-bit B port Data Input
   DIPA        => (others=>'1'),   -- 4-bit  A port parity Input
   DIPB        => (others=>'1'),   -- 4-bit  B port parity Input
   ENA         => '0',             -- 1-bit  A port Enable Input
   ENB         => '1',             -- 1-bit  B port Enable Input
   REGCEA      => '0',             -- 1-bit A port register enable input
   REGCEB      => '1',             -- 1-bit B port register enable input
   SSRA        => '0',             -- 1-bit  A port Synchronous Set/Reset 
Input
   SSRB        => '0',             -- 1-bit  B port Synchronous Set/Reset 
Input
   WEA         => (others=>'0'),   -- 4-bit  A port Write Enable Input
   WEB         => (others=>'0') ); -- 4-bit  B port Write Enable Input

 q <= dob(0);

end behavioral;



"David Ashley" <dash@nowhere.net.dont.email.me> wrote in message 
news:DIGdnY0WlLIGaJjYnZ2dnUVZ_tmdnZ2d@adelphia.com...
>I want to create a 1152 by 6 bit rom and I want to use > a bram. It can be clocked or not clocked, but I'd prefer > not clocked. Can someone point me to a template? >
> Embedded linux, device drivers, system architecture
Brad Smallridge wrote:
> Hi David, > > I just finished an 8 by 8 bit font for hex nibble outputs, 0 to F. > I did this for a Xilinx Virtex4 SX35 ML402 dev board in VHDL. > The code below might give you some ideas about how to proceed. > You can see the font better if you replace the 0s with periods, > and back again, when you are ready to synthesize. > ... > RAMB16_1 : RAMB16 > generic map ( > DOA_REG => 0, -- Optional output registers on the A port (0 or 1) > DOB_REG => 1, -- Optional output registers on the B port (0 or 1) > INIT_A => X"000000000", -- Initial values on A output port > INIT_B => X"000000000", -- Initial values on B output port > INVERT_CLK_DOA_REG => FALSE, -- Invert clock on A port output registers > (TRUE or FALSE) > INVERT_CLK_DOB_REG => FALSE, -- Invert clock on B port output registers > (TRUE or FALSE) > RAM_EXTENSION_A => "NONE", -- "UPPER", "LOWER" or "NONE" when cascaded > RAM_EXTENSION_B => "NONE", -- "UPPER", "LOWER" or "NONE" when cascaded > READ_WIDTH_A => 9, -- Valid values are 1,2,4,9,18 or 36 > READ_WIDTH_B => 1, -- Valid values are 1,2,4,9,18 or 36 > SIM_COLLISION_CHECK => "ALL", -- "ALL", "WARNING_ONLY", "GENERATE_X_ONLY" > or "NONE" > SRVAL_A => X"000000000", -- Port A ouput value upon SSR assertion > SRVAL_B => X"000000000", -- Port B ouput value upon SSR assertion > WRITE_MODE_A => "READ_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE > WRITE_MODE_B => "READ_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE > WRITE_WIDTH_A => 9, -- Valid values are 1,2,4,9,18 or 36 > WRITE_WIDTH_B => 9, -- Valid values are 1,2,4,9,18 or 36
Brad, Thanks. It looks too specific to xilinx though. When I added a clock the brams got inferred automatically. See sample below. The address input would have to be character# * font_row, and the result is a 6 bit strip for that row. 0 <= character# <= 0x5f --- ascii chars from 0x20 to 0x7f 0 <= font_row <= 11 -- row of font (6x12 font) -Dave library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std.all; entity fontrom is port ( clk : in std_logic; addr : in unsigned ( 10 downto 0); data : out std_logic_vector ( 5 downto 0) ); end fontrom; architecture rtl of fontrom is type small_rom is array (0 to 1151) of std_logic_vector(5 downto 0); constant this_rom : small_rom := ( 0 => "000000", 1 => "000000", 2 => "000000", 3 => "000000", 4 => "000000", 5 => "000000", -- font data deleted for brevity, font is 6x12, ascii characters from 0x20 to 0x7f 1145 => "111111", 1146 => "111111", 1147 => "111111", 1148 => "111111", 1149 => "111111", 1150 => "111111", 1151 => "111111", others => "000000" ); begin process(clk) begin if clk'event and clk = '1' then data <= this_rom(to_integer(addr)); end if; end process; end architecture rtl; -- David Ashley http://www.xdr.com/dash Embedded linux, device drivers, system architecture
Ben Jackson wrote:
> On 2006-09-11, David Ashley <dash@nowhere.net.dont.email.me> wrote: > > I want to create a 1152 by 6 bit rom and I want to use > > a bram. It can be clocked or not clocked, but I'd prefer > > not clocked. Can someone point me to a template? > > There's a whole PDF of them called "xst.pdf" which you can google.
I was not aware of this document. It looks very useful, but it seems to be a bit out of date. It does not mention a number of newer families including Spartan 3. I guess the information applies as appropriate depending on the feature. Will Xilinx be updating this document anytime soon?