1

生成不同的频率。信号,我使用了 3 种不同的方式。Do(440hz) 和 Re(494hz) 一个,使用 8mhz 的外部时钟。Me(523hz) 和 Fa(587) 的另一种方式,根据需要通过简单的延迟。另一种方法是针对 So(659hz) La(698hz) 和 Ti(784hz),根据需要使用延迟以及 for 循环。for 循环用于生成 1 秒的信号,因为信号为“1”。然而,使用外部时钟效果很好,但面临其他两种方式的问题。任何人都可以在这方面帮助我。三种使用方式哪个更好..??? 有没有其他方法可以做到这一点......???提前致谢。

----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity piano is
    Port ( do : in  STD_LOGIC;
           re : in  STD_LOGIC;
           me : in  STD_LOGIC;
           fa : in  STD_LOGIC;
           so : in  STD_LOGIC;
           la : in  STD_LOGIC;
           ti : in  STD_LOGIC;
           clk_8mhz : in  STD_LOGIC; --using the exterrnal clock of 8mhz.
           spek : out  STD_LOGIC);   --o/p connected to the speaker.
end piano;

architecture pbev of piano is
 signal Counter440: integer:= 0;
 signal Counter494: integer:= 0;
 signal temp: integer:= 0;
 signal clk_440hz: std_logic:= '0';
 signal clk_494hz: std_logic:= '0';
begin
 Prescaler440 : process(clk_8mhz) --process to convert 8mhz freq to 440hz.
 begin
        if rising_edge(clk_8mhz) then
            if Counter440 < 18180 then --8mhz/18181 = 440hz
                Counter440 <= Counter440 + 1;
            else
                clk_440hz <= not clk_440hz;
                Counter440 <= 0;
            end if;
        end if;
 end process Prescaler440; --gives o/p clk_440 as sq. wave of 440hz freq.

 Prescaler494 : process(clk_8mhz) --process to convert 8mhz freq to 494hz.
 begin
        if rising_edge(clk_8mhz) then
            if Counter494 < 16192 then --8mhz/16193 = 494hz
                Counter494 <= Counter494 + 1;
            else
                clk_494hz <= not clk_494hz;
                Counter494 <= 0;
            end if;
        end if;
 end process Prescaler494; --gives o/p clk_494 as sq. wave of 494hz freq.

pianoproc : process(do,re,me,fa,so,la,ti,clk_8mhz)
begin

if (do = '1') then
 spek <= clk_440hz; -- speaker gets i/p wave of 440hz.

elsif (re = '1') then
 spek <= clk_494hz; -- speaker gets i/p wave of 494hz.

elsif (me = '1') then
 spek <= '1'
 after 956023 ns; --1/(523 hz) = 1912045ns // (1912045/2) = 956023ns.
 spek <= '0'
 after 956023 ns;

elsif (fa = '1') then --1/(587 hz) = 1703577ns // (1703577/2) = 851789ns.
 spek <= '1'
 after 851789 ns;
 spek <= '0'
 after 851789 ns;

elsif (so <= '1') then
for temp in 0 to 659 loop --loop continues to generate sq. wave of 659hz for 659*(758725*2) ns = 1sec
   spek <= '1'
  after 758725 ns; --1/(659 hz) = 1517450ns // (1517450/2) = 758725ns
  spek <= '0'
  after 758725 ns;
end loop;


elsif (la <= '1') then
for temp in 0 to 698 loop --loop continues to generate sq. wave of 698hz for 698*(758725*2) ns = 1sec
 spek <= '1'
 after 716332 ns; --1/(698 hz) = 1432664ns // (1432664/2) = 716332ns
 spek <= '0'
 after 716332 ns;
end loop;

elsif (ti <= '1') then
for temp in 0 to 784 loop --loop continues to generate sq. wave of 784hz for 784*(637755*2) ns = 1sec
 spek <= '1'
 after 637755 ns; --1/(784 hz) = 1275510ns // (1275510/2) = 637755ns
 spek <= '0'
 after 637755 ns;
end loop;

else spek <= '0';

end if;
end process pianoproc;
end pbev;
4

1 回答 1

1

编码

for temp in 0 to 659 loop 
  spek <= '1' after 758725 ns; --1/(659 hz) = 1517450ns // (1517450/2) = 758725ns
  spek <= '0' after 758725 ns;
end loop;

在“spek”上安排 2 * 659 次转换,所有转换都在进入循环后 758 us 发生。最后一个转换获胜,它将 spek 设置为“0”。

for temp in 0 to 659 loop 
   spek <= '1' after 758725 ns, '0' after 1517450 ns;
   wait for 1517450ns;
end loop;

可能更接近你想要的。

但是,对于其他评论所说的合成,“do”或“re”的代码有效(和合成!)。

还有一点值得考虑:让编译器自己生成所有有趣的常量更容易——然后如果你改变一个参数,比如时钟频率,你就不需要花一个小时在计算器上......

clk_freq   : natural := 8000000;
clk_period : time := 1 sec / clk_freq;

或者对于仅限 SIM 卡的版本,

procedure note (freq : natural; duration : time) is
-- not synthesisable!
begin
   for temp in 1 to freq * duration / 1 sec loop 
      spek <= '1' after 1 sec / freq / 2, '0' after 1 sec / freq;
      wait for 1 sec / freq;
   end loop;
end note;

...
if (la <= '1') then
   note(698, 1 sec);
elsif
于 2014-04-01T18:09:46.917 回答