完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
嗨,
对于学校项目,我需要设计一个信号发生器,它可以产生持续时间为60-70 ms的数字按键音信号(DTMF),可用于DTMF电话。 之后的信号将被馈送到板载现有的数模转换器,然后馈送到现有的板载AC97音频编解码器。 我花了很长时间研究实施后的想法,但我仍然对正确的方向感到困惑。 我知道我需要产生总共8个不同的频率,每个DTMF音调必须包含来自高频组(1209,1336,1477和1633 Hz)的一个正弦曲线和来自低频组的一个正弦曲线(697,770,852和941 Hz) )。 如何使用VHDL代码进行设计? 我应该使用NCO(数控振荡器)的原理并对每个频率使用LUT吗? 如果是这样,我应该创建多大的LUT? 20个样本应该够了吗? 有没有更好的方法来实现这一点? 我非常感谢任何想法或暗示甚至更好的VHDL代码,它可以帮助我在这里。 先谢谢你, 大卫 以上来自于谷歌翻译 以下为原文 Hi, For a school project I need to design a signal generator which generates digital touch-tone-signals (DTMF) with duration of 60-70 ms that can be used in DTMF-telephony. the signals later will be fed to the on-board existing Digital-to-Analog converter and then to the exisiting on-board AC97 audio codec. I have spent long hours on researching after implementation ideas but I am still very confused about the right direction. I know I need to generate overall 8 different frequencies and each DTMF tone must contain one sinusoid from the high- frequency group (1209, 1336, 1477 and 1633 Hz) and one sinusoid from the low frequency group (697, 770, 852 and 941 Hz). How do I design it with VHDL code? should I use the principle of NCO (numerically controlled Oscillator) and use LUT for each frequency? if so, what size of LUT should I create? 20 samples dhould be enough? is there a better approach to implement this? I would very much appreciate any idea or an hint or even better, VHDL code which could help me out here. Thank you in advance, David |
|
相关推荐
6个回答
|
|
通常为了生成正弦波,您使用具有1/4波形的查找表然后再现完整波形,使用向后读取和反转输出值的组合以获得所有4个象限。
另一方面,如果您不需要太多分辨率(每个完整波周期的样本),那么您可以存储0到360度的完整波形。 通过将每个DAC采样周期的地址增量更改为查找表来更改频率。 该方法通常被称为DDS或直接数字合成。 在论坛和维基百科上搜索它以获取更多提示。 很久以前,按键式电话的每列按键都有一个振荡器,每一行按键都有一个振荡器。 按键将为每个振荡器选择不同的频率以创建两个音调。 您的DTMF发生器可能包含两个DDS正弦波发生器,加法器在将波形发送到DAC之前将波形组合在一起。 由于两个波形发生器具有相同的波形(即使频率不同),因此可以使用相同的LUT值。 当为LUT使用内部双端口BRAM时,同一个表可以为波形发生器提供服务,每个发生器为BRAM的不同端口提供地址,并从同一端口获取波形值(真正的双端口模式)。 请记住,添加波形时,峰值可以加倍。 因此,您要么右移输出以恢复原始范围,要么设置LUT以提供不超过DAC饱和值的1/2。 您需要为音频编解码器提供足够快的时钟,使其超出电话系统中300-3000 Hz带通滤波器的截止频率。 由于大多数音频编解码器在44 KHz及以上工作应该没有问题,但是你可以比CD质量音频所需的时钟慢得多,并且仍然可以使电话系统接受DTMF音调。 因此,对于每个频率(即8个LUT),您不需要LUT,但每个同时生成的音调(即2个LUT)只需要一个LUT,您可以共享使用双端口BRAM创建的LUT。 - Gabor 以上来自于谷歌翻译 以下为原文 Usually to generate sine waves you use a look-up table with 1/4 waveform and then to reproduce the full waveform, use a combination of reading out backwards and inverting the output value in order to get all 4 quadrants. On the other hand, if you don't need too much resolution (samples per full wave period) then you could store the complete wave from 0 to 360 degrees. Change the frequency by changing the address increment into the lookup table per DAC sampling period. This method is usually refered to as DDS or direct digital synthesis. Search for it on the forums and at wikipedia for more tips. A long time ago, touch tone phones had an oscillator for each column of keys and another for each row of keys. Pressing the key would select a different frequency for each oscillator to create the two tones. Your DTMF generator could consist of two DDS sine wave generators, with an adder to combine the waveforms before sending them to the DAC. Since you have the same waveform (even though different frequency) for the two waveform generators, you can have the same LUT values. When using the internal dual-port BRAM for the LUT, the same table can serve both waveform generators, each generator supplying address to a different port of the BRAM and getting the waveform value from that same port (true dual-port mode). Remember that when you add the waveforms, the peak value can double. So you either shift the output right to get back the original range or set up the LUT to provide no more than 1/2 the DAC's saturation value. You need to clock the audio CODEC fast enough to be beyond the cutoff of the 300-3000 Hz bandpass filter in the phone system. Since most audio CODEC's work at 44 KHz and above this should be no issue, but you could for example clock much slower than required for CD quality audio and still make DTMF tones acceptable for the phone system. So again you don't need a LUT for each frequency (i.e. 8 LUTs) but just one for each simultaneously generated tone (i.e. 2 LUTs), and you can share LUTs that are created with dual-port BRAM. -- Gabor |
|
|
|
None
以上来自于谷歌翻译 以下为原文 Thank you very much for your detailed reply. It was very helpful. few more questions that came up. How do I determine the address increment step which corresponds to a certain frequency? I found the following formula desired freq output = step address * the sampled freq / 2^(the number of ROMs address lines) when I assume for example that my desired output is 697Hz (the lowest DTMF tone freq.), the base clock is 8000Hz and the ROM address lines is 16 (The DAC takes 16 bits so I assumed I better save in the rom 16 bits values as lookup table values. correct? can I save values with less bits and just append '0's?). I get a result value for the step address of 5709. Does that mean that the phase increment should increment with 5709 steps for each clock cycle? How do I decide how many values I want in my look up table. I understand that the more I get, the better the resolution I have, but how do I determine what is the minimum amount of values in the LUT in order to generate signals which would be able to be detected with accuracy? For simulation purposes I worked with the following nco code in modelSim and plotted the output for different inputs. can you please help me to detect what is wrong? for every input I get the same exact sine wave output with the same frequency of 500Hz. Thank you very much! LIBRARY ieee;USE ieee.std_logic_1164.all;USE IEEE.numeric_std.ALL;ENTITY nco IS-- Declarationsport (clk : in std_logic;reset : in std_logic;din : in signed(11 downto 0);dout : out signed(7 downto 0));END nco ;-- hds interface_endARCHITECTURE behavior OF nco IStype vectype is array (0 to 256) of signed(7 downto 0);-- ROM cosrom constant cosrom : vectype := (0 => "01111111",1 => "01111111",2 => "01111111",3 => "01111111",4 => "01111111",5 => "01111111",6 => "01111111",7 => "01111111",8 => "01111111",9 => "01111111",10 => "01111111",11 => "01111111",12 => "01111111",13 => "01111111",14 => "01111111",15 => "01111111",16 => "01111111",17 => "01111111",18 => "01111111",19 => "01111111",20 => "01111111",21 => "01111111",22 => "01111111",23 => "01111111",24 => "01111111",25 => "01111110",26 => "01111110",27 => "01111110",28 => "01111110",29 => "01111110",30 => "01111110",31 => "01111110",32 => "01111110",33 => "01111101",34 => "01111101",35 => "01111101",36 => "01111101",37 => "01111101",38 => "01111101",39 => "01111100",40 => "01111100",41 => "01111100",42 => "01111100",43 => "01111100",44 => "01111011",45 => "01111011",46 => "01111011",47 => "01111011",48 => "01111010",49 => "01111010",50 => "01111010",51 => "01111010",52 => "01111010",53 => "01111001",54 => "01111001",55 => "01111001",56 => "01111001",57 => "01111000",58 => "01111000",59 => "01111000",60 => "01110111",61 => "01110111",62 => "01110111",63 => "01110111",64 => "01110110",65 => "01110110",66 => "01110110",67 => "01110101",68 => "01110101",69 => "01110101",70 => "01110100",71 => "01110100",72 => "01110100",73 => "01110011",74 => "01110011",75 => "01110011",76 => "01110010",77 => "01110010",78 => "01110010",79 => "01110001",80 => "01110001",81 => "01110001",82 => "01110000",83 => "01110000",84 => "01101111",85 => "01101111",86 => "01101111",87 => "01101110",88 => "01101110",89 => "01101101",90 => "01101101",91 => "01101101",92 => "01101100",93 => "01101100",94 => "01101011",95 => "01101011",96 => "01101010",97 => "01101010",98 => "01101010",99 => "01101001",100 => "01101001",101 => "01101000",102 => "01101000",103 => "01100111",104 => "01100111",105 => "01100110",106 => "01100110",107 => "01100101",108 => "01100101",109 => "01100100",110 => "01100100",111 => "01100011",112 => "01100011",113 => "01100010",114 => "01100010",115 => "01100001",116 => "01100001",117 => "01100000",118 => "01100000",119 => "01011111",120 => "01011111",121 => "01011110",122 => "01011110",123 => "01011101",124 => "01011101",125 => "01011100",126 => "01011100",127 => "01011011",128 => "01011011",129 => "01011010",130 => "01011001",131 => "01011001",132 => "01011000",133 => "01011000",134 => "01010111",135 => "01010111",136 => "01010110",137 => "01010101",138 => "01010101",139 => "01010100",140 => "01010100",141 => "01010011",142 => "01010010",143 => "01010010",144 => "01010001",145 => "01010001",146 => "01010000",147 => "01001111",148 => "01001111",149 => "01001110",150 => "01001110",151 => "01001101",152 => "01001100",153 => "01001100",154 => "01001011",155 => "01001010",156 => "01001010",157 => "01001001",158 => "01001000",159 => "01001000",160 => "01000111",161 => "01000111",162 => "01000110",163 => "01000101",164 => "01000101",165 => "01000100",166 => "01000011",167 => "01000011",168 => "01000010",169 => "01000001",170 => "01000001",171 => "01000000",172 => "00111111",173 => "00111110",174 => "00111110",175 => "00111101",176 => "00111100",177 => "00111100",178 => "00111011",179 => "00111010",180 => "00111010",181 => "00111001",182 => "00111000",183 => "00111000",184 => "00110111",185 => "00110110",186 => "00110101",187 => "00110101",188 => "00110100",189 => "00110011",190 => "00110011",191 => "00110010",192 => "00110001",193 => "00110000",194 => "00110000",195 => "00101111",196 => "00101110",197 => "00101101",198 => "00101101",199 => "00101100",200 => "00101011",201 => "00101010",202 => "00101010",203 => "00101001",204 => "00101000",205 => "00100111",206 => "00100111",207 => "00100110",208 => "00100101",209 => "00100100",210 => "00100100",211 => "00100011",212 => "00100010",213 => "00100001",214 => "00100001",215 => "00100000",216 => "00011111",217 => "00011110",218 => "00011110",219 => "00011101",220 => "00011100",221 => "00011011",222 => "00011011",223 => "00011010",224 => "00011001",225 => "00011000",226 => "00011000",227 => "00010111",228 => "00010110",229 => "00010101",230 => "00010100",231 => "00010100",232 => "00010011",233 => "00010010",234 => "00010001",235 => "00010001",236 => "00010000",237 => "00001111",238 => "00001110",239 => "00001101",240 => "00001101",241 => "00001100",242 => "00001011",243 => "00001010",244 => "00001010",245 => "00001001",246 => "00001000",247 => "00000111",248 => "00000110",249 => "00000110",250 => "00000101",251 => "00000100",252 => "00000011",253 => "00000010",254 => "00000010",255 => "00000001",256 => "00000000");signal dtemp : unsigned(17 downto 0);signal din_buf : signed(17 downto 0);signal dtemp1 : integer;constant offset : unsigned(17 downto 0) := "000100000000000000";beginprocess(CLK, RESET)beginif (RESET='1') thendout <= (others => '0');din_buf <= (others => '0');dtemp <= (others => '0');dtemp1 <= 0;elsif rising_edge(CLK) thendin_buf <= din(11)&din(11)&din(11)&din(11)&din(11)&din(11)&din;dtemp <= dtemp + unsigned(din_buf) + offset;dtemp1 <= to_integer(dtemp(17 downto 8));if (dtemp1 >= 0) and (dtemp1 < 257) thendout <= cosrom(dtemp1);elsif (dtemp1 >= 257) and (dtemp1 < 513) thendout <= -cosrom(512-dtemp1);elsif (dtemp1 >= 513) and (dtemp1 < 769) thendout <= -cosrom(dtemp1-512);elsedout <= cosrom(1024-dtemp1);end if;end if;end process;END behavior; |
|
|
|
我想你误解了这个公式。
首先,“ROM地址线”应该是NCO计数器大小。 即忘记你的ROM有多大,这完全是关于将地址输入ROM的计数器。 因此,在代码的情况下,您发布了它的18位。 现在代码正确地将此计数器的高位应用于ROM。 但是,在您发布的代码中,输入“din”不足以容纳您需要达到697 Hz的数字。 对于8000 Hz的18位: 地址增量= 697 * 2 ^ 18/8000 = 22,839 因此,首先将“din”18位和无符号(NCO地址计数器只需要计数)开始。 你最终将从只有几个值的表中获取它,所以它不会真正创建大量的额外硬件来使它成为18位。 请记住,NCO地址计数器中的位决定了频率的分辨率,因此您可以使用更多位来获得更严格的频率控制。 计数器中的更多位不会添加大量硬件,因为它们并非都连接到ROM。 ROM本身(在您的情况下为8位地址或256个条目)将决定您可以从NCO获得的正弦波的质量(总谐波失真)。 我的猜测是你所拥有的对于DTMF来说已经足够了,但我不知道具体的规格。 ROM的宽度决定了由ROM表示的正弦波上各个点的精度。 通常情况下,您可以使ROM宽度与DAC相同,但使用16位DAC可能会对DTMF造成过大的影响。 如果你认为256个条目是不够的,但你不想在这个问题上投入更多的RAM资源,你可以做我最初建议的,也就是只在RAM中存储1/4波,然后使用 来自NCO的高位两位用于反转ROM地址和/或ROM输出以重新创建其他三个象限。 - Gabor 以上来自于谷歌翻译 以下为原文 I think you misunderstood the formula. First and foremost, the "ROM address lines" should be the NCO counter size. i.e. forget how big your ROM is, this is all about the counter that feeds the address into the ROM. So in the case of the code you posted it's 18 bits. Now the code correctly applies the upper bits of this counter to the ROM. However in the code you posted, the input "din" is not large enough to hold the number you need to get up to 697 Hz. For 18 bits at 8000 Hz: Address increment = 697 * 2^18 / 8000 = 22,839 So start by making "din" 18 bits, and unsigned (the NCO address counter only needs to count up). You're eventually going to source this from a table of only a few values, so it won't really create a lot of extra hardware to make it 18 bits. Remember that the bits in the NCO address counter determines the resolution of your frequency, so you can get a tighter frequency control with more bits. More bits in the counter don't add a lot of hardware, since they are not all connected to the ROM. The ROM itself (8 bit address in your case or 256 entries) will determine the quality of the sine wave you can get (total harmonic distortion) from the NCO. My guess is that what you have is good enough for DTMF, but I don't know the exact specs. The width of the ROM determines the accuracy of the individual points on the sine wave represented by the ROM. Normally you would make the ROM width the same size as the DAC, but with a 16 bit DAC that could be overkill for DTMF. If you decide that 256 entries is not enough, but you don't want to throw more RAM resources at the problem, you could do what I originally suggested, which is to only store 1/4 wave in the RAM, and then use the upper two bits from the NCO to invert the ROM address and / or ROM output to recreate the other three quadrants. -- Gabor |
|
|
|
关于只存储¼波 - 是不是已经上面的代码正在实现?
dtemp1 在上面的行中,上10位被量化,其中量化相位角的两个最高有效位用于执行象限映射。 在以下行中创建第一象限: if(dtemp1> = 0)和(dtemp1 DOUT 然后重新创建其他3个象限: elsif(dtemp1> = 257)和(dtemp1 DOUT 。 。 。 在这种情况下,我只使用256字节的内存而不是1024个条目,因此使用1024字节的内存。 那是对的吗? 以上来自于谷歌翻译 以下为原文 Regarding to store only ¼ wave – isn’t it what already the code above is implementing? dtemp1 <= to_integer(dtemp(17 downto 8)); In the line above the upper 10 bits are quantized, where the two most significant bits of the quantized phase angle are used to perform quadrant mapping. And in the following lines the 1st quadrant is created: if (dtemp1 >= 0) and (dtemp1 < 257) then dout <= cosrom(dtemp1); and then the other 3 quadrants are recreated: elsif (dtemp1 >= 257) and (dtemp1 < 513) then dout <= -cosrom(512-dtemp1); . . . and in this case I only use 256 bytes of memory instead of having 1024 entries and therefore using 1024 bytes of memory. Is that correct? |
|
|
|
是的,这听起来很正确。
我想我没有深入研究代码,并假设你只是将高8位映射到ROM。 在任何情况下,频率问题都与输入的位数有关。 此外,我不确定你为什么会有偏移量,除非在描述一小段频率时允许更少的输入位。 - Gabor 以上来自于谷歌翻译 以下为原文 Yes, that sounds correct. I guess I didn't look that deeply into the code and assumed you just had the upper 8 bits mapped to the ROM. In any case the problem with the frequency was related to the number of bits input. Also I'm not sure why you had an offset, unless that was to allow fewer input bits while describing a small range of frequency. -- Gabor |
|
|
|
我按照你的建议将输入的位数改为18,并取消了偏移量。
有效。 谢谢! 以上来自于谷歌翻译 以下为原文 I changed the number of bits input to 18 as you suggested and took the offset away. it worked. thanks! |
|
|
|
只有小组成员才能发言,加入小组>>
2429 浏览 7 评论
2830 浏览 4 评论
Spartan 3-AN时钟和VHDL让ISE合成时出现错误该怎么办?
2298 浏览 9 评论
3378 浏览 0 评论
如何在RTL或xilinx spartan fpga的约束文件中插入1.56ns延迟缓冲区?
2468 浏览 15 评论
有输入,但是LVDS_25的FPGA内部接收不到数据,为什么?
1288浏览 1评论
请问vc707的电源线是如何连接的,我这边可能出现了缺失元件的情况导致无法供电
592浏览 1评论
求一块XILINX开发板KC705,VC707,KC105和KCU1500
455浏览 1评论
2010浏览 0评论
736浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-27 01:14 , Processed in 1.419888 second(s), Total 91, Slave 73 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号