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;
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