hi :
all guys. I wanna discribe a ROM in VHDL , but VHDL is very new to me. And my this ROM is designed to store sine wave table. Can someone help me?
Any help would be appreciate!
hi :
all guys. I wanna discribe a ROM in VHDL , but VHDL is very new to me. And my this ROM is designed to store sine wave table. Can someone help me?
Any help would be appreciate!
Here is a basic code for ROM in VHDL!
Hope this helps.
Code:library ieee; use ieee.std_logic_1164.all; entity ROM is port ( address : in std_logic_vector(3 downto 0); data : out std_logic_vector(7 downto 0) ); end entity ROM; architecture behavioral of ROM is type mem is array ( 0 to 2**4 - 1) of std_logic_vector(7 downto 0); constant my_Rom : mem := ( 0 => "00000000", 1 => "00000001", 2 => "00000010", 3 => "00000011", 4 => "00000100", 5 => "11110000", 6 => "11110000", 7 => "11110000", 8 => "11110000", 9 => "11110000", 10 => "11110000", 11 => "11110000", 12 => "11110000", 13 => "11110000", 14 => "11110000", 15 => "11110000"); begin process (address) begin case address is when "0000" => data <= my_rom(0); when "0001" => data <= my_rom(1); when "0010" => data <= my_rom(2); when "0011" => data <= my_rom(3); when "0100" => data <= my_rom(4); when "0101" => data <= my_rom(5); when "0110" => data <= my_rom(6); when "0111" => data <= my_rom(7); when "1000" => data <= my_rom(8); when "1001" => data <= my_rom(9); when "1010" => data <= my_rom(10); when "1011" => data <= my_rom(11); when "1100" => data <= my_rom(12); when "1101" => data <= my_rom(13); when "1110" => data <= my_rom(14); when "1111" => data <= my_rom(15); when others => data <= "00000000"; end case; end process; end architecture behavioral;
thanks for replies
The ROM I wanna describe is too large .
Is there any method else?
Any help would be appreciate!
Hi skycanny,
i feel u r trying to generate a direct digit synthesizer or a sine wave generator.
which is ur target device?
if u r using xilinx tools, then it's easy to generate the rom and dds using xilinx ise tool.
Coregen will automatically generate the rom which u need to generate the sine, depending upon the output sine frequency and step resolution.
hi,Renjith:
You are right
I am trying to implement a DDS and using Xilinx FPGA.
However, I do not want to use CoreGen because the module CoreGen creates is hard to migrate to other target device.
Could you help me?
Any help would be appreciate!
You can use a RAM of a FPGA inittialized with the content that you want (look at the Xilinx FPGAs BRAMs manual for instance). You just must take care that there aren't any writes to the RAM. The beautie of this is that you can easly initialize the RAM without the need to code a look-up table. The disavantage is that you waste BRAMs of the FPGA but you don't waste logic resources.
use "BlockRam" devices in case you plan to use xilinx devices or LPM library if you plan to use Altera ones...
both of them are very efficient.
You can treat BlockRam as a Rom Memory by disabling the RW line.
regards
maXer
I agree with nand_gates
I think that the best way to put RAM into an FPGA is by using a two dimensional array.
This is the way that I have done it on many occasions and it’s always been successful.
If I wanted to describe a large memory
(Which I haven’t in the past because it’s often easier/less expensive, just to attach some RAM to the FPGA, but I understand that this may not be true in your case, pin count, start case and so on).
I would use the method described by nand_gates and try to extend this idea using something like the “generate” statement.
Hope that helps
Kind Regards Bob
ok... r u trying to target to some other xilinx family or non-xilinx families or an ASIC prototype.Originally Posted by skycanny
if it's other xilinx families itself, then coregen is a solution for u.
if the target is a non-xilinx family, then u r right,
as u cannot port coregen modules to that.
so what i cud guess is, u want to generate a generic vhdl model of DDS.
in that case,u have to store the sine coeffiecients in the rom manually,
as nandgates suggested.
Again, u can use ur coregen tool to generate the sine coeffiencts,
when u r generating a DDS model thrg Coregen, then it automatically creates a .mif file, which has all the coefficients inside as per ur spec.
u have to take this and put it in your vhdl code, no matter which ever ur target is.
i also suggest the generate command. It is useful for a large number of similar devices one has to write code for. If you are newbie, just refer to the VHDL manual about generate command. Using Xilinx ISE is the fast way but anyway you should know VHDL code.
thank all guys
Hi skycanny,
You can use a high level language to do the job.
By using the "fprint" like function(fprint is a C funtion) to print out the rom content and other words(as nand_gates's code) to a single file. This code is portable.
I do the similar job by using Matlab.
Regard,
Jarod
Hi,jarodz:
thank you
I have done it by Matlab and added it to code
Matlab or C is a good choice.
hey...i created a rom this way
since i have to put inside it a large code, almost 10000 8bit packets, i created a script in matlab (using fprintf) that generated the data i need to put in file.Code:library ieee; use ieee.std_logic_1164.all; entity ROM is port ( clk : in std_logic; e : in std_logic; r : in std_logic; data : out std_logic_vector(7 downto 0) ); end entity ROM; architecture behavioral of ROM is signal i: integer range 0 to 6063:=0; signal enable : STD_LOGIC:='0'; type mem is array ( 0 to 6063) of std_logic_vector(7 downto 0); constant my_Rom : mem := DATA HERE... ... ... ...
my problem now is that when synthetizing in ise, this takes almost 40 minutes to complete.
coregen isnt a solution for me since we are not allowed to use it...
i hope anyone could give me a hand with this
thanks
you've created a large constant, not a ROM block,Originally Posted by moreins
that's why the compiler needs so much time to connect
inputs of logic cells to "1's" and "0's" accordingly
to your description;
the tool should recognize the ROM if you write it somehow
like in an example below:
---Code:process(clk) begin if(rising_edge(clk)) then q <= my_Rom(addr); <======= end if; end process;
hello
thanks for you reply
this is the complete code that i sinthetized last night. it took about 40 minutes.
i didnt post before the end of my code. here it is. maybe thats what youre trying to say with the example you gave me...Code:library ieee; use ieee.std_logic_1164.all; entity ROM is port ( clk : in std_logic; e : in std_logic; r : in std_logic; data : out std_logic_vector(7 downto 0) ); end entity ROM; architecture behavioral of ROM is signal i: integer range 0 to 6063:=0; signal enable : STD_LOGIC:='0'; type mem is array ( 0 to 6063) of std_logic_vector(7 downto 0); constant my_Rom : mem := ( "10000011", "10000100", "10000101", "10000011", .... .... .... .... ... ....7000 more lines ); begin process(e) begin if e'event and e='1' then enable<='1'; end if; end process; process(clk) begin if r = '1' then data <="00000000"; elsif enable='1' then if clk'event and clk='1' then data<=my_rom(i); i<=i+1; end if; end if; end process; end architecture behavioral;
hope you can help me
thanks
first - change the i range in your file to 7-0,
compile and carefully read compilation's messages;
look at the schematics and resource usage report;
I'm not experienced in vhdl, but even if the example
below is not perfect it should create a rom memory,
and give you a hint how it should be done;
I think it's better to keep a memory content values
in a seperate text file then in the RTL code;
how to do it ypu have to find out yourself in the
ise manual/handbook;
---Code:entity rom is port ( clk : in std_logic; e : in std_logic; r : in std_logic; data_out: out std_logic_vector (7 downto 0) ); end rom; architecture rtl of rom is signal i : integer range 0 to 7:=0; -- change the range value signal enable : std_logic:='0'; signal data : std_logic_vector (7 downto 0); BEGIN process (e) -- i don't like this, would be better begin -- to use clk as a sync. signal if e'event and e = '1' then enable <= '1'; end if; end process; process ( clk) begin if rising_edge (clk) then if (enable = '1') then i <= i + 1; end if; end if; end process; process (clk) begin if rising_edge (clk) then case i is when 0 => data <= "10111100"; when 1 => data <= "11011001"; when 2 => data <= "00000111"; when 3 => data <= "10101000"; when 4 => data <= "10101001"; when 5 => data <= "10101000"; when 6 => data <= "10101011"; when 7 => data <= "10110010"; -- .... fill in the correct values here for larger 'i' index end case; end if; end process; process (r,data) begin if r = '1' then data_out <= "00000000"; else data_out <= data; end if; end process; END rtl;
you can use quartus LMP ROM, it very easy. if you cann't do it yourself, tell me>
The rules for ROM inference from HDL code are tool dependant. As you are apparently using Xilinx, you should check the respective software handbooks. In addition, the ROM structure must be representable by the existing device hardware in terms of required address and/or data output latches.
A typical reason, why ROM or RAM inference fails is to include a logic feature, that isn't available in the hardware. I guess, this is the case with the r='1' condition in your design. You may want to remove this condition and also the enable signal first. Most likely, an auxilary register between the ROM and the output port is required to allow ROM inference in this case.
I append an Altera Quartus ROM template for reference. Please pay attention to the structure of the output process, that has no additional conditions. It may work with Xilinx as well.Code:if r = '1' then data <="00000000"; elsif enable='1' then if clk'event and clk='1' then data<=my_rom(i); i<=i+1; end if; end if;
Code:library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity single_port_rom is generic ( DATA_WIDTH : natural := 8; ADDR_WIDTH : natural := 8 ); port ( clk : in std_logic; addr : in natural range 0 to 2**ADDR_WIDTH - 1; q : out std_logic_vector((DATA_WIDTH -1) downto 0) ); end entity; architecture rtl of single_port_rom is -- Build a 2-D array type for the RoM subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0); type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t; function init_rom return memory_t is variable tmp : memory_t := (others => (others => '0')); begin for addr_pos in 0 to 2**ADDR_WIDTH - 1 loop -- Initialize each address with the address itself tmp(addr_pos) := std_logic_vector(to_unsigned(addr_pos, DATA_WIDTH)); end loop; return tmp; end init_rom; -- Declare the ROM signal and specify a default value. Quartus II -- will create a memory initialization file (.mif) based on the -- default value. signal rom : memory_t := init_rom; begin process(clk) begin if(rising_edge(clk)) then q <= rom(addr); end if; end process; end rtl;