There are a number of style issues here and one major problem.
Fru1tbat has pointed out that you never initialise MainCounter : one way to do so would be to drive the Reset input with a simple waveform :
RESET <= '0', '1' after 100 ns, '0' after 200 ns;
in the parallel execution region (after the architecture "begin") would do so. Note that this is for simulation only, and it would be MUCH better to make RESET an input port and drive it from your simulation testbench.
Secondly (and this is the major problem, waiting to bite you randomly in real hardware) the RESET clause in process COUNT should be simplified to ONLY clear MainCounter
on reset. Then the wrapround clear should be moved into the clocked part of the process:
if Reset = '1' then
MainCounter <= (others => '0');
elsif rising_edge(Clk) then
if MainCounter >= 12345 then
MainCounter <= (others => '0');
else
MainCounter <= MainCounter + 1;
end if;
end if;
The reason for this is subtle if you're not used to hardware design : as expressed, you have a pile of asynchronous logic waiting to clear the counter if it momentarily transitions to a high number while counting. So counting from X"7FFF" to X"8000" it will probably momentarily pass through X"FFFF" ... and reset itself.
By moving that logic to the clocked part, it will only reset if the temporary state persists until the next clock edge : and the timing analysis tools will report timing failure if that is even a possibility.
Now the warnings : Metavalues at 0 ns are basically harmless. Metavalues persisting AFTER reset is complete are a different matter...
And the style issues :
You can compare Unsigned against simple integer literals (because numeric_std overloads comparison operators with mixed operand types) and that would make the code MUCH more readable. Better : use constant declarations instead of magic numbers. (As you discovered, you can't assign an integer literal to an unsigned; because assignment is not an operator. There are to_unsigned and to_integer conversion functions for that purpose)
There is no need for parentheses around boolean expressions e.g. in if-statements. Some C programmers use them out of habit, but it looks needlessly cluttered to me.
Your SLOW process is unclocked, despite the clock in its sensitivity list... I prefer simple clocked processes; they avoid the problems that plague combinational processes such as SLOW - which will not work correctly unless you add all the RHS signals (here - only Maincounter) to the sensitivity list.
I assume that ctr_reg is of type (un)signed because it's a counter.
VHDL expect normal indices to be of type integer (natural, positive are subtypes of integer). See the definition for std_logic_vector:
type STD_LOGIC_VECTOR is array (NATURAL range <>) of STD_LOGIC;
So you must convert your counter from (un)signed to integer:
if (numerator(to_integer(ctr_reg)) = '1') then
If ctr_reg is of type std_logic_vector (slv), then you must also convert slv to unsigned:
if (numerator(to_integer(unsigned(ctr_reg))) = '1') then
If this construct is to long, write a function (let's say to_index(..)) which hides these conversions :)
if (numerator(to_index(ctr_reg)) = '1') then
A definition for to_index(..)
can be found here.
Edit 1:
List of commonly used packages in VHDL:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL; -- common std_logic(_vector) operations
use IEEE.NUMERIC_STD.ALL; -- defines signed and unsigned and their operations
Best Answer
You don't say what you want the code to do, but I can see a couple of trouble areas. The first is that you don't have any reset logic in your process. It's important to make sure that you properly initialize everything in order to prevent unusual operation. This however is not likely the cause of your trouble.
What I think is causing the incorrect operation is that you are looking for the clock signal to be high instead of checking for the clock to transition from a low to high. This is called the "rising edge" of the clock. Synchronous logic operates on clock edges rather than clock levels.
You mention that you should not have to look for a rising edge since the clock is in the sensitivity list, and thus if your process is executed you can only check the level of the clock. This may be theoretically true but synthesis tools work by inferring logic from the language used to describe it. Most synthesis tools I have used are designed to produce correct logic when described below.
Writing good HDL is just as much about getting the logic correct as it is describing it in the way the synthesis tools are expecting to see it. If you decide "it's the same thing" and write things in a non-standard way you may well find that the simulator tells you one thing but the synthesizer fails to see it the same way. This is a fine point to learn, and one that can cause you a lot of headache and frustration should you decide otherwise.