2013-11-24 4 views
0

В настоящее время я пытаюсь реализовать путь данных, который вычисляет следующее, за один такт.Комбинированное логическое время

  • Принимает ввод A и B и добавляет их.
  • Сдвиньте результат добавления, один бит вправо. (Деление на 2)
  • Вычесть сдвинутый результат от другого входа С.

Поведенческая архитектура объекта просто как показано ниже.

signal sum_out : std_logic_vector (7 downto 0); 
signal shift_out : std_logic_vector (7 downto 0); 

process (clock, data_in_a, data_in_b, data_in_c) 
begin 
    if clock'event and clock = '1' then 
     sum_out <= std_logic_vector(unsigned(data_in_a) + unsigned(data_in_b)); 
     shift_out <= '0' & sum_out(7 downto 1); 
     data_out <= std_logic_vector(unsigned(data_in_c) - unsigned(shift_out)); 
    end if; 
end process; 

Когда я имитирую вышеуказанный код, я получаю результат, который я ожидаю получить. Однако, я получаю результат, после 3 тактов, вместо 1, как я желаю. Форма волны моделирования показана ниже.

Simulation Waveform

Я еще не знаком с реализацией проектов с проблемами синхронизации. Мне было интересно, если есть способы достичь вышеуказанных расчетов, за один такт. Если есть, как я могу их реализовать?

ответ

2

Делать это с помощью сигналов просто регистрировать только последний элемент в цепочке (data_out). В этом анализе я не писал тестовый стенд для проверки моделирования.

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

entity signal_single_clock is 
    port ( 
     signal clock:  in std_logic; 
     signal data_in_a: in std_logic_vector(7 downto 0); 
     signal data_in_b: in std_logic_vector(7 downto 0); 
     signal data_in_c: in std_logic_vector(7 downto 0); 
     signal data_out: out std_logic_vector(7 downto 0) 
    ); 
end entity; 

architecture behave of signal_single_clock is 
    signal sum_out : std_logic_vector (7 downto 0); 
    signal shift_out : std_logic_vector (7 downto 0); 
begin 
    sum_out <= std_logic_vector(unsigned(data_in_a) + unsigned(data_in_b)); 
    shift_out <= '0' & sum_out(7 downto 1); 
single_reg: 
    process (clock) 
    begin 
     if clock'event and clock = '1' then 
      data_out <= std_logic_vector(unsigned(data_in_c) - unsigned(shift_out)); 
     end if; 
    end process; 
end architecture; 
+0

Спасибо, Дэвид. Код, который вы предоставили, также достиг цели синхронизации с правильным результатом. Означает ли это, что присвоение сигналов вне блока процесса происходит последовательным образом? (Sum_out оценивается до shift_out. Затем происходит процесс.)? – ElectroJunkie

+1

shift_out не должен был находиться в списке чувствительности процесса, я удалил его (многозадачность, ошибка автопилота). Причина, по которой он работает как цепочка, состоит в том, что оператор одновременного назначения сигналов чувствителен к сигналам с правой стороны. В модели с нулевым временем процесс будет ожидать часы, а shift_out уже будет готов. Назначения sum_out, shift_out и data_out являются последовательными, но не последовательными, упорядоченными по событиям. Синтез описания проекта будет зависеть от задержек задержек, добавляемых до менее чем одного периода тактового сигнала. – user1155120

+0

Мне приходилось много раз читать, чтобы понять это, но я думаю, что у меня есть это сейчас. Shift_out будет ожидать вычисления sum_out, потому что у присваивания shift_out есть sum_out с правой стороны. Это гарантирует, что sum_out и shift_out будут работать последовательно. Это была большая помощь. Большое спасибо, Дэвид! – ElectroJunkie

2

Когда вы назначаете новое значение сигналу внутри процесса, это новое значение будет доступно только после завершения процесса. Поэтому в любое время, когда вы читаете значение сигнала, вы будете использовать исходное значение с момента запуска процесса.

С другой стороны, присвоения varibles происходят немедленно, и новое значение может быть использовано в последующих операциях, если вы хотите.

Итак, чтобы решить вашу проблему, просто реализуйте sum_out, shift_out и data_out используя переменные, а не сигналы. Затем просто скопируйте значение data_out в выходной порт вашего объекта.

+0

Спасибо, Рик. Код теперь показывает результат в следующем такте. Если можно, могу ли я спросить, есть ли способ достичь того же, используя только сигналы, без использования переменных? – ElectroJunkie

+1

Да, в этом случае предложение Брайана именно то, что вам нужно, я предлагаю вам пойти с этим, если вы хотите использовать сигналы. – rick

+0

Спасибо за ваш ответ :) – ElectroJunkie

2

без использования переменных:

sum <= in_a + in_b; 
process (clock) 
begin 
    if rising_edge(clock) then 
     data_out <= in_c - ('0' & sum(7 downto 1)); 
    end if; 
end process; 

Все декларации, за исключением часов являются unsigned(7 downto 0); почему делают его более сложным, чем это?

Оригинальный, конвейерный до 3 тактов, вероятно, будет работать при более высоких тактовых частотах.

EDIT следующий комментарий:

Я хотел показать, что VHDL на самом деле не должны быть что многословным.

Однако, похоже, что многие люди «учат» VHDL, которые сосредоточены на элементарных элементах и ​​полностью теряют общую картину, поэтому я скажу немного об этом.

VHDL - это строго типизированный язык, чтобы избежать ошибок, возникающих при ошибках типов друг для друга и (например,) вы добавляете два больших числа и получаете отрицательный результат.

Это НЕ следует из того, что вам нужно преобразовать тип по всему месту. Действительно, если вам нужно много преобразований типов, это признак того, что ваш дизайн, вероятно, неправильный, и пришло время переосмыслить это, вместо того, чтобы пахать вперед по неправильному пути.

Код - на ЛЮБОЙ языке - должен быть максимально чистым и простым.

В противном случае это трудно прочитать, и в нем, вероятно, есть ошибки.

Большая разница между C-подобным языком и VHDL это:

В C, используя правильные типы данных, которые вы можете написать sum = in_a + in_b; и он будет работать. Используя неправильные типы данных, вы также можете написать sum = in_a + in_b; , и он будет компилироваться просто отлично; то, что он на самом деле делает, это другое дело! Ошибки скрыты: вам решать определить правильные типы, и если вы ошибаетесь, вы можете сделать это очень мало, кроме как продолжать тестирование.

в VHDL, используя правильные типы вы можете написать sum <= in_a + in_b; и используя неправильные типы, компилятор заставляет вас писать что-то вроде sum <= std_logic_vector(unsigned(in_a) + unsigned(in_b));, который чертовски некрасиво, но (возможно: см примечание 1) по-прежнему работать правильно.

Чтобы ответить на вопрос: как я могу использовать unsigned или std_logic_vector?

Я вижу, что мне нужны три входа и выход. I мог просто сделать их std_logic_vector, но я останавливаюсь и спрашиваю: что они представляют?

Номера.

Могут ли они быть отрицательными? Не согласно моему чтению спецификации (ваш вопрос).

Таким образом, без знака ... (Примечание 1)

мне нужно, не арифметические операции над ними делать? Да, есть сдвиг. (Примечание 2)

Итак, numeric_std.unsigned, что связано с std_logic_vector вместо natural, которое является целым числом.

Теперь вы не можете избежать преобразования типов вообще. Стандарты кодирования могут налагать такие ограничения, как «все порты верхнего уровня должны быть std_logic_vector», и вы должны реализовать спецификацию внешнего объекта, к которой вы просили; промежуточные сигналы для преобразования типов иногда более чистые, чем альтернативы, например. in_a <= unsigned(data_in_a);
Или, если вы получаете инструкции, символы и цифры выше из той же памяти, например, вы можете решить, что содержимое памяти должно быть std_logic_vector, потому что оно не просто содержит номера. Но выберите подходящее место для преобразования типа, и вы обнаружите, что 90% типов конверсий исчезают. Возьмите это как руководство по проектированию.

(Примечание 1: а что произойдет, если C < (A + B)/2 Если data_out подписываются Даже думать вдоль этих линий всплыл вероятную ошибку, STD_LOGIC_VECTOR оставил скрытые ...

право? ответ зависит от неизвестных, включая цель data_out: если он действительно должен быть неподписанным, напримерадрес памяти, вы можете пометить ошибку вместо того, чтобы он подписал)

(Примечание 2: не существует инструмент синтеза, который остался в живых не будет переводить signal a : natural; ... x <= a/2 в сдвиг вправо, так natural бы также работа, если не было других причин выбора неподписанных. Многим кажется, что их все еще учат, что целые числа не являются синтезируемыми, и это всего лишь неправильный.)

+0

Дорогой Брайан. Мне нравится ваше предложение. Он довольно сжат. Как бы вы решили, что используете unsigned напротив std_logic_vector? Вероятно, есть причины, по которым они используются отдельно, но я не могу понять, почему. – ElectroJunkie

Смежные вопросы