Вы создали серию из трех регистров, образующих каскад регистров.
Вы не предоставили сброс, поэтому содержимое регистра будет неизвестно. Вы используете регистры для расчетов без каких-либо условий. Таким образом, вы, арифметические вычисления, увидите неизвестные значения и потерпите неудачу, как вы видели.
Первое (самое простое) решение - добавить сброс. Но это не лучшее решение. Вы больше не будете получать предупреждения, но первые три цикла вашего вывода будут основаны на значении сброса регистра, а не на вашем входном сигнале.
Если у вас большой поток и вас не волнуют некоторые неправильные значения в первом такте, вы можете с этим смириться.
Действительно правильным способом было бы иметь «действительный» сигнал, транспортируемый вдоль ваших данных. Вы предоставляете выходные данные только тогда, когда есть «действительный». Это стандартный метод обработки данных через любую аппаратную структуру конвейера.
Кстати: вы обычно не строите D-ffs самостоятельно. Синтезатор сделает это за вас. Вы просто используете синхронизированный процесс и обрабатываете векторы данных в нем.
У меня есть несколько вопросов. Если я добавлю контакт сброса, когда я переключу его с 1 на 0? Как я могу создать эту схему без явного использования D-FFS?
Вы делаете сигнал сброса так же, как вы делаете свои часы.
Что касается D-регистров: они выходят, если вы используете стандартный код VHDL регистра:
reg : process (clk,reset_n)
begin
// a-synchronous active low reset
if (reset_n='0') then
s0 <= "0000";
s1 <= "0000";
s2 <= "0000";
elsif (rising_edge(clk)) then
s0 <= x;
s1 <= s0;
s2 <= s1;
....
(Код введен как есть, не проверен на синтаксис или ошибки при наборе)