
一、按键电路
常用的非编码键盘,每个键都是一个常开开关电路。
计数器输入脉冲最好不要直接接普通的按键开关,因为记数器的记数速度非常快,按键、触点等接触时会有多次接通和断开的现象。我们感觉不到,可是记数器却都记录了下来。例如,虽然只按了1下,记数器可能记了3下。因此,使用按键的记数电路都会增加单稳态电路避免记数错误。
二、按键消抖
通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号小型如下图。由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,如下图。抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。这是一个很重要的时间参数,在很多场合都要用到。
按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。键抖动会引起一次按键被误读多次。为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。按键的抖动,可用硬件或软件两种方法。
三、硬件消抖
在键数较少时可用硬件方法消除键抖动。下图所示的RS触发器为常用的硬件去抖。
图中两个“与非”门构成一个RS触发器。当按键未按下时,输出为1;当键按下时,输出为0。此时即使用按键的机械性能,使按键因弹性抖动而产生瞬时断开(抖动跳开B),中要按键不返回原始状态A,双稳态电路的状态不改变,输出保持为0,不会产生抖动的波形。也就是说,即使B点的电压波形是抖动的,但经双稳态电路之后,其输出为正规的矩形波。这一点通过分析RS触发器的工作过程很容易得到验证。
利用电容的放电延时,采用并联电容法,也可以实现硬件消抖:
四、软件延时消抖
如果按键较多,常用软件方法去抖,即检测出键闭合后执行一个延时程序,产生5ms~10ms的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。当检测到按键释放后,也要给5ms~10ms的延时,待后沿抖动消失后才能转入该键的处理程序。
五、VHDL按键去抖
按键检测需要消抖,一般有硬件和软件两种方式。硬件就是加去抖动电路,这样从根本上解决按键抖动问题。
除了用专用电路以外,用可编程FPGA或者CPLD设计相应的逻辑和时序电路,对按键信号进行处理,同样可以达到去抖动的目的。
本例中用状态机实现了消抖电路:
端口描述:clk 输入检测时钟;reset 复位信号;din 原始按键信号输入; dout 去抖动输出信号。
VHDL源码如下:
LIBRARY ieee;
USE ieee.std_logic_11.all;
USE ieee.std_logic_unsigned.all;
ENTITY xiaod IS
PORT
(
clk : IN STD_LOGIC ;
reset : IN STD_LOGIC ;
din : IN STD_LOGIC ;
dout : OUT STD_LOGIC
);
END ENTITY;
ARCHITECTURE RTL OF xiaod IS
TYPE state IS( s0,s1,s2,s3);
SIGNAL pre_s, next_s: state;
BEGIN
P0:PROCESS( reset, clk )
BEGIN
if reset = '0' then pre_s <= s0;
elsif rising_edge( clk ) then pre_s <= next_s;
else null;
end if;
END PROCESS P0;
P1:PROCESS( pre_s, next_s, din )
BEGIN
case pre_s is
when s0 =>dout <= '1';
if din = '1' then next_s <= s0; else next_s <= s1;
end if;
when s1 => dout <= '1';
if din = '1' then next_s <= s0; else next_s <= s2;
end if;
when s2 => dout <= '1';
if din = '1' then next_s <= s0; else next_s <= s3;
end if;
when s3 => dout <= '0';
if din = '1' then next_s <= s0; else next_s <= s1;
end if;
end case;
END PROCESS P1;
END RTL;
多按键去抖动电路VHDL源码,按键个数参数化,每个按键处理调用了上面的模块:
LIBRARY ieee;
USE ieee.std_logic_11.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
ENTITY Nxiaod IS
GENERIC( width: positive:= 5 );
PORT
(
clk : IN STD_LOGIC ;
reset : IN STD_LOGIC ;
din : IN STD_LOGIC_VECTOR( width - 1 DOWNTO 0);
dout : OUT STD_LOGIC_VECTOR( width - 1 DOWNTO 0)
);
END ENTITY;
ARCHITECTURE RTL OF Nxiaod IS
COMPONENT xiaod IS
PORT
(
clk : IN STD_LOGIC ;
reset : IN STD_LOGIC ;
din : IN STD_LOGIC ;
dout : OUT STD_LOGIC
);
END COMPONENT;
BEGIN
g1: FOR i IN 0 to width - 1 GENERATE
ux: xiaod port map( clk => clk, reset => reset, din => din(i), dout => dout(i));
END GENERATE;
END RTL;
2、TTL电平与CMOS电平的区别
TTL电平信号被利用的最多是因为通常数据表示采用二进制规定,+5V等价于逻辑"1",0V等价于逻辑"0",这被称做TTL(晶体管-晶体管逻辑电平)信号系统,这是计算机处理器控制的设备内部各部分之间通信的标准技术。
TTL电平信号对于计算机处理器控制的设备内部的数据传输是很理想的,首先计算机处理器控制的设备内部的数据传输对于电源的要求不高以及热损耗也较低,另外TTL电平信号直接与集成电路连接而不需要价格昂贵的线路驱动器以及接收器电路;再者,计算机处理器控制的设备内部的数据传输是在高速下进行的,而TTL接口的操作恰能满足这个要求。TTL型通信大多数情况下,是采用并行数据传输方式,而并行数据传输对于超过10英尺的距离就不适合了。这是由于可靠性和成本两面的原因。因为在并行接口中存在着偏相和不对称的问题,这些问题对可靠性均有影响;另外对于并行数据传输,电缆以及连接器的费用比起串行通信方式来也要高一些。
什么是TTL电平,什么是CMOS电平,他们的区别
(一)TTL高电平3.6~5V,低电平0V~2.4V
CMOS电平Vcc可达到12V
CMOS电路输出高电平约为0.9Vcc,而输出低电平约为
0.1Vcc。
CMOS电路不使用的输入端不能悬空,会造成逻辑混乱。
TTL电路不使用的输入端悬空为高电平
另外,CMOS集成电路电源电压可以在较大范围内变化,因而对电源的要求不像TTL集成电路那样严格。
用TTL电平他们就可以兼容
(二)TTL电平是5V,CMOS电平一般是12V。
因为TTL电路电源电压是5V,CMOS电路电源电压一般是12V。
5V的电平不能触发CMOS电路,12V的电平会损坏TTL电路,因此不能互相兼容匹配。
(三)TTL电平标准
输出 L: <0.8V ; H:>2.4V。
输入 L: <1.2V ; H:>2.0V
TTL器件输出低电平要小于0.8V,高电平要大于2.4V。输入,低于1.2V就认为是0,高于2.0就认为是1。
CMOS电平:
输出 L: <0.1*Vcc ; H:>0.9*Vcc。
输入 L: <0.3*Vcc ; H:>0.7*Vcc.
一般单片机、DSP、FPGA他们之间管教能否直接相连. 一般情况下,同电压的是可以的,不过最好是要好好查查技术手册上的VIL,VIH,VOL,VOH的值,看是否能够匹配(VOL要小于VIL,VOH要大于VIH,是指一个连接当中的)。有些在一般应用中没有问题,但是参数上就是有点不够匹配,在某些情况下可能就不够稳定,或者不同批次的器件就不能运行。
例如:74LS的器件的输出,接入74HC的器件。在一般情况下都能好好运行,但是,在参数上却是不匹配的,有些情况下就不能运行。
TTL与COMS电平使用区别
1、电平的上限和下限定义不一样,CMOS具有更大的抗噪区域。
同是5伏供电的话,ttl一般是1.7V和3.5V的样子,CMOS一般是
2.2V,2.9V的样子,不准确,仅供参考。
2、电流驱动能力不一样,ttl一般提供25毫安的驱动能力,而
CMOS一般在10毫安左右。
3、需要的电流输入大小也不一样,一般ttl需要2.5毫安左右,CMOS
几乎不需要电流输入。
4、很多器件都是兼容ttl和CMOS的,datasheet会有说明。如果不考虑
速度和性能,一般器件可以互换。但是需要注意有时候负载效应可能
引起电路工作不正常,因为有些ttl电路需要下一级的输入阻抗作为
负载才能正常工作。
TTL——Transistor-Transistor Logic
HTTL——High-speed TTL
LTTL——Low-power TTL
STTL——Schottky TTL
LSTTL——Low-power Schottky TTL
ASTTL——Advanced Schottky TTL
ALSTTL——Advanced Low-power Schottky TTL
FAST(F)——Fairchild Advanced schottky TTL
CMOS——Complementary metal-oxide-semiconductor
HC/HCT——High-speed CMOS Logic(HCT与TTL电平兼容)
AC/ACT——Advanced CMOS Logic(ACT与TTL电平兼容)(亦称ACL)
AHC/AHCT——Advanced High-speed CMOS Logic(AHCT与TTL电平兼容)
FCT——FACT扩展系列,与TTL电平兼容
FACT——Fairchild Advanced CMOS Technology,其
1,TTL电平:
输出高电平 〉2.4V 输出低电平 〈0.4V
在室温下,一般输出高电平是3.5V 输出低电平是0.2V。
最小输入高电平和低电平
输入高电平 〉=2.0V 输入低电平 《=0.8V
它的噪声容限是0.4V.
2,CMOS电平:
逻辑电平电压接近于电源电压,0逻辑电平接近于0V。而且具有很宽的噪声容限。
3,电平转换电路:
因为TTL和COMS的高低电平的值不一样(ttl 5vcmos 3.3v),所以互相连接时需
要电平的转换:就是用两个电阻对电平分压,没有什么高深的东西。
4,OC门,即集电极开路门电路,OD门,即漏极开路门电路,必须外界上拉电阻和电源才能
将开关电平作为高低电平用。否则它一般只作为开关大电压和大电流负载,所以又叫做驱
动门电路。
5,TTL和COMS电路比较:
1)TTL电路是电流控制器件,而coms电路是电压控制器件。
2)TTL电路的速度快,传输延迟时间短(5-10ns),但是功耗大。
COMS电路的速度慢,传输延迟时间长(25-50ns),但功耗低。
COMS电路本身的功耗与输入信号的脉冲频率有关,频率越高,芯片集越热,这是正常
现象。
3)COMS电路的锁定效应:
COMS电路由于输入太大的电流,内部的电流急剧增大,除非切断电源,电流一直在增大
。这种效应就是锁定效应。当产生锁定效应时,COMS的内部电流能达到40mA以上,很容易
烧毁芯片。
防御措施:
1)在输入端和输出端加钳位电路,使输入和输出不超过不超过规定电压。
2)芯片的电源输入端加去耦电路,防止VDD端出现瞬间的高压。
3)在VDD和外电源之间加线流电阻,即使有大的电流也不让它进去。
4)当系统由几个电源分别供电时,开关要按下列顺序:开启时,先开启COMS电路得电
源,再开启输入信号和负载的电源;关闭时,先关闭输入信号和负载的电源,再关闭COMS
电路的电源。
6,COMS电路的使用注意事项
1)COMS电路时电压控制器件,它的输入总抗很大,对干扰信号的捕捉能力很强。所以
,不用的管脚不要悬空,要接上拉电阻或者下拉电阻,给它一个恒定的电平。
2)输入端接低内组的信号源时,要在输入端和信号源之间要串联限流电阻,使输入的
电流在1mA之内。
3)当接长信号传输线时,在COMS电路端接匹配电阻。
4)当输入端接大电容时,应该在输入端和电容间接保护电阻。电阻值为R=V0/1mA.V0是
外界电容上的电压。
5)COMS的输入电流超过1mA,就有可能烧坏COMS。
7,TTL门电路中输入端负载特性(输入端带电阻特殊情况的处理):
1)悬空时相当于输入端接高电平。因为这时可以看作是输入端接一个无穷大的电阻。
2)在门电路输入端串联10K电阻后再输入低电平,输入端出呈现的是高电平而不是低电
平。因为由TTL门电路的输入端负载特性可知,只有在输入端接的串联电阻小于910欧时,
它输入来的低电平信号才能被门电路识别出来,串联电阻再大的话输入端就一直呈现高电
平。这个一定要注意。COMS门电路就不用考虑这些了。
8,TTL电路有集电极开路OC门,MOS管也有和集电极对应的漏极开路的OD门,它的输出就叫
做开漏输出。
OC门在截止时有漏电流输出,那就是漏电流,为什么有漏电流呢?那是因为当三机管截
止的时候,它的基极电流约等于0,但是并不是真正的为0,经过三极管的集电极的电流也
就不是真正的0,而是约0。而这个就是漏电流。开漏输出:OC门的输出就是开漏输出;OD
门的输出也是开漏输出。它可以吸收很大的电流,但是不能向外输出的电流。所以,为了
能输入和输出电流,它使用的时候要跟电源和上拉电阻一齐用。OD门一般作为输出缓冲/驱
动器、电平转换器以及满足吸收大负载电流的需要。
9,什么叫做图腾柱,它与开漏电路有什么区别?
TTL集成电路中,输出有接上拉三极管的输出叫做图腾柱输出,没有的叫做OC门。因为TTL就是一个三级关,图腾柱也就是两个三级管推挽相连。所以推挽就是图腾。一般图腾式输出,高电平400UA,低电平8MA
1. TTL电路和CMOS电路的逻辑电平
VOH: 逻辑电平 1 的输出电压
VOL: 逻辑电平 0 的输出电压
VIH : 逻辑电平 1 的输入电压
VIH : 逻辑电平 0 的输入电压
TTL电路临界值:
VOHmin = 2.4V VOLmax = 0.4V
VIHmin = 2.0V VILmax = 0.8V
CMOS电路临界值(电源电压为+5V)
VOHmin = 4.99V VOLmax = 0.01V
VIHmin = 3.5V VILmax = 1.5V
2. TTL和CMOS的逻辑电平转换
CMOS电平能驱动TTL电平
TTL电平不能驱动CMOS电平,需加上拉电阻。
3. 常用逻辑芯片特点
74LS系列: TTL 输入: TTL 输出: TTL
74HC系列: CMOS 输入: CMOS 输出: CMOS
74HCT系列: CMOS 输入: TTL 输出: CMOS
CD4000系列: CMOS 输入: CMOS 输出: CMOS
说明如下:
1.其中top file 为 division,其中的clk_com是比较的频率,用它来和分频后波形进行比较,便于观察,
2.any_enve为任意偶数分频文件
3.any_odd为任意奇数分频文件
4.是一个用于2进制与8进制的译码器,我用它来显示在数码管上当前到底是多少分频
5.由于用的是quartus7.1编辑的,中间无法加中文注释;以下是代码:
------the top file of the design division
library ieee;
use ieee.std_logic_11.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity division is
port (input : in std_logic_vector(7 downto 0);
clk : in std_logic;
clk_out : out std_logic;
clk_com : out std_logic;
led1: out std_logic_vector(6 downto 0);
led2: out std_logic_vector(6 downto 0);
led3: out std_logic_vector(6 downto 0));
end entity division;
--------------------------------------------------
architecture freq of division is
component decoder is ----decoder
port(bin : in std_logic_vector(2 downto 0);
de : out std_logic_vector(6 downto 0));
end component;
component any_even is ----any_even
generic (data_width : integer := 8 );
port(input1 : in std_logic_vector(data_width-1 downto 0);
clk_in : in std_logic;
clk_out : out std_logic);
end component any_even;
component any_odd is ----- any_odd
generic (data_width : integer := 8);
port(input2 : in std_logic_vector(data_width - 1 downto 0);
clk_in : in std_logic;
clk_out : out std_logic);
end component any_odd;
signal temp1,temp2 : std_logic;
begin
u1: decoder port map(bin=>input(2)&input(1)&input(0),de=>led1);
u2: decoder port map(bin=>input(5)&input(4)&input(3),de=>led2);
u3: decoder port map(bin=>'0'&input(7)&input(6),de=>led3);
u4: any_even port map(input,clk,temp1);
U5: any_odd port map(input,clk,temp2);
process(clk,input)
begin
if input(0)= '0' then
clk_out <= temp1;
else clk_out <= temp2;
end if;
end process;
clk_com <= clk;
end architecture freq;
library ieee;
use ieee.std_logic_11.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity any_even is
generic (data_width : integer := 8 );
port(input1 : in std_logic_vector(data_width-1 downto 0);
clk_in : in std_logic;
clk_out : out std_logic);
end entity any_even;
architecture div1 of any_even is
signal clk_outQ : std_logic ;
signal coutQ : std_logic_vector (data_width - 1 downto 0);
begin
-------------------------------------------------
process(clk_in)
begin
if clk_in'event and clk_in = '1' then
if coutQ < (conv_integer(input1) - 1) then
coutQ <= coutQ + 1;
else coutQ <= (others => '0');
end if;
end if;
end process;
---------------------------------------------------
process(coutQ)
begin
if coutQ < (conv_integer(input1))/2 then
clk_outQ <= '0';
else clk_outQ <= '1';
end if;
end process;
clk_out <= clk_outQ;
end architecture div1;
library ieee;
use ieee.std_logic_11.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity any_odd is
generic (data_width : integer := 8);
port(input2 : in std_logic_vector(data_width - 1 downto 0);
clk_in : in std_logic;
clk_out : out std_logic);
end entity any_odd;
architecture div2 of any_odd is
signal cout1,cout2 : std_logic_vector(data_width - 1 downto 0);
signal clk1,clk2 : std_logic;
begin
process(clk_in)------rising edge
begin
if clk_in'event and clk_in='1' then
if cout1 < (conv_integer(input2)-1) then
cout1 <= cout1 + 1;
else cout1 <= (others => '0');
end if;
if cout1 < (conv_integer(input2)-1)/2 then
clk1 <= '1';
else clk1 <= '0';
end if;
end if;
end process;
---------------------------
process(clk_in)------falling edge
begin
if clk_in'event and clk_in='0' then
if cout2 < (conv_integer(input2)-1) then
cout2 <= cout2 + 1;
else cout2 <= (others => '0');
end if;
if cout2 < (conv_integer(input2)-1)/2 then
clk2 <= '1';
else clk2 <= '0';
end if;
end if;
end process;
clk_out <= clk1 or clk2;
end architecture div2;
library ieee;
use ieee.std_logic_11.all;
entity decoder is
port(bin : in std_logic_vector(2 downto 0);
de : out std_logic_vector(6 downto 0));
end entity;
----------------------------------------------------
architecture deco of decoder is
begin
process(bin)
begin
case bin is
when "000" => de <= "0111111";---0
when "001" => de <= "0000110";---1
when "010" => de <= "1011011";---2
when "011" => de <= "1001111";---3
when "100" => de <= "1100110";---4
when "101" => de <= "1101101";---5
when "110" => de <= "1111101";---6
when others => de <= "0000111";---7
end case;
end process;
end architecture;
在数字电路中,常需要对较高频率的时钟进行分频操作,得到较低频率的时钟信号。我们知道,在硬件电路设计中时钟信号是非常重要的。
下面我们介绍分频器的VHDL描述,在源代码中完成对时钟信号CLK的2分频,4分频,8分频,16分频。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_11.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY clkdiv IS
PORT(clk : IN STD_LOGIC;
clk_div2 : OUT STD_LOGIC;
clk_div4 : OUT STD_LOGIC;
clk_div8 : OUT STD_LOGIC;
clk_div16 : OUT STD_LOGIC);
END clk_div;
ARCHITECTURE rtl OF clk_div IS
SIGNAL count : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(clk)
BEGIN
IF (clk’event AND clk=’1’) THEN
IF(count=”1111”) THEN
Count <= (OTHERS =>’0’);
ELSE
Count <= count +1;
END IF ;
END IF ;
END PROCESS;
clk_div2 <= count(0);
clk_div4 <= count(1);
clk_div8 <= count(2);
clk_div16 <= count(3);
END rtl;
对于分频倍数不是2的整数次幂的情况,我们只需要对源代码中的计数器进行一下计数控制就可以了,如下面源代码描述一个对时钟信号进行6分频的分频器。
ENTITY clkdiv IS
PORT(clk : IN STD_LOGIC;
clk_div6 : OUT STD_LOGIC);
END clk_div;
ARCHITECTURE rtl OF clk_div IS
SIGNAL count : STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL clk_temp : STD_LOGIC;
BEGIN
PROCESS(clk)
BEGIN
IF (clk’event AND clk=’1’) THEN
IF(count=”10”) THEN
count <= (OTHERS =>’0’);
clk_temp <=NOT clk_temp;
ELSE
count <= count +1;
END IF ;
END IF ;
END PROCESS;
clk_div6 <= clk_temp;
END rtl;
前面两个分频器的例子描述的将时钟信号进行分频,分频后得到的时钟信号的占空比为1:1。在进行硬件设计的时候,往往要求得到一个占空比不是1:1的分频信号,这时仍采用计数器的方法来产生占空比不是1:1的分频信号。下面源代码描述的是这样一个分频器:将输入的时钟信号进行16分频,分频信号的占空比为 1:15,也就是说,其中高电位的脉冲宽度为输入时钟信号的一个周期。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_11.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY clkdiv IS
PORT(clk : IN STD_LOGIC;
clk_div16 : OUT STD_LOGIC);
END clk_div;
ARCHITECTURE rtl OF clk_div IS
SIGNAL count : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(clk)
BEGIN
IF (clk’event AND clk=’1’) THEN
IF(count=”1111”) THEN
Count <= (OTHERS =>’0’);
ELSE
Count <= count +1;
END IF ;
END IF ;
END PROCESS;
PROCESS(clk)
BEGIN
IF (clk’event AND clk=’1’) THEN
IF(count=”1111”) THEN
Clk_div16 <= ‘1’;
ELSE
Clk_div <= ‘0’;
END IF ;
END IF ;
END PROCESS;
END rtl;
对于上述源代码描述的这种分频器,在硬件电路设计中应用十分广泛,设计人员常采用这种分频器来产生选通信号、中断信号和数字通信中常常用到的帧头信号等。
4、基于VHDL的数字倍频器设计
5、正弦波发生器的设计方案
一、设计思路:50MHZ的频率通过PLLU倍频到150MHZ,然后经过分频器控制分频后再输入到10位计数器和ROM的时钟,在这个的设计过程中有一些细小的问题耽误了我很多时间去调试.下面我就把我所遇到的问题都列举出来以供今后借鉴:
1、PLLU的设计:当时我就按书上的步骤来的,可是文件夹里就是没有生成任何文件。后来在他人的指导下我才发现执行到最后一步,要按ENTER键才能生成文件。
2、DVF模块的设计:
仿真的时候,发现分频关系是(D+1)* 2的关系。
3、ROM模块的设计
最初书上给出的是个点的ROM表,但是如果要扩展为1024个点的,就要修改一些参数。
我发现用我自己编的C程序得到的.MIF文件在编译时说超过了8位输出数据的大小,但是用群里面传的软件生成的文件编译时就成功了。后来我想了一下,你8位输出给DA,最大数字量为255,但是我的程序中却出现最大值为1024的值。这很明显是有错的。程序需要修改。
思考一下该怎么修改???
#include #include #define width 8 //mif 存储数据宽度,这个应该与所用的DA相匹配 #define depth 1024 //mif 存储数据总量 int main() { int i; float s; //在桌面新建Mif文件 FILE *fp; fp=fopen("C:\\\\Documents and Settings\\\\All Users\\\桌面\\\\Mif.mif在桌面生成一个.mif的文件,你在桌面就可以找到这个Mif.mif文件 fprintf(fp,"--Design by fyXXXfXX\\n"); //作者说明 fprintf(fp,"--For generating *.mif file(s) for QuartusII\\n\\n"); //文件使用功能说明 fprintf(fp,"WIDTH=%d;\\n",width); fprintf(fp,"DEPTH=%d;\\n",depth); fprintf(fp,"\\n"); fprintf(fp,"ADDRESS_RADIX=UNS;\\n"); fprintf(fp,"DATA_RADIX=UNS;\\n"); fprintf(fp,"\\n"); fprintf(fp,"CONTENT BEGIN \\n"); for(i=0;i s=sin(atan(1)*8*i/ depth); //这里是获得正弦波的功能语句,你也可以编写实现自己想要的波形的语句。这就看我们的读者想要生成什么样的波形了!呵呵! fprintf(fp,"\%d\:\%d;\\n",i,(int)((s+1)* (depth -1)/2)); //主体部分的语句格式 } fprintf(fp,"END;"); fclose(fp); return (0); } /*把以上程序在Visual C++6.0上运行,由于程序设置的是“C:\\\\Documents and Settings\\\\All Users\\\桌面\\\\Mif.mif”这个路径,于是就可以在桌面生成文件名为Mif.mif的文件。 至于说width的设定,就要与相应的DA转换器的位数相匹配,比如说一个8位的DA,width就应该设为8;而depth即为所取的点数。并不是说所取的点数越多越好,因为点数越多,你的输入频率也要做的相当高才能得到很宽频率范围的输出信号,这对锁相环的要求也相应提高。 这个程序是实现正弦波波形数据的输出。其核心算法如下: s=sin(atan(1)*8*i/ depth); fprintf(fp,"\%d\:\%d;\\n",i,(int)((s+1)* (depth -1)/2)); 第一句是求每一点经量化后的正弦值,而第二步是向文件中输入数据。我们可以看到,它并不是直接将S的值输出,而也是在经量化后输出的。我们可以这样理解(int)((s+1)* (depth -1)/2)这一句,将他拆开为S*1023/2+1023/2;这样就很好理解了。*/ 4、用原理图进行顶层设计 先要生成所要调用的模块。然后把这些生成的模块放在同一个文件夹中。特别是相关的.vhd文件我在编译时还出现过另一种情况,就是必须把那个1024点的.MIF文件也放在刚才所建的顶层文件的文件夹中。否则编译也会出错。 5、Quartus_II软件显示窗口标签(tab)的问题 第一次装Quartus II的时候(那时候还是6.0版本),使用过程中不小心在窗口标签上右键然后点了一下“Hide Tabs”(见下图),然后窗口就没标签了,查看和切换变成非常难用,当时找了很久也没有找到显示窗口标签的方法,后来实在不爽就重装了。 晚上在做一个设计的时候不小心又点了那个“Hide Tabs“,登时标签又没了,抓狂啊,搞不好还要重装,幸好,在网上搜了搜就找到了解决办法: 打开”Tools”–>”Option”对话框(如下图) 选中“Display Tabs for child window 现在标签重新显示了,虽然设置起来也很方便,不过不提示的话估计很多人都找不到,Altera公司的平台开发工程师不知道怎么想的,把显示范畴的设置放到Tools里,害的大家都找不到。 二、发散思考 1、先是近期所做的题目“网络导纳分析仪”该如何实现频率100Hz 的步进增加??? 有一种想法就是建一个小的ROM表,把所要实现的频率的控制字算出来经硬件调好了后存放在ROM里面。通过另一个周期约为1s的时钟来取ROM中的值。 现在我们的问题是要实现的频率无法达到所要的精度。100Hz、300Hz、1kHz、3kHz、10kHz 五个频率无法实现误差为所要求频率的1%。可能是由于原来的VHDL代码只能实现偶数分频,而无法实现任意整数的分频。 (1) 基本要求:制作正弦波信号发生器,技术指标如下: a、能产生 100Hz、300Hz、1kHz、3kHz、10kHz 五个频率,频率误差的绝对值小于所要求频率的1%; b、输出电压峰-峰值为1V,输出电压误差的绝对值小于20mV; c、输出电阻小于 1Ω(在设计报告中给出推导和计算结果,不进行测试);输出波形无明显失真。 (2)扩展要求:a、正弦波信号发生器的频率可以从 100Hz 开始,以100Hz 的步进增加,最后到达10kHz 结束; 2、若是做一个DDS信号发生器,频率和相位该如何控制??? 3、如何做到很高的频率???(这可能与运放的选择以及DA的选择有关)
