本帖最后由 fpgaw 于 2011-5-4 17:37 编辑  
 
一个老外写的DDS(VHDL)的例子,很经典 
 
-- DDFS.vhd 
------------------------------------- 
-- Direct Digital Freq. Synthesis -- 
------------------------------------- 
-- (c) Bert Cuzeau, ALSE - info@alse-fr.com 
-- May be reproduced provided that copyright above remains. 
-- We use one of the symetries in the sine function, 
-- so the lookup table is re-used twice (128 entries table) 
-- The Sine Table is built by a C program... 
------------------------------------- 
-- Design IOs : 
-- Clk : Global Clock input 
-- Rst : Global Reset input 
-- Freq_data : 8-bit frequency control vector 
-- from DIP switches on the board. 
-- Dout : is signed 8-bit output to the DAC. 
-- ----------------------------------------------- 
library IEEE; 
use IEEE.std_logic_1164.all; 
use IEEE.numeric_std.all; 
-- ----------------------------------------------- 
Entity DDFS is 
-- ----------------------------------------------- 
Port ( CLK : in std_logic; 
RST : in std_logic; 
Freq_Data : in std_logic_vector (7 downto 0); 
Dout : out std_logic_vector (7 downto 0) 
); 
end DDFS; 
-- ----------------------------------------------- 
Architecture RTL of DDFS is 
-- ----------------------------------------------- 
signal Address : unsigned (6 downto 0); 
signal Result : std_logic_vector (7 downto 0); 
signal Accum : unsigned (28 downto 0); -- we want very low Frequencies ! 
signal Sign : std_logic; 
begin 
-- Signed Accumulator 
-- ------------------ 
Acc: process (CLK,RST) 
begin 
if RST='1' then 
Accum '0'); 
elsif rising_edge(CLK) then 
Accum <= Accum + unsigned(Freq_Data); 
end if; 
END process acc; 
Sign <= Accum(Accum'high); -- MSB 
-- Lookup Table Index calculation 
-- ------------------------------ 
Address <= unsigned(Accum(Accum'high-1 downto Accum'high-Address'length)); 
-- SINE Look-Up TABLE 
-- ------------------- 
-- Inference of an Asynchronous Rom. 
-- A synchronous one would be better, but we register the output. 
-- This table has been built by GENVEC.exe (C program) 
-- We use only positive values ! (sign comes from quadrant info) 
-- This could be further optimized by coding only one quadrant... 
lookup: process (Address) 
subtype SLV8 is std_logic_vector (7 downto 0); 
type Rom128x8 is array (0 to 127) of SLV8; -- 0 to 2**Address'length - 1 
constant Sinus_Rom : Rom128x8 := ( 
x"00", x"03", x"06", x"09", x"0c", x"0f", x"12", x"15", 
x"18", x"1b", x"1e", x"21", x"24", x"27", x"2a", x"2d", 
x"30", x"33", x"36", x"39", x"3b", x"3e", x"41", x"43", 
x"46", x"49", x"4b", x"4e", x"50", x"52", x"55", x"57", 
x"59", x"5b", x"5e", x"60", x"62", x"64", x"66", x"67", 
x"69", x"6b", x"6c", x"6e", x"70", x"71", x"72", x"74", 
x"75", x"76", x"77", x"78", x"79", x"7a", x"7b", x"7b", 
x"7c", x"7d", x"7d", x"7e", x"7e", x"7e", x"7e", x"7e", 
x"7f", x"7e", x"7e", x"7e", x"7e", x"7e", x"7d", x"7d", 
x"7c", x"7b", x"7b", x"7a", x"79", x"78", x"77", x"76", 
x"75", x"74", x"72", x"71", x"70", x"6e", x"6c", x"6b", 
x"69", x"67", x"66", x"64", x"62", x"60", x"5e", x"5b", 
x"59", x"57", x"55", x"52", x"50", x"4e", x"4b", x"49", 
x"46", x"43", x"41", x"3e", x"3b", x"39", x"36", x"33", 
x"30", x"2d", x"2a", x"27", x"24", x"21", x"1e", x"1b", 
x"18", x"15", x"12", x"0f", x"0c", x"09", x"06", x"03" ); 
begin 
Result '0'); 
elsif rising_edge(CLK) then 
if Sign='1' then 
Dout <= Result; 
else 
Dout <= std_logic_vector (- signed(Result)); 
end if; 
end if; 
end process outreg; 
end RTL; |