2013-11-12 2 views
3

Я пытаюсь написать файл регистра в VHDL. Файл содержит 16 64-битных регистров. Каждый цикл, два регистра считываются и записывается один регистр (при условии, что запись включена). Должен быть обход данных (пересылка), так что только что написанное значение пересылается непосредственно на выход, если мы читаем и записываем в/из одного и того же регистра за один цикл.Запись файла регистра в VHDL

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

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

entity register_file is 
    port 
    (
    outA   : out std_logic_vector(63 downto 0); 
    outB   : out std_logic_vector(63 downto 0); 
    input   : in std_logic_vector(63 downto 0); 
    writeEnable : in std_logic; 
    regASel  : in std_logic_vector(5 downto 0); 
    regBSel  : in std_logic_vector(5 downto 0); 
    writeRegSel : in std_logic_vector(5 downto 0); 
    clk   : in std_logic 
    ); 
end register_file; 

architecture behavioral of register_file is 
type registerFile is array(0 to 15) of std_logic_vector(63 downto 0); 
signal registers : registerFile; 
begin 

    regFile: process(clk) 
    begin 
     if rising_edge(clk) then 
      if(writeEnable = '1') then 
       registers(to_integer(unsigned(writeRegSel))) <= input; 
      end if; 
      if falling_edge(clk) then 
       outA <= registers(to_integer(unsigned(regASel))); 
       outB <= registers(to_integer(unsigned(regBSel))); 
      end if; 
     end if; 
     if falling_edge(clk) then 
       outA <= registers(to_integer(unsigned(regASel))); 
       outB <= registers(to_integer(unsigned(regBSel))); 
     end if; 
    end process; 
end behavioral; 

Любая помощь будет оценена по достоинству.

+0

Если вы хотите только 16 (2^4) регистров, то почему у вас есть 6-битная строка «адрес», дающая вам 64 (2^6) возможных комбинаций? –

+0

да, ты прав. Я думаю, что я просто сделал это по привычке из-за работы с MIPS – audiFanatic

ответ

6

Представленный код VHDL имеет конструкцию с:

... 
if rising_edge(clk) then 
    ... 
    if falling_edge(clk) then 
    ... 

Это оставит мертвый код, так как rising_edge и falling_edge не может быть правда в то же время. Кроме того, идея использования как нарастающего, так и спадающего фронтов часто вызывает проблемы проектирования и синтеза.

Для обеспечения наилучшего времени и простоты проектирования и ограничения синтеза я предлагаю использовать использование только нарастающего фронта, если только не обязательно использовать как подъем, так и падение край.

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

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

entity register_file is 
    port(
    outA  : out std_logic_vector(63 downto 0); 
    outB  : out std_logic_vector(63 downto 0); 
    input  : in std_logic_vector(63 downto 0); 
    writeEnable : in std_logic; 
    regASel  : in std_logic_vector(3 downto 0); 
    regBSel  : in std_logic_vector(3 downto 0); 
    writeRegSel : in std_logic_vector(3 downto 0); 
    clk   : in std_logic 
    ); 
end register_file; 


architecture behavioral of register_file is 
    type registerFile is array(0 to 15) of std_logic_vector(63 downto 0); 
    signal registers : registerFile; 
begin 
    regFile : process (clk) is 
    begin 
    if rising_edge(clk) then 
     -- Read A and B before bypass 
     outA <= registers(to_integer(unsigned(regASel))); 
     outB <= registers(to_integer(unsigned(regBSel))); 
     -- Write and bypass 
     if writeEnable = '1' then 
     registers(to_integer(unsigned(writeRegSel))) <= input; -- Write 
     if regASel = writeRegSel then -- Bypass for read A 
      outA <= input; 
     end if; 
     if regBSel = writeRegSel then -- Bypass for read B 
      outB <= input; 
     end if; 
     end if; 
    end if; 
    end process; 
end behavioral; 

Обратите внимание, что «адрес» в * Sel снижаются только 4 бита, чтобы соответствовать 16 требуемым записям в файле регистра, как отмечает также Даниэль Камиль Козар.

Нет проверки значений X в симуляции, но это может быть добавлено функцией Is_X, если требуется.

1

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

Если вы хотите иметь байпас, то его код явно в нормальном процессе нарастающего фронта:

outa <= registers(to_integer(...etc)); 
if write_enable = '1' and regAsel = writeregsel then 
    outa <= input; 
end if; 
-- similar for regb 

Кроме того, почему бы не сделать ваши regsel входы integer типа, или, по крайней мере, unsigned - при условии, что они определенно представляют собой число (а не просто произвольный мешок бит, что имеет место для ваших векторов данных IO)?

+0

Использование 'integer', поскольку тип для regsel удалит возможность неопределенных значений (' X') в симуляции с риском скрыть проблемы с неопределенными значениями, которые в противном случае могли бы быть наблюдаемый во время моделирования. Использование 'unsigned' допускает неопределенные значения, но вопрос в том, что модули, создающие файл регистра, рассматривают regsel как нечто, кроме мешка с битами.Таким образом, использование 'std_logic_vector' - это общий подход, который откладывает преобразование до определенного контекста. –

+0

@MortenZdk - вы указываете на * a * действительный подход к дизайну. Мне нравится как можно более четко формулировать как можно больше. Я не могу предусмотреть дизайн, в котором что-то, что выбирает регистр, было бы отличным от числа лично, но каждый по своему усмотрению :) Педант во мне также вынужден указать, что 'X' не является неопределенным, это противоречиво * (который не срабатывал при разработке, если бы использовалось «целое число»). 'U' - неопределенное (или технически« неинициализированное ») значение - я уверен, что вы это знали, но я укажу его будущим читателям :) –

+0

Спасибо за ваши комментарии :-) –

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