Frage

To generate different freq. signal, I've used 3 different ways. One for Do(440hz) and Re(494hz), by using the external clock of 8mhz. The other way for Me(523hz) and Fa(587), by simply delay, as required. The other way is for So(659hz) La(698hz) and Ti(784hz), by using delay as required, along with for loop. The for loop is used to generate signal for 1sec, as the signal is '1'. However, the use of external clock works well but facing problem other two ways. Can anyone please help me in this. Which of the three used way is better..??? Are there any other way to do the same...??? Thanks in advance.

----------------------------------------------------------------------------------
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;
War es hilfreich?

Lösung

The code

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;

schedules 2 * 659 transitions on "spek", all occurring 758 us after the loop is entered. The last transition wins, which sets spek to '0'.

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

is probably closer to what you want.

However, for synthesis as other comments say, the code for "do" or "re" works (and synthesises!).

One other point worth thinking about : it's easier to let the compiler generate all the funny constants itself - then if you change a parameter such as the clock frequency you don't need to spend an hour with the calculator...

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

or for the sim only version,

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top