0

I'm doing a musicbox with VHDL. I first played just A4 and I was successful.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.NUMERIC_STD.ALL;


library UNISIM;

use UNISIM.VComponents.all;


entity Basic is

    Port(   clk : in STD_LOGIC;
        note : out STD_LOGIC;
        );
end Basic;

architecture Behavioral of Basic is

    signal count : unsigned (15 downto 0) := (others => '0');
begin

    note <= std_logic(count(15));
    process (clk)
    begin
        if rising_edge(clk) then
            if (count=56817) then
                count <= "0000000000000000";
            else
                count <= count + 1;
            end if;
            end if;
    end process;
end Behavioral;

My unfinished code is like this

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

library UNISIM;
use UNISIM.VComponents.all;

entity Basic is

    Port(   clk : in STD_LOGIC;
            note : out STD_LOGIC;
            address: in integer range 0 to 31
        );
end Basic;

architecture Behavioral of Basic is

    signal count : unsigned (15 downto 0) := (others => '0');
    signal reg_address : integer range 0 to 31 ;
    type rom_array is array (0 to 31) of integer (4 downto 0);
    constant rom: rom_array := (    "11011", "11011",
                    "11011", "11011","11011", "11011",
                    "11011", "11011", "11011", "11011",
                    "11011", "11011","11011", "11011",
                    "11011", "11011","11011", "11011",
                    "11011", "11011","11011", "11011",
                    "11011", "11011","11011", "11011",
                    "11011", "11011","11011", "11011",
                    "11011", "11011");
begin

    note <= std_logic(count(15));
    process (clk)
    begin
            if rising_edge(clk) then
                reg_address <= address;
                if (reg_address < 32) then
                    if (count = rom(reg_address)) then
                        count <= "0000000000000000";
                    else
                        count <= count + 1;
                    end if;
                else
                    reg_address <= "00000";
                end if;
            end if;
            reg_address <= reg_address + 1;
    end process;
end Behavioral;

the rom values are going to change. I'm trying to generate a sound by dividing the clock. Like 25mhz/56818 = 440. To play a song I thought of creating a rom filled with numbers needed to divide the clock, then do a for loop and play the song. But I can't because for loop isn't similar to java/C so I think I need to bypass it.

My errors are:

ERROR:HDLParsers:526 - "C:/Users/user/DigitalProje/Basic.vhd" Line 18. Non array type integer can not have a index constraint.

ERROR:HDLParsers:3312 - "C:/Users/user/DigitalProje/Basic.vhd" Line 19. Undefined symbol 'rom_array'.

ERROR:HDLParsers:1209 - "C:/Users/user/DigitalProje/Basic.vhd" Line 19. rom_array: Undefined symbol (last report in this block)

ERROR:HDLParsers:3285 - "C:/Users/user/DigitalProje/Basic.vhd" Line 19. No array or record type can be found that has elements of types matching the aggregate.

ERROR:HDLParsers:532 - "C:/Users/user/DigitalProje/Basic.vhd" Line 19. Deferred constant are allowed only in packages.

ERROR:HDLParsers:808 - "C:/Users/user/DigitalProje/Basic.vhd" Line 35. = can not have such operands in this context.

ERROR:HDLParsers:800 - "C:/Users/user/DigitalProje/Basic.vhd" Line 41. Type of reg_address is incompatible with type of 00000.

Community
  • 1
  • 1
Strider
  • 1
  • 1
  • Bear in mind that if you iterate though each division value once the previous one finishes, you will only be producing a single transition at each frequency. In order to play "notes" in sequence you will need to iterate through your note list based on a (much slower) steady clock to be able to hear each distinct tone. You also can't overlay tones with this method. This is why musical audio files (when uncompressed) have an amplitude measurement stored at 24,000+ times per second to replicate the actual waveform which may be composed of many individual tones. – QuantumRipple Dec 22 '14 at 17:50
  • Sorry to disturb you further but I'm a beginner and I don't know how to use a clock other than the embedded one. Can you elaborate? – Strider Dec 22 '14 at 18:12
  • There several ways to generate a slower clock from your existing clock. Most FPGAs have dedicated clock manipulation blocks that can multiply or divide clocks various ways, although you can also generate a divided clock using a counter just like you're doing with your tone generator. I would probably make a process on the 25MHz (primary clock) domain to increment the address of your note ROM when a counter rolls over instead of an actual separate clock. This uses a clock enable to get the desired slowdown without having to deal with multiple clock domains. – QuantumRipple Dec 22 '14 at 18:37

1 Answers1

0

VHDL is a strong-typed language, so you must be strict with the types.

Two issues, the rom_array is made with integer type elements, but it looks like the intention may have been to use unsigned (or another vector type) based on the constant assign to rom; so maybe do:

type rom_array is array (0 to 31) of unsigned (4 downto 0);

The reg_address is integer, thus it can't be assigned with string like in reg_address <= "00000";, so consider changing this to:

reg_address <= 0;
Morten Zilmer
  • 14,466
  • 2
  • 26
  • 47
  • but when I do that I can't add numbers like 56000 65000 to the array – Strider Dec 22 '14 at 17:55
  • Actually you can, you just need to convert them to unsigned (`to_unsigned(integer,width)`) and use a wide enough unsigned to handle the max value you want to use. – QuantumRipple Dec 22 '14 at 22:40