Doubt about counter implemented in VHDL


I'm trying to learn VHDL and I came across some example code for a counter that I find somewhat strange.

I understand what it does but I'm not sure why it is written the way it is.

The code is the following:

entity counter is

generic(n: natural :=2);
port(   clock:  in std_logic;
    clear:  in std_logic;
    count:  in std_logic;
    Q:  out std_logic_vector(n-1 downto 0)
end counter;

architecture behv of counter is           

    signal Pre_Q: std_logic_vector(n-1 downto 0);


    -- behavior describe the counter

    process(clock, count, clear)
    if clear = '1' then
        Pre_Q <= Pre_Q - Pre_Q;
    elsif (clock='1' and clock'event) then
        if count = '1' then
        Pre_Q <= Pre_Q + 1;
        end if;
    end if;
    end process;    

    -- concurrent assignment statement
    Q <= Pre_Q;

end behv;


Can't we just replace this line

Pre_Q <= Pre_Q - Pre_Q;

with something like this? (I'm not sure if I can do this)

Pre_Q <= 0;

Is there any reason why I should use the first method instead of the second?

I apologize for deleting my previous question but I made a mistake when rewriting the code and I forgot to explain what my doubt really was.

Best Answer

The only advantage to writing it the first way that I can see is that, I suppose, it's type-independent. Maybe the original coder wanted to be able to copy and paste the code without modifying it (though one would think the signal name would need to be modified anyway), and depend on the synthesis tool to optimize it (or not). Personally, I do not think this is a good justification - it's less clear, and copying/pasting code without looking at it carefully is never a good idea.

Your assignment statement will change depending on your type. Pre_Q <= 0; for integer types, Pre_Q <= (others => '0'); (or equivalent) for vector types, etc.

(I see you've updated the question, and given that you're using a std_logic_vector, you'd want the latter)

response to comment

You wrote:

I do not understand the assignment for vectors. Can't I just use Pre_Q <= '0'?

A std_logic_vector is an array of std_logic, each one of which is an enumeration of 9 possible values/states (including '0' and '1'). They're not technically 0s and 1s to the language, odd though that may seem. So a std_logic_vector is not inherently a numeric type, and can only be treated as such with function overloads. If you try to assign '0' to Pre_Q, you are attempting to assign a scalar (in this case, technically a character literal) to a vector, and these types are not compatible in this way. Nor can you assign the integer literal 0 - while it may be obvious to almost anyone what you are intending to do, VHDL's strong typing does not allow this.

When you use (others => '0'), you are using an array aggregate. others is a keyword that refers to all indices of the array that have not been explicitly assigned in the aggregate (in this case, all of them), and so when you map the "other bits" to '0', you're zeroing the entire vector. (You can also use a conversion function, but (others => '0') is the more conventional idiom)